diff --git a/.buildkite/ftr_security_serverless_configs.yml b/.buildkite/ftr_security_serverless_configs.yml index d6a92fbb5f446..cf1b374e68c60 100644 --- a/.buildkite/ftr_security_serverless_configs.yml +++ b/.buildkite/ftr_security_serverless_configs.yml @@ -65,6 +65,7 @@ enabled: - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/large_prebuilt_rules_package/trial_license_complete_tier/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/update_prebuilt_rules_package/trial_license_complete_tier/configs/serverless.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/trial_license_complete_tier/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/trial_license_complete_tier/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/basic_license_essentials_tier/configs/serverless.config.ts diff --git a/.buildkite/ftr_security_stateful_configs.yml b/.buildkite/ftr_security_stateful_configs.yml index 148d78583a613..a72f5287d189b 100644 --- a/.buildkite/ftr_security_stateful_configs.yml +++ b/.buildkite/ftr_security_stateful_configs.yml @@ -47,6 +47,7 @@ enabled: - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/large_prebuilt_rules_package/trial_license_complete_tier/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/management/trial_license_complete_tier/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/update_prebuilt_rules_package/trial_license_complete_tier/configs/ess.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/trial_license_complete_tier/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/trial_license_complete_tier/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/basic_license_essentials_tier/configs/ess.config.ts diff --git a/.buildkite/package-lock.json b/.buildkite/package-lock.json index de45e39fb4092..8d10b3c2b7bc1 100644 --- a/.buildkite/package-lock.json +++ b/.buildkite/package-lock.json @@ -1011,11 +1011,11 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -2416,11 +2416,11 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" }, "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "requires": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" } }, diff --git a/.buildkite/pipeline-utils/buildkite/client.test.ts b/.buildkite/pipeline-utils/buildkite/client.test.ts index ef70a0b3a4620..97b14815f6937 100644 --- a/.buildkite/pipeline-utils/buildkite/client.test.ts +++ b/.buildkite/pipeline-utils/buildkite/client.test.ts @@ -24,9 +24,7 @@ describe('BuildkiteClient', () => { id: 'id-1', retried_in_job_id: 'id-2', state: 'failed', - agent: { - meta_data: ['spot=true'], - }, + agent_query_rules: ['preemptible=true'], retried: true, exit_status: -1, type: 'script', @@ -35,9 +33,7 @@ describe('BuildkiteClient', () => { const retry: Job = { id: 'id-2', state: 'passed', - agent: { - meta_data: ['spot=true'], - }, + agent_query_rules: ['preemptible=true'], type: 'script', } as Job; @@ -58,9 +54,7 @@ describe('BuildkiteClient', () => { id: 'id-1', retried_in_job_id: 'id-2', state: 'failed', - agent: { - meta_data: ['spot=true'], - }, + agent_query_rules: ['preemptible=true'], retried: true, exit_status: 1, type: 'script', @@ -69,9 +63,7 @@ describe('BuildkiteClient', () => { const retry: Job = { id: 'id-2', state: 'passed', - agent: { - meta_data: ['spot=true'], - }, + agent_query_rules: ['preemptible=true'], type: 'script', } as Job; diff --git a/.buildkite/pipeline-utils/buildkite/client.ts b/.buildkite/pipeline-utils/buildkite/client.ts index a0232d90e8e07..45f09817dba8e 100644 --- a/.buildkite/pipeline-utils/buildkite/client.ts +++ b/.buildkite/pipeline-utils/buildkite/client.ts @@ -285,7 +285,7 @@ export class BuildkiteClient { hasRetries = true; const isPreemptionFailure = job.state === 'failed' && - job.agent?.meta_data?.some((el) => ['spot=true', 'gcp:preemptible=true'].includes(el)) && + job.agent_query_rules?.includes('preemptible=true') && job.exit_status === -1; if (!isPreemptionFailure) { diff --git a/.eslintrc.js b/.eslintrc.js index e8216f62792b2..811676f049158 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -928,7 +928,10 @@ module.exports = { }, }, { - files: ['x-pack/plugins/observability_solution/**/*.{ts,tsx}'], + files: [ + 'x-pack/plugins/observability_solution/**/*.{ts,tsx}', + 'x-pack/packages/observability/**/*.{ts,tsx}', + ], rules: { 'react-hooks/exhaustive-deps': [ 'error', @@ -944,6 +947,7 @@ module.exports = { 'x-pack/plugins/aiops/**/*.tsx', 'x-pack/plugins/observability_solution/**/*.tsx', 'src/plugins/ai_assistant_management/**/*.tsx', + 'x-pack/packages/observability/**/*.{ts,tsx}', ], rules: { '@kbn/telemetry/event_generating_elements_should_be_instrumented': 'error', diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b74db49fc30ea..c6beae627cb53 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -642,6 +642,7 @@ x-pack/plugins/observability_solution/observability_onboarding/e2e @elastic/obs- x-pack/plugins/observability_solution/observability_onboarding @elastic/obs-ux-logs-team @elastic/obs-ux-onboarding-team x-pack/plugins/observability_solution/observability @elastic/obs-ux-management-team x-pack/plugins/observability_solution/observability_shared @elastic/observability-ui +x-pack/packages/observability/observability_utils @elastic/observability-ui x-pack/test/security_api_integration/plugins/oidc_provider @elastic/kibana-security test/common/plugins/otel_metrics @elastic/obs-ux-infra_services-team packages/kbn-openapi-bundler @elastic/security-detection-rule-management @@ -774,6 +775,7 @@ x-pack/packages/security-solution/side_nav @elastic/security-threat-hunting-expl x-pack/packages/security-solution/storybook/config @elastic/security-threat-hunting-explore x-pack/packages/security-solution/upselling @elastic/security-threat-hunting-explore x-pack/test/security_functional/plugins/test_endpoints @elastic/kibana-security +x-pack/packages/security/ui_components @elastic/kibana-security packages/kbn-securitysolution-autocomplete @elastic/security-detection-engine x-pack/packages/security-solution/data_table @elastic/security-threat-hunting-investigations packages/kbn-securitysolution-ecs @elastic/security-threat-hunting-explore @@ -1555,18 +1557,18 @@ x-pack/test/security_solution_cypress/cypress/tasks/expandable_flyout @elastic/ ## Generative AI owner connectors # OpenAI -/x-pack/plugins/stack_connectors/public/connector_types/openai @elastic/security-generative-ai @elastic/obs-ai-assistant -/x-pack/plugins/stack_connectors/server/connector_types/openai @elastic/security-generative-ai @elastic/obs-ai-assistant -/x-pack/plugins/stack_connectors/common/openai @elastic/security-generative-ai @elastic/obs-ai-assistant +/x-pack/plugins/stack_connectors/public/connector_types/openai @elastic/security-generative-ai @elastic/obs-ai-assistant @elastic/appex-ai-infra +/x-pack/plugins/stack_connectors/server/connector_types/openai @elastic/security-generative-ai @elastic/obs-ai-assistant @elastic/appex-ai-infra +/x-pack/plugins/stack_connectors/common/openai @elastic/security-generative-ai @elastic/obs-ai-assistant @elastic/appex-ai-infra # Bedrock -/x-pack/plugins/stack_connectors/public/connector_types/bedrock @elastic/security-generative-ai @elastic/obs-ai-assistant -/x-pack/plugins/stack_connectors/server/connector_types/bedrock @elastic/security-generative-ai @elastic/obs-ai-assistant -/x-pack/plugins/stack_connectors/common/bedrock @elastic/security-generative-ai @elastic/obs-ai-assistant +/x-pack/plugins/stack_connectors/public/connector_types/bedrock @elastic/security-generative-ai @elastic/obs-ai-assistant @elastic/appex-ai-infra +/x-pack/plugins/stack_connectors/server/connector_types/bedrock @elastic/security-generative-ai @elastic/obs-ai-assistant @elastic/appex-ai-infra +/x-pack/plugins/stack_connectors/common/bedrock @elastic/security-generative-ai @elastic/obs-ai-assistant @elastic/appex-ai-infra # Gemini -/x-pack/plugins/stack_connectors/public/connector_types/gemini @elastic/security-generative-ai @elastic/obs-ai-assistant -/x-pack/plugins/stack_connectors/server/connector_types/gemini @elastic/security-generative-ai @elastic/obs-ai-assistant -/x-pack/plugins/stack_connectors/common/gemini @elastic/security-generative-ai @elastic/obs-ai-assistant +/x-pack/plugins/stack_connectors/public/connector_types/gemini @elastic/security-generative-ai @elastic/obs-ai-assistant @elastic/appex-ai-infra +/x-pack/plugins/stack_connectors/server/connector_types/gemini @elastic/security-generative-ai @elastic/obs-ai-assistant @elastic/appex-ai-infra +/x-pack/plugins/stack_connectors/common/gemini @elastic/security-generative-ai @elastic/obs-ai-assistant @elastic/appex-ai-infra ## Defend Workflows owner connectors /x-pack/plugins/stack_connectors/public/connector_types/sentinelone @elastic/security-defend-workflows diff --git a/.gitignore b/.gitignore index 02f11f9275184..c5c048f10d7d4 100644 --- a/.gitignore +++ b/.gitignore @@ -146,9 +146,9 @@ role_users.json .devcontainer/.env # Ignore temporary files in oas_docs -output/kibana.serverless.tmp1.yaml -output/kibana.serverless.tmp2.yaml -output/kibana.tmp1.yaml -output/kibana.tmp2.yaml -output/kibana.new.yaml -output/kibana.serverless.new.yaml +oas_docs/output/kibana.serverless.tmp1.yaml +oas_docs/output/kibana.serverless.tmp2.yaml +oas_docs/output/kibana.tmp1.yaml +oas_docs/output/kibana.tmp2.yaml +oas_docs/output/kibana.new.yaml +oas_docs/output/kibana.serverless.new.yaml diff --git a/.i18nrc.json b/.i18nrc.json index 59e33320eeea1..7707bfdcde172 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -33,6 +33,7 @@ "presentationPanel": "src/plugins/presentation_panel", "embeddableExamples": "examples/embeddable_examples", "esQuery": "packages/kbn-es-query/src", + "kbnGridLayout": "packages/kbn-grid-layout", "esUi": "src/plugins/es_ui_shared", "expandableFlyout": "packages/kbn-expandable-flyout", "expressionError": "src/plugins/expression_error", diff --git a/api_docs/actions.devdocs.json b/api_docs/actions.devdocs.json index 22c2fabddb90b..51049c59a926f 100644 --- a/api_docs/actions.devdocs.json +++ b/api_docs/actions.devdocs.json @@ -317,7 +317,9 @@ "label": "addComment", "description": [], "signature": [ - "({ incidentId, comment, }: { incidentId: string; comment: string; }) => Promise" + "({ incidentId, comment, }: { incidentId: string; comment: string; }, connectorUsageCollector: ", + "ConnectorUsageCollector", + ") => Promise" ], "path": "x-pack/plugins/actions/server/sub_action_framework/case.ts", "deprecated": false, @@ -328,7 +330,7 @@ "id": "def-server.CaseConnector.addComment.$1", "type": "Object", "tags": [], - "label": "{\n incidentId,\n comment,\n }", + "label": "{\n incidentId,\n comment,\n }", "description": [], "path": "x-pack/plugins/actions/server/sub_action_framework/case.ts", "deprecated": false, @@ -357,6 +359,21 @@ "trackAdoption": false } ] + }, + { + "parentPluginId": "actions", + "id": "def-server.CaseConnector.addComment.$2", + "type": "Object", + "tags": [], + "label": "connectorUsageCollector", + "description": [], + "signature": [ + "ConnectorUsageCollector" + ], + "path": "x-pack/plugins/actions/server/sub_action_framework/case.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true } ], "returnComment": [] @@ -369,7 +386,9 @@ "label": "createIncident", "description": [], "signature": [ - "(incident: Incident) => Promise<", + "(incident: Incident, connectorUsageCollector: ", + "ConnectorUsageCollector", + ") => Promise<", "ExternalServiceIncidentResponse", ">" ], @@ -391,6 +410,21 @@ "deprecated": false, "trackAdoption": false, "isRequired": true + }, + { + "parentPluginId": "actions", + "id": "def-server.CaseConnector.createIncident.$2", + "type": "Object", + "tags": [], + "label": "connectorUsageCollector", + "description": [], + "signature": [ + "ConnectorUsageCollector" + ], + "path": "x-pack/plugins/actions/server/sub_action_framework/case.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true } ], "returnComment": [] @@ -403,7 +437,9 @@ "label": "updateIncident", "description": [], "signature": [ - "({ incidentId, incident, }: { incidentId: string; incident: Incident; }) => Promise<", + "({ incidentId, incident, }: { incidentId: string; incident: Incident; }, connectorUsageCollector: ", + "ConnectorUsageCollector", + ") => Promise<", "ExternalServiceIncidentResponse", ">" ], @@ -416,7 +452,7 @@ "id": "def-server.CaseConnector.updateIncident.$1", "type": "Object", "tags": [], - "label": "{\n incidentId,\n incident,\n }", + "label": "{\n incidentId,\n incident,\n }", "description": [], "path": "x-pack/plugins/actions/server/sub_action_framework/case.ts", "deprecated": false, @@ -448,6 +484,21 @@ "trackAdoption": false } ] + }, + { + "parentPluginId": "actions", + "id": "def-server.CaseConnector.updateIncident.$2", + "type": "Object", + "tags": [], + "label": "connectorUsageCollector", + "description": [], + "signature": [ + "ConnectorUsageCollector" + ], + "path": "x-pack/plugins/actions/server/sub_action_framework/case.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true } ], "returnComment": [] @@ -460,7 +511,9 @@ "label": "getIncident", "description": [], "signature": [ - "({ id }: { id: string; }) => Promise" + "({ id }: { id: string; }, connectorUsageCollector: ", + "ConnectorUsageCollector", + ") => Promise" ], "path": "x-pack/plugins/actions/server/sub_action_framework/case.ts", "deprecated": false, @@ -489,6 +542,21 @@ "trackAdoption": false } ] + }, + { + "parentPluginId": "actions", + "id": "def-server.CaseConnector.getIncident.$2", + "type": "Object", + "tags": [], + "label": "connectorUsageCollector", + "description": [], + "signature": [ + "ConnectorUsageCollector" + ], + "path": "x-pack/plugins/actions/server/sub_action_framework/case.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true } ], "returnComment": [] @@ -501,7 +569,9 @@ "label": "pushToService", "description": [], "signature": [ - "(params: { incident: { externalId: string | null; } & Incident; comments: { commentId: string; comment: string; }[]; }) => Promise<", + "(params: { incident: { externalId: string | null; } & Incident; comments: { commentId: string; comment: string; }[]; }, connectorUsageCollector: ", + "ConnectorUsageCollector", + ") => Promise<", "PushToServiceResponse", ">" ], @@ -549,6 +619,21 @@ "trackAdoption": false } ] + }, + { + "parentPluginId": "actions", + "id": "def-server.CaseConnector.pushToService.$2", + "type": "Object", + "tags": [], + "label": "connectorUsageCollector", + "description": [], + "signature": [ + "ConnectorUsageCollector" + ], + "path": "x-pack/plugins/actions/server/sub_action_framework/case.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true } ], "returnComment": [] @@ -2116,7 +2201,9 @@ "signature": [ "({ url, data, method, responseSchema, headers, timeout, ...config }: ", "SubActionRequestParams", - ") => Promise<", + ", connectorUsageCollector: ", + "ConnectorUsageCollector", + ") => Promise<", "AxiosResponse", ">" ], @@ -2129,7 +2216,7 @@ "id": "def-server.SubActionConnector.request.$1", "type": "CompoundType", "tags": [], - "label": "{\n url,\n data,\n method = 'get',\n responseSchema,\n headers,\n timeout,\n ...config\n }", + "label": "{\n url,\n data,\n method = 'get',\n responseSchema,\n headers,\n timeout,\n ...config\n }", "description": [], "signature": [ "SubActionRequestParams", @@ -2139,6 +2226,21 @@ "deprecated": false, "trackAdoption": false, "isRequired": true + }, + { + "parentPluginId": "actions", + "id": "def-server.SubActionConnector.request.$2", + "type": "Object", + "tags": [], + "label": "connectorUsageCollector", + "description": [], + "signature": [ + "ConnectorUsageCollector" + ], + "path": "x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true } ], "returnComment": [] @@ -3141,6 +3243,20 @@ "path": "x-pack/plugins/actions/server/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "actions", + "id": "def-server.ActionTypeExecutorOptions.connectorUsageCollector", + "type": "Object", + "tags": [], + "label": "connectorUsageCollector", + "description": [], + "signature": [ + "ConnectorUsageCollector" + ], + "path": "x-pack/plugins/actions/server/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index d1b0d67338110..b8cbb98efa0c9 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-o | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 307 | 0 | 301 | 32 | +| 314 | 0 | 308 | 33 | ## Client diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index 00f292e066bd1..ba8f818c9b672 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/ai_assistant_management_selection.mdx b/api_docs/ai_assistant_management_selection.mdx index c693b3de6677e..bb5e1729f30a5 100644 --- a/api_docs/ai_assistant_management_selection.mdx +++ b/api_docs/ai_assistant_management_selection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiAssistantManagementSelection title: "aiAssistantManagementSelection" image: https://source.unsplash.com/400x175/?github description: API docs for the aiAssistantManagementSelection plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiAssistantManagementSelection'] --- import aiAssistantManagementSelectionObj from './ai_assistant_management_selection.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index be6ca5a797716..592da097ffa0c 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.devdocs.json b/api_docs/alerting.devdocs.json index a2ee90c61e223..b847d4bf6cbfd 100644 --- a/api_docs/alerting.devdocs.json +++ b/api_docs/alerting.devdocs.json @@ -3806,14 +3806,6 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts" }, - { - "plugin": "synthetics", - "path": "x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.ts" - }, - { - "plugin": "synthetics", - "path": "x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/tls_rule.ts" - }, { "plugin": "ruleRegistry", "path": "x-pack/plugins/rule_registry/server/utils/rule_executor.test_helpers.ts" diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index 1a063657bc3ca..2563c97cb6dcb 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 13e52a01e4bc3..f0872225f3ce0 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/apm_data_access.mdx b/api_docs/apm_data_access.mdx index 613931cbc07ad..2854ca2bbdaf0 100644 --- a/api_docs/apm_data_access.mdx +++ b/api_docs/apm_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apmDataAccess title: "apmDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the apmDataAccess plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apmDataAccess'] --- import apmDataAccessObj from './apm_data_access.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index c84613332411c..e7c6e707f8e45 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index 37d3c259bd800..619365af1643d 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] --- import bfetchObj from './bfetch.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index f197f466828e3..1ab3eddd7b991 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index 2df911cc5320b..7fa08935f7142 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; diff --git a/api_docs/charts.devdocs.json b/api_docs/charts.devdocs.json index 352a691873da8..ad5f7038d72fe 100644 --- a/api_docs/charts.devdocs.json +++ b/api_docs/charts.devdocs.json @@ -609,7 +609,8 @@ "Chart", ">, syncOptions: ", "ActiveCursorSyncOption", - ") => (cursor: any) => void" + ") => ", + "PointerUpdateListener" ], "path": "src/plugins/charts/public/services/active_cursor/use_active_cursor.ts", "deprecated": false, diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index 51bfb61d58d53..e36836b67f4b3 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.devdocs.json'; diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index c41165e1ee318..633628f928786 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index 78b45c64c1598..9b167e45282a1 100644 --- a/api_docs/cloud_data_migration.mdx +++ b/api_docs/cloud_data_migration.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDataMigration title: "cloudDataMigration" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDataMigration plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDataMigration'] --- import cloudDataMigrationObj from './cloud_data_migration.devdocs.json'; diff --git a/api_docs/cloud_defend.mdx b/api_docs/cloud_defend.mdx index 8924b2865f020..52f333202a58e 100644 --- a/api_docs/cloud_defend.mdx +++ b/api_docs/cloud_defend.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDefend title: "cloudDefend" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDefend plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend'] --- import cloudDefendObj from './cloud_defend.devdocs.json'; diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index dd48d4ac54d58..32b7228146223 100644 --- a/api_docs/cloud_experiments.mdx +++ b/api_docs/cloud_experiments.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudExperiments title: "cloudExperiments" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudExperiments plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudExperiments'] --- import cloudExperimentsObj from './cloud_experiments.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index 62fd884e90c6d..8ece2af4ae732 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture'] --- import cloudSecurityPostureObj from './cloud_security_posture.devdocs.json'; diff --git a/api_docs/console.mdx b/api_docs/console.mdx index daccfcd4cf298..b110b5f0b93ea 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/content_management.mdx b/api_docs/content_management.mdx index 68c4aee644c2c..9285ce9d55573 100644 --- a/api_docs/content_management.mdx +++ b/api_docs/content_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/contentManagement title: "contentManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the contentManagement plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'contentManagement'] --- import contentManagementObj from './content_management.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index c8b738ffc3cac..c27608737678d 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index be528efc795ec..95c3d19fd414b 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.devdocs.json b/api_docs/dashboard.devdocs.json index 3a5a539dc0807..805e3041563a0 100644 --- a/api_docs/dashboard.devdocs.json +++ b/api_docs/dashboard.devdocs.json @@ -1721,17 +1721,17 @@ "(id: string, references: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.Reference", + "section": "def-server.Reference", "text": "Reference" }, "[]) => ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.Reference", + "section": "def-server.Reference", "text": "Reference" }, "[]" @@ -1765,9 +1765,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.Reference", + "section": "def-server.Reference", "text": "Reference" }, "[]" @@ -2356,9 +2356,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.Reference", + "section": "def-server.Reference", "text": "Reference" }, "[] | undefined" diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index 485b62c398132..b0ad103707038 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index 42e081040e905..832f73db04e10 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.mdx b/api_docs/data.mdx index ae5937d365d80..cdb9131d3e7c2 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_quality.mdx b/api_docs/data_quality.mdx index 41028dd816d74..75a79d6bd9475 100644 --- a/api_docs/data_quality.mdx +++ b/api_docs/data_quality.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataQuality title: "dataQuality" image: https://source.unsplash.com/400x175/?github description: API docs for the dataQuality plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataQuality'] --- import dataQualityObj from './data_quality.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index fffe43296211b..55c89861e67d1 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index c25bda8943efb..388dfd43a359c 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 436eede1240b4..b5527231113c7 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] --- import dataViewEditorObj from './data_view_editor.devdocs.json'; diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index 89aa3a4b3ae7d..d8b1353e1060b 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] --- import dataViewFieldEditorObj from './data_view_field_editor.devdocs.json'; diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index 1757889dd6502..b3ca7699fce6b 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 6a74b9a11ded2..d9d3ead614386 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 91ca1bc925b24..2b966b1f67d3c 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/dataset_quality.devdocs.json b/api_docs/dataset_quality.devdocs.json index 22bb1d7a3e854..abb0b1320eb0c 100644 --- a/api_docs/dataset_quality.devdocs.json +++ b/api_docs/dataset_quality.devdocs.json @@ -240,15 +240,9 @@ "DatasetQualityRouteHandlerResources", " & { params: { path: { integration: string; }; }; }) => Promise<{ dashboards: { id: string; title: string; }[]; }>; } & ", "DatasetQualityRouteCreateOptions", - "; \"GET /internal/dataset_quality/integrations\": { endpoint: \"GET /internal/dataset_quality/integrations\"; params?: ", - "TypeC", - "<{ query: ", - "PartialC", - "<{ type: ", - "KeyofC", - "<{ logs: null; metrics: null; traces: null; synthetics: null; profiling: null; }>; }>; }> | undefined; handler: ({}: ", + "; \"GET /internal/dataset_quality/integrations\": { endpoint: \"GET /internal/dataset_quality/integrations\"; params?: undefined; handler: ({}: ", "DatasetQualityRouteHandlerResources", - " & { params: { query: { type?: \"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\" | undefined; }; }; }) => Promise<{ integrations: ({ name: string; } & { title?: string | undefined; version?: string | undefined; icons?: ({ src: string; } & { path?: string | undefined; size?: string | undefined; title?: string | undefined; type?: string | undefined; })[] | undefined; datasets?: { [x: string]: string; } | undefined; })[]; }>; } & ", + ") => Promise<{ integrations: ({ name: string; } & { title?: string | undefined; version?: string | undefined; icons?: ({ src: string; } & { path?: string | undefined; size?: string | undefined; title?: string | undefined; type?: string | undefined; })[] | undefined; datasets?: { [x: string]: string; } | undefined; })[]; }>; } & ", "DatasetQualityRouteCreateOptions", "; \"GET /internal/dataset_quality/data_streams/{dataStream}/settings\": { endpoint: \"GET /internal/dataset_quality/data_streams/{dataStream}/settings\"; params?: ", "TypeC", @@ -292,9 +286,13 @@ "DatasetQualityRouteHandlerResources", " & { params: { path: { dataStream: string; }; query: { start: number; end: number; }; }; }) => Promise<{ degradedFields: { name: string; count: number; lastOccurrence: number | null; timeSeries: { x: number; y: number; }[]; }[]; }>; } & ", "DatasetQualityRouteCreateOptions", - "; \"GET /internal/dataset_quality/data_streams/non_aggregatable\": { endpoint: \"GET /internal/dataset_quality/data_streams/non_aggregatable\"; params?: ", + "; \"GET /internal/dataset_quality/data_streams/{dataStream}/non_aggregatable\": { endpoint: \"GET /internal/dataset_quality/data_streams/{dataStream}/non_aggregatable\"; params?: ", "TypeC", - "<{ query: ", + "<{ path: ", + "TypeC", + "<{ dataStream: ", + "StringC", + "; }>; query: ", "IntersectionC", "<[", "TypeC", @@ -303,16 +301,34 @@ "; end: ", "Type", "; }>, ", - "PartialC", + "TypeC", "<{ type: ", "KeyofC", - "<{ logs: null; metrics: null; traces: null; synthetics: null; profiling: null; }>; }>, ", + "<{ logs: null; metrics: null; traces: null; synthetics: null; profiling: null; }>; }>]>; }> | undefined; handler: ({}: ", + "DatasetQualityRouteHandlerResources", + " & { params: { path: { dataStream: string; }; query: { start: number; end: number; } & { type: \"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\"; }; }; }) => Promise<{ aggregatable: boolean; datasets: string[]; }>; } & ", + "DatasetQualityRouteCreateOptions", + "; \"GET /internal/dataset_quality/data_streams/non_aggregatable\": { endpoint: \"GET /internal/dataset_quality/data_streams/non_aggregatable\"; params?: ", + "TypeC", + "<{ query: ", + "IntersectionC", + "<[", + "TypeC", + "<{ start: ", + "Type", + "; end: ", + "Type", + "; }>, ", + "TypeC", + "<{ types: ", + "Type", + "<(\"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\")[], (\"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\")[], unknown>; }>, ", "PartialC", "<{ dataStream: ", "StringC", "; }>]>; }> | undefined; handler: ({}: ", "DatasetQualityRouteHandlerResources", - " & { params: { query: { start: number; end: number; } & { type?: \"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\" | undefined; } & { dataStream?: string | undefined; }; }; }) => Promise<{ aggregatable: boolean; datasets: string[]; }>; } & ", + " & { params: { query: { start: number; end: number; } & { types: (\"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\")[]; } & { dataStream?: string | undefined; }; }; }) => Promise<{ aggregatable: boolean; datasets: string[]; }>; } & ", "DatasetQualityRouteCreateOptions", "; \"GET /internal/dataset_quality/data_streams/degraded_docs\": { endpoint: \"GET /internal/dataset_quality/data_streams/degraded_docs\"; params?: ", "TypeC", @@ -325,7 +341,7 @@ "; end: ", "Type", "; }>, ", - "PartialC", + "TypeC", "<{ type: ", "KeyofC", "<{ logs: null; metrics: null; traces: null; synthetics: null; profiling: null; }>; }>, ", @@ -334,23 +350,23 @@ "StringC", "; }>]>; }> | undefined; handler: ({}: ", "DatasetQualityRouteHandlerResources", - " & { params: { query: { start: number; end: number; } & { type?: \"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\" | undefined; } & { datasetQuery?: string | undefined; }; }; }) => Promise<{ degradedDocs: { dataset: string; count: number; docsCount: number; percentage: number; }[]; }>; } & ", + " & { params: { query: { start: number; end: number; } & { type: \"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\"; } & { datasetQuery?: string | undefined; }; }; }) => Promise<{ degradedDocs: { dataset: string; count: number; docsCount: number; percentage: number; }[]; }>; } & ", "DatasetQualityRouteCreateOptions", "; \"GET /internal/dataset_quality/data_streams/stats\": { endpoint: \"GET /internal/dataset_quality/data_streams/stats\"; params?: ", "TypeC", "<{ query: ", "IntersectionC", "<[", - "PartialC", - "<{ type: ", - "KeyofC", - "<{ logs: null; metrics: null; traces: null; synthetics: null; profiling: null; }>; }>, ", + "TypeC", + "<{ types: ", + "Type", + "<(\"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\")[], (\"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\")[], unknown>; }>, ", "PartialC", "<{ datasetQuery: ", "StringC", "; }>]>; }> | undefined; handler: ({}: ", "DatasetQualityRouteHandlerResources", - " & { params: { query: { type?: \"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\" | undefined; } & { datasetQuery?: string | undefined; }; }; }) => Promise<{ datasetUserPrivileges: { canMonitor: boolean; } & { canRead: boolean; canViewIntegrations: boolean; }; dataStreamsStats: ({ name: string; userPrivileges: { canMonitor: boolean; }; } & { size?: string | undefined; sizeBytes?: number | undefined; lastActivity?: number | undefined; integration?: string | undefined; totalDocs?: number | null | undefined; })[]; }>; } & ", + " & { params: { query: { types: (\"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\")[]; } & { datasetQuery?: string | undefined; }; }; }) => Promise<{ datasetUserPrivileges: { canMonitor: boolean; } & { canRead: boolean; canViewIntegrations: boolean; }; dataStreamsStats: ({ name: string; userPrivileges: { canMonitor: boolean; }; } & { size?: string | undefined; sizeBytes?: number | undefined; lastActivity?: number | undefined; integration?: string | undefined; totalDocs?: number | null | undefined; })[]; }>; } & ", "DatasetQualityRouteCreateOptions", "; }[TEndpoint] extends { endpoint: any; params?: infer TRouteParamsRT extends ", { @@ -401,15 +417,9 @@ "DatasetQualityRouteHandlerResources", " & { params: { path: { integration: string; }; }; }) => Promise<{ dashboards: { id: string; title: string; }[]; }>; } & ", "DatasetQualityRouteCreateOptions", - "; \"GET /internal/dataset_quality/integrations\": { endpoint: \"GET /internal/dataset_quality/integrations\"; params?: ", - "TypeC", - "<{ query: ", - "PartialC", - "<{ type: ", - "KeyofC", - "<{ logs: null; metrics: null; traces: null; synthetics: null; profiling: null; }>; }>; }> | undefined; handler: ({}: ", + "; \"GET /internal/dataset_quality/integrations\": { endpoint: \"GET /internal/dataset_quality/integrations\"; params?: undefined; handler: ({}: ", "DatasetQualityRouteHandlerResources", - " & { params: { query: { type?: \"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\" | undefined; }; }; }) => Promise<{ integrations: ({ name: string; } & { title?: string | undefined; version?: string | undefined; icons?: ({ src: string; } & { path?: string | undefined; size?: string | undefined; title?: string | undefined; type?: string | undefined; })[] | undefined; datasets?: { [x: string]: string; } | undefined; })[]; }>; } & ", + ") => Promise<{ integrations: ({ name: string; } & { title?: string | undefined; version?: string | undefined; icons?: ({ src: string; } & { path?: string | undefined; size?: string | undefined; title?: string | undefined; type?: string | undefined; })[] | undefined; datasets?: { [x: string]: string; } | undefined; })[]; }>; } & ", "DatasetQualityRouteCreateOptions", "; \"GET /internal/dataset_quality/data_streams/{dataStream}/settings\": { endpoint: \"GET /internal/dataset_quality/data_streams/{dataStream}/settings\"; params?: ", "TypeC", @@ -453,9 +463,13 @@ "DatasetQualityRouteHandlerResources", " & { params: { path: { dataStream: string; }; query: { start: number; end: number; }; }; }) => Promise<{ degradedFields: { name: string; count: number; lastOccurrence: number | null; timeSeries: { x: number; y: number; }[]; }[]; }>; } & ", "DatasetQualityRouteCreateOptions", - "; \"GET /internal/dataset_quality/data_streams/non_aggregatable\": { endpoint: \"GET /internal/dataset_quality/data_streams/non_aggregatable\"; params?: ", + "; \"GET /internal/dataset_quality/data_streams/{dataStream}/non_aggregatable\": { endpoint: \"GET /internal/dataset_quality/data_streams/{dataStream}/non_aggregatable\"; params?: ", "TypeC", - "<{ query: ", + "<{ path: ", + "TypeC", + "<{ dataStream: ", + "StringC", + "; }>; query: ", "IntersectionC", "<[", "TypeC", @@ -464,16 +478,34 @@ "; end: ", "Type", "; }>, ", - "PartialC", + "TypeC", "<{ type: ", "KeyofC", - "<{ logs: null; metrics: null; traces: null; synthetics: null; profiling: null; }>; }>, ", + "<{ logs: null; metrics: null; traces: null; synthetics: null; profiling: null; }>; }>]>; }> | undefined; handler: ({}: ", + "DatasetQualityRouteHandlerResources", + " & { params: { path: { dataStream: string; }; query: { start: number; end: number; } & { type: \"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\"; }; }; }) => Promise<{ aggregatable: boolean; datasets: string[]; }>; } & ", + "DatasetQualityRouteCreateOptions", + "; \"GET /internal/dataset_quality/data_streams/non_aggregatable\": { endpoint: \"GET /internal/dataset_quality/data_streams/non_aggregatable\"; params?: ", + "TypeC", + "<{ query: ", + "IntersectionC", + "<[", + "TypeC", + "<{ start: ", + "Type", + "; end: ", + "Type", + "; }>, ", + "TypeC", + "<{ types: ", + "Type", + "<(\"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\")[], (\"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\")[], unknown>; }>, ", "PartialC", "<{ dataStream: ", "StringC", "; }>]>; }> | undefined; handler: ({}: ", "DatasetQualityRouteHandlerResources", - " & { params: { query: { start: number; end: number; } & { type?: \"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\" | undefined; } & { dataStream?: string | undefined; }; }; }) => Promise<{ aggregatable: boolean; datasets: string[]; }>; } & ", + " & { params: { query: { start: number; end: number; } & { types: (\"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\")[]; } & { dataStream?: string | undefined; }; }; }) => Promise<{ aggregatable: boolean; datasets: string[]; }>; } & ", "DatasetQualityRouteCreateOptions", "; \"GET /internal/dataset_quality/data_streams/degraded_docs\": { endpoint: \"GET /internal/dataset_quality/data_streams/degraded_docs\"; params?: ", "TypeC", @@ -486,7 +518,7 @@ "; end: ", "Type", "; }>, ", - "PartialC", + "TypeC", "<{ type: ", "KeyofC", "<{ logs: null; metrics: null; traces: null; synthetics: null; profiling: null; }>; }>, ", @@ -495,23 +527,23 @@ "StringC", "; }>]>; }> | undefined; handler: ({}: ", "DatasetQualityRouteHandlerResources", - " & { params: { query: { start: number; end: number; } & { type?: \"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\" | undefined; } & { datasetQuery?: string | undefined; }; }; }) => Promise<{ degradedDocs: { dataset: string; count: number; docsCount: number; percentage: number; }[]; }>; } & ", + " & { params: { query: { start: number; end: number; } & { type: \"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\"; } & { datasetQuery?: string | undefined; }; }; }) => Promise<{ degradedDocs: { dataset: string; count: number; docsCount: number; percentage: number; }[]; }>; } & ", "DatasetQualityRouteCreateOptions", "; \"GET /internal/dataset_quality/data_streams/stats\": { endpoint: \"GET /internal/dataset_quality/data_streams/stats\"; params?: ", "TypeC", "<{ query: ", "IntersectionC", "<[", - "PartialC", - "<{ type: ", - "KeyofC", - "<{ logs: null; metrics: null; traces: null; synthetics: null; profiling: null; }>; }>, ", + "TypeC", + "<{ types: ", + "Type", + "<(\"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\")[], (\"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\")[], unknown>; }>, ", "PartialC", "<{ datasetQuery: ", "StringC", "; }>]>; }> | undefined; handler: ({}: ", "DatasetQualityRouteHandlerResources", - " & { params: { query: { type?: \"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\" | undefined; } & { datasetQuery?: string | undefined; }; }; }) => Promise<{ datasetUserPrivileges: { canMonitor: boolean; } & { canRead: boolean; canViewIntegrations: boolean; }; dataStreamsStats: ({ name: string; userPrivileges: { canMonitor: boolean; }; } & { size?: string | undefined; sizeBytes?: number | undefined; lastActivity?: number | undefined; integration?: string | undefined; totalDocs?: number | null | undefined; })[]; }>; } & ", + " & { params: { query: { types: (\"profiling\" | \"metrics\" | \"synthetics\" | \"traces\" | \"logs\")[]; } & { datasetQuery?: string | undefined; }; }; }) => Promise<{ datasetUserPrivileges: { canMonitor: boolean; } & { canRead: boolean; canViewIntegrations: boolean; }; dataStreamsStats: ({ name: string; userPrivileges: { canMonitor: boolean; }; } & { size?: string | undefined; sizeBytes?: number | undefined; lastActivity?: number | undefined; integration?: string | undefined; totalDocs?: number | null | undefined; })[]; }>; } & ", "DatasetQualityRouteCreateOptions", "; }[TEndpoint] extends { endpoint: any; params?: any; handler: ({}: any) => Promise; } & ", { diff --git a/api_docs/dataset_quality.mdx b/api_docs/dataset_quality.mdx index f3589688ad057..a004742ecdb4f 100644 --- a/api_docs/dataset_quality.mdx +++ b/api_docs/dataset_quality.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/datasetQuality title: "datasetQuality" image: https://source.unsplash.com/400x175/?github description: API docs for the datasetQuality plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'datasetQuality'] --- import datasetQualityObj from './dataset_quality.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index 3f4966f0c7a88..042e262eebdfb 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -22,7 +22,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | actions, savedObjectsTagging, ml, enterpriseSearch | - | | | @kbn/core-saved-objects-browser-internal, @kbn/core, savedObjects, visualizations, aiops, dataVisualizer, ml, dashboardEnhanced, graph, lens, securitySolution, eventAnnotation, @kbn/core-saved-objects-browser-mocks | - | | | @kbn/core, savedObjects, embeddable, visualizations, canvas, graph, ml | - | -| | @kbn/core-saved-objects-base-server-internal, @kbn/core-saved-objects-migration-server-internal, @kbn/core-saved-objects-server-internal, @kbn/core-ui-settings-server-internal, @kbn/core-usage-data-server-internal, spaces, taskManager, actions, @kbn/core-saved-objects-migration-server-mocks, share, dataViews, data, alerting, lens, cases, savedSearch, canvas, fleet, cloudSecurityPosture, ml, logsShared, graph, lists, maps, visualizations, infra, apmDataAccess, securitySolution, apm, slo, synthetics, uptime, dashboard, eventAnnotation, links, savedObjectsManagement, @kbn/core-test-helpers-so-type-serializer, @kbn/core-saved-objects-api-server-internal | - | +| | @kbn/core-saved-objects-base-server-internal, @kbn/core-saved-objects-migration-server-internal, @kbn/core-saved-objects-server-internal, @kbn/core-ui-settings-server-internal, @kbn/core-usage-data-server-internal, taskManager, spaces, actions, @kbn/core-saved-objects-migration-server-mocks, share, dataViews, data, alerting, lens, cases, savedSearch, canvas, fleet, cloudSecurityPosture, ml, logsShared, graph, lists, maps, visualizations, infra, apmDataAccess, securitySolution, apm, slo, synthetics, uptime, dashboard, eventAnnotation, links, savedObjectsManagement, @kbn/core-test-helpers-so-type-serializer, @kbn/core-saved-objects-api-server-internal | - | | | stackAlerts, alerting, securitySolution, inputControlVis | - | | | graph, stackAlerts, inputControlVis, securitySolution, savedObjects | - | | | dashboard, dataVisualizer, stackAlerts, expressionPartitionVis | - | @@ -30,7 +30,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | triggersActionsUi | - | | | triggersActionsUi | - | | | @kbn/core, visualizations, triggersActionsUi | - | -| | ruleRegistry, securitySolution, synthetics, slo | - | +| | ruleRegistry, securitySolution, slo | - | | | security, actions, alerting, ruleRegistry, files, cases, fleet, securitySolution | - | | | securitySolution, cloudChat, observabilityOnboarding | - | | | alerting, securitySolution | - | @@ -67,10 +67,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | securitySolution | - | | | @kbn/monaco, securitySolution | - | | | cloudSecurityPosture, securitySolution | - | -| | fleet, exploratoryView, osquery, synthetics | - | -| | alerting, observabilityAIAssistant, fleet, cloudSecurityPosture, enterpriseSearch, serverlessSearch, transform, upgradeAssistant, apm, entityManager, synthetics, security | - | | | cloudChat | - | | | @kbn/core-elasticsearch-server-internal, @kbn/core-plugins-server-internal, enterpriseSearch, observabilityOnboarding, console | - | +| | alerting, observabilityAIAssistant, fleet, cloudSecurityPosture, enterpriseSearch, serverlessSearch, transform, upgradeAssistant, apm, entityManager, synthetics, security | - | | | actions, alerting | - | | | monitoring | - | | | @kbn/core-saved-objects-api-browser, @kbn/core, savedObjects, savedObjectsManagement, visualizations, savedObjectsTagging, eventAnnotation, lens, maps, graph, dashboard, savedObjectsTaggingOss, kibanaUtils, expressions, data, embeddable, uiActionsEnhanced, controls, canvas, dashboardEnhanced, globalSearchProviders | - | @@ -107,6 +106,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | @kbn/core-saved-objects-api-server-internal | - | | | @kbn/core-saved-objects-api-server-internal, canvas | - | | | @kbn/core-saved-objects-api-server-internal, @kbn/core-saved-objects-migration-server-internal, spaces, data, savedSearch, cloudSecurityPosture, visualizations, dashboard, @kbn/core-test-helpers-so-type-serializer | - | +| | fleet, exploratoryView, osquery, synthetics | - | | | graph, visTypeTimeseries, dataViewManagement, dataViews | - | | | graph, visTypeTimeseries, dataViewManagement, dataViews | - | | | graph, visTypeTimeseries, dataViewManagement | - | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 9d2017898746e..ff486f398a86f 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -978,7 +978,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [register_embeddable_widget.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability_solution/investigate_app/public/widgets/embeddable_widget/register_embeddable_widget.tsx#:~:text=getEmbeddableFactory) | - | +| | [register_embeddable_item.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability_solution/investigate_app/public/items/embeddable_item/register_embeddable_item.tsx#:~:text=getEmbeddableFactory) | - | @@ -1374,8 +1374,8 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | | [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch) | - | | | [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/hooks/eql/api.ts#:~:text=options) | - | | | [create_sourcerer_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/sourcerer/containers/create_sourcerer_data_view.ts#:~:text=title), [create_sourcerer_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/sourcerer/containers/create_sourcerer_data_view.ts#:~:text=title), [create_sourcerer_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/sourcerer/containers/create_sourcerer_data_view.ts#:~:text=title), [validators.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/eql_query_bar/validators.ts#:~:text=title) | - | -| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx#:~:text=policy_id), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx#:~:text=policy_id), [fleet_services.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts#:~:text=policy_id), [fleet_services.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts#:~:text=policy_id), [endpoint_metadata_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.test.ts#:~:text=policy_id), [endpoint_package_policies.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/endpoint_package_policies.test.ts#:~:text=policy_id), [policy_settings_middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_settings_middleware.ts#:~:text=policy_id), [policy_settings_middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_settings_middleware.ts#:~:text=policy_id), [index.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts#:~:text=policy_id) | - | -| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx#:~:text=policy_id), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx#:~:text=policy_id), [fleet_services.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts#:~:text=policy_id), [fleet_services.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts#:~:text=policy_id), [endpoint_metadata_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.test.ts#:~:text=policy_id), [endpoint_package_policies.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/endpoint_package_policies.test.ts#:~:text=policy_id), [policy_settings_middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_settings_middleware.ts#:~:text=policy_id), [policy_settings_middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_settings_middleware.ts#:~:text=policy_id), [index.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts#:~:text=policy_id) | - | +| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx#:~:text=policy_id), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx#:~:text=policy_id), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx#:~:text=policy_id), [fleet_services.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts#:~:text=policy_id), [fleet_services.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts#:~:text=policy_id), [endpoint_metadata_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.test.ts#:~:text=policy_id), [endpoint_package_policies.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/endpoint_package_policies.test.ts#:~:text=policy_id), [policy_settings_middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_settings_middleware.ts#:~:text=policy_id), [policy_settings_middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_settings_middleware.ts#:~:text=policy_id), [index.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts#:~:text=policy_id) | - | +| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx#:~:text=policy_id), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx#:~:text=policy_id), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx#:~:text=policy_id), [fleet_services.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts#:~:text=policy_id), [fleet_services.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts#:~:text=policy_id), [endpoint_metadata_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.test.ts#:~:text=policy_id), [endpoint_package_policies.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/endpoint_package_policies.test.ts#:~:text=policy_id), [policy_settings_middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_settings_middleware.ts#:~:text=policy_id), [policy_settings_middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_settings_middleware.ts#:~:text=policy_id), [index.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts#:~:text=policy_id) | - | | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode)+ 7 more | 8.8.0 | | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode)+ 7 more | 8.8.0 | | | [get_is_alert_suppression_active.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_is_alert_suppression_active.ts#:~:text=license%24), [create_threat_signals.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signals.ts#:~:text=license%24), [query.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/query.ts#:~:text=license%24), [threshold.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/threshold/threshold.ts#:~:text=license%24), [get_is_alert_suppression_active.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_is_alert_suppression_active.test.ts#:~:text=license%24), [get_is_alert_suppression_active.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_is_alert_suppression_active.test.ts#:~:text=license%24), [get_is_alert_suppression_active.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/get_is_alert_suppression_active.test.ts#:~:text=license%24) | 8.8.0 | @@ -1384,7 +1384,7 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx#:~:text=DeprecatedCellValueElementProps), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx#:~:text=DeprecatedCellValueElementProps) | - | | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx#:~:text=DeprecatedRowRenderer), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx#:~:text=DeprecatedRowRenderer) | - | | | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts#:~:text=BeatFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=BeatFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=BeatFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=BeatFields) | - | -| | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/timeline/cells/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/timeline/cells/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/header_actions/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/header_actions/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields)+ 76 more | - | +| | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/timeline/cells/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/timeline/cells/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/header_actions/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/types/header_actions/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts#:~:text=BrowserFields)+ 74 more | - | | | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts#:~:text=IndexFieldsStrategyRequest), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=IndexFieldsStrategyRequest), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=IndexFieldsStrategyRequest), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=IndexFieldsStrategyRequest), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=IndexFieldsStrategyRequest), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=IndexFieldsStrategyRequest) | - | | | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts#:~:text=IndexFieldsStrategyResponse), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=IndexFieldsStrategyResponse), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=IndexFieldsStrategyResponse), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts#:~:text=IndexFieldsStrategyResponse), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=IndexFieldsStrategyResponse), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=IndexFieldsStrategyResponse) | - | | | [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/hooks/types.ts#:~:text=SimpleSavedObject), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/hooks/types.ts#:~:text=SimpleSavedObject) | - | @@ -1477,7 +1477,6 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [message_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.ts#:~:text=alertFactory), [tls_rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/tls_rule.ts#:~:text=alertFactory) | - | | | [stderr_logs.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/components/stderr_logs.tsx#:~:text=indexPatternId) | - | | | [synthetics_private_location.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/private_location/synthetics_private_location.ts#:~:text=policy_id) | - | | | [synthetics_private_location.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/private_location/synthetics_private_location.ts#:~:text=policy_id) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 8e248de96b0bd..ff84592761b61 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 763357dce3d34..416e31787c74c 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index fc1bfd676d94d..071e5e688a0f2 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index 8b59717c8123d..c7c4032f0512e 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/discover_shared.mdx b/api_docs/discover_shared.mdx index 97e775ece5349..7c573ebb8fdd1 100644 --- a/api_docs/discover_shared.mdx +++ b/api_docs/discover_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverShared title: "discoverShared" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverShared plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverShared'] --- import discoverSharedObj from './discover_shared.devdocs.json'; diff --git a/api_docs/ecs_data_quality_dashboard.mdx b/api_docs/ecs_data_quality_dashboard.mdx index d4ae7cd36f63d..37297441ca339 100644 --- a/api_docs/ecs_data_quality_dashboard.mdx +++ b/api_docs/ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ecsDataQualityDashboard title: "ecsDataQualityDashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the ecsDataQualityDashboard plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/elastic_assistant.mdx b/api_docs/elastic_assistant.mdx index 632160f5c04a9..f417b757a472f 100644 --- a/api_docs/elastic_assistant.mdx +++ b/api_docs/elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/elasticAssistant title: "elasticAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the elasticAssistant plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'elasticAssistant'] --- import elasticAssistantObj from './elastic_assistant.devdocs.json'; diff --git a/api_docs/embeddable.devdocs.json b/api_docs/embeddable.devdocs.json index a8f0320e4e8a1..c0aa77ca3f341 100644 --- a/api_docs/embeddable.devdocs.json +++ b/api_docs/embeddable.devdocs.json @@ -14281,9 +14281,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "" @@ -14874,7 +14874,7 @@ }, { "plugin": "investigateApp", - "path": "x-pack/plugins/observability_solution/investigate_app/public/widgets/embeddable_widget/register_embeddable_widget.tsx" + "path": "x-pack/plugins/observability_solution/investigate_app/public/items/embeddable_item/register_embeddable_item.tsx" }, { "plugin": "dashboard", diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 6afa158bf1204..8d2e058404ec9 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index 34e8d7bd33b28..af76b2b9f51f3 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] --- import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json'; diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index 01c434f316a48..48fe25d07357c 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] --- import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json'; diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index a86dd58f54772..c672c9411cf31 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/entities_data_access.mdx b/api_docs/entities_data_access.mdx index 9bc9b25dd0bfc..47bd2cdb4f29b 100644 --- a/api_docs/entities_data_access.mdx +++ b/api_docs/entities_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/entitiesDataAccess title: "entitiesDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the entitiesDataAccess plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'entitiesDataAccess'] --- import entitiesDataAccessObj from './entities_data_access.devdocs.json'; diff --git a/api_docs/entity_manager.mdx b/api_docs/entity_manager.mdx index b52d2f36b5f39..789c49a7b6b78 100644 --- a/api_docs/entity_manager.mdx +++ b/api_docs/entity_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/entityManager title: "entityManager" image: https://source.unsplash.com/400x175/?github description: API docs for the entityManager plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'entityManager'] --- import entityManagerObj from './entity_manager.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 1f1a0ded169d4..06657f643de68 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/esql.mdx b/api_docs/esql.mdx index 45d20a01d3834..bd671f5ca74f8 100644 --- a/api_docs/esql.mdx +++ b/api_docs/esql.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esql title: "esql" image: https://source.unsplash.com/400x175/?github description: API docs for the esql plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esql'] --- import esqlObj from './esql.devdocs.json'; diff --git a/api_docs/esql_data_grid.mdx b/api_docs/esql_data_grid.mdx index c961d5ad93093..123fa10f8aad9 100644 --- a/api_docs/esql_data_grid.mdx +++ b/api_docs/esql_data_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esqlDataGrid title: "esqlDataGrid" image: https://source.unsplash.com/400x175/?github description: API docs for the esqlDataGrid plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esqlDataGrid'] --- import esqlDataGridObj from './esql_data_grid.devdocs.json'; diff --git a/api_docs/event_annotation.devdocs.json b/api_docs/event_annotation.devdocs.json index 008a69c12c41d..b82e76cd7f98c 100644 --- a/api_docs/event_annotation.devdocs.json +++ b/api_docs/event_annotation.devdocs.json @@ -584,9 +584,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "<", @@ -1102,9 +1102,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.ContentManagementCrudTypes", + "section": "def-server.ContentManagementCrudTypes", "text": "ContentManagementCrudTypes" }, "<\"event-annotation-group\", ", diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index 041bac091bc0b..711d4025d5653 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_annotation_listing.mdx b/api_docs/event_annotation_listing.mdx index 5079a06b4d0f0..cffa4a7a37623 100644 --- a/api_docs/event_annotation_listing.mdx +++ b/api_docs/event_annotation_listing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotationListing title: "eventAnnotationListing" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotationListing plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotationListing'] --- import eventAnnotationListingObj from './event_annotation_listing.devdocs.json'; diff --git a/api_docs/event_log.devdocs.json b/api_docs/event_log.devdocs.json index 7ce5819610f98..5233179e19fd1 100644 --- a/api_docs/event_log.devdocs.json +++ b/api_docs/event_log.devdocs.json @@ -1450,7 +1450,7 @@ "label": "data", "description": [], "signature": [ - "(Readonly<{ log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; error?: Readonly<{ id?: string | undefined; type?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; version?: string | undefined; name?: string | undefined; license?: string | undefined; description?: string | undefined; uuid?: string | undefined; category?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ source?: string | undefined; uuid?: string | undefined; gen_ai?: Readonly<{ usage?: Readonly<{ prompt_tokens?: string | number | undefined; completion_tokens?: string | number | undefined; total_tokens?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ outcome?: string | undefined; status?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; revision?: string | number | undefined; execution?: Readonly<{ uuid?: string | undefined; status?: string | undefined; metrics?: Readonly<{ total_search_duration_ms?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_delayed_alerts?: string | number | undefined; number_of_searches?: string | number | undefined; es_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; persist_alerts_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status_order?: string | number | undefined; backfill?: Readonly<{ id?: string | undefined; start?: string | undefined; interval?: string | undefined; } & {}> | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; uuid?: string | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; space_ids?: string[] | undefined; server_uuid?: string | undefined; saved_objects?: Readonly<{ id?: string | undefined; type?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; } & {}> | undefined; event?: Readonly<{ id?: string | undefined; type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; start?: string | undefined; end?: string | undefined; outcome?: string | undefined; duration?: string | number | undefined; severity?: string | number | undefined; category?: string[] | undefined; timezone?: string | undefined; risk_score?: number | undefined; code?: string | undefined; url?: string | undefined; created?: string | undefined; dataset?: string | undefined; provider?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; original?: string | undefined; reference?: string | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; user?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | undefined; } & {}> | undefined)[]" + "(Readonly<{ log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; error?: Readonly<{ id?: string | undefined; type?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; version?: string | undefined; name?: string | undefined; license?: string | undefined; description?: string | undefined; uuid?: string | undefined; category?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ source?: string | undefined; uuid?: string | undefined; gen_ai?: Readonly<{ usage?: Readonly<{ prompt_tokens?: string | number | undefined; completion_tokens?: string | number | undefined; total_tokens?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; usage?: Readonly<{ request_body_bytes?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; type_id?: string | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ outcome?: string | undefined; status?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; revision?: string | number | undefined; execution?: Readonly<{ uuid?: string | undefined; status?: string | undefined; metrics?: Readonly<{ total_search_duration_ms?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_delayed_alerts?: string | number | undefined; number_of_searches?: string | number | undefined; es_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; persist_alerts_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status_order?: string | number | undefined; backfill?: Readonly<{ id?: string | undefined; start?: string | undefined; interval?: string | undefined; } & {}> | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; uuid?: string | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; space_ids?: string[] | undefined; server_uuid?: string | undefined; saved_objects?: Readonly<{ id?: string | undefined; type?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; } & {}> | undefined; event?: Readonly<{ id?: string | undefined; type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; start?: string | undefined; end?: string | undefined; outcome?: string | undefined; duration?: string | number | undefined; severity?: string | number | undefined; category?: string[] | undefined; timezone?: string | undefined; risk_score?: number | undefined; code?: string | undefined; url?: string | undefined; created?: string | undefined; dataset?: string | undefined; provider?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; original?: string | undefined; reference?: string | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; user?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | undefined; } & {}> | undefined)[]" ], "path": "x-pack/plugins/event_log/server/es/cluster_client_adapter.ts", "deprecated": false, @@ -1470,7 +1470,7 @@ "label": "IEvent", "description": [], "signature": [ - "DeepPartial | undefined; error?: Readonly<{ id?: string | undefined; type?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; version?: string | undefined; name?: string | undefined; license?: string | undefined; description?: string | undefined; uuid?: string | undefined; category?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ source?: string | undefined; uuid?: string | undefined; gen_ai?: Readonly<{ usage?: Readonly<{ prompt_tokens?: string | number | undefined; completion_tokens?: string | number | undefined; total_tokens?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ outcome?: string | undefined; status?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; revision?: string | number | undefined; execution?: Readonly<{ uuid?: string | undefined; status?: string | undefined; metrics?: Readonly<{ total_search_duration_ms?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_delayed_alerts?: string | number | undefined; number_of_searches?: string | number | undefined; es_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; persist_alerts_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status_order?: string | number | undefined; backfill?: Readonly<{ id?: string | undefined; start?: string | undefined; interval?: string | undefined; } & {}> | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; uuid?: string | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; space_ids?: string[] | undefined; server_uuid?: string | undefined; saved_objects?: Readonly<{ id?: string | undefined; type?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; } & {}> | undefined; event?: Readonly<{ id?: string | undefined; type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; start?: string | undefined; end?: string | undefined; outcome?: string | undefined; duration?: string | number | undefined; severity?: string | number | undefined; category?: string[] | undefined; timezone?: string | undefined; risk_score?: number | undefined; code?: string | undefined; url?: string | undefined; created?: string | undefined; dataset?: string | undefined; provider?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; original?: string | undefined; reference?: string | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; user?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | undefined; } & {}>>> | undefined" + "DeepPartial | undefined; error?: Readonly<{ id?: string | undefined; type?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; version?: string | undefined; name?: string | undefined; license?: string | undefined; description?: string | undefined; uuid?: string | undefined; category?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ source?: string | undefined; uuid?: string | undefined; gen_ai?: Readonly<{ usage?: Readonly<{ prompt_tokens?: string | number | undefined; completion_tokens?: string | number | undefined; total_tokens?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; usage?: Readonly<{ request_body_bytes?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; type_id?: string | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ outcome?: string | undefined; status?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; revision?: string | number | undefined; execution?: Readonly<{ uuid?: string | undefined; status?: string | undefined; metrics?: Readonly<{ total_search_duration_ms?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_delayed_alerts?: string | number | undefined; number_of_searches?: string | number | undefined; es_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; persist_alerts_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status_order?: string | number | undefined; backfill?: Readonly<{ id?: string | undefined; start?: string | undefined; interval?: string | undefined; } & {}> | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; uuid?: string | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; space_ids?: string[] | undefined; server_uuid?: string | undefined; saved_objects?: Readonly<{ id?: string | undefined; type?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; } & {}> | undefined; event?: Readonly<{ id?: string | undefined; type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; start?: string | undefined; end?: string | undefined; outcome?: string | undefined; duration?: string | number | undefined; severity?: string | number | undefined; category?: string[] | undefined; timezone?: string | undefined; risk_score?: number | undefined; code?: string | undefined; url?: string | undefined; created?: string | undefined; dataset?: string | undefined; provider?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; original?: string | undefined; reference?: string | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; user?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | undefined; } & {}>>> | undefined" ], "path": "x-pack/plugins/event_log/generated/schemas.ts", "deprecated": false, @@ -1485,7 +1485,7 @@ "label": "IValidatedEvent", "description": [], "signature": [ - "Readonly<{ log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; error?: Readonly<{ id?: string | undefined; type?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; version?: string | undefined; name?: string | undefined; license?: string | undefined; description?: string | undefined; uuid?: string | undefined; category?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ source?: string | undefined; uuid?: string | undefined; gen_ai?: Readonly<{ usage?: Readonly<{ prompt_tokens?: string | number | undefined; completion_tokens?: string | number | undefined; total_tokens?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ outcome?: string | undefined; status?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; revision?: string | number | undefined; execution?: Readonly<{ uuid?: string | undefined; status?: string | undefined; metrics?: Readonly<{ total_search_duration_ms?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_delayed_alerts?: string | number | undefined; number_of_searches?: string | number | undefined; es_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; persist_alerts_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status_order?: string | number | undefined; backfill?: Readonly<{ id?: string | undefined; start?: string | undefined; interval?: string | undefined; } & {}> | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; uuid?: string | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; space_ids?: string[] | undefined; server_uuid?: string | undefined; saved_objects?: Readonly<{ id?: string | undefined; type?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; } & {}> | undefined; event?: Readonly<{ id?: string | undefined; type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; start?: string | undefined; end?: string | undefined; outcome?: string | undefined; duration?: string | number | undefined; severity?: string | number | undefined; category?: string[] | undefined; timezone?: string | undefined; risk_score?: number | undefined; code?: string | undefined; url?: string | undefined; created?: string | undefined; dataset?: string | undefined; provider?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; original?: string | undefined; reference?: string | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; user?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | undefined; } & {}> | undefined" + "Readonly<{ log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; error?: Readonly<{ id?: string | undefined; type?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; version?: string | undefined; name?: string | undefined; license?: string | undefined; description?: string | undefined; uuid?: string | undefined; category?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ source?: string | undefined; uuid?: string | undefined; gen_ai?: Readonly<{ usage?: Readonly<{ prompt_tokens?: string | number | undefined; completion_tokens?: string | number | undefined; total_tokens?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; usage?: Readonly<{ request_body_bytes?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; type_id?: string | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ outcome?: string | undefined; status?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; revision?: string | number | undefined; execution?: Readonly<{ uuid?: string | undefined; status?: string | undefined; metrics?: Readonly<{ total_search_duration_ms?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_delayed_alerts?: string | number | undefined; number_of_searches?: string | number | undefined; es_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; persist_alerts_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status_order?: string | number | undefined; backfill?: Readonly<{ id?: string | undefined; start?: string | undefined; interval?: string | undefined; } & {}> | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; uuid?: string | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; space_ids?: string[] | undefined; server_uuid?: string | undefined; saved_objects?: Readonly<{ id?: string | undefined; type?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; } & {}> | undefined; event?: Readonly<{ id?: string | undefined; type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; start?: string | undefined; end?: string | undefined; outcome?: string | undefined; duration?: string | number | undefined; severity?: string | number | undefined; category?: string[] | undefined; timezone?: string | undefined; risk_score?: number | undefined; code?: string | undefined; url?: string | undefined; created?: string | undefined; dataset?: string | undefined; provider?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; original?: string | undefined; reference?: string | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; user?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | undefined; } & {}> | undefined" ], "path": "x-pack/plugins/event_log/generated/schemas.ts", "deprecated": false, diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index 57ee52ba4ebb6..1534b3b3f1730 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/exploratory_view.mdx b/api_docs/exploratory_view.mdx index 3472ef2cd2b8e..cb40d975cd3b1 100644 --- a/api_docs/exploratory_view.mdx +++ b/api_docs/exploratory_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/exploratoryView title: "exploratoryView" image: https://source.unsplash.com/400x175/?github description: API docs for the exploratoryView plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'exploratoryView'] --- import exploratoryViewObj from './exploratory_view.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index 98f8d449dacad..914fed24aff6a 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index c1ec78c25a48d..0d2419e1eecad 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index 1220aeaeb1197..b3db561e3d18a 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index 63a3bb1804286..5c1c5e907a715 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] --- import expressionImageObj from './expression_image.devdocs.json'; diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index 0f53d63b6f7b6..29d3b842af38e 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] --- import expressionLegacyMetricVisObj from './expression_legacy_metric_vis.devdocs.json'; diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index da30f6abd5686..41ad0e8fc6bfd 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] --- import expressionMetricObj from './expression_metric.devdocs.json'; diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index 66b5f5c744a70..5eed957cca3e1 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index d31843a6fb7cc..04a1f127f3057 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index 2e80c4db64538..e501402fd044b 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] --- import expressionRepeatImageObj from './expression_repeat_image.devdocs.json'; diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index 0c54bc0c3bf43..0013e9322c03b 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] --- import expressionRevealImageObj from './expression_reveal_image.devdocs.json'; diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index 1807e75907553..5b534beca1c59 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] --- import expressionShapeObj from './expression_shape.devdocs.json'; diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index 9e08043cf7ad3..86858a80556e7 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index cad02c831acd9..092bb02509863 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index 91eae5512c2eb..512fc82b621d1 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.mdx b/api_docs/features.mdx index f67e6ab2de725..117718a0bb747 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index e985fa2b90bff..034cbdbcafa5d 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/fields_metadata.mdx b/api_docs/fields_metadata.mdx index 00c482ea0b345..e1e39ab378317 100644 --- a/api_docs/fields_metadata.mdx +++ b/api_docs/fields_metadata.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldsMetadata title: "fieldsMetadata" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldsMetadata plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldsMetadata'] --- import fieldsMetadataObj from './fields_metadata.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index d717a1ed62e1e..c347050e5ab7b 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.mdx b/api_docs/files.mdx index 60537517ae2ec..1859456f51b3e 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index 93407e10b2fd2..f41ed80b4634c 100644 --- a/api_docs/files_management.mdx +++ b/api_docs/files_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/filesManagement title: "filesManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the filesManagement plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index 6fdb547691329..9583242b66d73 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -1491,14 +1491,14 @@ { "parentPluginId": "fleet", "id": "def-public.NewPackagePolicy.policy_id", - "type": "string", + "type": "CompoundType", "tags": [ "deprecated" ], "label": "policy_id", "description": [], "signature": [ - "string | undefined" + "string | null | undefined" ], "path": "x-pack/plugins/fleet/common/types/models/package_policy.ts", "deprecated": true, @@ -1552,6 +1552,10 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx" + }, { "plugin": "cloudDefend", "path": "x-pack/plugins/cloud_defend/public/test/mocks.ts" @@ -2922,7 +2926,7 @@ "The updated Integration Policy to be merged back and included in the API call" ], "signature": [ - "{ id?: string | number | undefined; name?: string | undefined; description?: string | undefined; namespace?: string | undefined; enabled?: boolean | undefined; is_managed?: boolean | undefined; policy_id?: string | undefined; policy_ids?: string[] | undefined; output_id?: string | null | undefined; package?: ", + "{ id?: string | number | undefined; name?: string | undefined; description?: string | undefined; namespace?: string | undefined; enabled?: boolean | undefined; is_managed?: boolean | undefined; policy_id?: string | null | undefined; policy_ids?: string[] | undefined; output_id?: string | null | undefined; package?: ", { "pluginId": "fleet", "scope": "common", @@ -6558,7 +6562,7 @@ "section": "def-server.SavedObjectsClientContract", "text": "SavedObjectsClientContract" }, - ", { perPage, kuery }?: ", + ", { perPage, kuery, spaceId }?: ", "FetchAllAgentPolicyIdsOptions", ") => Promise>" ], @@ -6590,12 +6594,20 @@ { "parentPluginId": "fleet", "id": "def-server.AgentPolicyServiceInterface.fetchAllAgentPolicyIds.$2", - "type": "Object", + "type": "CompoundType", "tags": [], "label": "__1", "description": [], "signature": [ - "{ perPage?: number | undefined; kuery?: string | undefined; }" + "Pick<", + { + "pluginId": "fleet", + "scope": "common", + "docId": "kibFleetPluginApi", + "section": "def-common.ListWithKuery", + "text": "ListWithKuery" + }, + ", \"perPage\" | \"kuery\"> & { spaceId?: string | undefined; }" ], "path": "x-pack/plugins/fleet/server/services/agent_policy.ts", "deprecated": false, @@ -16351,7 +16363,7 @@ "section": "def-common.PackagePolicyPackage", "text": "PackagePolicyPackage" }, - " | undefined; policy_id?: string | undefined; policy_ids?: string[] | undefined; output_id?: string | undefined; statusCode?: number | undefined; body?: { message: string; } | undefined; }>, soClient: ", + " | undefined; policy_id?: string | null | undefined; policy_ids?: string[] | undefined; output_id?: string | undefined; statusCode?: number | undefined; body?: { message: string; } | undefined; }>, soClient: ", { "pluginId": "@kbn/core-saved-objects-api-server", "scope": "server", @@ -16407,7 +16419,7 @@ "section": "def-common.PackagePolicyPackage", "text": "PackagePolicyPackage" }, - " | undefined; policy_id?: string | undefined; policy_ids?: string[] | undefined; output_id?: string | undefined; statusCode?: number | undefined; body?: { message: string; } | undefined; }>" + " | undefined; policy_id?: string | null | undefined; policy_ids?: string[] | undefined; output_id?: string | undefined; statusCode?: number | undefined; body?: { message: string; } | undefined; }>" ], "path": "x-pack/plugins/fleet/server/types/extensions.ts", "deprecated": false, @@ -23839,14 +23851,14 @@ { "parentPluginId": "fleet", "id": "def-common.NewPackagePolicy.policy_id", - "type": "string", + "type": "CompoundType", "tags": [ "deprecated" ], "label": "policy_id", "description": [], "signature": [ - "string | undefined" + "string | null | undefined" ], "path": "x-pack/plugins/fleet/common/types/models/package_policy.ts", "deprecated": true, @@ -23900,6 +23912,10 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx" + }, { "plugin": "cloudDefend", "path": "x-pack/plugins/cloud_defend/public/test/mocks.ts" @@ -28017,7 +28033,7 @@ "section": "def-common.PackagePolicyPackage", "text": "PackagePolicyPackage" }, - " | undefined; policy_id?: string | undefined; policy_ids?: string[] | undefined; output_id?: string | undefined; statusCode?: number | undefined; body?: { message: string; } | undefined; }[]" + " | undefined; policy_id?: string | null | undefined; policy_ids?: string[] | undefined; output_id?: string | undefined; statusCode?: number | undefined; body?: { message: string; } | undefined; }[]" ], "path": "x-pack/plugins/fleet/common/types/rest_spec/package_policy.ts", "deprecated": false, diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index b64018272a21b..c0bb90cf8793b 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index eac71905ded56..605a3827d95f4 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index 197a35e1a463c..32bda919f72b6 100644 --- a/api_docs/guided_onboarding.mdx +++ b/api_docs/guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/guidedOnboarding title: "guidedOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the guidedOnboarding plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'guidedOnboarding'] --- import guidedOnboardingObj from './guided_onboarding.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index 8d281fc9b1aef..6183d6c23ce1d 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/image_embeddable.mdx b/api_docs/image_embeddable.mdx index 16d8e69eaeebd..2aeefa4708285 100644 --- a/api_docs/image_embeddable.mdx +++ b/api_docs/image_embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/imageEmbeddable title: "imageEmbeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the imageEmbeddable plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'imageEmbeddable'] --- import imageEmbeddableObj from './image_embeddable.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index 15a25b6609373..f0806320100da 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 84f5f3de0a2c0..251b67a03df88 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/inference.mdx b/api_docs/inference.mdx index fd95715a8cc2f..76e50a67fabed 100644 --- a/api_docs/inference.mdx +++ b/api_docs/inference.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inference title: "inference" image: https://source.unsplash.com/400x175/?github description: API docs for the inference plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inference'] --- import inferenceObj from './inference.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 19175d82460f5..9999901b9f6c3 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/ingest_pipelines.mdx b/api_docs/ingest_pipelines.mdx index e4cafbc124649..5e95bca75db21 100644 --- a/api_docs/ingest_pipelines.mdx +++ b/api_docs/ingest_pipelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ingestPipelines title: "ingestPipelines" image: https://source.unsplash.com/400x175/?github description: API docs for the ingestPipelines plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ingestPipelines'] --- import ingestPipelinesObj from './ingest_pipelines.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 5cf566b63af27..d2b30a4b8aa61 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/integration_assistant.devdocs.json b/api_docs/integration_assistant.devdocs.json index ab607c4fa22fe..3fafbef540dff 100644 --- a/api_docs/integration_assistant.devdocs.json +++ b/api_docs/integration_assistant.devdocs.json @@ -164,6 +164,48 @@ "interfaces": [], "enums": [], "misc": [ + { + "parentPluginId": "integrationAssistant", + "id": "def-common.ANALYZE_LOGS_PATH", + "type": "string", + "tags": [], + "label": "ANALYZE_LOGS_PATH", + "description": [], + "path": "x-pack/plugins/integration_assistant/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.AnalyzeLogsRequestBody", + "type": "Type", + "tags": [], + "label": "AnalyzeLogsRequestBody", + "description": [], + "signature": [ + "{ connectorId: string; logSamples: string[]; langSmithOptions?: { apiKey: string; projectName: string; } | undefined; }" + ], + "path": "x-pack/plugins/integration_assistant/common/api/analyze_logs/analyze_logs_route.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.AnalyzeLogsResponse", + "type": "Type", + "tags": [], + "label": "AnalyzeLogsResponse", + "description": [], + "signature": [ + "{ results: { samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; parsedSamples: string[]; }; }" + ], + "path": "x-pack/plugins/integration_assistant/common/api/analyze_logs/analyze_logs_route.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "integrationAssistant", "id": "def-common.BuildIntegrationRequestBody", @@ -188,7 +230,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }[]; logo?: string | undefined; }; }" + "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }[]; logo?: string | undefined; }; }" ], "path": "x-pack/plugins/integration_assistant/common/api/build_integration/build_integration.ts", "deprecated": false, @@ -353,7 +395,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }" + "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }" ], "path": "x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts", "deprecated": false, @@ -497,7 +539,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }[]; logo?: string | undefined; }" + "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }[]; logo?: string | undefined; }" ], "path": "x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts", "deprecated": false, @@ -678,7 +720,7 @@ "\nFormat of the provided log samples." ], "signature": [ - "{ name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }" + "{ name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }" ], "path": "x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts", "deprecated": false, @@ -687,6 +729,36 @@ } ], "objects": [ + { + "parentPluginId": "integrationAssistant", + "id": "def-common.AnalyzeLogsRequestBody", + "type": "Object", + "tags": [], + "label": "AnalyzeLogsRequestBody", + "description": [], + "signature": [ + "Zod.ZodObject<{ logSamples: Zod.ZodArray; connectorId: Zod.ZodString; langSmithOptions: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; logSamples: string[]; langSmithOptions?: { apiKey: string; projectName: string; } | undefined; }, { connectorId: string; logSamples: string[]; langSmithOptions?: { apiKey: string; projectName: string; } | undefined; }>" + ], + "path": "x-pack/plugins/integration_assistant/common/api/analyze_logs/analyze_logs_route.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "integrationAssistant", + "id": "def-common.AnalyzeLogsResponse", + "type": "Object", + "tags": [], + "label": "AnalyzeLogsResponse", + "description": [], + "signature": [ + "Zod.ZodObject<{ results: Zod.ZodObject<{ samplesFormat: Zod.ZodObject<{ name: Zod.ZodEnum<[\"ndjson\", \"json\", \"csv\", \"structured\", \"unstructured\", \"unsupported\"]>; multiline: Zod.ZodOptional; json_path: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }, { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }>; parsedSamples: Zod.ZodArray; }, \"strip\", Zod.ZodTypeAny, { samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; parsedSamples: string[]; }, { samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; parsedSamples: string[]; }>; }, \"strip\", Zod.ZodTypeAny, { results: { samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; parsedSamples: string[]; }; }, { results: { samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; parsedSamples: string[]; }; }>" + ], + "path": "x-pack/plugins/integration_assistant/common/api/analyze_logs/analyze_logs_route.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "integrationAssistant", "id": "def-common.BuildIntegrationRequestBody", @@ -759,7 +831,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }>; docs: Zod.ZodArray, Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">>, \"many\">; samplesFormat: Zod.ZodObject<{ name: Zod.ZodEnum<[\"ndjson\", \"json\"]>; multiline: Zod.ZodOptional; json_path: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }, { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + "[] | undefined; }>; docs: Zod.ZodArray, Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">>, \"many\">; samplesFormat: Zod.ZodObject<{ name: Zod.ZodEnum<[\"ndjson\", \"json\", \"csv\", \"structured\", \"unstructured\", \"unsupported\"]>; multiline: Zod.ZodOptional; json_path: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }, { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", { "pluginId": "integrationAssistant", "scope": "common", @@ -775,7 +847,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", { "pluginId": "integrationAssistant", "scope": "common", @@ -791,7 +863,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }; docs: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }>, \"many\">; logo: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + "[] | undefined; }; docs: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }>, \"many\">; logo: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", { "pluginId": "integrationAssistant", "scope": "common", @@ -807,7 +879,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }[]; logo?: string | undefined; }, { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }[]; logo?: string | undefined; }, { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", { "pluginId": "integrationAssistant", "scope": "common", @@ -823,7 +895,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }; docs: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }[]; logo?: string | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { integration: { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + "[] | undefined; }; docs: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }[]; logo?: string | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { integration: { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", { "pluginId": "integrationAssistant", "scope": "common", @@ -839,7 +911,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }[]; logo?: string | undefined; }; }, { integration: { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }[]; logo?: string | undefined; }; }, { integration: { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", { "pluginId": "integrationAssistant", "scope": "common", @@ -855,7 +927,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }; docs: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }[]; logo?: string | undefined; }; }>" + "[] | undefined; }; docs: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }[]; logo?: string | undefined; }; }>" ], "path": "x-pack/plugins/integration_assistant/common/api/build_integration/build_integration.ts", "deprecated": false, @@ -1314,7 +1386,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }>; docs: Zod.ZodArray, Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">>, \"many\">; samplesFormat: Zod.ZodObject<{ name: Zod.ZodEnum<[\"ndjson\", \"json\"]>; multiline: Zod.ZodOptional; json_path: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }, { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + "[] | undefined; }>; docs: Zod.ZodArray, Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">>, \"many\">; samplesFormat: Zod.ZodObject<{ name: Zod.ZodEnum<[\"ndjson\", \"json\", \"csv\", \"structured\", \"unstructured\", \"unsupported\"]>; multiline: Zod.ZodOptional; json_path: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }, { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", { "pluginId": "integrationAssistant", "scope": "common", @@ -1330,7 +1402,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", { "pluginId": "integrationAssistant", "scope": "common", @@ -1346,7 +1418,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }; docs: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }>" + "[] | undefined; }; docs: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }>" ], "path": "x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts", "deprecated": false, @@ -1644,7 +1716,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }>; docs: Zod.ZodArray, Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">>, \"many\">; samplesFormat: Zod.ZodObject<{ name: Zod.ZodEnum<[\"ndjson\", \"json\"]>; multiline: Zod.ZodOptional; json_path: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }, { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + "[] | undefined; }>; docs: Zod.ZodArray, Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">>, \"many\">; samplesFormat: Zod.ZodObject<{ name: Zod.ZodEnum<[\"ndjson\", \"json\", \"csv\", \"structured\", \"unstructured\", \"unsupported\"]>; multiline: Zod.ZodOptional; json_path: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }, { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", { "pluginId": "integrationAssistant", "scope": "common", @@ -1660,7 +1732,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }, { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", { "pluginId": "integrationAssistant", "scope": "common", @@ -1676,7 +1748,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }; docs: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }>, \"many\">; logo: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + "[] | undefined; }; docs: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }>, \"many\">; logo: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", { "pluginId": "integrationAssistant", "scope": "common", @@ -1692,7 +1764,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }[]; logo?: string | undefined; }, { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", + "[] | undefined; }; docs: Zod.objectOutputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }[]; logo?: string | undefined; }, { name: string; title: string; description: string; dataStreams: { name: string; title: string; description: string; inputTypes: (\"kafka\" | \"aws-cloudwatch\" | \"aws-s3\" | \"azure-blob-storage\" | \"azure-eventhub\" | \"cel\" | \"cloudfoundry\" | \"filestream\" | \"gcp-pubsub\" | \"gcs\" | \"http-endpoint\" | \"journald\" | \"tcp\" | \"udp\")[]; rawSamples: string[]; pipeline: { processors: ", { "pluginId": "integrationAssistant", "scope": "common", @@ -1708,7 +1780,7 @@ "section": "def-common.ESProcessorItem", "text": "ESProcessorItem" }, - "[] | undefined; }; docs: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }[]; logo?: string | undefined; }>" + "[] | undefined; }; docs: Zod.objectInputType<{}, Zod.ZodTypeAny, \"passthrough\">[]; samplesFormat: { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }; }[]; logo?: string | undefined; }>" ], "path": "x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts", "deprecated": false, @@ -2056,7 +2128,7 @@ "label": "SamplesFormat", "description": [], "signature": [ - "Zod.ZodObject<{ name: Zod.ZodEnum<[\"ndjson\", \"json\"]>; multiline: Zod.ZodOptional; json_path: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }, { name: \"json\" | \"ndjson\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }>" + "Zod.ZodObject<{ name: Zod.ZodEnum<[\"ndjson\", \"json\", \"csv\", \"structured\", \"unstructured\", \"unsupported\"]>; multiline: Zod.ZodOptional; json_path: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }, { name: \"json\" | \"ndjson\" | \"csv\" | \"structured\" | \"unstructured\" | \"unsupported\"; multiline?: boolean | undefined; json_path?: string[] | undefined; }>" ], "path": "x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts", "deprecated": false, diff --git a/api_docs/integration_assistant.mdx b/api_docs/integration_assistant.mdx index 2812e63061be9..682bd1b467bee 100644 --- a/api_docs/integration_assistant.mdx +++ b/api_docs/integration_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/integrationAssistant title: "integrationAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the integrationAssistant plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'integrationAssistant'] --- import integrationAssistantObj from './integration_assistant.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-scalability](https://github.com/orgs/elastic/teams/se | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 49 | 0 | 41 | 3 | +| 54 | 0 | 46 | 3 | ## Client diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index 4200b4df55f6d..ca7d19c11c2d4 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/investigate.devdocs.json b/api_docs/investigate.devdocs.json index 8febc4c6ac5f4..6027d5241e210 100644 --- a/api_docs/investigate.devdocs.json +++ b/api_docs/investigate.devdocs.json @@ -3,109 +3,6 @@ "client": { "classes": [], "functions": [ - { - "parentPluginId": "investigate", - "id": "def-public.createEsqlWidget", - "type": "Function", - "tags": [], - "label": "createEsqlWidget", - "description": [], - "signature": [ - ", \"type\">>(widgetCreate: T) => Pick<", - { - "pluginId": "investigate", - "scope": "common", - "docId": "kibInvestigatePluginApi", - "section": "def-common.InvestigateWidgetCreate", - "text": "InvestigateWidgetCreate" - }, - "<", - { - "pluginId": "investigate", - "scope": "public", - "docId": "kibInvestigatePluginApi", - "section": "def-public.EsqlWidgetParameters", - "text": "EsqlWidgetParameters" - }, - ">, \"type\"> & Omit & { parameters: T[\"parameters\"] & ", - "_DeepPartialObject", - "<", - "GlobalWidgetParameters", - ">; }" - ], - "path": "x-pack/plugins/observability_solution/investigate/public/esql_widget/create_esql_widget.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "investigate", - "id": "def-public.createEsqlWidget.$1", - "type": "Uncategorized", - "tags": [], - "label": "widgetCreate", - "description": [], - "signature": [ - "T" - ], - "path": "x-pack/plugins/observability_solution/investigate/public/create_widget.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.createWidgetFactory", - "type": "Function", - "tags": [], - "label": "createWidgetFactory", - "description": [], - "signature": [ - "(type: string) => ", - "WidgetFactory", - "" - ], - "path": "x-pack/plugins/observability_solution/investigate/public/create_widget.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "investigate", - "id": "def-public.createWidgetFactory.$1", - "type": "string", - "tags": [], - "label": "type", - "description": [], - "signature": [ - "string" - ], - "path": "x-pack/plugins/observability_solution/investigate/public/create_widget.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "investigate", "id": "def-public.getEsFilterFromGlobalParameters", @@ -393,45 +290,6 @@ } ], "interfaces": [ - { - "parentPluginId": "investigate", - "id": "def-public.EsqlWidgetParameters", - "type": "Interface", - "tags": [], - "label": "EsqlWidgetParameters", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/public/esql_widget/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "investigate", - "id": "def-public.EsqlWidgetParameters.esql", - "type": "string", - "tags": [], - "label": "esql", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/public/esql_widget/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.EsqlWidgetParameters.suggestion", - "type": "Object", - "tags": [], - "label": "suggestion", - "description": [], - "signature": [ - "Suggestion | undefined" - ], - "path": "x-pack/plugins/observability_solution/investigate/public/esql_widget/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "investigate", "id": "def-public.GlobalWidgetParameters", @@ -459,316 +317,10 @@ } ], "initialIsOpen": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.InvestigateWidget", - "type": "Interface", - "tags": [], - "label": "InvestigateWidget", - "description": [], - "signature": [ - { - "pluginId": "investigate", - "scope": "common", - "docId": "kibInvestigatePluginApi", - "section": "def-common.InvestigateWidget", - "text": "InvestigateWidget" - }, - "" - ], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "investigate", - "id": "def-public.InvestigateWidget.id", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.InvestigateWidget.createdAt", - "type": "number", - "tags": [], - "label": "createdAt", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.InvestigateWidget.createdBy", - "type": "string", - "tags": [], - "label": "createdBy", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.InvestigateWidget.title", - "type": "string", - "tags": [], - "label": "title", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.InvestigateWidget.type", - "type": "string", - "tags": [], - "label": "type", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.InvestigateWidget.parameters", - "type": "CompoundType", - "tags": [], - "label": "parameters", - "description": [], - "signature": [ - "GlobalWidgetParameters", - " & TParameters" - ], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.InvestigateWidget.data", - "type": "Uncategorized", - "tags": [], - "label": "data", - "description": [], - "signature": [ - "TData" - ], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.Investigation", - "type": "Interface", - "tags": [], - "label": "Investigation", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "investigate", - "id": "def-public.Investigation.id", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.Investigation.createdAt", - "type": "number", - "tags": [], - "label": "createdAt", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.Investigation.title", - "type": "string", - "tags": [], - "label": "title", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.Investigation.items", - "type": "Array", - "tags": [], - "label": "items", - "description": [], - "signature": [ - { - "pluginId": "investigate", - "scope": "common", - "docId": "kibInvestigatePluginApi", - "section": "def-common.InvestigateWidget", - "text": "InvestigateWidget" - }, - "<{}, {}>[]" - ], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.Investigation.notes", - "type": "Array", - "tags": [], - "label": "notes", - "description": [], - "signature": [ - { - "pluginId": "investigate", - "scope": "common", - "docId": "kibInvestigatePluginApi", - "section": "def-common.InvestigationNote", - "text": "InvestigationNote" - }, - "[]" - ], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.Investigation.parameters", - "type": "Object", - "tags": [], - "label": "parameters", - "description": [], - "signature": [ - "GlobalWidgetParameters" - ], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false } ], "enums": [], - "misc": [ - { - "parentPluginId": "investigate", - "id": "def-public.ESQL_WIDGET_NAME", - "type": "string", - "tags": [], - "label": "ESQL_WIDGET_NAME", - "description": [], - "signature": [ - "\"esql\"" - ], - "path": "x-pack/plugins/observability_solution/investigate/public/esql_widget/constants.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.InvestigateWidgetCreate", - "type": "Type", - "tags": [], - "label": "InvestigateWidgetCreate", - "description": [], - "signature": [ - "Pick<", - { - "pluginId": "investigate", - "scope": "common", - "docId": "kibInvestigatePluginApi", - "section": "def-common.InvestigateWidget", - "text": "InvestigateWidget" - }, - "<{}, {}>, \"type\" | \"title\"> & { parameters: ", - "_DeepPartialObject", - "<", - "GlobalWidgetParameters", - "> & TParameters; }" - ], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.OnWidgetAdd", - "type": "Type", - "tags": [], - "label": "OnWidgetAdd", - "description": [], - "signature": [ - "(create: ", - { - "pluginId": "investigate", - "scope": "common", - "docId": "kibInvestigatePluginApi", - "section": "def-common.InvestigateWidgetCreate", - "text": "InvestigateWidgetCreate" - }, - "<{}>) => Promise" - ], - "path": "x-pack/plugins/observability_solution/investigate/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "investigate", - "id": "def-public.OnWidgetAdd.$1", - "type": "CompoundType", - "tags": [], - "label": "create", - "description": [], - "signature": [ - "Pick<", - { - "pluginId": "investigate", - "scope": "common", - "docId": "kibInvestigatePluginApi", - "section": "def-common.InvestigateWidget", - "text": "InvestigateWidget" - }, - "<{}, {}>, \"type\" | \"title\"> & { parameters: ", - "_DeepPartialObject", - "<", - "GlobalWidgetParameters", - ">; }" - ], - "path": "x-pack/plugins/observability_solution/investigate/public/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - } - ], + "misc": [], "objects": [], "setup": { "parentPluginId": "investigate", @@ -783,15 +335,19 @@ "children": [ { "parentPluginId": "investigate", - "id": "def-public.InvestigatePublicSetup.register", + "id": "def-public.InvestigatePublicSetup.registerItemDefinition", "type": "Function", "tags": [], - "label": "register", + "label": "registerItemDefinition", "description": [], "signature": [ - "(callback: (registerWidget: ", - "RegisterWidget", - ") => Promise) => void" + "(itemDefinition: ", + "ItemDefinition", + ") => void" ], "path": "x-pack/plugins/observability_solution/investigate/public/types.ts", "deprecated": false, @@ -799,15 +355,14 @@ "children": [ { "parentPluginId": "investigate", - "id": "def-public.InvestigatePublicSetup.register.$1", - "type": "Function", + "id": "def-public.InvestigatePublicSetup.registerItemDefinition.$1", + "type": "Object", "tags": [], - "label": "callback", + "label": "itemDefinition", "description": [], "signature": [ - "(registerWidget: ", - "RegisterWidget", - ") => Promise" + "ItemDefinition", + "" ], "path": "x-pack/plugins/observability_solution/investigate/public/types.ts", "deprecated": false, @@ -834,15 +389,15 @@ "children": [ { "parentPluginId": "investigate", - "id": "def-public.InvestigatePublicStart.getWidgetDefinitions", + "id": "def-public.InvestigatePublicStart.getItemDefinitions", "type": "Function", "tags": [], - "label": "getWidgetDefinitions", + "label": "getItemDefinitions", "description": [], "signature": [ "() => ", - "WidgetDefinition", - "[]" + "ItemDefinition", + "<{}, {}>[]" ], "path": "x-pack/plugins/observability_solution/investigate/public/types.ts", "deprecated": false, @@ -852,22 +407,15 @@ }, { "parentPluginId": "investigate", - "id": "def-public.InvestigatePublicStart.useInvestigation", + "id": "def-public.InvestigatePublicStart.getItemDefinitionByType", "type": "Function", "tags": [], - "label": "useInvestigation", + "label": "getItemDefinitionByType", "description": [], "signature": [ - "({}: { user: ", - { - "pluginId": "@kbn/core-security-common", - "scope": "common", - "docId": "kibKbnCoreSecurityCommonPluginApi", - "section": "def-common.AuthenticatedUser", - "text": "AuthenticatedUser" - }, - "; investigationData?: { id: string; title: string; createdAt: number; createdBy: string; params: { timeRange: { from: number; to: number; }; }; origin: { type: \"alert\"; id: string; } | { type: \"blank\"; }; status: \"closed\" | \"ongoing\"; notes: { id: string; content: string; createdAt: number; createdBy: string; }[]; items: ({ id: string; createdAt: number; createdBy: string; } & { title: string; type: \"esql\"; params: { esql: string; suggestion: any; }; })[]; } | undefined; }) => ", - "UseInvestigationApi" + "(type: string) => ", + "ItemDefinition", + "<{}, {}> | undefined" ], "path": "x-pack/plugins/observability_solution/investigate/public/types.ts", "deprecated": false, @@ -875,50 +423,18 @@ "children": [ { "parentPluginId": "investigate", - "id": "def-public.InvestigatePublicStart.useInvestigation.$1", - "type": "Object", + "id": "def-public.InvestigatePublicStart.getItemDefinitionByType.$1", + "type": "string", "tags": [], - "label": "{}", + "label": "type", "description": [], + "signature": [ + "string" + ], "path": "x-pack/plugins/observability_solution/investigate/public/types.ts", "deprecated": false, "trackAdoption": false, - "children": [ - { - "parentPluginId": "investigate", - "id": "def-public.InvestigatePublicStart.useInvestigation.$1.user", - "type": "Object", - "tags": [], - "label": "user", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-security-common", - "scope": "common", - "docId": "kibKbnCoreSecurityCommonPluginApi", - "section": "def-common.AuthenticatedUser", - "text": "AuthenticatedUser" - } - ], - "path": "x-pack/plugins/observability_solution/investigate/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-public.InvestigatePublicStart.useInvestigation.$1.investigationData", - "type": "Object", - "tags": [], - "label": "investigationData", - "description": [], - "signature": [ - "{ id: string; title: string; createdAt: number; createdBy: string; params: { timeRange: { from: number; to: number; }; }; origin: { type: \"alert\"; id: string; } | { type: \"blank\"; }; status: \"closed\" | \"ongoing\"; notes: { id: string; content: string; createdAt: number; createdBy: string; }[]; items: ({ id: string; createdAt: number; createdBy: string; } & { title: string; type: \"esql\"; params: { esql: string; suggestion: any; }; })[]; } | undefined" - ], - "path": "x-pack/plugins/observability_solution/investigate/public/types.ts", - "deprecated": false, - "trackAdoption": false - } - ] + "isRequired": true } ], "returnComment": [] @@ -1208,307 +724,9 @@ "initialIsOpen": false } ], - "interfaces": [ - { - "parentPluginId": "investigate", - "id": "def-common.InvestigateWidget", - "type": "Interface", - "tags": [], - "label": "InvestigateWidget", - "description": [], - "signature": [ - { - "pluginId": "investigate", - "scope": "common", - "docId": "kibInvestigatePluginApi", - "section": "def-common.InvestigateWidget", - "text": "InvestigateWidget" - }, - "" - ], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "investigate", - "id": "def-common.InvestigateWidget.id", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-common.InvestigateWidget.createdAt", - "type": "number", - "tags": [], - "label": "createdAt", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-common.InvestigateWidget.createdBy", - "type": "string", - "tags": [], - "label": "createdBy", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-common.InvestigateWidget.title", - "type": "string", - "tags": [], - "label": "title", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-common.InvestigateWidget.type", - "type": "string", - "tags": [], - "label": "type", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-common.InvestigateWidget.parameters", - "type": "CompoundType", - "tags": [], - "label": "parameters", - "description": [], - "signature": [ - "GlobalWidgetParameters", - " & TParameters" - ], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-common.InvestigateWidget.data", - "type": "Uncategorized", - "tags": [], - "label": "data", - "description": [], - "signature": [ - "TData" - ], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "investigate", - "id": "def-common.Investigation", - "type": "Interface", - "tags": [], - "label": "Investigation", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "investigate", - "id": "def-common.Investigation.id", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-common.Investigation.createdAt", - "type": "number", - "tags": [], - "label": "createdAt", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-common.Investigation.title", - "type": "string", - "tags": [], - "label": "title", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-common.Investigation.items", - "type": "Array", - "tags": [], - "label": "items", - "description": [], - "signature": [ - { - "pluginId": "investigate", - "scope": "common", - "docId": "kibInvestigatePluginApi", - "section": "def-common.InvestigateWidget", - "text": "InvestigateWidget" - }, - "<{}, {}>[]" - ], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-common.Investigation.notes", - "type": "Array", - "tags": [], - "label": "notes", - "description": [], - "signature": [ - { - "pluginId": "investigate", - "scope": "common", - "docId": "kibInvestigatePluginApi", - "section": "def-common.InvestigationNote", - "text": "InvestigationNote" - }, - "[]" - ], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-common.Investigation.parameters", - "type": "Object", - "tags": [], - "label": "parameters", - "description": [], - "signature": [ - "GlobalWidgetParameters" - ], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "investigate", - "id": "def-common.InvestigationNote", - "type": "Interface", - "tags": [], - "label": "InvestigationNote", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "investigate", - "id": "def-common.InvestigationNote.id", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-common.InvestigationNote.createdAt", - "type": "number", - "tags": [], - "label": "createdAt", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-common.InvestigationNote.createdBy", - "type": "string", - "tags": [], - "label": "createdBy", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "investigate", - "id": "def-common.InvestigationNote.content", - "type": "string", - "tags": [], - "label": "content", - "description": [], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - } - ], + "interfaces": [], "enums": [], - "misc": [ - { - "parentPluginId": "investigate", - "id": "def-common.InvestigateWidgetCreate", - "type": "Type", - "tags": [], - "label": "InvestigateWidgetCreate", - "description": [], - "signature": [ - "Pick<", - { - "pluginId": "investigate", - "scope": "common", - "docId": "kibInvestigatePluginApi", - "section": "def-common.InvestigateWidget", - "text": "InvestigateWidget" - }, - "<{}, {}>, \"type\" | \"title\"> & { parameters: ", - "_DeepPartialObject", - "<", - "GlobalWidgetParameters", - "> & TParameters; }" - ], - "path": "x-pack/plugins/observability_solution/investigate/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - } - ], + "misc": [], "objects": [] } } \ No newline at end of file diff --git a/api_docs/investigate.mdx b/api_docs/investigate.mdx index e9fa8ccba29e8..b70e93645437e 100644 --- a/api_docs/investigate.mdx +++ b/api_docs/investigate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/investigate title: "investigate" image: https://source.unsplash.com/400x175/?github description: API docs for the investigate plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'investigate'] --- import investigateObj from './investigate.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/ | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 92 | 0 | 92 | 5 | +| 43 | 0 | 43 | 4 | ## Client @@ -37,9 +37,6 @@ Contact [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/ ### Interfaces -### Consts, variables and types - - ## Server ### Setup @@ -53,9 +50,3 @@ Contact [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/ ### Functions -### Interfaces - - -### Consts, variables and types - - diff --git a/api_docs/investigate_app.devdocs.json b/api_docs/investigate_app.devdocs.json index cb7fd681facbe..425c031088c32 100644 --- a/api_docs/investigate_app.devdocs.json +++ b/api_docs/investigate_app.devdocs.json @@ -58,7 +58,7 @@ "StringC", "; }>; }> | undefined; handler: ({}: ", "InvestigateAppRouteHandlerResources", - " & { params: { path: { investigationId: string; }; }; }) => Promise<({ id: string; createdAt: number; createdBy: string; } & { title: string; type: \"esql\"; params: { esql: string; suggestion: any; }; })[]>; } & ", + " & { params: { path: { investigationId: string; }; }; }) => Promise<({ id: string; createdAt: number; createdBy: string; } & { title: string; type: string; params: { [x: string]: any; }; })[]>; } & ", "InvestigateAppRouteCreateOptions", "; \"DELETE /api/observability/investigations/{investigationId}/items/{itemId} 2023-10-31\": { endpoint: \"DELETE /api/observability/investigations/{investigationId}/items/{itemId} 2023-10-31\"; params?: ", "TypeC", @@ -83,16 +83,16 @@ "<{ title: ", "StringC", "; type: ", - "LiteralC", - "<\"esql\">; params: ", - "TypeC", - "<{ esql: ", "StringC", - "; suggestion: ", + "; params: ", + "RecordC", + "<", + "StringC", + ", ", "AnyC", - "; }>; }>; }> | undefined; handler: ({}: ", + ">; }>; }> | undefined; handler: ({}: ", "InvestigateAppRouteHandlerResources", - " & { params: { path: { investigationId: string; }; body: { title: string; type: \"esql\"; params: { esql: string; suggestion: any; }; }; }; }) => Promise<{ id: string; createdAt: number; createdBy: string; } & { title: string; type: \"esql\"; params: { esql: string; suggestion: any; }; }>; } & ", + " & { params: { path: { investigationId: string; }; body: { title: string; type: string; params: { [x: string]: any; }; }; }; }) => Promise<{ id: string; createdAt: number; createdBy: string; } & { title: string; type: string; params: { [x: string]: any; }; }>; } & ", "InvestigateAppRouteCreateOptions", "; \"DELETE /api/observability/investigations/{investigationId}/notes/{noteId} 2023-10-31\": { endpoint: \"DELETE /api/observability/investigations/{investigationId}/notes/{noteId} 2023-10-31\"; params?: ", "TypeC", @@ -148,7 +148,7 @@ "StringC", "; }>; }> | undefined; handler: ({}: ", "InvestigateAppRouteHandlerResources", - " & { params: { path: { investigationId: string; }; }; }) => Promise<{ id: string; title: string; createdAt: number; createdBy: string; params: { timeRange: { from: number; to: number; }; }; origin: { type: \"alert\"; id: string; } | { type: \"blank\"; }; status: \"closed\" | \"ongoing\"; notes: { id: string; content: string; createdAt: number; createdBy: string; }[]; items: ({ id: string; createdAt: number; createdBy: string; } & { title: string; type: \"esql\"; params: { esql: string; suggestion: any; }; })[]; }>; } & ", + " & { params: { path: { investigationId: string; }; }; }) => Promise<{ id: string; title: string; createdAt: number; createdBy: string; params: { timeRange: { from: number; to: number; }; }; origin: { type: \"alert\"; id: string; } | { type: \"blank\"; }; status: \"closed\" | \"ongoing\"; notes: { id: string; content: string; createdAt: number; createdBy: string; }[]; items: ({ id: string; createdAt: number; createdBy: string; } & { title: string; type: string; params: { [x: string]: any; }; })[]; }>; } & ", "InvestigateAppRouteCreateOptions", "; \"GET /api/observability/investigations 2023-10-31\": { endpoint: \"GET /api/observability/investigations 2023-10-31\"; params?: ", "PartialC", @@ -162,7 +162,7 @@ "StringC", "; }>; }> | undefined; handler: ({}: ", "InvestigateAppRouteHandlerResources", - " & { params?: { query?: { alertId?: string | undefined; page?: string | undefined; perPage?: string | undefined; } | undefined; } | undefined; }) => Promise<{ page: number; perPage: number; total: number; results: { id: string; title: string; createdAt: number; createdBy: string; params: { timeRange: { from: number; to: number; }; }; origin: { type: \"alert\"; id: string; } | { type: \"blank\"; }; status: \"closed\" | \"ongoing\"; notes: { id: string; content: string; createdAt: number; createdBy: string; }[]; items: ({ id: string; createdAt: number; createdBy: string; } & { title: string; type: \"esql\"; params: { esql: string; suggestion: any; }; })[]; }[]; }>; } & ", + " & { params?: { query?: { alertId?: string | undefined; page?: string | undefined; perPage?: string | undefined; } | undefined; } | undefined; }) => Promise<{ page: number; perPage: number; total: number; results: { id: string; title: string; createdAt: number; createdBy: string; params: { timeRange: { from: number; to: number; }; }; origin: { type: \"alert\"; id: string; } | { type: \"blank\"; }; status: \"closed\" | \"ongoing\"; notes: { id: string; content: string; createdAt: number; createdBy: string; }[]; items: ({ id: string; createdAt: number; createdBy: string; } & { title: string; type: string; params: { [x: string]: any; }; })[]; }[]; }>; } & ", "InvestigateAppRouteCreateOptions", "; \"POST /api/observability/investigations 2023-10-31\": { endpoint: \"POST /api/observability/investigations 2023-10-31\"; params?: ", "TypeC", @@ -194,7 +194,7 @@ "LiteralC", "<\"blank\">; }>]>; }>; }> | undefined; handler: ({}: ", "InvestigateAppRouteHandlerResources", - " & { params: { body: { id: string; title: string; params: { timeRange: { from: number; to: number; }; }; origin: { type: \"alert\"; id: string; } | { type: \"blank\"; }; }; }; }) => Promise<{ id: string; title: string; createdAt: number; createdBy: string; params: { timeRange: { from: number; to: number; }; }; origin: { type: \"alert\"; id: string; } | { type: \"blank\"; }; status: \"closed\" | \"ongoing\"; notes: { id: string; content: string; createdAt: number; createdBy: string; }[]; items: ({ id: string; createdAt: number; createdBy: string; } & { title: string; type: \"esql\"; params: { esql: string; suggestion: any; }; })[]; }>; } & ", + " & { params: { body: { id: string; title: string; params: { timeRange: { from: number; to: number; }; }; origin: { type: \"alert\"; id: string; } | { type: \"blank\"; }; }; }; }) => Promise<{ id: string; title: string; createdAt: number; createdBy: string; params: { timeRange: { from: number; to: number; }; }; origin: { type: \"alert\"; id: string; } | { type: \"blank\"; }; status: \"closed\" | \"ongoing\"; notes: { id: string; content: string; createdAt: number; createdBy: string; }[]; items: ({ id: string; createdAt: number; createdBy: string; } & { title: string; type: string; params: { [x: string]: any; }; })[]; }>; } & ", "InvestigateAppRouteCreateOptions", "; }" ], diff --git a/api_docs/investigate_app.mdx b/api_docs/investigate_app.mdx index 2348c5fcb711b..1a96a005cbad7 100644 --- a/api_docs/investigate_app.mdx +++ b/api_docs/investigate_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/investigateApp title: "investigateApp" image: https://source.unsplash.com/400x175/?github description: API docs for the investigateApp plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'investigateApp'] --- import investigateAppObj from './investigate_app.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index 36a873aa0aa93..c2bec03adf02e 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_actions_types.mdx b/api_docs/kbn_actions_types.mdx index 2b22f5d6fc202..86aa210a61988 100644 --- a/api_docs/kbn_actions_types.mdx +++ b/api_docs/kbn_actions_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-actions-types title: "@kbn/actions-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/actions-types plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/actions-types'] --- import kbnActionsTypesObj from './kbn_actions_types.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index 879e63ec94b52..ec20c870397e4 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_log_pattern_analysis.mdx b/api_docs/kbn_aiops_log_pattern_analysis.mdx index be52419021093..1fb44a6ba2de5 100644 --- a/api_docs/kbn_aiops_log_pattern_analysis.mdx +++ b/api_docs/kbn_aiops_log_pattern_analysis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-log-pattern-analysis title: "@kbn/aiops-log-pattern-analysis" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-log-pattern-analysis plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-log-pattern-analysis'] --- import kbnAiopsLogPatternAnalysisObj from './kbn_aiops_log_pattern_analysis.devdocs.json'; diff --git a/api_docs/kbn_aiops_log_rate_analysis.mdx b/api_docs/kbn_aiops_log_rate_analysis.mdx index 4eddc3c8f1588..9148cd56ee082 100644 --- a/api_docs/kbn_aiops_log_rate_analysis.mdx +++ b/api_docs/kbn_aiops_log_rate_analysis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-log-rate-analysis title: "@kbn/aiops-log-rate-analysis" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-log-rate-analysis plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-log-rate-analysis'] --- import kbnAiopsLogRateAnalysisObj from './kbn_aiops_log_rate_analysis.devdocs.json'; diff --git a/api_docs/kbn_alerting_api_integration_helpers.mdx b/api_docs/kbn_alerting_api_integration_helpers.mdx index f4a1536f13765..81d6969c574ed 100644 --- a/api_docs/kbn_alerting_api_integration_helpers.mdx +++ b/api_docs/kbn_alerting_api_integration_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-api-integration-helpers title: "@kbn/alerting-api-integration-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-api-integration-helpers plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-api-integration-helpers'] --- import kbnAlertingApiIntegrationHelpersObj from './kbn_alerting_api_integration_helpers.devdocs.json'; diff --git a/api_docs/kbn_alerting_comparators.mdx b/api_docs/kbn_alerting_comparators.mdx index 7fb32ced0de89..f8183c0225b6a 100644 --- a/api_docs/kbn_alerting_comparators.mdx +++ b/api_docs/kbn_alerting_comparators.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-comparators title: "@kbn/alerting-comparators" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-comparators plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-comparators'] --- import kbnAlertingComparatorsObj from './kbn_alerting_comparators.devdocs.json'; diff --git a/api_docs/kbn_alerting_state_types.mdx b/api_docs/kbn_alerting_state_types.mdx index 7429ff247175c..4b6938882fb4c 100644 --- a/api_docs/kbn_alerting_state_types.mdx +++ b/api_docs/kbn_alerting_state_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-state-types title: "@kbn/alerting-state-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-state-types plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-state-types'] --- import kbnAlertingStateTypesObj from './kbn_alerting_state_types.devdocs.json'; diff --git a/api_docs/kbn_alerting_types.mdx b/api_docs/kbn_alerting_types.mdx index ca1cc6be7b68c..85e0efabe824b 100644 --- a/api_docs/kbn_alerting_types.mdx +++ b/api_docs/kbn_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-types title: "@kbn/alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-types plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-types'] --- import kbnAlertingTypesObj from './kbn_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_alerts_as_data_utils.mdx b/api_docs/kbn_alerts_as_data_utils.mdx index f4446f2c69f3d..5ba4e8ccdb11f 100644 --- a/api_docs/kbn_alerts_as_data_utils.mdx +++ b/api_docs/kbn_alerts_as_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-as-data-utils title: "@kbn/alerts-as-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-as-data-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-as-data-utils'] --- import kbnAlertsAsDataUtilsObj from './kbn_alerts_as_data_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts_grouping.mdx b/api_docs/kbn_alerts_grouping.mdx index 0870d46f2715d..ead5dbc68e9e9 100644 --- a/api_docs/kbn_alerts_grouping.mdx +++ b/api_docs/kbn_alerts_grouping.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-grouping title: "@kbn/alerts-grouping" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-grouping plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-grouping'] --- import kbnAlertsGroupingObj from './kbn_alerts_grouping.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index f4ae83ee2bb5d..2f4f06d62f2ec 100644 --- a/api_docs/kbn_alerts_ui_shared.mdx +++ b/api_docs/kbn_alerts_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-ui-shared title: "@kbn/alerts-ui-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-ui-shared plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-ui-shared'] --- import kbnAlertsUiSharedObj from './kbn_alerts_ui_shared.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index b1116871df3d5..871f9c2786434 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_collection_utils.mdx b/api_docs/kbn_analytics_collection_utils.mdx index 9d2cf63cd98a9..ca10af2336113 100644 --- a/api_docs/kbn_analytics_collection_utils.mdx +++ b/api_docs/kbn_analytics_collection_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-collection-utils title: "@kbn/analytics-collection-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-collection-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-collection-utils'] --- import kbnAnalyticsCollectionUtilsObj from './kbn_analytics_collection_utils.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index baab52fcd0c72..27a71a2f9a74a 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_data_view.mdx b/api_docs/kbn_apm_data_view.mdx index 5bd1bdf21cf2c..0cf3b6ec4242c 100644 --- a/api_docs/kbn_apm_data_view.mdx +++ b/api_docs/kbn_apm_data_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-data-view title: "@kbn/apm-data-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-data-view plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-data-view'] --- import kbnApmDataViewObj from './kbn_apm_data_view.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index f2cd1fc825be9..5c29e8fcdbcd2 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx index cd6976985d516..6daa9485c935c 100644 --- a/api_docs/kbn_apm_synthtrace_client.mdx +++ b/api_docs/kbn_apm_synthtrace_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace-client title: "@kbn/apm-synthtrace-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace-client plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace-client'] --- import kbnApmSynthtraceClientObj from './kbn_apm_synthtrace_client.devdocs.json'; diff --git a/api_docs/kbn_apm_types.mdx b/api_docs/kbn_apm_types.mdx index 7e25637a0387f..04e1465b5ecfd 100644 --- a/api_docs/kbn_apm_types.mdx +++ b/api_docs/kbn_apm_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-types title: "@kbn/apm-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-types plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-types'] --- import kbnApmTypesObj from './kbn_apm_types.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index 4a5c5681ea201..bda841b9357f2 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_avc_banner.mdx b/api_docs/kbn_avc_banner.mdx index 81e4caa4db02e..98cd4073f07f3 100644 --- a/api_docs/kbn_avc_banner.mdx +++ b/api_docs/kbn_avc_banner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-avc-banner title: "@kbn/avc-banner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/avc-banner plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/avc-banner'] --- import kbnAvcBannerObj from './kbn_avc_banner.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index 83ffe3d48c656..abd16eaf2bda0 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_bfetch_error.mdx b/api_docs/kbn_bfetch_error.mdx index 0e695ad07bcff..856ac761d93ca 100644 --- a/api_docs/kbn_bfetch_error.mdx +++ b/api_docs/kbn_bfetch_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-bfetch-error title: "@kbn/bfetch-error" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/bfetch-error plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/bfetch-error'] --- import kbnBfetchErrorObj from './kbn_bfetch_error.devdocs.json'; diff --git a/api_docs/kbn_calculate_auto.mdx b/api_docs/kbn_calculate_auto.mdx index 56a0eec50a8f2..af7347e5f019c 100644 --- a/api_docs/kbn_calculate_auto.mdx +++ b/api_docs/kbn_calculate_auto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-calculate-auto title: "@kbn/calculate-auto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/calculate-auto plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/calculate-auto'] --- import kbnCalculateAutoObj from './kbn_calculate_auto.devdocs.json'; diff --git a/api_docs/kbn_calculate_width_from_char_count.mdx b/api_docs/kbn_calculate_width_from_char_count.mdx index 91398cbf372ed..1f1b428851c22 100644 --- a/api_docs/kbn_calculate_width_from_char_count.mdx +++ b/api_docs/kbn_calculate_width_from_char_count.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-calculate-width-from-char-count title: "@kbn/calculate-width-from-char-count" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/calculate-width-from-char-count plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/calculate-width-from-char-count'] --- import kbnCalculateWidthFromCharCountObj from './kbn_calculate_width_from_char_count.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index 83fef34dce621..3127bd446582e 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_cbor.mdx b/api_docs/kbn_cbor.mdx index 5720f6996dfdf..d3902c9dfc683 100644 --- a/api_docs/kbn_cbor.mdx +++ b/api_docs/kbn_cbor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cbor title: "@kbn/cbor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cbor plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cbor'] --- import kbnCborObj from './kbn_cbor.devdocs.json'; diff --git a/api_docs/kbn_cell_actions.mdx b/api_docs/kbn_cell_actions.mdx index a07787f1fbc3a..e40d6e271db55 100644 --- a/api_docs/kbn_cell_actions.mdx +++ b/api_docs/kbn_cell_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cell-actions title: "@kbn/cell-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cell-actions plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cell-actions'] --- import kbnCellActionsObj from './kbn_cell_actions.devdocs.json'; diff --git a/api_docs/kbn_chart_expressions_common.devdocs.json b/api_docs/kbn_chart_expressions_common.devdocs.json index cf8c8c64ccfcc..d5271d494e0a0 100644 --- a/api_docs/kbn_chart_expressions_common.devdocs.json +++ b/api_docs/kbn_chart_expressions_common.devdocs.json @@ -133,7 +133,7 @@ "section": "def-common.DatatableRow", "text": "DatatableRow" }, - "[], accessor: string | undefined) => (string | string[])[]" + "[], accessor: string | undefined, isTransposed: boolean | undefined, exclude: any[] | undefined) => (string | string[])[]" ], "path": "src/plugins/chart_expressions/common/color_categories.ts", "deprecated": false, @@ -175,6 +175,36 @@ "deprecated": false, "trackAdoption": false, "isRequired": false + }, + { + "parentPluginId": "@kbn/chart-expressions-common", + "id": "def-common.getColorCategories.$3", + "type": "CompoundType", + "tags": [], + "label": "isTransposed", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/chart_expressions/common/color_categories.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + }, + { + "parentPluginId": "@kbn/chart-expressions-common", + "id": "def-common.getColorCategories.$4", + "type": "Array", + "tags": [], + "label": "exclude", + "description": [], + "signature": [ + "any[] | undefined" + ], + "path": "src/plugins/chart_expressions/common/color_categories.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false } ], "returnComment": [], diff --git a/api_docs/kbn_chart_expressions_common.mdx b/api_docs/kbn_chart_expressions_common.mdx index 56b27d69fcece..c179d3f6fe721 100644 --- a/api_docs/kbn_chart_expressions_common.mdx +++ b/api_docs/kbn_chart_expressions_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-expressions-common title: "@kbn/chart-expressions-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-expressions-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-expressions-common'] --- import kbnChartExpressionsCommonObj from './kbn_chart_expressions_common.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 23 | 0 | 19 | 0 | +| 25 | 0 | 21 | 0 | ## Common diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index 795e67895a493..1c798e4bfe695 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index 3e7cdf023bff6..eefbddd3fee38 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] --- import kbnCiStatsCoreObj from './kbn_ci_stats_core.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index 80e3fe3bef8b4..a4831f5248c3b 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] --- import kbnCiStatsPerformanceMetricsObj from './kbn_ci_stats_performance_metrics.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index 6f6944f783e90..ec7bb460d141e 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] --- import kbnCiStatsReporterObj from './kbn_ci_stats_reporter.devdocs.json'; diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index 622447bc9ecd5..1e899d11711d4 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_cloud_security_posture.devdocs.json b/api_docs/kbn_cloud_security_posture.devdocs.json new file mode 100644 index 0000000000000..56abf5d314460 --- /dev/null +++ b/api_docs/kbn_cloud_security_posture.devdocs.json @@ -0,0 +1,563 @@ +{ + "id": "@kbn/cloud-security-posture", + "client": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.showErrorToast", + "type": "Function", + "tags": [], + "label": "showErrorToast", + "description": [], + "signature": [ + "(toasts: ", + { + "pluginId": "@kbn/core-notifications-browser", + "scope": "public", + "docId": "kibKbnCoreNotificationsBrowserPluginApi", + "section": "def-public.IToasts", + "text": "IToasts" + }, + ", error: unknown) => void" + ], + "path": "x-pack/packages/kbn-cloud-security-posture/src/utils/show_error_toast.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.showErrorToast.$1", + "type": "Object", + "tags": [], + "label": "toasts", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-notifications-browser", + "scope": "public", + "docId": "kibKbnCoreNotificationsBrowserPluginApi", + "section": "def-public.IToasts", + "text": "IToasts" + } + ], + "path": "x-pack/packages/kbn-cloud-security-posture/src/utils/show_error_toast.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.showErrorToast.$2", + "type": "Unknown", + "tags": [], + "label": "error", + "description": [], + "signature": [ + "unknown" + ], + "path": "x-pack/packages/kbn-cloud-security-posture/src/utils/show_error_toast.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps", + "type": "Interface", + "tags": [], + "label": "CspClientPluginStartDeps", + "description": [], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps.data", + "type": "Object", + "tags": [], + "label": "data", + "description": [], + "signature": [ + { + "pluginId": "data", + "scope": "public", + "docId": "kibDataPluginApi", + "section": "def-public.DataPublicPluginStart", + "text": "DataPublicPluginStart" + } + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps.dataViews", + "type": "Object", + "tags": [], + "label": "dataViews", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "public", + "docId": "kibDataViewsPluginApi", + "section": "def-public.DataViewsServicePublic", + "text": "DataViewsServicePublic" + } + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps.dataViewFieldEditor", + "type": "Object", + "tags": [], + "label": "dataViewFieldEditor", + "description": [], + "signature": [ + { + "pluginId": "dataViewFieldEditor", + "scope": "public", + "docId": "kibDataViewFieldEditorPluginApi", + "section": "def-public.PluginStart", + "text": "PluginStart" + } + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps.unifiedSearch", + "type": "Object", + "tags": [], + "label": "unifiedSearch", + "description": [], + "signature": [ + { + "pluginId": "unifiedSearch", + "scope": "public", + "docId": "kibUnifiedSearchPluginApi", + "section": "def-public.UnifiedSearchPublicPluginStart", + "text": "UnifiedSearchPublicPluginStart" + } + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps.uiActions", + "type": "Object", + "tags": [], + "label": "uiActions", + "description": [], + "signature": [ + "{ readonly registerTrigger: (trigger: ", + { + "pluginId": "@kbn/ui-actions-browser", + "scope": "common", + "docId": "kibKbnUiActionsBrowserPluginApi", + "section": "def-common.Trigger", + "text": "Trigger" + }, + ") => void; readonly hasTrigger: (triggerId: string) => boolean; readonly getTrigger: (triggerId: string) => ", + "TriggerContract", + "; readonly registerAction: (definition: ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.ActionDefinition", + "text": "ActionDefinition" + }, + ") => ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.Action", + "text": "Action" + }, + "; readonly unregisterAction: (actionId: string) => void; readonly hasAction: (actionId: string) => boolean; readonly attachAction: (triggerId: string, actionId: string) => void; readonly detachAction: (triggerId: string, actionId: string) => void; readonly addTriggerAction: (triggerId: string, action: ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.ActionDefinition", + "text": "ActionDefinition" + }, + ") => void; readonly getAction: (id: string) => ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.Action", + "text": "Action" + }, + "; readonly getTriggerActions: (triggerId: string) => ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.Action", + "text": "Action" + }, + "[]; readonly getTriggerCompatibleActions: (triggerId: string, context: object) => Promise<", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.Action", + "text": "Action" + }, + "[]>; readonly getFrequentlyChangingActionsForTrigger: (triggerId: string, context: object) => ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.FrequentCompatibilityChangeAction", + "text": "FrequentCompatibilityChangeAction" + }, + "[]; readonly executeTriggerActions: (triggerId: string, context: object) => Promise; readonly clear: () => void; readonly fork: () => ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.UiActionsService", + "text": "UiActionsService" + }, + "; }" + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps.fieldFormats", + "type": "CompoundType", + "tags": [], + "label": "fieldFormats", + "description": [], + "signature": [ + "Omit<", + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.FieldFormatsRegistry", + "text": "FieldFormatsRegistry" + }, + ", \"init\" | \"register\"> & { deserialize: ", + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.FormatFactory", + "text": "FormatFactory" + }, + "; }" + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps.toastNotifications", + "type": "Object", + "tags": [], + "label": "toastNotifications", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-notifications-browser", + "scope": "public", + "docId": "kibKbnCoreNotificationsBrowserPluginApi", + "section": "def-public.IToasts", + "text": "IToasts" + } + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps.charts", + "type": "CompoundType", + "tags": [], + "label": "charts", + "description": [], + "signature": [ + { + "pluginId": "charts", + "scope": "public", + "docId": "kibChartsPluginApi", + "section": "def-public.ChartsPluginSetup", + "text": "ChartsPluginSetup" + }, + " & { activeCursor: ", + "ActiveCursor", + "; }" + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps.discover", + "type": "Object", + "tags": [], + "label": "discover", + "description": [], + "signature": [ + { + "pluginId": "discover", + "scope": "public", + "docId": "kibDiscoverPluginApi", + "section": "def-public.DiscoverStart", + "text": "DiscoverStart" + } + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps.fleet", + "type": "Object", + "tags": [], + "label": "fleet", + "description": [], + "signature": [ + { + "pluginId": "fleet", + "scope": "public", + "docId": "kibFleetPluginApi", + "section": "def-public.FleetStart", + "text": "FleetStart" + } + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps.licensing", + "type": "Object", + "tags": [], + "label": "licensing", + "description": [], + "signature": [ + { + "pluginId": "licensing", + "scope": "public", + "docId": "kibLicensingPluginApi", + "section": "def-public.LicensingPluginStart", + "text": "LicensingPluginStart" + } + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps.share", + "type": "CompoundType", + "tags": [], + "label": "share", + "description": [], + "signature": [ + "{ toggleShareContextMenu: (options: ", + { + "pluginId": "share", + "scope": "public", + "docId": "kibSharePluginApi", + "section": "def-public.ShowShareMenuOptions", + "text": "ShowShareMenuOptions" + }, + ") => void; } & { url: ", + { + "pluginId": "share", + "scope": "public", + "docId": "kibSharePluginApi", + "section": "def-public.BrowserUrlService", + "text": "BrowserUrlService" + }, + "; navigate(options: ", + "RedirectOptions", + "<", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.SerializableRecord", + "text": "SerializableRecord" + }, + ">): void; }" + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps.storage", + "type": "Object", + "tags": [], + "label": "storage", + "description": [], + "signature": [ + { + "pluginId": "kibanaUtils", + "scope": "public", + "docId": "kibKibanaUtilsPluginApi", + "section": "def-public.Storage", + "text": "Storage" + } + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps.spaces", + "type": "Object", + "tags": [], + "label": "spaces", + "description": [], + "signature": [ + { + "pluginId": "spaces", + "scope": "public", + "docId": "kibSpacesPluginApi", + "section": "def-public.SpacesApi", + "text": "SpacesApi" + } + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps.cloud", + "type": "Object", + "tags": [], + "label": "cloud", + "description": [], + "signature": [ + { + "pluginId": "cloud", + "scope": "public", + "docId": "kibCloudPluginApi", + "section": "def-public.CloudSetup", + "text": "CloudSetup" + } + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.CspClientPluginStartDeps.usageCollection", + "type": "Object", + "tags": [], + "label": "usageCollection", + "description": [], + "signature": [ + { + "pluginId": "usageCollection", + "scope": "public", + "docId": "kibUsageCollectionPluginApi", + "section": "def-public.UsageCollectionStart", + "text": "UsageCollectionStart" + }, + " | undefined" + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.FindingsBaseEsQuery", + "type": "Interface", + "tags": [], + "label": "FindingsBaseEsQuery", + "description": [], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/cloud-security-posture", + "id": "def-public.FindingsBaseEsQuery.query", + "type": "Object", + "tags": [], + "label": "query", + "description": [], + "signature": [ + "{ bool: ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.BoolQuery", + "text": "BoolQuery" + }, + "; } | undefined" + ], + "path": "x-pack/packages/kbn-cloud-security-posture/type.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_cloud_security_posture.mdx b/api_docs/kbn_cloud_security_posture.mdx new file mode 100644 index 0000000000000..d45a101061453 --- /dev/null +++ b/api_docs/kbn_cloud_security_posture.mdx @@ -0,0 +1,33 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnCloudSecurityPosturePluginApi +slug: /kibana-dev-docs/api/kbn-cloud-security-posture +title: "@kbn/cloud-security-posture" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/cloud-security-posture plugin +date: 2024-08-29 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cloud-security-posture'] +--- +import kbnCloudSecurityPostureObj from './kbn_cloud_security_posture.devdocs.json'; + + + +Contact [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 22 | 0 | 22 | 0 | + +## Client + +### Functions + + +### Interfaces + + diff --git a/api_docs/kbn_cloud_security_posture_common.devdocs.json b/api_docs/kbn_cloud_security_posture_common.devdocs.json new file mode 100644 index 0000000000000..ccac5b517f03c --- /dev/null +++ b/api_docs/kbn_cloud_security_posture_common.devdocs.json @@ -0,0 +1,754 @@ +{ + "id": "@kbn/cloud-security-posture-common", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.buildMutedRulesFilter", + "type": "Function", + "tags": [], + "label": "buildMutedRulesFilter", + "description": [], + "signature": [ + "(rulesStates: Record>) => ", + "QueryDslQueryContainer", + "[]" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/utils/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.buildMutedRulesFilter.$1", + "type": "Object", + "tags": [], + "label": "rulesStates", + "description": [], + "signature": [ + "Record>" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/utils/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.extractErrorMessage", + "type": "Function", + "tags": [], + "label": "extractErrorMessage", + "description": [], + "signature": [ + "(e: unknown, fallbackMessage?: string | undefined) => string" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/utils/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.extractErrorMessage.$1", + "type": "Unknown", + "tags": [], + "label": "e", + "description": [], + "signature": [ + "unknown" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/utils/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.extractErrorMessage.$2", + "type": "string", + "tags": [], + "label": "fallbackMessage", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/utils/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.BaseCspSetupBothPolicy", + "type": "Interface", + "tags": [], + "label": "BaseCspSetupBothPolicy", + "description": [], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.BaseCspSetupBothPolicy.status", + "type": "CompoundType", + "tags": [], + "label": "status", + "description": [], + "signature": [ + "\"indexed\" | \"unprivileged\" | \"indexing\" | \"index-timeout\" | \"not-deployed\" | \"not-installed\" | \"waiting_for_results\"" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.BaseCspSetupBothPolicy.installedPackagePolicies", + "type": "number", + "tags": [], + "label": "installedPackagePolicies", + "description": [], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.BaseCspSetupBothPolicy.healthyAgents", + "type": "number", + "tags": [], + "label": "healthyAgents", + "description": [], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.BaseCspSetupStatus", + "type": "Interface", + "tags": [], + "label": "BaseCspSetupStatus", + "description": [], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.BaseCspSetupStatus.indicesDetails", + "type": "Array", + "tags": [], + "label": "indicesDetails", + "description": [], + "signature": [ + { + "pluginId": "@kbn/cloud-security-posture-common", + "scope": "common", + "docId": "kibKbnCloudSecurityPostureCommonPluginApi", + "section": "def-common.IndexDetails", + "text": "IndexDetails" + }, + "[]" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.BaseCspSetupStatus.latestPackageVersion", + "type": "string", + "tags": [], + "label": "latestPackageVersion", + "description": [], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.BaseCspSetupStatus.cspm", + "type": "Object", + "tags": [], + "label": "cspm", + "description": [], + "signature": [ + { + "pluginId": "@kbn/cloud-security-posture-common", + "scope": "common", + "docId": "kibKbnCloudSecurityPostureCommonPluginApi", + "section": "def-common.BaseCspSetupBothPolicy", + "text": "BaseCspSetupBothPolicy" + } + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.BaseCspSetupStatus.kspm", + "type": "Object", + "tags": [], + "label": "kspm", + "description": [], + "signature": [ + { + "pluginId": "@kbn/cloud-security-posture-common", + "scope": "common", + "docId": "kibKbnCloudSecurityPostureCommonPluginApi", + "section": "def-common.BaseCspSetupBothPolicy", + "text": "BaseCspSetupBothPolicy" + } + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.BaseCspSetupStatus.vuln_mgmt", + "type": "Object", + "tags": [], + "label": "vuln_mgmt", + "description": [], + "signature": [ + { + "pluginId": "@kbn/cloud-security-posture-common", + "scope": "common", + "docId": "kibKbnCloudSecurityPostureCommonPluginApi", + "section": "def-common.BaseCspSetupBothPolicy", + "text": "BaseCspSetupBothPolicy" + } + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.BaseCspSetupStatus.isPluginInitialized", + "type": "boolean", + "tags": [], + "label": "isPluginInitialized", + "description": [], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.BaseCspSetupStatus.installedPackageVersion", + "type": "string", + "tags": [], + "label": "installedPackageVersion", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.BaseCspSetupStatus.hasMisconfigurationsFindings", + "type": "CompoundType", + "tags": [], + "label": "hasMisconfigurationsFindings", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CspFinding", + "type": "Interface", + "tags": [], + "label": "CspFinding", + "description": [], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CspFinding.timestamp", + "type": "string", + "tags": [], + "label": "'@timestamp'", + "description": [], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CspFinding.cluster_id", + "type": "string", + "tags": [], + "label": "cluster_id", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CspFinding.orchestrator", + "type": "Object", + "tags": [], + "label": "orchestrator", + "description": [], + "signature": [ + "CspFindingOrchestrator | undefined" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CspFinding.cloud", + "type": "Object", + "tags": [], + "label": "cloud", + "description": [], + "signature": [ + "CspFindingCloud | undefined" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CspFinding.result", + "type": "Object", + "tags": [], + "label": "result", + "description": [], + "signature": [ + "CspFindingResult" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CspFinding.resource", + "type": "Object", + "tags": [], + "label": "resource", + "description": [], + "signature": [ + "CspFindingResource" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CspFinding.rule", + "type": "Object", + "tags": [], + "label": "rule", + "description": [], + "signature": [ + "{ readonly impact?: string | undefined; readonly references?: string | undefined; readonly default_value?: string | undefined; readonly id: string; readonly version: string; readonly name: string; readonly tags: string[]; readonly description: string; readonly section: string; readonly audit: string; readonly benchmark: Readonly<{ posture_type?: \"kspm\" | \"cspm\" | undefined; rule_number?: string | undefined; } & { id: string; version: string; name: string; }>; readonly profile_applicability: string; readonly rationale: string; readonly rego_rule_id: string; readonly remediation: string; }" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CspFinding.host", + "type": "Object", + "tags": [], + "label": "host", + "description": [], + "signature": [ + "CspFindingHost" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CspFinding.event", + "type": "Object", + "tags": [], + "label": "event", + "description": [], + "signature": [ + "EcsEvent" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CspFinding.data_stream", + "type": "Object", + "tags": [], + "label": "data_stream", + "description": [], + "signature": [ + "EcsDataStream" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CspFinding.agent", + "type": "Object", + "tags": [], + "label": "agent", + "description": [], + "signature": [ + "CspFindingAgent" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CspFinding.ecs", + "type": "Object", + "tags": [], + "label": "ecs", + "description": [], + "signature": [ + "{ version: string; }" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.IndexDetails", + "type": "Interface", + "tags": [], + "label": "IndexDetails", + "description": [], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.IndexDetails.index", + "type": "string", + "tags": [], + "label": "index", + "description": [], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.IndexDetails.status", + "type": "CompoundType", + "tags": [], + "label": "status", + "description": [], + "signature": [ + "\"empty\" | \"not-empty\" | \"unprivileged\"" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.BenchmarksCisId", + "type": "Type", + "tags": [], + "label": "BenchmarksCisId", + "description": [], + "signature": [ + "\"cis_k8s\" | \"cis_azure\" | \"cis_aws\" | \"cis_eks\" | \"cis_gcp\"" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/benchmark.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CDR_LATEST_NATIVE_MISCONFIGURATIONS_INDEX_PATTERN", + "type": "string", + "tags": [], + "label": "CDR_LATEST_NATIVE_MISCONFIGURATIONS_INDEX_PATTERN", + "description": [], + "signature": [ + "\"logs-cloud_security_posture.findings_latest-default\"" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CDR_LATEST_THIRD_PARTY_MISCONFIGURATIONS_INDEX_PATTERN", + "type": "string", + "tags": [], + "label": "CDR_LATEST_THIRD_PARTY_MISCONFIGURATIONS_INDEX_PATTERN", + "description": [], + "signature": [ + "\"logs-*_latest_misconfigurations_cdr\"" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CDR_MISCONFIGURATIONS_INDEX_PATTERN", + "type": "string", + "tags": [], + "label": "CDR_MISCONFIGURATIONS_INDEX_PATTERN", + "description": [], + "path": "x-pack/packages/kbn-cloud-security-posture-common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CSP_GET_BENCHMARK_RULES_STATE_API_CURRENT_VERSION", + "type": "string", + "tags": [], + "label": "CSP_GET_BENCHMARK_RULES_STATE_API_CURRENT_VERSION", + "description": [], + "signature": [ + "\"1\"" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CSP_GET_BENCHMARK_RULES_STATE_ROUTE_PATH", + "type": "string", + "tags": [], + "label": "CSP_GET_BENCHMARK_RULES_STATE_ROUTE_PATH", + "description": [], + "signature": [ + "\"/internal/cloud_security_posture/rules/_get_states\"" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CSPM_POLICY_TEMPLATE", + "type": "string", + "tags": [], + "label": "CSPM_POLICY_TEMPLATE", + "description": [], + "signature": [ + "\"cspm\"" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CspSetupStatus", + "type": "Type", + "tags": [], + "label": "CspSetupStatus", + "description": [], + "signature": [ + { + "pluginId": "@kbn/cloud-security-posture-common", + "scope": "common", + "docId": "kibKbnCloudSecurityPostureCommonPluginApi", + "section": "def-common.BaseCspSetupStatus", + "text": "BaseCspSetupStatus" + } + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.CspStatusCode", + "type": "Type", + "tags": [], + "label": "CspStatusCode", + "description": [], + "signature": [ + "\"indexed\" | \"unprivileged\" | \"indexing\" | \"index-timeout\" | \"not-deployed\" | \"not-installed\" | \"waiting_for_results\"" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.IndexStatus", + "type": "Type", + "tags": [], + "label": "IndexStatus", + "description": [], + "signature": [ + "\"empty\" | \"not-empty\" | \"unprivileged\"" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/types/status.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.KSPM_POLICY_TEMPLATE", + "type": "string", + "tags": [], + "label": "KSPM_POLICY_TEMPLATE", + "description": [], + "signature": [ + "\"kspm\"" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.LATEST_FINDINGS_RETENTION_POLICY", + "type": "string", + "tags": [], + "label": "LATEST_FINDINGS_RETENTION_POLICY", + "description": [], + "signature": [ + "\"26h\"" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.MAX_FINDINGS_TO_LOAD", + "type": "number", + "tags": [], + "label": "MAX_FINDINGS_TO_LOAD", + "description": [], + "signature": [ + "500" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.STATUS_API_CURRENT_VERSION", + "type": "string", + "tags": [], + "label": "STATUS_API_CURRENT_VERSION", + "description": [], + "signature": [ + "\"1\"" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cloud-security-posture-common", + "id": "def-common.STATUS_ROUTE_PATH", + "type": "string", + "tags": [], + "label": "STATUS_ROUTE_PATH", + "description": [], + "signature": [ + "\"/internal/cloud_security_posture/status\"" + ], + "path": "x-pack/packages/kbn-cloud-security-posture-common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_cloud_security_posture_common.mdx b/api_docs/kbn_cloud_security_posture_common.mdx new file mode 100644 index 0000000000000..08aac5b54cf57 --- /dev/null +++ b/api_docs/kbn_cloud_security_posture_common.mdx @@ -0,0 +1,36 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnCloudSecurityPostureCommonPluginApi +slug: /kibana-dev-docs/api/kbn-cloud-security-posture-common +title: "@kbn/cloud-security-posture-common" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/cloud-security-posture-common plugin +date: 2024-08-29 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cloud-security-posture-common'] +--- +import kbnCloudSecurityPostureCommonObj from './kbn_cloud_security_posture_common.devdocs.json'; + + + +Contact [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 49 | 0 | 49 | 0 | + +## Common + +### Functions + + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_code_editor.mdx b/api_docs/kbn_code_editor.mdx index 85f1b3317f0f0..c2ed421dc1c53 100644 --- a/api_docs/kbn_code_editor.mdx +++ b/api_docs/kbn_code_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor title: "@kbn/code-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor'] --- import kbnCodeEditorObj from './kbn_code_editor.devdocs.json'; diff --git a/api_docs/kbn_code_editor_mock.mdx b/api_docs/kbn_code_editor_mock.mdx index ee54ac976c335..d7fa4bb3f7476 100644 --- a/api_docs/kbn_code_editor_mock.mdx +++ b/api_docs/kbn_code_editor_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor-mock title: "@kbn/code-editor-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor-mock plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor-mock'] --- import kbnCodeEditorMockObj from './kbn_code_editor_mock.devdocs.json'; diff --git a/api_docs/kbn_code_owners.mdx b/api_docs/kbn_code_owners.mdx index b284131e2e21a..926f78a9e34ae 100644 --- a/api_docs/kbn_code_owners.mdx +++ b/api_docs/kbn_code_owners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-owners title: "@kbn/code-owners" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-owners plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-owners'] --- import kbnCodeOwnersObj from './kbn_code_owners.devdocs.json'; diff --git a/api_docs/kbn_coloring.devdocs.json b/api_docs/kbn_coloring.devdocs.json index 16719bc0c8a0e..a1d23178234a6 100644 --- a/api_docs/kbn_coloring.devdocs.json +++ b/api_docs/kbn_coloring.devdocs.json @@ -1297,6 +1297,41 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/coloring", + "id": "def-common.getSpecialString", + "type": "Function", + "tags": [], + "label": "getSpecialString", + "description": [ + "\nReturns special string for sake of color mapping/syncing" + ], + "signature": [ + "(value: string) => string" + ], + "path": "packages/kbn-coloring/src/shared_components/color_mapping/color/rule_matching.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/coloring", + "id": "def-common.getSpecialString.$1", + "type": "string", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-coloring/src/shared_components/color_mapping/color/rule_matching.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/coloring", "id": "def-common.getStepValue", @@ -1817,6 +1852,111 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/coloring", + "id": "def-common.ColorMappingInputCategoricalData", + "type": "Interface", + "tags": [], + "label": "ColorMappingInputCategoricalData", + "description": [], + "path": "packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/coloring", + "id": "def-common.ColorMappingInputCategoricalData.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "\"categories\"" + ], + "path": "packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/coloring", + "id": "def-common.ColorMappingInputCategoricalData.categories", + "type": "Array", + "tags": [], + "label": "categories", + "description": [ + "an ORDERED array of categories rendered in the visualization" + ], + "signature": [ + "(string | string[])[]" + ], + "path": "packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/coloring", + "id": "def-common.ColorMappingInputContinuousData", + "type": "Interface", + "tags": [], + "label": "ColorMappingInputContinuousData", + "description": [], + "path": "packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/coloring", + "id": "def-common.ColorMappingInputContinuousData.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "\"ranges\"" + ], + "path": "packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/coloring", + "id": "def-common.ColorMappingInputContinuousData.min", + "type": "number", + "tags": [], + "label": "min", + "description": [], + "path": "packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/coloring", + "id": "def-common.ColorMappingInputContinuousData.max", + "type": "number", + "tags": [], + "label": "max", + "description": [], + "path": "packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/coloring", + "id": "def-common.ColorMappingInputContinuousData.bins", + "type": "number", + "tags": [], + "label": "bins", + "description": [], + "path": "packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/coloring", "id": "def-common.ColorMappingProps", @@ -1874,7 +2014,21 @@ "A data description of what needs to be colored" ], "signature": [ - "{ type: \"categories\"; categories: (string | string[])[]; } | { type: \"ranges\"; min: number; max: number; bins: number; }" + { + "pluginId": "@kbn/coloring", + "scope": "common", + "docId": "kibKbnColoringPluginApi", + "section": "def-common.ColorMappingInputCategoricalData", + "text": "ColorMappingInputCategoricalData" + }, + " | ", + { + "pluginId": "@kbn/coloring", + "scope": "common", + "docId": "kibKbnColoringPluginApi", + "section": "def-common.ColorMappingInputContinuousData", + "text": "ColorMappingInputContinuousData" + } ], "path": "packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx", "deprecated": false, @@ -2790,7 +2944,21 @@ "\nA configuration object that is required to populate correctly the visible categories\nor the ranges in the CategoricalColorMapping component" ], "signature": [ - "{ type: \"categories\"; categories: (string | string[])[]; } | { type: \"ranges\"; min: number; max: number; bins: number; }" + { + "pluginId": "@kbn/coloring", + "scope": "common", + "docId": "kibKbnColoringPluginApi", + "section": "def-common.ColorMappingInputCategoricalData", + "text": "ColorMappingInputCategoricalData" + }, + " | ", + { + "pluginId": "@kbn/coloring", + "scope": "common", + "docId": "kibKbnColoringPluginApi", + "section": "def-common.ColorMappingInputContinuousData", + "text": "ColorMappingInputContinuousData" + } ], "path": "packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx", "deprecated": false, @@ -3686,10 +3854,10 @@ }, { "parentPluginId": "@kbn/coloring", - "id": "def-common.SPECIAL_TOKENS_STRING_CONVERTION", + "id": "def-common.SPECIAL_TOKENS_STRING_CONVERSION", "type": "Object", "tags": [], - "label": "SPECIAL_TOKENS_STRING_CONVERTION", + "label": "SPECIAL_TOKENS_STRING_CONVERSION", "description": [], "signature": [ "Map" diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index acd67820e9cbf..d3a065b8dc211 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] --- import kbnColoringObj from './kbn_coloring.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 217 | 0 | 180 | 9 | +| 227 | 0 | 188 | 9 | ## Common diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index 2fbfe5daa0121..63a936f7e2366 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index 8520b4bb8e954..989543bcf19f9 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index ab0b8b39b7997..332adb157e365 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_editor.mdx b/api_docs/kbn_content_management_content_editor.mdx index 35107047deb46..e1bf511ecc5e4 100644 --- a/api_docs/kbn_content_management_content_editor.mdx +++ b/api_docs/kbn_content_management_content_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-editor title: "@kbn/content-management-content-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-editor plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-editor'] --- import kbnContentManagementContentEditorObj from './kbn_content_management_content_editor.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_insights_public.mdx b/api_docs/kbn_content_management_content_insights_public.mdx index 25b8de8994840..92696453da6fa 100644 --- a/api_docs/kbn_content_management_content_insights_public.mdx +++ b/api_docs/kbn_content_management_content_insights_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-insights-public title: "@kbn/content-management-content-insights-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-insights-public plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-insights-public'] --- import kbnContentManagementContentInsightsPublicObj from './kbn_content_management_content_insights_public.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_insights_server.mdx b/api_docs/kbn_content_management_content_insights_server.mdx index a91bfa36b7375..9b5d0fd8e1024 100644 --- a/api_docs/kbn_content_management_content_insights_server.mdx +++ b/api_docs/kbn_content_management_content_insights_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-insights-server title: "@kbn/content-management-content-insights-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-insights-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-insights-server'] --- import kbnContentManagementContentInsightsServerObj from './kbn_content_management_content_insights_server.devdocs.json'; diff --git a/api_docs/kbn_content_management_favorites_public.mdx b/api_docs/kbn_content_management_favorites_public.mdx index 6c125110686fe..e25533f713255 100644 --- a/api_docs/kbn_content_management_favorites_public.mdx +++ b/api_docs/kbn_content_management_favorites_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-favorites-public title: "@kbn/content-management-favorites-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-favorites-public plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-favorites-public'] --- import kbnContentManagementFavoritesPublicObj from './kbn_content_management_favorites_public.devdocs.json'; diff --git a/api_docs/kbn_content_management_favorites_server.mdx b/api_docs/kbn_content_management_favorites_server.mdx index c61ad339ebc0b..e26262cee9b9c 100644 --- a/api_docs/kbn_content_management_favorites_server.mdx +++ b/api_docs/kbn_content_management_favorites_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-favorites-server title: "@kbn/content-management-favorites-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-favorites-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-favorites-server'] --- import kbnContentManagementFavoritesServerObj from './kbn_content_management_favorites_server.devdocs.json'; diff --git a/api_docs/kbn_content_management_tabbed_table_list_view.mdx b/api_docs/kbn_content_management_tabbed_table_list_view.mdx index 6999daa312b6d..06d373073c96e 100644 --- a/api_docs/kbn_content_management_tabbed_table_list_view.mdx +++ b/api_docs/kbn_content_management_tabbed_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-tabbed-table-list-view title: "@kbn/content-management-tabbed-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-tabbed-table-list-view plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-tabbed-table-list-view'] --- import kbnContentManagementTabbedTableListViewObj from './kbn_content_management_tabbed_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view.mdx b/api_docs/kbn_content_management_table_list_view.mdx index 76046ecedaef1..7b30566e188b2 100644 --- a/api_docs/kbn_content_management_table_list_view.mdx +++ b/api_docs/kbn_content_management_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view title: "@kbn/content-management-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view'] --- import kbnContentManagementTableListViewObj from './kbn_content_management_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_common.mdx b/api_docs/kbn_content_management_table_list_view_common.mdx index e37e79687ed42..d6b55f4c778ea 100644 --- a/api_docs/kbn_content_management_table_list_view_common.mdx +++ b/api_docs/kbn_content_management_table_list_view_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-common title: "@kbn/content-management-table-list-view-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-common'] --- import kbnContentManagementTableListViewCommonObj from './kbn_content_management_table_list_view_common.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_table.mdx b/api_docs/kbn_content_management_table_list_view_table.mdx index 3681ee8831136..704e81d77e954 100644 --- a/api_docs/kbn_content_management_table_list_view_table.mdx +++ b/api_docs/kbn_content_management_table_list_view_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-table title: "@kbn/content-management-table-list-view-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-table plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-table'] --- import kbnContentManagementTableListViewTableObj from './kbn_content_management_table_list_view_table.devdocs.json'; diff --git a/api_docs/kbn_content_management_user_profiles.mdx b/api_docs/kbn_content_management_user_profiles.mdx index 8da1564b81135..324af8596e167 100644 --- a/api_docs/kbn_content_management_user_profiles.mdx +++ b/api_docs/kbn_content_management_user_profiles.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-user-profiles title: "@kbn/content-management-user-profiles" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-user-profiles plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-user-profiles'] --- import kbnContentManagementUserProfilesObj from './kbn_content_management_user_profiles.devdocs.json'; diff --git a/api_docs/kbn_content_management_utils.devdocs.json b/api_docs/kbn_content_management_utils.devdocs.json index 5ad26a1d86d38..fcff56097ad51 100644 --- a/api_docs/kbn_content_management_utils.devdocs.json +++ b/api_docs/kbn_content_management_utils.devdocs.json @@ -9,18 +9,10 @@ "objects": [] }, "server": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - }, - "common": { "classes": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage", + "id": "def-server.SOContentStorage", "type": "Class", "tags": [], "label": "SOContentStorage", @@ -28,9 +20,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOContentStorage", + "section": "def-server.SOContentStorage", "text": "SOContentStorage" }, " implements ", @@ -57,7 +49,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.Unnamed", + "id": "def-server.SOContentStorage.Unnamed", "type": "Function", "tags": [], "label": "Constructor", @@ -71,7 +63,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.Unnamed.$1", + "id": "def-server.SOContentStorage.Unnamed.$1", "type": "Object", "tags": [], "label": "{\n savedObjectType,\n cmServicesDefinition,\n createArgsToSoCreateOptions,\n updateArgsToSoUpdateOptions,\n searchArgsToSOFindOptions,\n enableMSearch,\n allowedSavedObjectAttributes,\n mSearchAdditionalSearchFields,\n logger,\n throwOnResultValidationError,\n }", @@ -79,9 +71,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOContentStorageConstructorParams", + "section": "def-server.SOContentStorageConstructorParams", "text": "SOContentStorageConstructorParams" }, "" @@ -96,7 +88,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.mSearch", + "id": "def-server.SOContentStorage.mSearch", "type": "Object", "tags": [], "label": "mSearch", @@ -126,7 +118,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.get", + "id": "def-server.SOContentStorage.get", "type": "Function", "tags": [], "label": "get", @@ -148,7 +140,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.get.$1", + "id": "def-server.SOContentStorage.get.$1", "type": "Object", "tags": [], "label": "ctx", @@ -169,7 +161,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.get.$2", + "id": "def-server.SOContentStorage.get.$2", "type": "string", "tags": [], "label": "id", @@ -187,7 +179,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.bulkGet", + "id": "def-server.SOContentStorage.bulkGet", "type": "Function", "tags": [], "label": "bulkGet", @@ -203,7 +195,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.create", + "id": "def-server.SOContentStorage.create", "type": "Function", "tags": [], "label": "create", @@ -225,7 +217,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.create.$1", + "id": "def-server.SOContentStorage.create.$1", "type": "Object", "tags": [], "label": "ctx", @@ -246,7 +238,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.create.$2", + "id": "def-server.SOContentStorage.create.$2", "type": "Uncategorized", "tags": [], "label": "data", @@ -261,7 +253,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.create.$3", + "id": "def-server.SOContentStorage.create.$3", "type": "Uncategorized", "tags": [], "label": "options", @@ -279,7 +271,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.update", + "id": "def-server.SOContentStorage.update", "type": "Function", "tags": [], "label": "update", @@ -301,7 +293,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.update.$1", + "id": "def-server.SOContentStorage.update.$1", "type": "Object", "tags": [], "label": "ctx", @@ -322,7 +314,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.update.$2", + "id": "def-server.SOContentStorage.update.$2", "type": "string", "tags": [], "label": "id", @@ -337,7 +329,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.update.$3", + "id": "def-server.SOContentStorage.update.$3", "type": "Uncategorized", "tags": [], "label": "data", @@ -352,7 +344,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.update.$4", + "id": "def-server.SOContentStorage.update.$4", "type": "Uncategorized", "tags": [], "label": "options", @@ -370,7 +362,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.delete", + "id": "def-server.SOContentStorage.delete", "type": "Function", "tags": [], "label": "delete", @@ -392,7 +384,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.delete.$1", + "id": "def-server.SOContentStorage.delete.$1", "type": "Object", "tags": [], "label": "ctx", @@ -413,7 +405,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.delete.$2", + "id": "def-server.SOContentStorage.delete.$2", "type": "string", "tags": [], "label": "id", @@ -428,7 +420,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.delete.$3", + "id": "def-server.SOContentStorage.delete.$3", "type": "Object", "tags": [], "label": "options", @@ -439,7 +431,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.delete.$3.force", + "id": "def-server.SOContentStorage.delete.$3.force", "type": "boolean", "tags": [], "label": "force", @@ -455,7 +447,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.search", + "id": "def-server.SOContentStorage.search", "type": "Function", "tags": [], "label": "search", @@ -485,7 +477,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.search.$1", + "id": "def-server.SOContentStorage.search.$1", "type": "Object", "tags": [], "label": "ctx", @@ -506,7 +498,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.search.$2", + "id": "def-server.SOContentStorage.search.$2", "type": "Object", "tags": [], "label": "query", @@ -527,7 +519,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorage.search.$3", + "id": "def-server.SOContentStorage.search.$3", "type": "Uncategorized", "tags": [], "label": "options", @@ -550,7 +542,7 @@ "functions": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.createArgsToSoCreateOptionsDefault", + "id": "def-server.createArgsToSoCreateOptionsDefault", "type": "Function", "tags": [], "label": "createArgsToSoCreateOptionsDefault", @@ -579,7 +571,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.createArgsToSoCreateOptionsDefault.$1", + "id": "def-server.createArgsToSoCreateOptionsDefault.$1", "type": "Object", "tags": [], "label": "params", @@ -604,7 +596,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.createResultSchema", + "id": "def-server.createResultSchema", "type": "Function", "tags": [], "label": "createResultSchema", @@ -642,7 +634,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.createResultSchema.$1", + "id": "def-server.createResultSchema.$1", "type": "Object", "tags": [], "label": "soSchema", @@ -668,7 +660,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.getMSearch", + "id": "def-server.getMSearch", "type": "Function", "tags": [], "label": "getMSearch", @@ -698,7 +690,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.getMSearch.$1", + "id": "def-server.getMSearch.$1", "type": "Object", "tags": [], "label": "{\n savedObjectType,\n cmServicesDefinition,\n allowedSavedObjectAttributes,\n}", @@ -717,7 +709,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.objectTypeToGetResultSchema", + "id": "def-server.objectTypeToGetResultSchema", "type": "Function", "tags": [], "label": "objectTypeToGetResultSchema", @@ -787,7 +779,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.objectTypeToGetResultSchema.$1", + "id": "def-server.objectTypeToGetResultSchema.$1", "type": "Object", "tags": [], "label": "soSchema", @@ -813,7 +805,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.savedObjectSchema", + "id": "def-server.savedObjectSchema", "type": "Function", "tags": [], "label": "savedObjectSchema", @@ -923,7 +915,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.savedObjectSchema.$1", + "id": "def-server.savedObjectSchema.$1", "type": "Object", "tags": [], "label": "attributesSchema", @@ -949,7 +941,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchArgsToSOFindOptionsDefault", + "id": "def-server.searchArgsToSOFindOptionsDefault", "type": "Function", "tags": [], "label": "searchArgsToSOFindOptionsDefault", @@ -966,9 +958,9 @@ ") => ", @@ -986,7 +978,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchArgsToSOFindOptionsDefault.$1", + "id": "def-server.searchArgsToSOFindOptionsDefault.$1", "type": "Object", "tags": [], "label": "params", @@ -1002,9 +994,9 @@ "" @@ -1020,7 +1012,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.tagsToFindOptions", + "id": "def-server.tagsToFindOptions", "type": "Function", "tags": [], "label": "tagsToFindOptions", @@ -1050,7 +1042,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.tagsToFindOptions.$1", + "id": "def-server.tagsToFindOptions.$1", "type": "Object", "tags": [], "label": "{\n included,\n excluded,\n}", @@ -1061,7 +1053,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.tagsToFindOptions.$1.included", + "id": "def-server.tagsToFindOptions.$1.included", "type": "Array", "tags": [], "label": "included", @@ -1075,7 +1067,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.tagsToFindOptions.$1.excluded", + "id": "def-server.tagsToFindOptions.$1.excluded", "type": "Array", "tags": [], "label": "excluded", @@ -1095,7 +1087,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.updateArgsToSoUpdateOptionsDefault", + "id": "def-server.updateArgsToSoUpdateOptionsDefault", "type": "Function", "tags": [], "label": "updateArgsToSoUpdateOptionsDefault", @@ -1104,9 +1096,9 @@ "(params: ", @@ -1133,7 +1125,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.updateArgsToSoUpdateOptionsDefault.$1", + "id": "def-server.updateArgsToSoUpdateOptionsDefault.$1", "type": "Object", "tags": [], "label": "params", @@ -1161,7 +1153,7 @@ "interfaces": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes", + "id": "def-server.CMCrudTypes", "type": "Interface", "tags": [], "label": "CMCrudTypes", @@ -1172,7 +1164,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes.Attributes", + "id": "def-server.CMCrudTypes.Attributes", "type": "Uncategorized", "tags": [], "label": "Attributes", @@ -1188,7 +1180,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes.Item", + "id": "def-server.CMCrudTypes.Item", "type": "Object", "tags": [], "label": "Item", @@ -1198,9 +1190,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "" @@ -1211,7 +1203,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes.PartialItem", + "id": "def-server.CMCrudTypes.PartialItem", "type": "CompoundType", "tags": [], "label": "PartialItem", @@ -1222,17 +1214,17 @@ "Omit<", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, ", \"attributes\" | \"references\"> & { attributes: object; references: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.Reference", + "section": "def-server.Reference", "text": "Reference" }, "[] | undefined; }" @@ -1243,7 +1235,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes.GetIn", + "id": "def-server.CMCrudTypes.GetIn", "type": "Object", "tags": [], "label": "GetIn", @@ -1266,7 +1258,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes.GetOut", + "id": "def-server.CMCrudTypes.GetOut", "type": "Object", "tags": [], "label": "GetOut", @@ -1277,9 +1269,9 @@ "{ item: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "; meta: { outcome: \"exactMatch\" | \"aliasMatch\" | \"conflict\"; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; }; }" @@ -1290,7 +1282,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes.CreateIn", + "id": "def-server.CMCrudTypes.CreateIn", "type": "Object", "tags": [], "label": "CreateIn", @@ -1313,7 +1305,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes.CreateOut", + "id": "def-server.CMCrudTypes.CreateOut", "type": "Object", "tags": [], "label": "CreateOut", @@ -1324,9 +1316,9 @@ "{ item: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "; meta?: undefined; }" @@ -1337,7 +1329,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes.CreateOptions", + "id": "def-server.CMCrudTypes.CreateOptions", "type": "Uncategorized", "tags": [], "label": "CreateOptions", @@ -1353,7 +1345,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes.SearchIn", + "id": "def-server.CMCrudTypes.SearchIn", "type": "Object", "tags": [], "label": "SearchIn", @@ -1376,7 +1368,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes.SearchOut", + "id": "def-server.CMCrudTypes.SearchOut", "type": "Object", "tags": [], "label": "SearchOut", @@ -1387,9 +1379,9 @@ "{ hits: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "[]; pagination: { total: number; cursor?: string | undefined; }; }" @@ -1400,7 +1392,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes.SearchOptions", + "id": "def-server.CMCrudTypes.SearchOptions", "type": "Uncategorized", "tags": [], "label": "SearchOptions", @@ -1416,7 +1408,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes.UpdateIn", + "id": "def-server.CMCrudTypes.UpdateIn", "type": "Object", "tags": [], "label": "UpdateIn", @@ -1439,7 +1431,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes.UpdateOut", + "id": "def-server.CMCrudTypes.UpdateOut", "type": "Object", "tags": [], "label": "UpdateOut", @@ -1450,9 +1442,9 @@ "{ item: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadataPartial", + "section": "def-server.SOWithMetadataPartial", "text": "SOWithMetadataPartial" }, "; meta?: undefined; }" @@ -1463,7 +1455,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes.UpdateOptions", + "id": "def-server.CMCrudTypes.UpdateOptions", "type": "Uncategorized", "tags": [], "label": "UpdateOptions", @@ -1479,7 +1471,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes.DeleteIn", + "id": "def-server.CMCrudTypes.DeleteIn", "type": "Object", "tags": [], "label": "DeleteIn", @@ -1502,7 +1494,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CMCrudTypes.DeleteOut", + "id": "def-server.CMCrudTypes.DeleteOut", "type": "Object", "tags": [], "label": "DeleteOut", @@ -1527,7 +1519,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes", + "id": "def-server.ContentManagementCrudTypes", "type": "Interface", "tags": [ "argument", @@ -1540,9 +1532,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.ContentManagementCrudTypes", + "section": "def-server.ContentManagementCrudTypes", "text": "ContentManagementCrudTypes" }, "" @@ -1553,7 +1545,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes.Attributes", + "id": "def-server.ContentManagementCrudTypes.Attributes", "type": "Uncategorized", "tags": [], "label": "Attributes", @@ -1567,7 +1559,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes.Item", + "id": "def-server.ContentManagementCrudTypes.Item", "type": "Object", "tags": [], "label": "Item", @@ -1577,9 +1569,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "" @@ -1590,7 +1582,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes.PartialItem", + "id": "def-server.ContentManagementCrudTypes.PartialItem", "type": "CompoundType", "tags": [], "label": "PartialItem", @@ -1601,17 +1593,17 @@ "Omit<", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, ", \"attributes\" | \"references\"> & { attributes: Partial; references: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.Reference", + "section": "def-server.Reference", "text": "Reference" }, "[] | undefined; }" @@ -1622,7 +1614,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes.CreateOptions", + "id": "def-server.ContentManagementCrudTypes.CreateOptions", "type": "Uncategorized", "tags": [], "label": "CreateOptions", @@ -1638,7 +1630,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes.UpdateOptions", + "id": "def-server.ContentManagementCrudTypes.UpdateOptions", "type": "Uncategorized", "tags": [], "label": "UpdateOptions", @@ -1654,7 +1646,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes.SearchOptions", + "id": "def-server.ContentManagementCrudTypes.SearchOptions", "type": "Uncategorized", "tags": [], "label": "SearchOptions", @@ -1670,7 +1662,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes.GetIn", + "id": "def-server.ContentManagementCrudTypes.GetIn", "type": "Object", "tags": [], "label": "GetIn", @@ -1693,7 +1685,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes.GetOut", + "id": "def-server.ContentManagementCrudTypes.GetOut", "type": "Object", "tags": [], "label": "GetOut", @@ -1704,9 +1696,9 @@ "{ item: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "; meta: { outcome: \"exactMatch\" | \"aliasMatch\" | \"conflict\"; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; }; }" @@ -1717,7 +1709,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes.CreateIn", + "id": "def-server.ContentManagementCrudTypes.CreateIn", "type": "Object", "tags": [], "label": "CreateIn", @@ -1740,7 +1732,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes.CreateOut", + "id": "def-server.ContentManagementCrudTypes.CreateOut", "type": "Object", "tags": [], "label": "CreateOut", @@ -1751,9 +1743,9 @@ "{ item: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "; meta?: undefined; }" @@ -1764,7 +1756,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes.SearchIn", + "id": "def-server.ContentManagementCrudTypes.SearchIn", "type": "Object", "tags": [], "label": "SearchIn", @@ -1787,7 +1779,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes.SearchOut", + "id": "def-server.ContentManagementCrudTypes.SearchOut", "type": "Object", "tags": [], "label": "SearchOut", @@ -1798,9 +1790,9 @@ "{ hits: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "[]; pagination: { total: number; cursor?: string | undefined; }; }" @@ -1811,7 +1803,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes.UpdateIn", + "id": "def-server.ContentManagementCrudTypes.UpdateIn", "type": "Object", "tags": [], "label": "UpdateIn", @@ -1834,7 +1826,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes.UpdateOut", + "id": "def-server.ContentManagementCrudTypes.UpdateOut", "type": "Object", "tags": [], "label": "UpdateOut", @@ -1845,9 +1837,9 @@ "{ item: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadataPartial", + "section": "def-server.SOWithMetadataPartial", "text": "SOWithMetadataPartial" }, "; meta?: undefined; }" @@ -1858,7 +1850,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes.DeleteIn", + "id": "def-server.ContentManagementCrudTypes.DeleteIn", "type": "Object", "tags": [], "label": "DeleteIn", @@ -1881,7 +1873,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ContentManagementCrudTypes.DeleteOut", + "id": "def-server.ContentManagementCrudTypes.DeleteOut", "type": "Object", "tags": [], "label": "DeleteOut", @@ -1906,7 +1898,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.GetMSearchType", + "id": "def-server.GetMSearchType", "type": "Interface", "tags": [], "label": "GetMSearchType", @@ -1914,9 +1906,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.GetMSearchType", + "section": "def-server.GetMSearchType", "text": "GetMSearchType" }, "" @@ -1927,7 +1919,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.GetMSearchType.savedObjectType", + "id": "def-server.GetMSearchType.savedObjectType", "type": "string", "tags": [], "label": "savedObjectType", @@ -1938,7 +1930,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.GetMSearchType.toItemResult", + "id": "def-server.GetMSearchType.toItemResult", "type": "Function", "tags": [], "label": "toItemResult", @@ -1968,7 +1960,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.GetMSearchType.toItemResult.$1", + "id": "def-server.GetMSearchType.toItemResult.$1", "type": "Object", "tags": [], "label": "ctx", @@ -1989,7 +1981,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.GetMSearchType.toItemResult.$2", + "id": "def-server.GetMSearchType.toItemResult.$2", "type": "Object", "tags": [], "label": "savedObject", @@ -2017,7 +2009,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.Reference", + "id": "def-server.Reference", "type": "Interface", "tags": [], "label": "Reference", @@ -2028,7 +2020,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.Reference.type", + "id": "def-server.Reference.type", "type": "string", "tags": [], "label": "type", @@ -2039,7 +2031,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.Reference.id", + "id": "def-server.Reference.id", "type": "string", "tags": [], "label": "id", @@ -2050,7 +2042,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.Reference.name", + "id": "def-server.Reference.name", "type": "string", "tags": [], "label": "name", @@ -2064,7 +2056,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectCreateOptions", + "id": "def-server.SavedObjectCreateOptions", "type": "Interface", "tags": [], "label": "SavedObjectCreateOptions", @@ -2077,7 +2069,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectCreateOptions.id", + "id": "def-server.SavedObjectCreateOptions.id", "type": "string", "tags": [], "label": "id", @@ -2093,7 +2085,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectCreateOptions.overwrite", + "id": "def-server.SavedObjectCreateOptions.overwrite", "type": "CompoundType", "tags": [], "label": "overwrite", @@ -2109,7 +2101,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectCreateOptions.version", + "id": "def-server.SavedObjectCreateOptions.version", "type": "string", "tags": [], "label": "version", @@ -2125,7 +2117,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectCreateOptions.references", + "id": "def-server.SavedObjectCreateOptions.references", "type": "Array", "tags": [], "label": "references", @@ -2135,9 +2127,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.Reference", + "section": "def-server.Reference", "text": "Reference" }, "[] | undefined" @@ -2148,7 +2140,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectCreateOptions.refresh", + "id": "def-server.SavedObjectCreateOptions.refresh", "type": "CompoundType", "tags": [], "label": "refresh", @@ -2164,7 +2156,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectCreateOptions.initialNamespaces", + "id": "def-server.SavedObjectCreateOptions.initialNamespaces", "type": "Array", "tags": [], "label": "initialNamespaces", @@ -2183,7 +2175,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions", + "id": "def-server.SavedObjectSearchOptions", "type": "Interface", "tags": [], "label": "SavedObjectSearchOptions", @@ -2196,7 +2188,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.page", + "id": "def-server.SavedObjectSearchOptions.page", "type": "number", "tags": [], "label": "page", @@ -2212,7 +2204,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.perPage", + "id": "def-server.SavedObjectSearchOptions.perPage", "type": "number", "tags": [], "label": "perPage", @@ -2228,7 +2220,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.sortField", + "id": "def-server.SavedObjectSearchOptions.sortField", "type": "string", "tags": [], "label": "sortField", @@ -2244,7 +2236,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.sortOrder", + "id": "def-server.SavedObjectSearchOptions.sortOrder", "type": "CompoundType", "tags": [], "label": "sortOrder", @@ -2261,7 +2253,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.fields", + "id": "def-server.SavedObjectSearchOptions.fields", "type": "Array", "tags": [], "label": "fields", @@ -2277,7 +2269,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.search", + "id": "def-server.SavedObjectSearchOptions.search", "type": "string", "tags": [], "label": "search", @@ -2293,7 +2285,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.searchFields", + "id": "def-server.SavedObjectSearchOptions.searchFields", "type": "Array", "tags": [], "label": "searchFields", @@ -2309,7 +2301,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.searchAfter", + "id": "def-server.SavedObjectSearchOptions.searchAfter", "type": "Array", "tags": [], "label": "searchAfter", @@ -2326,7 +2318,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.rootSearchFields", + "id": "def-server.SavedObjectSearchOptions.rootSearchFields", "type": "Array", "tags": [], "label": "rootSearchFields", @@ -2342,7 +2334,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.hasReference", + "id": "def-server.SavedObjectSearchOptions.hasReference", "type": "CompoundType", "tags": [], "label": "hasReference", @@ -2373,7 +2365,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.hasReferenceOperator", + "id": "def-server.SavedObjectSearchOptions.hasReferenceOperator", "type": "CompoundType", "tags": [], "label": "hasReferenceOperator", @@ -2389,7 +2381,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.hasNoReference", + "id": "def-server.SavedObjectSearchOptions.hasNoReference", "type": "CompoundType", "tags": [], "label": "hasNoReference", @@ -2420,7 +2412,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.hasNoReferenceOperator", + "id": "def-server.SavedObjectSearchOptions.hasNoReferenceOperator", "type": "CompoundType", "tags": [], "label": "hasNoReferenceOperator", @@ -2436,7 +2428,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.defaultSearchOperator", + "id": "def-server.SavedObjectSearchOptions.defaultSearchOperator", "type": "CompoundType", "tags": [], "label": "defaultSearchOperator", @@ -2452,7 +2444,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.filter", + "id": "def-server.SavedObjectSearchOptions.filter", "type": "Any", "tags": [], "label": "filter", @@ -2468,7 +2460,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.aggs", + "id": "def-server.SavedObjectSearchOptions.aggs", "type": "Object", "tags": [ "alpha" @@ -2488,7 +2480,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.namespaces", + "id": "def-server.SavedObjectSearchOptions.namespaces", "type": "Array", "tags": [], "label": "namespaces", @@ -2504,7 +2496,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectSearchOptions.pit", + "id": "def-server.SavedObjectSearchOptions.pit", "type": "Object", "tags": [], "label": "pit", @@ -2530,7 +2522,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectUpdateOptions", + "id": "def-server.SavedObjectUpdateOptions", "type": "Interface", "tags": [], "label": "SavedObjectUpdateOptions", @@ -2540,9 +2532,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SavedObjectUpdateOptions", + "section": "def-server.SavedObjectUpdateOptions", "text": "SavedObjectUpdateOptions" }, "" @@ -2553,7 +2545,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectUpdateOptions.references", + "id": "def-server.SavedObjectUpdateOptions.references", "type": "Array", "tags": [], "label": "references", @@ -2563,9 +2555,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.Reference", + "section": "def-server.Reference", "text": "Reference" }, "[] | undefined" @@ -2576,7 +2568,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectUpdateOptions.version", + "id": "def-server.SavedObjectUpdateOptions.version", "type": "string", "tags": [], "label": "version", @@ -2590,7 +2582,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectUpdateOptions.refresh", + "id": "def-server.SavedObjectUpdateOptions.refresh", "type": "CompoundType", "tags": [], "label": "refresh", @@ -2613,7 +2605,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectUpdateOptions.upsert", + "id": "def-server.SavedObjectUpdateOptions.upsert", "type": "Uncategorized", "tags": [], "label": "upsert", @@ -2629,7 +2621,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectUpdateOptions.retryOnConflict", + "id": "def-server.SavedObjectUpdateOptions.retryOnConflict", "type": "number", "tags": [], "label": "retryOnConflict", @@ -2645,7 +2637,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SavedObjectUpdateOptions.mergeAttributes", + "id": "def-server.SavedObjectUpdateOptions.mergeAttributes", "type": "CompoundType", "tags": [], "label": "mergeAttributes", @@ -2664,7 +2656,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SearchArgsToSOFindOptionsOptionsDefault", + "id": "def-server.SearchArgsToSOFindOptionsOptionsDefault", "type": "Interface", "tags": [], "label": "SearchArgsToSOFindOptionsOptionsDefault", @@ -2675,7 +2667,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SearchArgsToSOFindOptionsOptionsDefault.fields", + "id": "def-server.SearchArgsToSOFindOptionsOptionsDefault.fields", "type": "Array", "tags": [], "label": "fields", @@ -2689,7 +2681,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SearchArgsToSOFindOptionsOptionsDefault.searchFields", + "id": "def-server.SearchArgsToSOFindOptionsOptionsDefault.searchFields", "type": "Array", "tags": [], "label": "searchFields", @@ -2706,7 +2698,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ServicesDefinitionSet", + "id": "def-server.ServicesDefinitionSet", "type": "Interface", "tags": [], "label": "ServicesDefinitionSet", @@ -2717,7 +2709,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.ServicesDefinitionSet.Unnamed", + "id": "def-server.ServicesDefinitionSet.Unnamed", "type": "IndexSignature", "tags": [], "label": "[version: number]: ServicesDefinition", @@ -2741,7 +2733,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorageConstructorParams", + "id": "def-server.SOContentStorageConstructorParams", "type": "Interface", "tags": [], "label": "SOContentStorageConstructorParams", @@ -2749,9 +2741,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOContentStorageConstructorParams", + "section": "def-server.SOContentStorageConstructorParams", "text": "SOContentStorageConstructorParams" }, "" @@ -2762,7 +2754,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorageConstructorParams.savedObjectType", + "id": "def-server.SOContentStorageConstructorParams.savedObjectType", "type": "string", "tags": [], "label": "savedObjectType", @@ -2773,7 +2765,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorageConstructorParams.cmServicesDefinition", + "id": "def-server.SOContentStorageConstructorParams.cmServicesDefinition", "type": "Object", "tags": [], "label": "cmServicesDefinition", @@ -2781,9 +2773,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.ServicesDefinitionSet", + "section": "def-server.ServicesDefinitionSet", "text": "ServicesDefinitionSet" } ], @@ -2793,7 +2785,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorageConstructorParams.allowedSavedObjectAttributes", + "id": "def-server.SOContentStorageConstructorParams.allowedSavedObjectAttributes", "type": "Array", "tags": [], "label": "allowedSavedObjectAttributes", @@ -2807,7 +2799,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorageConstructorParams.createArgsToSoCreateOptions", + "id": "def-server.SOContentStorageConstructorParams.createArgsToSoCreateOptions", "type": "Function", "tags": [], "label": "createArgsToSoCreateOptions", @@ -2815,9 +2807,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.CreateArgsToSoCreateOptions", + "section": "def-server.CreateArgsToSoCreateOptions", "text": "CreateArgsToSoCreateOptions" }, " | undefined" @@ -2828,7 +2820,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorageConstructorParams.updateArgsToSoUpdateOptions", + "id": "def-server.SOContentStorageConstructorParams.updateArgsToSoUpdateOptions", "type": "Function", "tags": [], "label": "updateArgsToSoUpdateOptions", @@ -2836,9 +2828,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.UpdateArgsToSoUpdateOptions", + "section": "def-server.UpdateArgsToSoUpdateOptions", "text": "UpdateArgsToSoUpdateOptions" }, " | undefined" @@ -2849,7 +2841,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorageConstructorParams.searchArgsToSOFindOptions", + "id": "def-server.SOContentStorageConstructorParams.searchArgsToSOFindOptions", "type": "Function", "tags": [], "label": "searchArgsToSOFindOptions", @@ -2857,9 +2849,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SearchArgsToSOFindOptions", + "section": "def-server.SearchArgsToSOFindOptions", "text": "SearchArgsToSOFindOptions" }, " | undefined" @@ -2870,7 +2862,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorageConstructorParams.enableMSearch", + "id": "def-server.SOContentStorageConstructorParams.enableMSearch", "type": "CompoundType", "tags": [], "label": "enableMSearch", @@ -2886,7 +2878,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorageConstructorParams.mSearchAdditionalSearchFields", + "id": "def-server.SOContentStorageConstructorParams.mSearchAdditionalSearchFields", "type": "Array", "tags": [], "label": "mSearchAdditionalSearchFields", @@ -2900,7 +2892,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorageConstructorParams.logger", + "id": "def-server.SOContentStorageConstructorParams.logger", "type": "Object", "tags": [], "label": "logger", @@ -2920,7 +2912,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOContentStorageConstructorParams.throwOnResultValidationError", + "id": "def-server.SOContentStorageConstructorParams.throwOnResultValidationError", "type": "boolean", "tags": [], "label": "throwOnResultValidationError", @@ -2934,7 +2926,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOWithMetadata", + "id": "def-server.SOWithMetadata", "type": "Interface", "tags": [], "label": "SOWithMetadata", @@ -2944,9 +2936,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "" @@ -2957,7 +2949,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOWithMetadata.id", + "id": "def-server.SOWithMetadata.id", "type": "string", "tags": [], "label": "id", @@ -2968,7 +2960,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOWithMetadata.type", + "id": "def-server.SOWithMetadata.type", "type": "string", "tags": [], "label": "type", @@ -2979,7 +2971,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOWithMetadata.version", + "id": "def-server.SOWithMetadata.version", "type": "string", "tags": [], "label": "version", @@ -2993,7 +2985,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOWithMetadata.createdAt", + "id": "def-server.SOWithMetadata.createdAt", "type": "string", "tags": [], "label": "createdAt", @@ -3007,7 +2999,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOWithMetadata.updatedAt", + "id": "def-server.SOWithMetadata.updatedAt", "type": "string", "tags": [], "label": "updatedAt", @@ -3021,7 +3013,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOWithMetadata.createdBy", + "id": "def-server.SOWithMetadata.createdBy", "type": "string", "tags": [], "label": "createdBy", @@ -3035,7 +3027,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOWithMetadata.updatedBy", + "id": "def-server.SOWithMetadata.updatedBy", "type": "string", "tags": [], "label": "updatedBy", @@ -3049,7 +3041,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOWithMetadata.error", + "id": "def-server.SOWithMetadata.error", "type": "Object", "tags": [], "label": "error", @@ -3063,7 +3055,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOWithMetadata.managed", + "id": "def-server.SOWithMetadata.managed", "type": "CompoundType", "tags": [], "label": "managed", @@ -3077,7 +3069,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOWithMetadata.attributes", + "id": "def-server.SOWithMetadata.attributes", "type": "Uncategorized", "tags": [], "label": "attributes", @@ -3091,7 +3083,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOWithMetadata.references", + "id": "def-server.SOWithMetadata.references", "type": "Array", "tags": [], "label": "references", @@ -3099,9 +3091,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.Reference", + "section": "def-server.Reference", "text": "Reference" }, "[]" @@ -3112,7 +3104,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOWithMetadata.namespaces", + "id": "def-server.SOWithMetadata.namespaces", "type": "Array", "tags": [], "label": "namespaces", @@ -3126,7 +3118,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOWithMetadata.originId", + "id": "def-server.SOWithMetadata.originId", "type": "string", "tags": [], "label": "originId", @@ -3146,7 +3138,7 @@ "misc": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CreateArgsToSoCreateOptions", + "id": "def-server.CreateArgsToSoCreateOptions", "type": "Type", "tags": [], "label": "CreateArgsToSoCreateOptions", @@ -3168,7 +3160,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.CreateArgsToSoCreateOptions.$1", + "id": "def-server.CreateArgsToSoCreateOptions.$1", "type": "Uncategorized", "tags": [], "label": "params", @@ -3185,7 +3177,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.GetResultSO", + "id": "def-server.GetResultSO", "type": "Type", "tags": [], "label": "GetResultSO", @@ -3202,7 +3194,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SearchArgsToSOFindOptions", + "id": "def-server.SearchArgsToSOFindOptions", "type": "Type", "tags": [], "label": "SearchArgsToSOFindOptions", @@ -3224,7 +3216,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SearchArgsToSOFindOptions.$1", + "id": "def-server.SearchArgsToSOFindOptions.$1", "type": "Uncategorized", "tags": [], "label": "params", @@ -3241,7 +3233,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.SOWithMetadataPartial", + "id": "def-server.SOWithMetadataPartial", "type": "Type", "tags": [], "label": "SOWithMetadataPartial", @@ -3250,17 +3242,17 @@ "Omit<", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, ", \"attributes\" | \"references\"> & { attributes: Partial; references: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.Reference", + "section": "def-server.Reference", "text": "Reference" }, "[] | undefined; }" @@ -3272,7 +3264,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.UpdateArgsToSoUpdateOptions", + "id": "def-server.UpdateArgsToSoUpdateOptions", "type": "Type", "tags": [], "label": "UpdateArgsToSoUpdateOptions", @@ -3295,7 +3287,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.UpdateArgsToSoUpdateOptions.$1", + "id": "def-server.UpdateArgsToSoUpdateOptions.$1", "type": "Uncategorized", "tags": [], "label": "params", @@ -3314,7 +3306,7 @@ "objects": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.apiError", + "id": "def-server.apiError", "type": "Object", "tags": [], "label": "apiError", @@ -3368,7 +3360,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.createOptionsSchemas", + "id": "def-server.createOptionsSchemas", "type": "Object", "tags": [], "label": "createOptionsSchemas", @@ -3379,7 +3371,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.createOptionsSchemas.id", + "id": "def-server.createOptionsSchemas.id", "type": "Object", "tags": [], "label": "id", @@ -3400,7 +3392,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.createOptionsSchemas.references", + "id": "def-server.createOptionsSchemas.references", "type": "Object", "tags": [], "label": "references", @@ -3421,7 +3413,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.createOptionsSchemas.overwrite", + "id": "def-server.createOptionsSchemas.overwrite", "type": "Object", "tags": [], "label": "overwrite", @@ -3442,7 +3434,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.createOptionsSchemas.version", + "id": "def-server.createOptionsSchemas.version", "type": "Object", "tags": [], "label": "version", @@ -3463,7 +3455,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.createOptionsSchemas.refresh", + "id": "def-server.createOptionsSchemas.refresh", "type": "Object", "tags": [], "label": "refresh", @@ -3484,7 +3476,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.createOptionsSchemas.initialNamespaces", + "id": "def-server.createOptionsSchemas.initialNamespaces", "type": "Object", "tags": [], "label": "initialNamespaces", @@ -3508,7 +3500,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.referenceSchema", + "id": "def-server.referenceSchema", "type": "Object", "tags": [], "label": "referenceSchema", @@ -3554,7 +3546,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.referencesSchema", + "id": "def-server.referencesSchema", "type": "Object", "tags": [], "label": "referencesSchema", @@ -3576,7 +3568,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.schemaAndOr", + "id": "def-server.schemaAndOr", "type": "Object", "tags": [], "label": "schemaAndOr", @@ -3598,7 +3590,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas", + "id": "def-server.searchOptionsSchemas", "type": "Object", "tags": [], "label": "searchOptionsSchemas", @@ -3609,7 +3601,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.page", + "id": "def-server.searchOptionsSchemas.page", "type": "Object", "tags": [], "label": "page", @@ -3630,7 +3622,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.perPage", + "id": "def-server.searchOptionsSchemas.perPage", "type": "Object", "tags": [], "label": "perPage", @@ -3651,7 +3643,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.sortField", + "id": "def-server.searchOptionsSchemas.sortField", "type": "Object", "tags": [], "label": "sortField", @@ -3672,7 +3664,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.sortOrder", + "id": "def-server.searchOptionsSchemas.sortOrder", "type": "Object", "tags": [], "label": "sortOrder", @@ -3693,7 +3685,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.fields", + "id": "def-server.searchOptionsSchemas.fields", "type": "Object", "tags": [], "label": "fields", @@ -3714,7 +3706,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.search", + "id": "def-server.searchOptionsSchemas.search", "type": "Object", "tags": [], "label": "search", @@ -3735,7 +3727,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.searchFields", + "id": "def-server.searchOptionsSchemas.searchFields", "type": "Object", "tags": [], "label": "searchFields", @@ -3756,7 +3748,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.rootSearchFields", + "id": "def-server.searchOptionsSchemas.rootSearchFields", "type": "Object", "tags": [], "label": "rootSearchFields", @@ -3777,7 +3769,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.hasReference", + "id": "def-server.searchOptionsSchemas.hasReference", "type": "Object", "tags": [], "label": "hasReference", @@ -3798,7 +3790,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.hasReferenceOperator", + "id": "def-server.searchOptionsSchemas.hasReferenceOperator", "type": "Object", "tags": [], "label": "hasReferenceOperator", @@ -3819,7 +3811,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.hasNoReference", + "id": "def-server.searchOptionsSchemas.hasNoReference", "type": "Object", "tags": [], "label": "hasNoReference", @@ -3840,7 +3832,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.hasNoReferenceOperator", + "id": "def-server.searchOptionsSchemas.hasNoReferenceOperator", "type": "Object", "tags": [], "label": "hasNoReferenceOperator", @@ -3861,7 +3853,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.defaultSearchOperator", + "id": "def-server.searchOptionsSchemas.defaultSearchOperator", "type": "Object", "tags": [], "label": "defaultSearchOperator", @@ -3882,7 +3874,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.namespaces", + "id": "def-server.searchOptionsSchemas.namespaces", "type": "Object", "tags": [], "label": "namespaces", @@ -3903,7 +3895,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.type", + "id": "def-server.searchOptionsSchemas.type", "type": "Object", "tags": [], "label": "type", @@ -3924,7 +3916,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.filter", + "id": "def-server.searchOptionsSchemas.filter", "type": "Object", "tags": [], "label": "filter", @@ -3945,7 +3937,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.searchOptionsSchemas.pit", + "id": "def-server.searchOptionsSchemas.pit", "type": "Object", "tags": [], "label": "pit", @@ -3969,7 +3961,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.updateOptionsSchema", + "id": "def-server.updateOptionsSchema", "type": "Object", "tags": [], "label": "updateOptionsSchema", @@ -3980,7 +3972,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.updateOptionsSchema.references", + "id": "def-server.updateOptionsSchema.references", "type": "Object", "tags": [], "label": "references", @@ -4001,7 +3993,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.updateOptionsSchema.version", + "id": "def-server.updateOptionsSchema.version", "type": "Object", "tags": [], "label": "version", @@ -4022,7 +4014,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.updateOptionsSchema.refresh", + "id": "def-server.updateOptionsSchema.refresh", "type": "Object", "tags": [], "label": "refresh", @@ -4043,7 +4035,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.updateOptionsSchema.upsert", + "id": "def-server.updateOptionsSchema.upsert", "type": "Function", "tags": [], "label": "upsert", @@ -4073,7 +4065,7 @@ "children": [ { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.updateOptionsSchema.upsert.$1", + "id": "def-server.updateOptionsSchema.upsert.$1", "type": "Object", "tags": [], "label": "attributesSchema", @@ -4098,7 +4090,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.updateOptionsSchema.retryOnConflict", + "id": "def-server.updateOptionsSchema.retryOnConflict", "type": "Object", "tags": [], "label": "retryOnConflict", @@ -4119,7 +4111,7 @@ }, { "parentPluginId": "@kbn/content-management-utils", - "id": "def-common.updateOptionsSchema.mergeAttributes", + "id": "def-server.updateOptionsSchema.mergeAttributes", "type": "Object", "tags": [], "label": "mergeAttributes", @@ -4142,5 +4134,13 @@ "initialIsOpen": false } ] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] } } \ No newline at end of file diff --git a/api_docs/kbn_content_management_utils.mdx b/api_docs/kbn_content_management_utils.mdx index 4cb63afb92a40..15b4b43713a02 100644 --- a/api_docs/kbn_content_management_utils.mdx +++ b/api_docs/kbn_content_management_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-utils title: "@kbn/content-management-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-utils'] --- import kbnContentManagementUtilsObj from './kbn_content_management_utils.devdocs.json'; @@ -23,20 +23,20 @@ Contact [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/k |-------------------|-----------|------------------------|-----------------| | 195 | 1 | 128 | 0 | -## Common +## Server ### Objects - + ### Functions - + ### Classes - + ### Interfaces - + ### Consts, variables and types - + diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 78f7eb84efd71..56f247497ffda 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] --- import kbnCoreAnalyticsBrowserObj from './kbn_core_analytics_browser.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index abbefe10b46a9..ca63afd28d58e 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] --- import kbnCoreAnalyticsBrowserInternalObj from './kbn_core_analytics_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index 9b231d77175e5..9289e659e0218 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] --- import kbnCoreAnalyticsBrowserMocksObj from './kbn_core_analytics_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index a45480f32cc93..f0728061ebdc4 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] --- import kbnCoreAnalyticsServerObj from './kbn_core_analytics_server.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index 9ac1416eb37b8..5cb3b7a5d9602 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] --- import kbnCoreAnalyticsServerInternalObj from './kbn_core_analytics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index 5bc9d9db9e7e8..7f88ab68074c3 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] --- import kbnCoreAnalyticsServerMocksObj from './kbn_core_analytics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 81748a4eaf9da..7b3e3d50b1cd0 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser'] --- import kbnCoreApplicationBrowserObj from './kbn_core_application_browser.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_internal.mdx b/api_docs/kbn_core_application_browser_internal.mdx index 99e6f7ed95a38..644ecf90dc402 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-internal'] --- import kbnCoreApplicationBrowserInternalObj from './kbn_core_application_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_mocks.mdx b/api_docs/kbn_core_application_browser_mocks.mdx index 4ff1b45d2732a..cd545bdb88acb 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-mocks'] --- import kbnCoreApplicationBrowserMocksObj from './kbn_core_application_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_common.mdx b/api_docs/kbn_core_application_common.mdx index 90369a003db04..2199d5cdbe7f6 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-common'] --- import kbnCoreApplicationCommonObj from './kbn_core_application_common.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_internal.mdx b/api_docs/kbn_core_apps_browser_internal.mdx index 8b18bdd944c3b..b01ea07a6ccdc 100644 --- a/api_docs/kbn_core_apps_browser_internal.mdx +++ b/api_docs/kbn_core_apps_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-internal title: "@kbn/core-apps-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-internal'] --- import kbnCoreAppsBrowserInternalObj from './kbn_core_apps_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_mocks.mdx b/api_docs/kbn_core_apps_browser_mocks.mdx index b80bddb5b128c..02dd69d0b2538 100644 --- a/api_docs/kbn_core_apps_browser_mocks.mdx +++ b/api_docs/kbn_core_apps_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-mocks title: "@kbn/core-apps-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-mocks'] --- import kbnCoreAppsBrowserMocksObj from './kbn_core_apps_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_apps_server_internal.mdx b/api_docs/kbn_core_apps_server_internal.mdx index 0c2868074529e..f5dc067f67194 100644 --- a/api_docs/kbn_core_apps_server_internal.mdx +++ b/api_docs/kbn_core_apps_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-server-internal title: "@kbn/core-apps-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-server-internal'] --- import kbnCoreAppsServerInternalObj from './kbn_core_apps_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index b235d092cd2bd..b898ca85db4f8 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] --- import kbnCoreBaseBrowserMocksObj from './kbn_core_base_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index 64dfef98a4f3e..1a3ff723eb4e6 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] --- import kbnCoreBaseCommonObj from './kbn_core_base_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index 86ec2b57b7b67..7fc314639e1b1 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] --- import kbnCoreBaseServerInternalObj from './kbn_core_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index 4f2e8d28523ff..e59e47ccd1692 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] --- import kbnCoreBaseServerMocksObj from './kbn_core_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_browser_mocks.mdx b/api_docs/kbn_core_capabilities_browser_mocks.mdx index 52767b383d9c8..6cfcb6f94f6a4 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-browser-mocks'] --- import kbnCoreCapabilitiesBrowserMocksObj from './kbn_core_capabilities_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_common.mdx b/api_docs/kbn_core_capabilities_common.mdx index 6b5767a496834..6163030964d57 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-common'] --- import kbnCoreCapabilitiesCommonObj from './kbn_core_capabilities_common.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server.mdx b/api_docs/kbn_core_capabilities_server.mdx index 6c0a063c27065..9ab5d917ef407 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server'] --- import kbnCoreCapabilitiesServerObj from './kbn_core_capabilities_server.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server_mocks.mdx b/api_docs/kbn_core_capabilities_server_mocks.mdx index a1419417c6872..d9db907fadebe 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server-mocks'] --- import kbnCoreCapabilitiesServerMocksObj from './kbn_core_capabilities_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser.mdx b/api_docs/kbn_core_chrome_browser.mdx index 54eac3381fa00..f962a7241b4ca 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser'] --- import kbnCoreChromeBrowserObj from './kbn_core_chrome_browser.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser_mocks.mdx b/api_docs/kbn_core_chrome_browser_mocks.mdx index caa80ce744939..1292119a1058d 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser-mocks'] --- import kbnCoreChromeBrowserMocksObj from './kbn_core_chrome_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index 82991cfd78825..25d7622d4863a 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] --- import kbnCoreConfigServerInternalObj from './kbn_core_config_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser.mdx b/api_docs/kbn_core_custom_branding_browser.mdx index 850127c0c6951..cf55fa92654e6 100644 --- a/api_docs/kbn_core_custom_branding_browser.mdx +++ b/api_docs/kbn_core_custom_branding_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser title: "@kbn/core-custom-branding-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser'] --- import kbnCoreCustomBrandingBrowserObj from './kbn_core_custom_branding_browser.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_internal.mdx b/api_docs/kbn_core_custom_branding_browser_internal.mdx index 4a7a8dd051701..f98de8505e1f8 100644 --- a/api_docs/kbn_core_custom_branding_browser_internal.mdx +++ b/api_docs/kbn_core_custom_branding_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-internal title: "@kbn/core-custom-branding-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-internal'] --- import kbnCoreCustomBrandingBrowserInternalObj from './kbn_core_custom_branding_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_mocks.mdx b/api_docs/kbn_core_custom_branding_browser_mocks.mdx index b3271d594ffe6..65939649fc33e 100644 --- a/api_docs/kbn_core_custom_branding_browser_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-mocks title: "@kbn/core-custom-branding-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-mocks'] --- import kbnCoreCustomBrandingBrowserMocksObj from './kbn_core_custom_branding_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_common.mdx b/api_docs/kbn_core_custom_branding_common.mdx index 300f618e11429..0080504544aee 100644 --- a/api_docs/kbn_core_custom_branding_common.mdx +++ b/api_docs/kbn_core_custom_branding_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-common title: "@kbn/core-custom-branding-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-common'] --- import kbnCoreCustomBrandingCommonObj from './kbn_core_custom_branding_common.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server.mdx b/api_docs/kbn_core_custom_branding_server.mdx index 343244e747a0b..db45503be1298 100644 --- a/api_docs/kbn_core_custom_branding_server.mdx +++ b/api_docs/kbn_core_custom_branding_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server title: "@kbn/core-custom-branding-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server'] --- import kbnCoreCustomBrandingServerObj from './kbn_core_custom_branding_server.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_internal.mdx b/api_docs/kbn_core_custom_branding_server_internal.mdx index 4423046fa5028..1a7320779ebca 100644 --- a/api_docs/kbn_core_custom_branding_server_internal.mdx +++ b/api_docs/kbn_core_custom_branding_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-internal title: "@kbn/core-custom-branding-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-internal'] --- import kbnCoreCustomBrandingServerInternalObj from './kbn_core_custom_branding_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_mocks.mdx b/api_docs/kbn_core_custom_branding_server_mocks.mdx index 4dd709e997aaf..2ba409ecbdc6d 100644 --- a/api_docs/kbn_core_custom_branding_server_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-mocks title: "@kbn/core-custom-branding-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-mocks'] --- import kbnCoreCustomBrandingServerMocksObj from './kbn_core_custom_branding_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index af8c1e840fe65..31f59bfcad944 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser'] --- import kbnCoreDeprecationsBrowserObj from './kbn_core_deprecations_browser.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_internal.mdx b/api_docs/kbn_core_deprecations_browser_internal.mdx index f970fd5519df1..5f85d5883fe62 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-internal'] --- import kbnCoreDeprecationsBrowserInternalObj from './kbn_core_deprecations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_mocks.mdx b/api_docs/kbn_core_deprecations_browser_mocks.mdx index 5bc6fab00131a..dbf6d4b8c9c0f 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-mocks'] --- import kbnCoreDeprecationsBrowserMocksObj from './kbn_core_deprecations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_common.mdx b/api_docs/kbn_core_deprecations_common.mdx index f34c100d033d2..6905cc90e3c91 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-common'] --- import kbnCoreDeprecationsCommonObj from './kbn_core_deprecations_common.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server.mdx b/api_docs/kbn_core_deprecations_server.mdx index 8efa9cc15b783..ce189d907b6b8 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server'] --- import kbnCoreDeprecationsServerObj from './kbn_core_deprecations_server.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_internal.mdx b/api_docs/kbn_core_deprecations_server_internal.mdx index bd58da2512681..1586f020aca01 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-internal'] --- import kbnCoreDeprecationsServerInternalObj from './kbn_core_deprecations_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_mocks.mdx b/api_docs/kbn_core_deprecations_server_mocks.mdx index fd91a5d75ddcf..cf227eb174946 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-mocks'] --- import kbnCoreDeprecationsServerMocksObj from './kbn_core_deprecations_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index b3952c730cbd7..acce0aad66232 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] --- import kbnCoreDocLinksBrowserObj from './kbn_core_doc_links_browser.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index 4dc289ee83060..6920f677e82dc 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] --- import kbnCoreDocLinksBrowserMocksObj from './kbn_core_doc_links_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index a45de1f50f75c..2aecc91585752 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] --- import kbnCoreDocLinksServerObj from './kbn_core_doc_links_server.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index 25e1837f73ebe..57da52aa0718f 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] --- import kbnCoreDocLinksServerMocksObj from './kbn_core_doc_links_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx index 7dcb66bdfb339..33333bc8a8ccd 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-internal'] --- import kbnCoreElasticsearchClientServerInternalObj from './kbn_core_elasticsearch_client_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index f0873aeae9a46..2a121bf37e631 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index 5ffef6d967286..8362ef2eca044 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index 1210c31594e05..d0cb51210fba1 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index 47b6947eaa2c9..37929f5bde93e 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index fc49467aa290c..3904ae973f588 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] --- import kbnCoreEnvironmentServerInternalObj from './kbn_core_environment_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index 1ea2637231f60..1eeb489f401bd 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] --- import kbnCoreEnvironmentServerMocksObj from './kbn_core_environment_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index 6615011e3671e..849afd32c7594 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] --- import kbnCoreExecutionContextBrowserObj from './kbn_core_execution_context_browser.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index 8e08648a5df1e..9687209d71c51 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] --- import kbnCoreExecutionContextBrowserInternalObj from './kbn_core_execution_context_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index 43f43eb6e7c92..7e023b7c8e87f 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] --- import kbnCoreExecutionContextBrowserMocksObj from './kbn_core_execution_context_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index 0756d85c34738..2be170be56451 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] --- import kbnCoreExecutionContextCommonObj from './kbn_core_execution_context_common.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index 1af4fbadbb98b..2b91d0dbbd1d2 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] --- import kbnCoreExecutionContextServerObj from './kbn_core_execution_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index 3537972f3b5b9..eefdee2bed0df 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] --- import kbnCoreExecutionContextServerInternalObj from './kbn_core_execution_context_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index f6018a8997841..435deacf6d7c2 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] --- import kbnCoreExecutionContextServerMocksObj from './kbn_core_execution_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index 98c5b513b4ad7..a98faf2c038d7 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] --- import kbnCoreFatalErrorsBrowserObj from './kbn_core_fatal_errors_browser.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index ebbe78fb88e75..05a44f46b0649 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] --- import kbnCoreFatalErrorsBrowserMocksObj from './kbn_core_fatal_errors_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index 12684496d21aa..b142744f526d0 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser'] --- import kbnCoreHttpBrowserObj from './kbn_core_http_browser.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_internal.mdx b/api_docs/kbn_core_http_browser_internal.mdx index b67b829b28626..c29fb53cb87de 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-internal'] --- import kbnCoreHttpBrowserInternalObj from './kbn_core_http_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_mocks.mdx b/api_docs/kbn_core_http_browser_mocks.mdx index 2856c722ac306..7ddf92f8670b3 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-mocks'] --- import kbnCoreHttpBrowserMocksObj from './kbn_core_http_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_common.mdx b/api_docs/kbn_core_http_common.mdx index 877056537d0e1..c0e44f87fb8f6 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-common'] --- import kbnCoreHttpCommonObj from './kbn_core_http_common.devdocs.json'; diff --git a/api_docs/kbn_core_http_context_server_mocks.mdx b/api_docs/kbn_core_http_context_server_mocks.mdx index 40305d4076732..b2f801695bd2f 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-context-server-mocks'] --- import kbnCoreHttpContextServerMocksObj from './kbn_core_http_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_request_handler_context_server.mdx b/api_docs/kbn_core_http_request_handler_context_server.mdx index 72f125b8ea29d..8698e8700a9bf 100644 --- a/api_docs/kbn_core_http_request_handler_context_server.mdx +++ b/api_docs/kbn_core_http_request_handler_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-request-handler-context-server title: "@kbn/core-http-request-handler-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-request-handler-context-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-request-handler-context-server'] --- import kbnCoreHttpRequestHandlerContextServerObj from './kbn_core_http_request_handler_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server.mdx b/api_docs/kbn_core_http_resources_server.mdx index ed5ca78ddc8e8..4a9ffd9f5a486 100644 --- a/api_docs/kbn_core_http_resources_server.mdx +++ b/api_docs/kbn_core_http_resources_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server title: "@kbn/core-http-resources-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server'] --- import kbnCoreHttpResourcesServerObj from './kbn_core_http_resources_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_internal.mdx b/api_docs/kbn_core_http_resources_server_internal.mdx index e5947d81fd6c6..dfe1b75f1d512 100644 --- a/api_docs/kbn_core_http_resources_server_internal.mdx +++ b/api_docs/kbn_core_http_resources_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-internal title: "@kbn/core-http-resources-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-internal'] --- import kbnCoreHttpResourcesServerInternalObj from './kbn_core_http_resources_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_mocks.mdx b/api_docs/kbn_core_http_resources_server_mocks.mdx index 1f8db0d8a5648..c14f8e640f5e5 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.mdx +++ b/api_docs/kbn_core_http_resources_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-mocks title: "@kbn/core-http-resources-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-mocks'] --- import kbnCoreHttpResourcesServerMocksObj from './kbn_core_http_resources_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index 87de6afc3b871..267bef0eacf61 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index 0ff64e5fb2d77..a86012081af4a 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-mocks'] --- import kbnCoreHttpRouterServerMocksObj from './kbn_core_http_router_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_server.devdocs.json b/api_docs/kbn_core_http_server.devdocs.json index 8e5138f237f33..6f04acd9efdd4 100644 --- a/api_docs/kbn_core_http_server.devdocs.json +++ b/api_docs/kbn_core_http_server.devdocs.json @@ -3506,6 +3506,18 @@ "plugin": "usageCollection", "path": "src/plugins/usage_collection/server/routes/stats/stats.ts" }, + { + "plugin": "taskManager", + "path": "x-pack/plugins/task_manager/server/routes/health.ts" + }, + { + "plugin": "taskManager", + "path": "x-pack/plugins/task_manager/server/routes/background_task_utilization.ts" + }, + { + "plugin": "taskManager", + "path": "x-pack/plugins/task_manager/server/routes/metrics.ts" + }, { "plugin": "licensing", "path": "x-pack/plugins/licensing/server/routes/info.ts" @@ -3550,18 +3562,6 @@ "plugin": "spaces", "path": "x-pack/plugins/spaces/server/routes/api/internal/get_content_summary.ts" }, - { - "plugin": "taskManager", - "path": "x-pack/plugins/task_manager/server/routes/health.ts" - }, - { - "plugin": "taskManager", - "path": "x-pack/plugins/task_manager/server/routes/background_task_utilization.ts" - }, - { - "plugin": "taskManager", - "path": "x-pack/plugins/task_manager/server/routes/metrics.ts" - }, { "plugin": "security", "path": "x-pack/plugins/security/server/routes/api_keys/enabled.ts" @@ -15748,6 +15748,10 @@ "plugin": "canvas", "path": "x-pack/plugins/canvas/server/routes/workpad/import.ts" }, + { + "plugin": "canvas", + "path": "x-pack/plugins/canvas/server/routes/functions/functions.ts" + }, { "plugin": "telemetry", "path": "src/plugins/telemetry/server/routes/telemetry_opt_in_stats.ts" @@ -16176,6 +16180,10 @@ "plugin": "integrationAssistant", "path": "x-pack/plugins/integration_assistant/server/routes/pipeline_routes.ts" }, + { + "plugin": "integrationAssistant", + "path": "x-pack/plugins/integration_assistant/server/routes/analyze_logs_routes.ts" + }, { "plugin": "lists", "path": "x-pack/plugins/lists/server/routes/create_endpoint_list_item_route.ts" diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index 55da7f47659f9..216b0f2650245 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index c5bac179c2545..15c40600aad85 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] --- import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index 334266aa40623..6d79a75de9571 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] --- import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index 219e972879623..430909fbeb9b8 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] --- import kbnCoreI18nBrowserObj from './kbn_core_i18n_browser.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index 410e09d20f712..334e72f32f389 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] --- import kbnCoreI18nBrowserMocksObj from './kbn_core_i18n_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server.mdx b/api_docs/kbn_core_i18n_server.mdx index e842d03d48211..cb2ef3b21e97a 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server'] --- import kbnCoreI18nServerObj from './kbn_core_i18n_server.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_internal.mdx b/api_docs/kbn_core_i18n_server_internal.mdx index 1f1016f813882..d0122640c3b4d 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-internal'] --- import kbnCoreI18nServerInternalObj from './kbn_core_i18n_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_mocks.mdx b/api_docs/kbn_core_i18n_server_mocks.mdx index b4f5d3f18ba56..6ae5cd08528fe 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-mocks'] --- import kbnCoreI18nServerMocksObj from './kbn_core_i18n_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index b331240f986c8..2da1456d75879 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] --- import kbnCoreInjectedMetadataBrowserMocksObj from './kbn_core_injected_metadata_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_internal.mdx b/api_docs/kbn_core_integrations_browser_internal.mdx index 4abfafaac0fa8..f764c7ccd9401 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-internal'] --- import kbnCoreIntegrationsBrowserInternalObj from './kbn_core_integrations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_mocks.mdx b/api_docs/kbn_core_integrations_browser_mocks.mdx index 3d16fb52525e7..8c327ce9b6b9f 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-mocks'] --- import kbnCoreIntegrationsBrowserMocksObj from './kbn_core_integrations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index 2ac6ec6eec448..91f4d4c2c1b90 100644 --- a/api_docs/kbn_core_lifecycle_browser.mdx +++ b/api_docs/kbn_core_lifecycle_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser title: "@kbn/core-lifecycle-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser'] --- import kbnCoreLifecycleBrowserObj from './kbn_core_lifecycle_browser.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser_mocks.mdx b/api_docs/kbn_core_lifecycle_browser_mocks.mdx index 18faa4d7ee048..fd1f4165f2df9 100644 --- a/api_docs/kbn_core_lifecycle_browser_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser-mocks title: "@kbn/core-lifecycle-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser-mocks'] --- import kbnCoreLifecycleBrowserMocksObj from './kbn_core_lifecycle_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server.mdx b/api_docs/kbn_core_lifecycle_server.mdx index 4c178de68c5eb..add3289086a37 100644 --- a/api_docs/kbn_core_lifecycle_server.mdx +++ b/api_docs/kbn_core_lifecycle_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server title: "@kbn/core-lifecycle-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server'] --- import kbnCoreLifecycleServerObj from './kbn_core_lifecycle_server.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server_mocks.mdx b/api_docs/kbn_core_lifecycle_server_mocks.mdx index d1274781df178..70ef4c84dcea5 100644 --- a/api_docs/kbn_core_lifecycle_server_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server-mocks title: "@kbn/core-lifecycle-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server-mocks'] --- import kbnCoreLifecycleServerMocksObj from './kbn_core_lifecycle_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_browser_mocks.mdx b/api_docs/kbn_core_logging_browser_mocks.mdx index 42ef59d4e8fe9..7751b8612805f 100644 --- a/api_docs/kbn_core_logging_browser_mocks.mdx +++ b/api_docs/kbn_core_logging_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-browser-mocks title: "@kbn/core-logging-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-browser-mocks'] --- import kbnCoreLoggingBrowserMocksObj from './kbn_core_logging_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_common_internal.mdx b/api_docs/kbn_core_logging_common_internal.mdx index 77b4a8b95e19e..f0d55cd21685e 100644 --- a/api_docs/kbn_core_logging_common_internal.mdx +++ b/api_docs/kbn_core_logging_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-common-internal title: "@kbn/core-logging-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-common-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-common-internal'] --- import kbnCoreLoggingCommonInternalObj from './kbn_core_logging_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index 2cc392c023c13..4610200ab7f4c 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] --- import kbnCoreLoggingServerObj from './kbn_core_logging_server.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index 8ab79b655f46a..e70b9146fdc7b 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] --- import kbnCoreLoggingServerInternalObj from './kbn_core_logging_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index 5a7b43608a23d..8150eeb3b34dc 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] --- import kbnCoreLoggingServerMocksObj from './kbn_core_logging_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_internal.mdx b/api_docs/kbn_core_metrics_collectors_server_internal.mdx index 256b5c47368e7..cd5f2e4f9a42c 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-internal'] --- import kbnCoreMetricsCollectorsServerInternalObj from './kbn_core_metrics_collectors_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx index 53b94f64191be..10621cabbc820 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-mocks'] --- import kbnCoreMetricsCollectorsServerMocksObj from './kbn_core_metrics_collectors_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server.mdx b/api_docs/kbn_core_metrics_server.mdx index aed7cfbfdc30e..a9681cc5819d3 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server'] --- import kbnCoreMetricsServerObj from './kbn_core_metrics_server.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_internal.mdx b/api_docs/kbn_core_metrics_server_internal.mdx index d6b34efb368a3..94385934616e1 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-internal'] --- import kbnCoreMetricsServerInternalObj from './kbn_core_metrics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_mocks.mdx b/api_docs/kbn_core_metrics_server_mocks.mdx index a14d996e88b08..6ac70bdf8feb2 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-mocks'] --- import kbnCoreMetricsServerMocksObj from './kbn_core_metrics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_mount_utils_browser.mdx b/api_docs/kbn_core_mount_utils_browser.mdx index 4424eec6d6d88..e9ba06110dee3 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-mount-utils-browser'] --- import kbnCoreMountUtilsBrowserObj from './kbn_core_mount_utils_browser.devdocs.json'; diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index 38e3dec36efdf..3ef9a2ba20764 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] --- import kbnCoreNodeServerObj from './kbn_core_node_server.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index 7ba63fc4e4015..462894e9225d3 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] --- import kbnCoreNodeServerInternalObj from './kbn_core_node_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index 1d768b6e2654d..d84e43e11cddb 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] --- import kbnCoreNodeServerMocksObj from './kbn_core_node_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser.mdx b/api_docs/kbn_core_notifications_browser.mdx index dd6fa5f7be57e..29abf25a72a96 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser'] --- import kbnCoreNotificationsBrowserObj from './kbn_core_notifications_browser.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_internal.mdx b/api_docs/kbn_core_notifications_browser_internal.mdx index d74667afb522d..589145bfc6956 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-internal'] --- import kbnCoreNotificationsBrowserInternalObj from './kbn_core_notifications_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_mocks.mdx b/api_docs/kbn_core_notifications_browser_mocks.mdx index 64fd700def2a2..b3bedd4ff1ec9 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-mocks'] --- import kbnCoreNotificationsBrowserMocksObj from './kbn_core_notifications_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser.mdx b/api_docs/kbn_core_overlays_browser.mdx index 4134abee4f1ef..856aa43772b0b 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser'] --- import kbnCoreOverlaysBrowserObj from './kbn_core_overlays_browser.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_internal.mdx b/api_docs/kbn_core_overlays_browser_internal.mdx index ac0db52af91fa..54a5f4877415f 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-internal'] --- import kbnCoreOverlaysBrowserInternalObj from './kbn_core_overlays_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_mocks.mdx b/api_docs/kbn_core_overlays_browser_mocks.mdx index b890ce90ed3a0..356970549b5e8 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-mocks'] --- import kbnCoreOverlaysBrowserMocksObj from './kbn_core_overlays_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser.mdx b/api_docs/kbn_core_plugins_browser.mdx index 8dd9ac49ed57c..41c71210a45aa 100644 --- a/api_docs/kbn_core_plugins_browser.mdx +++ b/api_docs/kbn_core_plugins_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser title: "@kbn/core-plugins-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser'] --- import kbnCorePluginsBrowserObj from './kbn_core_plugins_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser_mocks.mdx b/api_docs/kbn_core_plugins_browser_mocks.mdx index 3890cf2b4f21f..d5b270192baef 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.mdx +++ b/api_docs/kbn_core_plugins_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser-mocks title: "@kbn/core-plugins-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser-mocks'] --- import kbnCorePluginsBrowserMocksObj from './kbn_core_plugins_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_contracts_browser.mdx b/api_docs/kbn_core_plugins_contracts_browser.mdx index cecf2378392fb..97afbbc2bc283 100644 --- a/api_docs/kbn_core_plugins_contracts_browser.mdx +++ b/api_docs/kbn_core_plugins_contracts_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-browser title: "@kbn/core-plugins-contracts-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-contracts-browser'] --- import kbnCorePluginsContractsBrowserObj from './kbn_core_plugins_contracts_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_contracts_server.mdx b/api_docs/kbn_core_plugins_contracts_server.mdx index d26af5c3ff7fb..4247aa3eaefdb 100644 --- a/api_docs/kbn_core_plugins_contracts_server.mdx +++ b/api_docs/kbn_core_plugins_contracts_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-server title: "@kbn/core-plugins-contracts-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-contracts-server'] --- import kbnCorePluginsContractsServerObj from './kbn_core_plugins_contracts_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index a4268ddcaf062..1653daaeb963e 100644 --- a/api_docs/kbn_core_plugins_server.mdx +++ b/api_docs/kbn_core_plugins_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server title: "@kbn/core-plugins-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server'] --- import kbnCorePluginsServerObj from './kbn_core_plugins_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server_mocks.mdx b/api_docs/kbn_core_plugins_server_mocks.mdx index f8c9730625e84..701f1f3a92ac3 100644 --- a/api_docs/kbn_core_plugins_server_mocks.mdx +++ b/api_docs/kbn_core_plugins_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server-mocks title: "@kbn/core-plugins-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server-mocks'] --- import kbnCorePluginsServerMocksObj from './kbn_core_plugins_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index cd0e0b68a49dc..18c0a7963f760 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server'] --- import kbnCorePrebootServerObj from './kbn_core_preboot_server.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server_mocks.mdx b/api_docs/kbn_core_preboot_server_mocks.mdx index 26ebc2421a387..ef81a023363c8 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] --- import kbnCorePrebootServerMocksObj from './kbn_core_preboot_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index 25a90fdc8d227..dd5fe30a0f3f0 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser-mocks'] --- import kbnCoreRenderingBrowserMocksObj from './kbn_core_rendering_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_internal.mdx b/api_docs/kbn_core_rendering_server_internal.mdx index 4ff5c77ce916e..e9e82932bff9c 100644 --- a/api_docs/kbn_core_rendering_server_internal.mdx +++ b/api_docs/kbn_core_rendering_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-internal title: "@kbn/core-rendering-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-internal'] --- import kbnCoreRenderingServerInternalObj from './kbn_core_rendering_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_mocks.mdx b/api_docs/kbn_core_rendering_server_mocks.mdx index ca449f755492b..1626a9c40107f 100644 --- a/api_docs/kbn_core_rendering_server_mocks.mdx +++ b/api_docs/kbn_core_rendering_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-mocks title: "@kbn/core-rendering-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-mocks'] --- import kbnCoreRenderingServerMocksObj from './kbn_core_rendering_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_root_server_internal.mdx b/api_docs/kbn_core_root_server_internal.mdx index fc30ca847bfd4..53dd770b22454 100644 --- a/api_docs/kbn_core_root_server_internal.mdx +++ b/api_docs/kbn_core_root_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-root-server-internal title: "@kbn/core-root-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-root-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-root-server-internal'] --- import kbnCoreRootServerInternalObj from './kbn_core_root_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index ec1da87fb3620..56a716f94c073 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index e9b0377c3c715..e781f01a07a94 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index ccc6a504fb80e..511f10dbafeec 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-mocks'] --- import kbnCoreSavedObjectsApiServerMocksObj from './kbn_core_saved_objects_api_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_internal.mdx b/api_docs/kbn_core_saved_objects_base_server_internal.mdx index d02f91af0efc3..2633d21c6e805 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-internal'] --- import kbnCoreSavedObjectsBaseServerInternalObj from './kbn_core_saved_objects_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx index d6de68dec8b87..fbb848e78eff8 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-mocks'] --- import kbnCoreSavedObjectsBaseServerMocksObj from './kbn_core_saved_objects_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index e925f5c58a09d..8f8553d6ffb0c 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser'] --- import kbnCoreSavedObjectsBrowserObj from './kbn_core_saved_objects_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_internal.mdx b/api_docs/kbn_core_saved_objects_browser_internal.mdx index bb5cdd9673a52..9530ba874caa8 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-internal'] --- import kbnCoreSavedObjectsBrowserInternalObj from './kbn_core_saved_objects_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_mocks.mdx b/api_docs/kbn_core_saved_objects_browser_mocks.mdx index 859044161ee5d..36da011dc2c6d 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.devdocs.json b/api_docs/kbn_core_saved_objects_common.devdocs.json index 12f98a813006b..aaef3b4e30c50 100644 --- a/api_docs/kbn_core_saved_objects_common.devdocs.json +++ b/api_docs/kbn_core_saved_objects_common.devdocs.json @@ -2004,19 +2004,19 @@ }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/utils.ts" + "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/utils.ts" + "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/utils.ts" + "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/utils.ts" + "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" }, { "plugin": "lens", @@ -2024,35 +2024,35 @@ }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" + "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.tsx" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" + "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.tsx" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" + "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.tsx" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/loader.ts" + "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.tsx" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.tsx" + "path": "x-pack/plugins/lens/public/utils.ts" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.tsx" + "path": "x-pack/plugins/lens/public/utils.ts" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.tsx" + "path": "x-pack/plugins/lens/public/utils.ts" }, { "plugin": "lens", - "path": "x-pack/plugins/lens/public/datasources/form_based/form_based.tsx" + "path": "x-pack/plugins/lens/public/utils.ts" }, { "plugin": "lens", diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index f11258261cb8d..8eba6577eb294 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-common'] --- import kbnCoreSavedObjectsCommonObj from './kbn_core_saved_objects_common.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx index b18c1ef66575a..c5539cd067718 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-internal'] --- import kbnCoreSavedObjectsImportExportServerInternalObj from './kbn_core_saved_objects_import_export_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx index a6287689c0aa9..9a1ec59ae1b2b 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index 601ada984a49f..00a946314aee1 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx index a84384a614463..751d35e01a656 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-mocks'] --- import kbnCoreSavedObjectsMigrationServerMocksObj from './kbn_core_saved_objects_migration_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server.devdocs.json b/api_docs/kbn_core_saved_objects_server.devdocs.json index e4e1ef0784aeb..9ebfadee68a64 100644 --- a/api_docs/kbn_core_saved_objects_server.devdocs.json +++ b/api_docs/kbn_core_saved_objects_server.devdocs.json @@ -10594,16 +10594,16 @@ "path": "packages/core/usage-data/core-usage-data-server-internal/src/saved_objects/core_usage_stats.ts" }, { - "plugin": "spaces", - "path": "x-pack/plugins/spaces/server/saved_objects/saved_objects_service.ts" + "plugin": "taskManager", + "path": "x-pack/plugins/task_manager/server/saved_objects/index.ts" }, { "plugin": "spaces", "path": "x-pack/plugins/spaces/server/saved_objects/saved_objects_service.ts" }, { - "plugin": "taskManager", - "path": "x-pack/plugins/task_manager/server/saved_objects/index.ts" + "plugin": "spaces", + "path": "x-pack/plugins/spaces/server/saved_objects/saved_objects_service.ts" }, { "plugin": "actions", diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index 623d97858eee7..35e42df96db25 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index ecd587fa487bb..a29a59ddaf646 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-internal'] --- import kbnCoreSavedObjectsServerInternalObj from './kbn_core_saved_objects_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_mocks.mdx b/api_docs/kbn_core_saved_objects_server_mocks.mdx index 6500015899b6c..6aac7635466f9 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-mocks'] --- import kbnCoreSavedObjectsServerMocksObj from './kbn_core_saved_objects_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_utils_server.mdx b/api_docs/kbn_core_saved_objects_utils_server.mdx index 7fb5702fe6d79..4cf16a777c894 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_security_browser.mdx b/api_docs/kbn_core_security_browser.mdx index 0c27a8397688a..e7c1ddade6b2d 100644 --- a/api_docs/kbn_core_security_browser.mdx +++ b/api_docs/kbn_core_security_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser title: "@kbn/core-security-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser'] --- import kbnCoreSecurityBrowserObj from './kbn_core_security_browser.devdocs.json'; diff --git a/api_docs/kbn_core_security_browser_internal.mdx b/api_docs/kbn_core_security_browser_internal.mdx index 8bc3c7ed935e8..4d2b0e5f58045 100644 --- a/api_docs/kbn_core_security_browser_internal.mdx +++ b/api_docs/kbn_core_security_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser-internal title: "@kbn/core-security-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser-internal'] --- import kbnCoreSecurityBrowserInternalObj from './kbn_core_security_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_security_browser_mocks.mdx b/api_docs/kbn_core_security_browser_mocks.mdx index 0d58383363544..905322c2a4c53 100644 --- a/api_docs/kbn_core_security_browser_mocks.mdx +++ b/api_docs/kbn_core_security_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser-mocks title: "@kbn/core-security-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser-mocks'] --- import kbnCoreSecurityBrowserMocksObj from './kbn_core_security_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_security_common.mdx b/api_docs/kbn_core_security_common.mdx index c70b857db551a..ac169ab4025d0 100644 --- a/api_docs/kbn_core_security_common.mdx +++ b/api_docs/kbn_core_security_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-common title: "@kbn/core-security-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-common'] --- import kbnCoreSecurityCommonObj from './kbn_core_security_common.devdocs.json'; diff --git a/api_docs/kbn_core_security_server.mdx b/api_docs/kbn_core_security_server.mdx index 45100b7f7459d..9d7e275ead0b2 100644 --- a/api_docs/kbn_core_security_server.mdx +++ b/api_docs/kbn_core_security_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server title: "@kbn/core-security-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server'] --- import kbnCoreSecurityServerObj from './kbn_core_security_server.devdocs.json'; diff --git a/api_docs/kbn_core_security_server_internal.mdx b/api_docs/kbn_core_security_server_internal.mdx index 4b74c9a28a5d9..c9367aac121fc 100644 --- a/api_docs/kbn_core_security_server_internal.mdx +++ b/api_docs/kbn_core_security_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server-internal title: "@kbn/core-security-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server-internal'] --- import kbnCoreSecurityServerInternalObj from './kbn_core_security_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_security_server_mocks.mdx b/api_docs/kbn_core_security_server_mocks.mdx index fddd1940b8528..c3186f03df986 100644 --- a/api_docs/kbn_core_security_server_mocks.mdx +++ b/api_docs/kbn_core_security_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server-mocks title: "@kbn/core-security-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server-mocks'] --- import kbnCoreSecurityServerMocksObj from './kbn_core_security_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index 1add8c563cd14..b3b82c6d0bf70 100644 --- a/api_docs/kbn_core_status_common.mdx +++ b/api_docs/kbn_core_status_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common title: "@kbn/core-status-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common'] --- import kbnCoreStatusCommonObj from './kbn_core_status_common.devdocs.json'; diff --git a/api_docs/kbn_core_status_common_internal.mdx b/api_docs/kbn_core_status_common_internal.mdx index 977a119ee22dd..94034fcf6bf98 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common-internal'] --- import kbnCoreStatusCommonInternalObj from './kbn_core_status_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server.mdx b/api_docs/kbn_core_status_server.mdx index f14a21281cd55..b2c0fa67337d6 100644 --- a/api_docs/kbn_core_status_server.mdx +++ b/api_docs/kbn_core_status_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server title: "@kbn/core-status-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server'] --- import kbnCoreStatusServerObj from './kbn_core_status_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_internal.mdx b/api_docs/kbn_core_status_server_internal.mdx index 7f933cef04d0f..b817f6521fec5 100644 --- a/api_docs/kbn_core_status_server_internal.mdx +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-internal title: "@kbn/core-status-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-internal'] --- import kbnCoreStatusServerInternalObj from './kbn_core_status_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_mocks.mdx b/api_docs/kbn_core_status_server_mocks.mdx index 0e1040e88f886..40434b27e53d8 100644 --- a/api_docs/kbn_core_status_server_mocks.mdx +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-mocks title: "@kbn/core-status-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-mocks'] --- import kbnCoreStatusServerMocksObj from './kbn_core_status_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx index 3c230369dabc6..1d9f275eaa77e 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-deprecations-getters'] --- import kbnCoreTestHelpersDeprecationsGettersObj from './kbn_core_test_helpers_deprecations_getters.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx index d548b5b3f6950..8797e269cd2b4 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] --- import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_kbn_server.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index 5864ba9c263ef..9f3517e0e5ef1 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.mdx +++ b/api_docs/kbn_core_test_helpers_kbn_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-kbn-server title: "@kbn/core-test-helpers-kbn-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-kbn-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-kbn-server'] --- import kbnCoreTestHelpersKbnServerObj from './kbn_core_test_helpers_kbn_server.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_model_versions.mdx b/api_docs/kbn_core_test_helpers_model_versions.mdx index 310c13b531f52..68bae7d10f25f 100644 --- a/api_docs/kbn_core_test_helpers_model_versions.mdx +++ b/api_docs/kbn_core_test_helpers_model_versions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-model-versions title: "@kbn/core-test-helpers-model-versions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-model-versions plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-model-versions'] --- import kbnCoreTestHelpersModelVersionsObj from './kbn_core_test_helpers_model_versions.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx index 9ad53365f8f8f..4519a3967cf38 100644 --- a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx +++ b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-so-type-serializer title: "@kbn/core-test-helpers-so-type-serializer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-so-type-serializer plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-so-type-serializer'] --- import kbnCoreTestHelpersSoTypeSerializerObj from './kbn_core_test_helpers_so_type_serializer.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_test_utils.mdx b/api_docs/kbn_core_test_helpers_test_utils.mdx index 480af28046991..0bb70f1211527 100644 --- a/api_docs/kbn_core_test_helpers_test_utils.mdx +++ b/api_docs/kbn_core_test_helpers_test_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-test-utils title: "@kbn/core-test-helpers-test-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-test-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-test-utils'] --- import kbnCoreTestHelpersTestUtilsObj from './kbn_core_test_helpers_test_utils.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index 89401bbaf4f88..e398e1802f7a5 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] --- import kbnCoreThemeBrowserObj from './kbn_core_theme_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index c2dc85da0bc2a..e0b6017f619ba 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] --- import kbnCoreThemeBrowserMocksObj from './kbn_core_theme_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser.mdx b/api_docs/kbn_core_ui_settings_browser.mdx index a4daf6a03b792..2edc8360ea37a 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] --- import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx index 2fb4050563b21..5e55c418c8bd3 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] --- import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx index 8fe61a5fd852d..f87403775f0e8 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] --- import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index 8ac665cc00b13..b9639f10680fc 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] --- import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server.mdx b/api_docs/kbn_core_ui_settings_server.mdx index b960f54080fa8..bc148124ff898 100644 --- a/api_docs/kbn_core_ui_settings_server.mdx +++ b/api_docs/kbn_core_ui_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server title: "@kbn/core-ui-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server'] --- import kbnCoreUiSettingsServerObj from './kbn_core_ui_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_internal.mdx b/api_docs/kbn_core_ui_settings_server_internal.mdx index 0909823486fd3..62f39e77143da 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.mdx +++ b/api_docs/kbn_core_ui_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-internal title: "@kbn/core-ui-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-internal'] --- import kbnCoreUiSettingsServerInternalObj from './kbn_core_ui_settings_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_mocks.mdx b/api_docs/kbn_core_ui_settings_server_mocks.mdx index d45fa251ca54a..d77a7b0453bbf 100644 --- a/api_docs/kbn_core_ui_settings_server_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-mocks title: "@kbn/core-ui-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-mocks'] --- import kbnCoreUiSettingsServerMocksObj from './kbn_core_ui_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index abc774274415d..39a2dfe21db4a 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index bc200cc7e5a5a..c408708fbc885 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-internal'] --- import kbnCoreUsageDataServerInternalObj from './kbn_core_usage_data_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_mocks.mdx b/api_docs/kbn_core_usage_data_server_mocks.mdx index 2eb282d66a231..cca3346d6aa7a 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_browser.mdx b/api_docs/kbn_core_user_profile_browser.mdx index f3b23040adfa2..25c456b828802 100644 --- a/api_docs/kbn_core_user_profile_browser.mdx +++ b/api_docs/kbn_core_user_profile_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser title: "@kbn/core-user-profile-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser'] --- import kbnCoreUserProfileBrowserObj from './kbn_core_user_profile_browser.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_browser_internal.mdx b/api_docs/kbn_core_user_profile_browser_internal.mdx index 3dbf7eadf3636..c3be4a1f1ec01 100644 --- a/api_docs/kbn_core_user_profile_browser_internal.mdx +++ b/api_docs/kbn_core_user_profile_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser-internal title: "@kbn/core-user-profile-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser-internal'] --- import kbnCoreUserProfileBrowserInternalObj from './kbn_core_user_profile_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_browser_mocks.mdx b/api_docs/kbn_core_user_profile_browser_mocks.mdx index 19f9c984b80a0..90b8bb4602bc3 100644 --- a/api_docs/kbn_core_user_profile_browser_mocks.mdx +++ b/api_docs/kbn_core_user_profile_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser-mocks title: "@kbn/core-user-profile-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser-mocks'] --- import kbnCoreUserProfileBrowserMocksObj from './kbn_core_user_profile_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_common.mdx b/api_docs/kbn_core_user_profile_common.mdx index ff4289de5ba4c..82b70a57bd727 100644 --- a/api_docs/kbn_core_user_profile_common.mdx +++ b/api_docs/kbn_core_user_profile_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-common title: "@kbn/core-user-profile-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-common'] --- import kbnCoreUserProfileCommonObj from './kbn_core_user_profile_common.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server.mdx b/api_docs/kbn_core_user_profile_server.mdx index 5e94d232e6e0a..68185206cd22e 100644 --- a/api_docs/kbn_core_user_profile_server.mdx +++ b/api_docs/kbn_core_user_profile_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server title: "@kbn/core-user-profile-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server'] --- import kbnCoreUserProfileServerObj from './kbn_core_user_profile_server.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server_internal.mdx b/api_docs/kbn_core_user_profile_server_internal.mdx index 243cce4ec3906..afe318c75ddd1 100644 --- a/api_docs/kbn_core_user_profile_server_internal.mdx +++ b/api_docs/kbn_core_user_profile_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server-internal title: "@kbn/core-user-profile-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server-internal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server-internal'] --- import kbnCoreUserProfileServerInternalObj from './kbn_core_user_profile_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server_mocks.mdx b/api_docs/kbn_core_user_profile_server_mocks.mdx index 2afc049d4af3a..0ec76e40f86e6 100644 --- a/api_docs/kbn_core_user_profile_server_mocks.mdx +++ b/api_docs/kbn_core_user_profile_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server-mocks title: "@kbn/core-user-profile-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server-mocks'] --- import kbnCoreUserProfileServerMocksObj from './kbn_core_user_profile_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server.mdx b/api_docs/kbn_core_user_settings_server.mdx index 2a99a186eb1e2..7dce73b50b0e7 100644 --- a/api_docs/kbn_core_user_settings_server.mdx +++ b/api_docs/kbn_core_user_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server title: "@kbn/core-user-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server'] --- import kbnCoreUserSettingsServerObj from './kbn_core_user_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server_mocks.mdx b/api_docs/kbn_core_user_settings_server_mocks.mdx index 1e21317615285..e44bfe3905db1 100644 --- a/api_docs/kbn_core_user_settings_server_mocks.mdx +++ b/api_docs/kbn_core_user_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server-mocks title: "@kbn/core-user-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server-mocks'] --- import kbnCoreUserSettingsServerMocksObj from './kbn_core_user_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index feca7186f57ab..cb4af6014f825 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] --- import kbnCryptoObj from './kbn_crypto.devdocs.json'; diff --git a/api_docs/kbn_crypto_browser.mdx b/api_docs/kbn_crypto_browser.mdx index 2727940f5d96a..d249a40ef932b 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_custom_icons.mdx b/api_docs/kbn_custom_icons.mdx index 7effa5043c39e..29fcff84d8b17 100644 --- a/api_docs/kbn_custom_icons.mdx +++ b/api_docs/kbn_custom_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-icons title: "@kbn/custom-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-icons plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-icons'] --- import kbnCustomIconsObj from './kbn_custom_icons.devdocs.json'; diff --git a/api_docs/kbn_custom_integrations.mdx b/api_docs/kbn_custom_integrations.mdx index 1d813af16a080..7336aeb870493 100644 --- a/api_docs/kbn_custom_integrations.mdx +++ b/api_docs/kbn_custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-integrations title: "@kbn/custom-integrations" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-integrations plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-integrations'] --- import kbnCustomIntegrationsObj from './kbn_custom_integrations.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index f5cf1e2c93a31..bf31146018ae3 100644 --- a/api_docs/kbn_cypress_config.mdx +++ b/api_docs/kbn_cypress_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cypress-config title: "@kbn/cypress-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cypress-config plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cypress-config'] --- import kbnCypressConfigObj from './kbn_cypress_config.devdocs.json'; diff --git a/api_docs/kbn_data_forge.mdx b/api_docs/kbn_data_forge.mdx index 3a34ca782dbd0..3b2fdf8b10992 100644 --- a/api_docs/kbn_data_forge.mdx +++ b/api_docs/kbn_data_forge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-forge title: "@kbn/data-forge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-forge plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-forge'] --- import kbnDataForgeObj from './kbn_data_forge.devdocs.json'; diff --git a/api_docs/kbn_data_service.mdx b/api_docs/kbn_data_service.mdx index 9b8a9c6d92707..57e1a538f8bfc 100644 --- a/api_docs/kbn_data_service.mdx +++ b/api_docs/kbn_data_service.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-service title: "@kbn/data-service" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-service plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-service'] --- import kbnDataServiceObj from './kbn_data_service.devdocs.json'; diff --git a/api_docs/kbn_data_stream_adapter.mdx b/api_docs/kbn_data_stream_adapter.mdx index ea492b42c41c9..e7382e3d09d2e 100644 --- a/api_docs/kbn_data_stream_adapter.mdx +++ b/api_docs/kbn_data_stream_adapter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-stream-adapter title: "@kbn/data-stream-adapter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-stream-adapter plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-stream-adapter'] --- import kbnDataStreamAdapterObj from './kbn_data_stream_adapter.devdocs.json'; diff --git a/api_docs/kbn_data_view_utils.mdx b/api_docs/kbn_data_view_utils.mdx index eb5f327efbba4..3d51cc8c8a260 100644 --- a/api_docs/kbn_data_view_utils.mdx +++ b/api_docs/kbn_data_view_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-view-utils title: "@kbn/data-view-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-view-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-view-utils'] --- import kbnDataViewUtilsObj from './kbn_data_view_utils.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index b3dee69a77a3c..887fec4110041 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_analytics.mdx b/api_docs/kbn_deeplinks_analytics.mdx index b2cc0651c36fd..108ad531828ba 100644 --- a/api_docs/kbn_deeplinks_analytics.mdx +++ b/api_docs/kbn_deeplinks_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-analytics title: "@kbn/deeplinks-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-analytics plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-analytics'] --- import kbnDeeplinksAnalyticsObj from './kbn_deeplinks_analytics.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_devtools.mdx b/api_docs/kbn_deeplinks_devtools.mdx index 8f87c878d9210..51e461117346d 100644 --- a/api_docs/kbn_deeplinks_devtools.mdx +++ b/api_docs/kbn_deeplinks_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-devtools title: "@kbn/deeplinks-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-devtools plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-devtools'] --- import kbnDeeplinksDevtoolsObj from './kbn_deeplinks_devtools.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_fleet.mdx b/api_docs/kbn_deeplinks_fleet.mdx index 36a785292f177..2d7e104007316 100644 --- a/api_docs/kbn_deeplinks_fleet.mdx +++ b/api_docs/kbn_deeplinks_fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-fleet title: "@kbn/deeplinks-fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-fleet plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-fleet'] --- import kbnDeeplinksFleetObj from './kbn_deeplinks_fleet.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_management.mdx b/api_docs/kbn_deeplinks_management.mdx index 403e1f990da63..6500dcff3976c 100644 --- a/api_docs/kbn_deeplinks_management.mdx +++ b/api_docs/kbn_deeplinks_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-management title: "@kbn/deeplinks-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-management plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-management'] --- import kbnDeeplinksManagementObj from './kbn_deeplinks_management.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_ml.mdx b/api_docs/kbn_deeplinks_ml.mdx index 3daff33862051..c87217e743f3a 100644 --- a/api_docs/kbn_deeplinks_ml.mdx +++ b/api_docs/kbn_deeplinks_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-ml title: "@kbn/deeplinks-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-ml plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-ml'] --- import kbnDeeplinksMlObj from './kbn_deeplinks_ml.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_observability.devdocs.json b/api_docs/kbn_deeplinks_observability.devdocs.json index 7379ba1cbcfca..8f071974422c8 100644 --- a/api_docs/kbn_deeplinks_observability.devdocs.json +++ b/api_docs/kbn_deeplinks_observability.devdocs.json @@ -22,18 +22,18 @@ "interfaces": [ { "parentPluginId": "@kbn/deeplinks-observability", - "id": "def-common.DataQualityLocatorParams", + "id": "def-common.DataQualityDetailsLocatorParams", "type": "Interface", "tags": [], - "label": "DataQualityLocatorParams", + "label": "DataQualityDetailsLocatorParams", "description": [], "signature": [ { "pluginId": "@kbn/deeplinks-observability", "scope": "common", "docId": "kibKbnDeeplinksObservabilityPluginApi", - "section": "def-common.DataQualityLocatorParams", - "text": "DataQualityLocatorParams" + "section": "def-common.DataQualityDetailsLocatorParams", + "text": "DataQualityDetailsLocatorParams" }, " extends ", { @@ -44,33 +44,103 @@ "text": "SerializableRecord" } ], - "path": "packages/deeplinks/observability/locators/dataset_quality.ts", + "path": "packages/deeplinks/observability/locators/dataset_quality_details.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/deeplinks-observability", - "id": "def-common.DataQualityLocatorParams.filters", + "id": "def-common.DataQualityDetailsLocatorParams.dataStream", + "type": "string", + "tags": [], + "label": "dataStream", + "description": [], + "path": "packages/deeplinks/observability/locators/dataset_quality_details.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/deeplinks-observability", + "id": "def-common.DataQualityDetailsLocatorParams.timeRange", "type": "Object", "tags": [], - "label": "filters", + "label": "timeRange", "description": [], "signature": [ - "Filters | undefined" + "TimeRangeConfig | undefined" ], - "path": "packages/deeplinks/observability/locators/dataset_quality.ts", + "path": "packages/deeplinks/observability/locators/dataset_quality_details.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "@kbn/deeplinks-observability", - "id": "def-common.DataQualityLocatorParams.flyout", + "id": "def-common.DataQualityDetailsLocatorParams.breakdownField", + "type": "string", + "tags": [], + "label": "breakdownField", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/deeplinks/observability/locators/dataset_quality_details.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/deeplinks-observability", + "id": "def-common.DataQualityDetailsLocatorParams.degradedFields", "type": "Object", "tags": [], - "label": "flyout", + "label": "degradedFields", "description": [], "signature": [ - "{ dataset: DatasetConfig; } | undefined" + "{ table?: DegradedFieldsTable | undefined; } | undefined" + ], + "path": "packages/deeplinks/observability/locators/dataset_quality_details.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/deeplinks-observability", + "id": "def-common.DataQualityLocatorParams", + "type": "Interface", + "tags": [], + "label": "DataQualityLocatorParams", + "description": [], + "signature": [ + { + "pluginId": "@kbn/deeplinks-observability", + "scope": "common", + "docId": "kibKbnDeeplinksObservabilityPluginApi", + "section": "def-common.DataQualityLocatorParams", + "text": "DataQualityLocatorParams" + }, + " extends ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.SerializableRecord", + "text": "SerializableRecord" + } + ], + "path": "packages/deeplinks/observability/locators/dataset_quality.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/deeplinks-observability", + "id": "def-common.DataQualityLocatorParams.filters", + "type": "Object", + "tags": [], + "label": "filters", + "description": [], + "signature": [ + "Filters | undefined" ], "path": "packages/deeplinks/observability/locators/dataset_quality.ts", "deprecated": false, @@ -766,6 +836,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/deeplinks-observability", + "id": "def-common.DATA_QUALITY_DETAILS_LOCATOR_ID", + "type": "string", + "tags": [], + "label": "DATA_QUALITY_DETAILS_LOCATOR_ID", + "description": [], + "signature": [ + "\"DATA_QUALITY_DETAILS_LOCATOR\"" + ], + "path": "packages/deeplinks/observability/locators/dataset_quality_details.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/deeplinks-observability", "id": "def-common.DATA_QUALITY_LOCATOR_ID", diff --git a/api_docs/kbn_deeplinks_observability.mdx b/api_docs/kbn_deeplinks_observability.mdx index 8b1f3f5648581..e43a9e71f1294 100644 --- a/api_docs/kbn_deeplinks_observability.mdx +++ b/api_docs/kbn_deeplinks_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-observability title: "@kbn/deeplinks-observability" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-observability plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-observability'] --- import kbnDeeplinksObservabilityObj from './kbn_deeplinks_observability.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 56 | 0 | 44 | 0 | +| 61 | 0 | 49 | 0 | ## Common diff --git a/api_docs/kbn_deeplinks_search.mdx b/api_docs/kbn_deeplinks_search.mdx index be9ae071f666a..c676b0d469ca3 100644 --- a/api_docs/kbn_deeplinks_search.mdx +++ b/api_docs/kbn_deeplinks_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-search title: "@kbn/deeplinks-search" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-search plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-search'] --- import kbnDeeplinksSearchObj from './kbn_deeplinks_search.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_security.mdx b/api_docs/kbn_deeplinks_security.mdx index 07313929d2152..ad19ad4ccae2c 100644 --- a/api_docs/kbn_deeplinks_security.mdx +++ b/api_docs/kbn_deeplinks_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-security title: "@kbn/deeplinks-security" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-security plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-security'] --- import kbnDeeplinksSecurityObj from './kbn_deeplinks_security.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_shared.mdx b/api_docs/kbn_deeplinks_shared.mdx index 98f500d49629e..3e527dacab04f 100644 --- a/api_docs/kbn_deeplinks_shared.mdx +++ b/api_docs/kbn_deeplinks_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-shared title: "@kbn/deeplinks-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-shared plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-shared'] --- import kbnDeeplinksSharedObj from './kbn_deeplinks_shared.devdocs.json'; diff --git a/api_docs/kbn_default_nav_analytics.mdx b/api_docs/kbn_default_nav_analytics.mdx index 0046e85e69576..3c56b9505a43d 100644 --- a/api_docs/kbn_default_nav_analytics.mdx +++ b/api_docs/kbn_default_nav_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-analytics title: "@kbn/default-nav-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-analytics plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-analytics'] --- import kbnDefaultNavAnalyticsObj from './kbn_default_nav_analytics.devdocs.json'; diff --git a/api_docs/kbn_default_nav_devtools.mdx b/api_docs/kbn_default_nav_devtools.mdx index e163e5e835c3c..830d9e4f50878 100644 --- a/api_docs/kbn_default_nav_devtools.mdx +++ b/api_docs/kbn_default_nav_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-devtools title: "@kbn/default-nav-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-devtools plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-devtools'] --- import kbnDefaultNavDevtoolsObj from './kbn_default_nav_devtools.devdocs.json'; diff --git a/api_docs/kbn_default_nav_management.mdx b/api_docs/kbn_default_nav_management.mdx index db8e105b37cf5..102d2da6dd73e 100644 --- a/api_docs/kbn_default_nav_management.mdx +++ b/api_docs/kbn_default_nav_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-management title: "@kbn/default-nav-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-management plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-management'] --- import kbnDefaultNavManagementObj from './kbn_default_nav_management.devdocs.json'; diff --git a/api_docs/kbn_default_nav_ml.mdx b/api_docs/kbn_default_nav_ml.mdx index e129fa1a192da..4f2c606a3e8a0 100644 --- a/api_docs/kbn_default_nav_ml.mdx +++ b/api_docs/kbn_default_nav_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-ml title: "@kbn/default-nav-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-ml plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-ml'] --- import kbnDefaultNavMlObj from './kbn_default_nav_ml.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index c832a66dda064..f026f10630fda 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] --- import kbnDevCliErrorsObj from './kbn_dev_cli_errors.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index 9d17daf67d863..2ff3b29a3dce7 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] --- import kbnDevCliRunnerObj from './kbn_dev_cli_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index 064fdc1dba74d..6b07b6dc419d6 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] --- import kbnDevProcRunnerObj from './kbn_dev_proc_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index 5a25941f17f75..2f63945e9989b 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_discover_utils.devdocs.json b/api_docs/kbn_discover_utils.devdocs.json index 6fdce1d53b5e2..1e985acf20643 100644 --- a/api_docs/kbn_discover_utils.devdocs.json +++ b/api_docs/kbn_discover_utils.devdocs.json @@ -817,6 +817,68 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/discover-utils", + "id": "def-common.getFieldValue", + "type": "Function", + "tags": [], + "label": "getFieldValue", + "description": [], + "signature": [ + "(record: ", + { + "pluginId": "@kbn/discover-utils", + "scope": "common", + "docId": "kibKbnDiscoverUtilsPluginApi", + "section": "def-common.DataTableRecord", + "text": "DataTableRecord" + }, + ", field: string) => any" + ], + "path": "packages/kbn-discover-utils/src/utils/get_field_value.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/discover-utils", + "id": "def-common.getFieldValue.$1", + "type": "Object", + "tags": [], + "label": "record", + "description": [], + "signature": [ + { + "pluginId": "@kbn/discover-utils", + "scope": "common", + "docId": "kibKbnDiscoverUtilsPluginApi", + "section": "def-common.DataTableRecord", + "text": "DataTableRecord" + } + ], + "path": "packages/kbn-discover-utils/src/utils/get_field_value.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/discover-utils", + "id": "def-common.getFieldValue.$2", + "type": "string", + "tags": [], + "label": "field", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-discover-utils/src/utils/get_field_value.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/discover-utils", "id": "def-common.getIgnoredReason", diff --git a/api_docs/kbn_discover_utils.mdx b/api_docs/kbn_discover_utils.mdx index e9e7da44ba4f7..05c729b9dff2d 100644 --- a/api_docs/kbn_discover_utils.mdx +++ b/api_docs/kbn_discover_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-discover-utils title: "@kbn/discover-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/discover-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/discover-utils'] --- import kbnDiscoverUtilsObj from './kbn_discover_utils.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 133 | 0 | 106 | 1 | +| 136 | 0 | 109 | 1 | ## Common diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 727523f24632e..6dd87a7d363e1 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index af9b82a99ccca..9d73c84cafacd 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_dom_drag_drop.devdocs.json b/api_docs/kbn_dom_drag_drop.devdocs.json index 434b89203c86e..4112bf83a67b0 100644 --- a/api_docs/kbn_dom_drag_drop.devdocs.json +++ b/api_docs/kbn_dom_drag_drop.devdocs.json @@ -159,7 +159,13 @@ ], "signature": [ "(props: ", - "DroppableProps", + { + "pluginId": "@kbn/dom-drag-drop", + "scope": "common", + "docId": "kibKbnDomDragDropPluginApi", + "section": "def-common.DroppableProps", + "text": "DroppableProps" + }, ") => JSX.Element" ], "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", @@ -174,7 +180,13 @@ "label": "props", "description": [], "signature": [ - "DroppableProps" + { + "pluginId": "@kbn/dom-drag-drop", + "scope": "common", + "docId": "kibKbnDomDragDropPluginApi", + "section": "def-common.DroppableProps", + "text": "DroppableProps" + } ], "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", "deprecated": false, @@ -528,6 +540,322 @@ } ], "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/dom-drag-drop", + "id": "def-common.DroppableProps", + "type": "Interface", + "tags": [], + "label": "DroppableProps", + "description": [ + "\nThe base props to the Droppable component." + ], + "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/dom-drag-drop", + "id": "def-common.DroppableProps.className", + "type": "string", + "tags": [], + "label": "className", + "description": [ + "\nThe CSS class(es) for the root element." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/dom-drag-drop", + "id": "def-common.DroppableProps.onDrop", + "type": "Function", + "tags": [], + "label": "onDrop", + "description": [ + "\nThe event handler that fires when an item\nis dropped onto this Droppable component." + ], + "signature": [ + "DropHandler", + " | undefined" + ], + "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/dom-drag-drop", + "id": "def-common.DroppableProps.value", + "type": "CompoundType", + "tags": [], + "label": "value", + "description": [ + "\nThe value associated with this item." + ], + "signature": [ + "Record & { id: string; humanData: ", + "HumanData", + "; }" + ], + "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/dom-drag-drop", + "id": "def-common.DroppableProps.children", + "type": "Object", + "tags": [], + "label": "children", + "description": [ + "\nThe React element which will be passed the draggable handlers" + ], + "signature": [ + "React.ReactElement>" + ], + "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/dom-drag-drop", + "id": "def-common.DroppableProps.isDisabled", + "type": "CompoundType", + "tags": [], + "label": "isDisabled", + "description": [ + "\nDisable any drag & drop behaviour" + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/dom-drag-drop", + "id": "def-common.DroppableProps.getAdditionalClassesOnEnter", + "type": "Function", + "tags": [], + "label": "getAdditionalClassesOnEnter", + "description": [ + "\nAdditional class names to apply when another element is over the drop target" + ], + "signature": [ + "((dropType?: ", + { + "pluginId": "@kbn/dom-drag-drop", + "scope": "common", + "docId": "kibKbnDomDragDropPluginApi", + "section": "def-common.DropType", + "text": "DropType" + }, + " | undefined) => string | undefined) | undefined" + ], + "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/dom-drag-drop", + "id": "def-common.DroppableProps.getAdditionalClassesOnEnter.$1", + "type": "CompoundType", + "tags": [], + "label": "dropType", + "description": [], + "signature": [ + { + "pluginId": "@kbn/dom-drag-drop", + "scope": "common", + "docId": "kibKbnDomDragDropPluginApi", + "section": "def-common.DropType", + "text": "DropType" + }, + " | undefined" + ], + "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/dom-drag-drop", + "id": "def-common.DroppableProps.getAdditionalClassesOnDroppable", + "type": "Function", + "tags": [], + "label": "getAdditionalClassesOnDroppable", + "description": [ + "\nAdditional class names to apply when another element is droppable for a currently dragged item" + ], + "signature": [ + "((dropType?: ", + { + "pluginId": "@kbn/dom-drag-drop", + "scope": "common", + "docId": "kibKbnDomDragDropPluginApi", + "section": "def-common.DropType", + "text": "DropType" + }, + " | undefined) => string | undefined) | undefined" + ], + "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/dom-drag-drop", + "id": "def-common.DroppableProps.getAdditionalClassesOnDroppable.$1", + "type": "CompoundType", + "tags": [], + "label": "dropType", + "description": [], + "signature": [ + { + "pluginId": "@kbn/dom-drag-drop", + "scope": "common", + "docId": "kibKbnDomDragDropPluginApi", + "section": "def-common.DropType", + "text": "DropType" + }, + " | undefined" + ], + "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/dom-drag-drop", + "id": "def-common.DroppableProps.dataTestSubj", + "type": "string", + "tags": [], + "label": "dataTestSubj", + "description": [ + "\nThe optional test subject associated with this DOM element." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/dom-drag-drop", + "id": "def-common.DroppableProps.reorderableGroup", + "type": "Array", + "tags": [], + "label": "reorderableGroup", + "description": [ + "\nitems belonging to the same group that can be reordered" + ], + "signature": [ + "{ id: string; }[] | undefined" + ], + "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/dom-drag-drop", + "id": "def-common.DroppableProps.dropTypes", + "type": "Array", + "tags": [], + "label": "dropTypes", + "description": [ + "\nIndicates the type of drop targets - when undefined, the currently dragged item\ncannot be dropped onto this component." + ], + "signature": [ + { + "pluginId": "@kbn/dom-drag-drop", + "scope": "common", + "docId": "kibKbnDomDragDropPluginApi", + "section": "def-common.DropType", + "text": "DropType" + }, + "[] | undefined" + ], + "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/dom-drag-drop", + "id": "def-common.DroppableProps.order", + "type": "Array", + "tags": [], + "label": "order", + "description": [ + "\nOrder for keyboard dragging. This takes an array of numbers which will be used to order hierarchically" + ], + "signature": [ + "number[]" + ], + "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/dom-drag-drop", + "id": "def-common.DroppableProps.getCustomDropTarget", + "type": "Function", + "tags": [], + "label": "getCustomDropTarget", + "description": [ + "\nExtra drop targets by dropType" + ], + "signature": [ + "((dropType: ", + { + "pluginId": "@kbn/dom-drag-drop", + "scope": "common", + "docId": "kibKbnDomDragDropPluginApi", + "section": "def-common.DropType", + "text": "DropType" + }, + ") => React.ReactElement> | null) | undefined" + ], + "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/dom-drag-drop", + "id": "def-common.DroppableProps.getCustomDropTarget.$1", + "type": "CompoundType", + "tags": [], + "label": "dropType", + "description": [], + "signature": [ + { + "pluginId": "@kbn/dom-drag-drop", + "scope": "common", + "docId": "kibKbnDomDragDropPluginApi", + "section": "def-common.DropType", + "text": "DropType" + } + ], + "path": "packages/kbn-dom-drag-drop/src/droppable.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false } ], "enums": [], diff --git a/api_docs/kbn_dom_drag_drop.mdx b/api_docs/kbn_dom_drag_drop.mdx index c37c010bc0f0b..16a5f8adc7c0e 100644 --- a/api_docs/kbn_dom_drag_drop.mdx +++ b/api_docs/kbn_dom_drag_drop.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dom-drag-drop title: "@kbn/dom-drag-drop" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dom-drag-drop plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dom-drag-drop'] --- import kbnDomDragDropObj from './kbn_dom_drag_drop.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 41 | 0 | 27 | 6 | +| 57 | 0 | 30 | 6 | ## Common diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index 78bb449ad9c28..bd1dd6c8245a5 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_ecs_data_quality_dashboard.devdocs.json b/api_docs/kbn_ecs_data_quality_dashboard.devdocs.json index 031d3c58d56f4..a74c5506b1f6a 100644 --- a/api_docs/kbn_ecs_data_quality_dashboard.devdocs.json +++ b/api_docs/kbn_ecs_data_quality_dashboard.devdocs.json @@ -159,6 +159,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/ecs-data-quality-dashboard", + "id": "def-public.ECS_FIELD_REFERENCE_URL", + "type": "string", + "tags": [], + "label": "ECS_FIELD_REFERENCE_URL", + "description": [], + "signature": [ + "\"https://www.elastic.co/guide/en/ecs/current/ecs-field-reference.html\"" + ], + "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/ecs-data-quality-dashboard", "id": "def-public.ECS_REFERENCE_URL", @@ -171,7 +186,7 @@ "signature": [ "\"https://www.elastic.co/guide/en/ecs/current/ecs-reference.html\"" ], - "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/markdown/helpers.ts", + "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/constants.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -204,6 +219,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/ecs-data-quality-dashboard", + "id": "def-public.MAPPING_URL", + "type": "string", + "tags": [], + "label": "MAPPING_URL", + "description": [], + "signature": [ + "\"https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html\"" + ], + "path": "x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/ecs-data-quality-dashboard", "id": "def-public.SELECT_ONE_OR_MORE_ILM_PHASES", diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index 116ac314da649..7592132923708 100644 --- a/api_docs/kbn_ecs_data_quality_dashboard.mdx +++ b/api_docs/kbn_ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs-data-quality-dashboard title: "@kbn/ecs-data-quality-dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs-data-quality-dashboard plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs-data-quality-dashboard'] --- import kbnEcsDataQualityDashboardObj from './kbn_ecs_data_quality_dashboard.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-threat-hunting-explore](https://github.com/orgs/elast | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 14 | 0 | 6 | 0 | +| 16 | 0 | 8 | 0 | ## Client diff --git a/api_docs/kbn_elastic_agent_utils.mdx b/api_docs/kbn_elastic_agent_utils.mdx index ecb8be31b9bb9..14ee67b0a5cd2 100644 --- a/api_docs/kbn_elastic_agent_utils.mdx +++ b/api_docs/kbn_elastic_agent_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-agent-utils title: "@kbn/elastic-agent-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-agent-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-agent-utils'] --- import kbnElasticAgentUtilsObj from './kbn_elastic_agent_utils.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant.mdx b/api_docs/kbn_elastic_assistant.mdx index 7b70f3b376749..a58f8d0928cdd 100644 --- a/api_docs/kbn_elastic_assistant.mdx +++ b/api_docs/kbn_elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant title: "@kbn/elastic-assistant" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant'] --- import kbnElasticAssistantObj from './kbn_elastic_assistant.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant_common.devdocs.json b/api_docs/kbn_elastic_assistant_common.devdocs.json index 22e41b3b3c6c7..b30a7523fd7fd 100644 --- a/api_docs/kbn_elastic_assistant_common.devdocs.json +++ b/api_docs/kbn_elastic_assistant_common.devdocs.json @@ -1169,7 +1169,7 @@ "label": "ChatCompleteProps", "description": [], "signature": [ - "{ connectorId: string; persist: boolean; messages: { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }[]; conversationId?: string | undefined; model?: string | undefined; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; responseLanguage?: string | undefined; promptId?: string | undefined; isStream?: boolean | undefined; }" + "{ connectorId: string; persist: boolean; messages: { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }[]; conversationId?: string | undefined; model?: string | undefined; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; promptId?: string | undefined; isStream?: boolean | undefined; responseLanguage?: string | undefined; }" ], "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/chat/post_chat_complete_route.gen.ts", "deprecated": false, @@ -1184,7 +1184,7 @@ "label": "ChatCompleteRequestBody", "description": [], "signature": [ - "{ connectorId: string; persist: boolean; messages: { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }[]; conversationId?: string | undefined; model?: string | undefined; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; responseLanguage?: string | undefined; promptId?: string | undefined; isStream?: boolean | undefined; }" + "{ connectorId: string; persist: boolean; messages: { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }[]; conversationId?: string | undefined; model?: string | undefined; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; promptId?: string | undefined; isStream?: boolean | undefined; responseLanguage?: string | undefined; }" ], "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/chat/post_chat_complete_route.gen.ts", "deprecated": false, @@ -1199,7 +1199,7 @@ "label": "ChatCompleteRequestBodyInput", "description": [], "signature": [ - "{ connectorId: string; persist: boolean; messages: { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }[]; conversationId?: string | undefined; model?: string | undefined; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; responseLanguage?: string | undefined; promptId?: string | undefined; isStream?: boolean | undefined; }" + "{ connectorId: string; persist: boolean; messages: { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }[]; conversationId?: string | undefined; model?: string | undefined; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; promptId?: string | undefined; isStream?: boolean | undefined; responseLanguage?: string | undefined; }" ], "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/chat/post_chat_complete_route.gen.ts", "deprecated": false, @@ -3738,7 +3738,7 @@ "label": "ChatCompleteProps", "description": [], "signature": [ - "Zod.ZodObject<{ conversationId: Zod.ZodOptional; promptId: Zod.ZodOptional; isStream: Zod.ZodOptional; responseLanguage: Zod.ZodOptional; langSmithProject: Zod.ZodOptional; langSmithApiKey: Zod.ZodOptional; connectorId: Zod.ZodString; model: Zod.ZodOptional; persist: Zod.ZodBoolean; messages: Zod.ZodArray; role: Zod.ZodEnum<[\"system\", \"user\", \"assistant\"]>; data: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\">>>; fields_to_anonymize: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }, { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }>, \"many\">; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; persist: boolean; messages: { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }[]; conversationId?: string | undefined; model?: string | undefined; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; responseLanguage?: string | undefined; promptId?: string | undefined; isStream?: boolean | undefined; }, { connectorId: string; persist: boolean; messages: { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }[]; conversationId?: string | undefined; model?: string | undefined; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; responseLanguage?: string | undefined; promptId?: string | undefined; isStream?: boolean | undefined; }>" + "Zod.ZodObject<{ conversationId: Zod.ZodOptional; promptId: Zod.ZodOptional; isStream: Zod.ZodOptional; responseLanguage: Zod.ZodOptional; langSmithProject: Zod.ZodOptional; langSmithApiKey: Zod.ZodOptional; connectorId: Zod.ZodString; model: Zod.ZodOptional; persist: Zod.ZodBoolean; messages: Zod.ZodArray; role: Zod.ZodEnum<[\"system\", \"user\", \"assistant\"]>; data: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\">>>; fields_to_anonymize: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }, { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }>, \"many\">; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; persist: boolean; messages: { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }[]; conversationId?: string | undefined; model?: string | undefined; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; promptId?: string | undefined; isStream?: boolean | undefined; responseLanguage?: string | undefined; }, { connectorId: string; persist: boolean; messages: { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }[]; conversationId?: string | undefined; model?: string | undefined; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; promptId?: string | undefined; isStream?: boolean | undefined; responseLanguage?: string | undefined; }>" ], "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/chat/post_chat_complete_route.gen.ts", "deprecated": false, @@ -3753,7 +3753,7 @@ "label": "ChatCompleteRequestBody", "description": [], "signature": [ - "Zod.ZodObject<{ conversationId: Zod.ZodOptional; promptId: Zod.ZodOptional; isStream: Zod.ZodOptional; responseLanguage: Zod.ZodOptional; langSmithProject: Zod.ZodOptional; langSmithApiKey: Zod.ZodOptional; connectorId: Zod.ZodString; model: Zod.ZodOptional; persist: Zod.ZodBoolean; messages: Zod.ZodArray; role: Zod.ZodEnum<[\"system\", \"user\", \"assistant\"]>; data: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\">>>; fields_to_anonymize: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }, { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }>, \"many\">; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; persist: boolean; messages: { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }[]; conversationId?: string | undefined; model?: string | undefined; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; responseLanguage?: string | undefined; promptId?: string | undefined; isStream?: boolean | undefined; }, { connectorId: string; persist: boolean; messages: { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }[]; conversationId?: string | undefined; model?: string | undefined; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; responseLanguage?: string | undefined; promptId?: string | undefined; isStream?: boolean | undefined; }>" + "Zod.ZodObject<{ conversationId: Zod.ZodOptional; promptId: Zod.ZodOptional; isStream: Zod.ZodOptional; responseLanguage: Zod.ZodOptional; langSmithProject: Zod.ZodOptional; langSmithApiKey: Zod.ZodOptional; connectorId: Zod.ZodString; model: Zod.ZodOptional; persist: Zod.ZodBoolean; messages: Zod.ZodArray; role: Zod.ZodEnum<[\"system\", \"user\", \"assistant\"]>; data: Zod.ZodOptional, Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\">>>; fields_to_anonymize: Zod.ZodOptional>; }, \"strip\", Zod.ZodTypeAny, { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }, { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }>, \"many\">; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; persist: boolean; messages: { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectOutputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }[]; conversationId?: string | undefined; model?: string | undefined; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; promptId?: string | undefined; isStream?: boolean | undefined; responseLanguage?: string | undefined; }, { connectorId: string; persist: boolean; messages: { role: \"user\" | \"system\" | \"assistant\"; data?: Zod.objectInputType<{}, Zod.ZodUnknown, \"strip\"> | undefined; content?: string | undefined; fields_to_anonymize?: string[] | undefined; }[]; conversationId?: string | undefined; model?: string | undefined; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; promptId?: string | undefined; isStream?: boolean | undefined; responseLanguage?: string | undefined; }>" ], "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/chat/post_chat_complete_route.gen.ts", "deprecated": false, diff --git a/api_docs/kbn_elastic_assistant_common.mdx b/api_docs/kbn_elastic_assistant_common.mdx index 7af819c876f97..40b5a9737edde 100644 --- a/api_docs/kbn_elastic_assistant_common.mdx +++ b/api_docs/kbn_elastic_assistant_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant-common title: "@kbn/elastic-assistant-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant-common'] --- import kbnElasticAssistantCommonObj from './kbn_elastic_assistant_common.devdocs.json'; diff --git a/api_docs/kbn_entities_schema.mdx b/api_docs/kbn_entities_schema.mdx index 92dc7af7432dc..d061a4db5ef9a 100644 --- a/api_docs/kbn_entities_schema.mdx +++ b/api_docs/kbn_entities_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-entities-schema title: "@kbn/entities-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/entities-schema plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/entities-schema'] --- import kbnEntitiesSchemaObj from './kbn_entities_schema.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index f59d42a818657..312883a2315b0 100644 --- a/api_docs/kbn_es.mdx +++ b/api_docs/kbn_es.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es title: "@kbn/es" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es'] --- import kbnEsObj from './kbn_es.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index a85cb56faac7e..b83e432f2f7b9 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] --- import kbnEsArchiverObj from './kbn_es_archiver.devdocs.json'; diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index 66b96f0831e53..5f3423c360629 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index 39290298bbf43..f3338830a9d0b 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_es_types.mdx b/api_docs/kbn_es_types.mdx index 7defc402c73ae..13b5133e0c8ff 100644 --- a/api_docs/kbn_es_types.mdx +++ b/api_docs/kbn_es_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-types title: "@kbn/es-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-types plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-types'] --- import kbnEsTypesObj from './kbn_es_types.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 4682902de18c0..1d64199a22c57 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_esql_ast.mdx b/api_docs/kbn_esql_ast.mdx index 37f59971731b8..f1c289674b475 100644 --- a/api_docs/kbn_esql_ast.mdx +++ b/api_docs/kbn_esql_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-ast title: "@kbn/esql-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-ast plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-ast'] --- import kbnEsqlAstObj from './kbn_esql_ast.devdocs.json'; diff --git a/api_docs/kbn_esql_utils.mdx b/api_docs/kbn_esql_utils.mdx index ceff3fc8ccc09..54625dca73133 100644 --- a/api_docs/kbn_esql_utils.mdx +++ b/api_docs/kbn_esql_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-utils title: "@kbn/esql-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-utils'] --- import kbnEsqlUtilsObj from './kbn_esql_utils.devdocs.json'; diff --git a/api_docs/kbn_esql_validation_autocomplete.devdocs.json b/api_docs/kbn_esql_validation_autocomplete.devdocs.json index 64858bc5fa7f7..11b9a155e213d 100644 --- a/api_docs/kbn_esql_validation_autocomplete.devdocs.json +++ b/api_docs/kbn_esql_validation_autocomplete.devdocs.json @@ -3193,7 +3193,7 @@ "label": "type", "description": [], "signature": [ - "\"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"version\" | \"integer\" | \"long\" | \"double\" | \"unsigned_long\" | \"cartesian_point\" | \"cartesian_shape\" | \"counter_integer\" | \"counter_long\" | \"counter_double\" | \"unsupported\"" + "\"boolean\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"keyword\" | \"text\" | \"date\" | \"date_nanos\" | \"version\" | \"integer\" | \"long\" | \"double\" | \"unsigned_long\" | \"unsupported\" | \"cartesian_point\" | \"cartesian_shape\" | \"counter_integer\" | \"counter_long\" | \"counter_double\"" ], "path": "packages/kbn-esql-validation-autocomplete/src/validation/types.ts", "deprecated": false, diff --git a/api_docs/kbn_esql_validation_autocomplete.mdx b/api_docs/kbn_esql_validation_autocomplete.mdx index 2ac95c4c555f1..76ee11fd354c3 100644 --- a/api_docs/kbn_esql_validation_autocomplete.mdx +++ b/api_docs/kbn_esql_validation_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-validation-autocomplete title: "@kbn/esql-validation-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-validation-autocomplete plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-validation-autocomplete'] --- import kbnEsqlValidationAutocompleteObj from './kbn_esql_validation_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_common.mdx b/api_docs/kbn_event_annotation_common.mdx index efac234b0c359..9aac9ed37881b 100644 --- a/api_docs/kbn_event_annotation_common.mdx +++ b/api_docs/kbn_event_annotation_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-common title: "@kbn/event-annotation-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-common'] --- import kbnEventAnnotationCommonObj from './kbn_event_annotation_common.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_components.devdocs.json b/api_docs/kbn_event_annotation_components.devdocs.json index b17e02bb66ce2..840ff9690d6ef 100644 --- a/api_docs/kbn_event_annotation_components.devdocs.json +++ b/api_docs/kbn_event_annotation_components.devdocs.json @@ -924,9 +924,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "<", diff --git a/api_docs/kbn_event_annotation_components.mdx b/api_docs/kbn_event_annotation_components.mdx index c6d229e10c886..41fb91f43ba94 100644 --- a/api_docs/kbn_event_annotation_components.mdx +++ b/api_docs/kbn_event_annotation_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-components title: "@kbn/event-annotation-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-components plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-components'] --- import kbnEventAnnotationComponentsObj from './kbn_event_annotation_components.devdocs.json'; diff --git a/api_docs/kbn_expandable_flyout.devdocs.json b/api_docs/kbn_expandable_flyout.devdocs.json index 88d40c2acec00..79c990355a921 100644 --- a/api_docs/kbn_expandable_flyout.devdocs.json +++ b/api_docs/kbn_expandable_flyout.devdocs.json @@ -140,6 +140,57 @@ "children": [], "returnComment": [], "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/expandable-flyout", + "id": "def-public.withExpandableFlyoutProvider", + "type": "Function", + "tags": [], + "label": "withExpandableFlyoutProvider", + "description": [], + "signature": [ + "(Component: React.ComponentType, expandableProviderProps?: ", + "ExpandableFlyoutContextProviderProps", + " | undefined) => (props: Props) => JSX.Element" + ], + "path": "packages/kbn-expandable-flyout/src/with_provider.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/expandable-flyout", + "id": "def-public.withExpandableFlyoutProvider.$1", + "type": "CompoundType", + "tags": [], + "label": "Component", + "description": [], + "signature": [ + "React.ComponentType" + ], + "path": "packages/kbn-expandable-flyout/src/with_provider.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/expandable-flyout", + "id": "def-public.withExpandableFlyoutProvider.$2", + "type": "Object", + "tags": [], + "label": "expandableProviderProps", + "description": [], + "signature": [ + "ExpandableFlyoutContextProviderProps", + " | undefined" + ], + "path": "packages/kbn-expandable-flyout/src/with_provider.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false } ], "interfaces": [ diff --git a/api_docs/kbn_expandable_flyout.mdx b/api_docs/kbn_expandable_flyout.mdx index 3b3bc618408ac..81fcd30e18036 100644 --- a/api_docs/kbn_expandable_flyout.mdx +++ b/api_docs/kbn_expandable_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-expandable-flyout title: "@kbn/expandable-flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/expandable-flyout plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/expandable-flyout'] --- import kbnExpandableFlyoutObj from './kbn_expandable_flyout.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-threat-hunting-investigations](https://github.com/org | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 39 | 0 | 14 | 1 | +| 42 | 0 | 17 | 2 | ## Client diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 6f95154559c0f..f12664ef7e9d6 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_field_utils.mdx b/api_docs/kbn_field_utils.mdx index 840b94c6099f2..fa45be6f73663 100644 --- a/api_docs/kbn_field_utils.mdx +++ b/api_docs/kbn_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-utils title: "@kbn/field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-utils'] --- import kbnFieldUtilsObj from './kbn_field_utils.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index c6792527501e6..0b77115186b5e 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_formatters.mdx b/api_docs/kbn_formatters.mdx index 975f0d8b3d26c..be551c8703ff6 100644 --- a/api_docs/kbn_formatters.mdx +++ b/api_docs/kbn_formatters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-formatters title: "@kbn/formatters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/formatters plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/formatters'] --- import kbnFormattersObj from './kbn_formatters.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index 9c4ce7cd1354f..1a37a1335b980 100644 --- a/api_docs/kbn_ftr_common_functional_services.mdx +++ b/api_docs/kbn_ftr_common_functional_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-services title: "@kbn/ftr-common-functional-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-services plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_ui_services.mdx b/api_docs/kbn_ftr_common_functional_ui_services.mdx index cfebddd016b50..cfae6be4c1932 100644 --- a/api_docs/kbn_ftr_common_functional_ui_services.mdx +++ b/api_docs/kbn_ftr_common_functional_ui_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-ui-services title: "@kbn/ftr-common-functional-ui-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-ui-services plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-ui-services'] --- import kbnFtrCommonFunctionalUiServicesObj from './kbn_ftr_common_functional_ui_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index b2e6edad7e89d..e0039da0d056f 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_generate_console_definitions.mdx b/api_docs/kbn_generate_console_definitions.mdx index c6d1d68f7a327..b0eb1280b84df 100644 --- a/api_docs/kbn_generate_console_definitions.mdx +++ b/api_docs/kbn_generate_console_definitions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-console-definitions title: "@kbn/generate-console-definitions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-console-definitions plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-console-definitions'] --- import kbnGenerateConsoleDefinitionsObj from './kbn_generate_console_definitions.devdocs.json'; diff --git a/api_docs/kbn_generate_csv.mdx b/api_docs/kbn_generate_csv.mdx index 1464998937fe7..04ae953662bd8 100644 --- a/api_docs/kbn_generate_csv.mdx +++ b/api_docs/kbn_generate_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-csv title: "@kbn/generate-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-csv plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv'] --- import kbnGenerateCsvObj from './kbn_generate_csv.devdocs.json'; diff --git a/api_docs/kbn_grid_layout.mdx b/api_docs/kbn_grid_layout.mdx index d0c7b1be21c63..2648e8ad46c4a 100644 --- a/api_docs/kbn_grid_layout.mdx +++ b/api_docs/kbn_grid_layout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-grid-layout title: "@kbn/grid-layout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/grid-layout plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/grid-layout'] --- import kbnGridLayoutObj from './kbn_grid_layout.devdocs.json'; diff --git a/api_docs/kbn_grouping.devdocs.json b/api_docs/kbn_grouping.devdocs.json index be6c1495f9a0b..545bf1de1263c 100644 --- a/api_docs/kbn_grouping.devdocs.json +++ b/api_docs/kbn_grouping.devdocs.json @@ -108,7 +108,9 @@ "\nHook to configure grouping component" ], "signature": [ - "({ componentProps, defaultGroupingOptions, fields, groupingId, maxGroupingLevels, onGroupChange, onOptionsChange, tracker, title, }: GroupingArgs) => ", + "({ componentProps, defaultGroupingOptions, fields, groupingId, maxGroupingLevels, onGroupChange, onOptionsChange, tracker, title, }: ", + "GroupingArgs", + ") => ", "UseGrouping", "" ], @@ -124,7 +126,8 @@ "label": "{\n componentProps,\n defaultGroupingOptions,\n fields,\n groupingId,\n maxGroupingLevels,\n onGroupChange,\n onOptionsChange,\n tracker,\n title,\n}", "description": [], "signature": [ - "GroupingArgs" + "GroupingArgs", + "" ], "path": "packages/kbn-grouping/src/hooks/use_grouping.tsx", "deprecated": false, diff --git a/api_docs/kbn_grouping.mdx b/api_docs/kbn_grouping.mdx index e7e86425d091f..77c8c2d539cf4 100644 --- a/api_docs/kbn_grouping.mdx +++ b/api_docs/kbn_grouping.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-grouping title: "@kbn/grouping" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/grouping plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/grouping'] --- import kbnGroupingObj from './kbn_grouping.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-o | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 17 | 0 | 12 | 10 | +| 17 | 0 | 12 | 11 | ## Common diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index 84fda653e2328..89b26dd3eeef2 100644 --- a/api_docs/kbn_guided_onboarding.mdx +++ b/api_docs/kbn_guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-guided-onboarding title: "@kbn/guided-onboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/guided-onboarding plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/guided-onboarding'] --- import kbnGuidedOnboardingObj from './kbn_guided_onboarding.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index f94a968bc8644..3afc33ae99277 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] --- import kbnHandlebarsObj from './kbn_handlebars.devdocs.json'; diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index 43784a2c1d056..4f48d76871004 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_health_gateway_server.mdx b/api_docs/kbn_health_gateway_server.mdx index 79395e0977fd1..c8870bdafb45c 100644 --- a/api_docs/kbn_health_gateway_server.mdx +++ b/api_docs/kbn_health_gateway_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-health-gateway-server title: "@kbn/health-gateway-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/health-gateway-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/health-gateway-server'] --- import kbnHealthGatewayServerObj from './kbn_health_gateway_server.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index 0ee681a28e023..c4b79fb3d1f79 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-card'] --- import kbnHomeSampleDataCardObj from './kbn_home_sample_data_card.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_tab.mdx b/api_docs/kbn_home_sample_data_tab.mdx index 42732c51a4ffb..5172add4ca105 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-tab'] --- import kbnHomeSampleDataTabObj from './kbn_home_sample_data_tab.devdocs.json'; diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index 28004f413df58..4b7e35cb370a0 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_i18n_react.mdx b/api_docs/kbn_i18n_react.mdx index a48990ffc2fa5..1ce5b440b8938 100644 --- a/api_docs/kbn_i18n_react.mdx +++ b/api_docs/kbn_i18n_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n-react title: "@kbn/i18n-react" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n-react plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n-react'] --- import kbnI18nReactObj from './kbn_i18n_react.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index d139435df3ccf..230e9b73c3938 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_index_management.mdx b/api_docs/kbn_index_management.mdx index b09f55a9e5f97..64189be5ce9f4 100644 --- a/api_docs/kbn_index_management.mdx +++ b/api_docs/kbn_index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-index-management title: "@kbn/index-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/index-management plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/index-management'] --- import kbnIndexManagementObj from './kbn_index_management.devdocs.json'; diff --git a/api_docs/kbn_inference_integration_flyout.mdx b/api_docs/kbn_inference_integration_flyout.mdx index f8aca0a66b844..ef503c4f11836 100644 --- a/api_docs/kbn_inference_integration_flyout.mdx +++ b/api_docs/kbn_inference_integration_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-inference_integration_flyout title: "@kbn/inference_integration_flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/inference_integration_flyout plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/inference_integration_flyout'] --- import kbnInferenceIntegrationFlyoutObj from './kbn_inference_integration_flyout.devdocs.json'; diff --git a/api_docs/kbn_infra_forge.mdx b/api_docs/kbn_infra_forge.mdx index 7163a7ed32568..711ad60964dc7 100644 --- a/api_docs/kbn_infra_forge.mdx +++ b/api_docs/kbn_infra_forge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-infra-forge title: "@kbn/infra-forge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/infra-forge plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/infra-forge'] --- import kbnInfraForgeObj from './kbn_infra_forge.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index 1fc1c9353910c..33b4ef4e63a51 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_investigation_shared.devdocs.json b/api_docs/kbn_investigation_shared.devdocs.json index cf946715b36b0..154f2c342d7f2 100644 --- a/api_docs/kbn_investigation_shared.devdocs.json +++ b/api_docs/kbn_investigation_shared.devdocs.json @@ -30,7 +30,7 @@ "label": "CreateInvestigationItemParams", "description": [], "signature": [ - "{ title: string; type: \"esql\"; params: { esql: string; suggestion: any; }; }" + "{ title: string; type: string; params: { [x: string]: any; }; }" ], "path": "packages/kbn-investigation-shared/src/rest_specs/create_item.ts", "deprecated": false, @@ -45,7 +45,7 @@ "label": "CreateInvestigationItemResponse", "description": [], "signature": [ - "{ id: string; createdAt: number; createdBy: string; } & { title: string; type: \"esql\"; params: { esql: string; suggestion: any; }; }" + "{ id: string; createdAt: number; createdBy: string; } & { title: string; type: string; params: { [x: string]: any; }; }" ], "path": "packages/kbn-investigation-shared/src/rest_specs/create_item.ts", "deprecated": false, @@ -105,7 +105,7 @@ "label": "CreateInvestigationResponse", "description": [], "signature": [ - "{ id: string; title: string; createdAt: number; createdBy: string; params: { timeRange: { from: number; to: number; }; }; origin: { type: \"alert\"; id: string; } | { type: \"blank\"; }; status: \"closed\" | \"ongoing\"; notes: { id: string; content: string; createdAt: number; createdBy: string; }[]; items: ({ id: string; createdAt: number; createdBy: string; } & { title: string; type: \"esql\"; params: { esql: string; suggestion: any; }; })[]; }" + "{ id: string; title: string; createdAt: number; createdBy: string; params: { timeRange: { from: number; to: number; }; }; origin: { type: \"alert\"; id: string; } | { type: \"blank\"; }; status: \"closed\" | \"ongoing\"; notes: { id: string; content: string; createdAt: number; createdBy: string; }[]; items: ({ id: string; createdAt: number; createdBy: string; } & { title: string; type: string; params: { [x: string]: any; }; })[]; }" ], "path": "packages/kbn-investigation-shared/src/rest_specs/create.ts", "deprecated": false, @@ -180,7 +180,7 @@ "label": "FindInvestigationsResponse", "description": [], "signature": [ - "{ page: number; perPage: number; total: number; results: { id: string; title: string; createdAt: number; createdBy: string; params: { timeRange: { from: number; to: number; }; }; origin: { type: \"alert\"; id: string; } | { type: \"blank\"; }; status: \"closed\" | \"ongoing\"; notes: { id: string; content: string; createdAt: number; createdBy: string; }[]; items: ({ id: string; createdAt: number; createdBy: string; } & { title: string; type: \"esql\"; params: { esql: string; suggestion: any; }; })[]; }[]; }" + "{ page: number; perPage: number; total: number; results: { id: string; title: string; createdAt: number; createdBy: string; params: { timeRange: { from: number; to: number; }; }; origin: { type: \"alert\"; id: string; } | { type: \"blank\"; }; status: \"closed\" | \"ongoing\"; notes: { id: string; content: string; createdAt: number; createdBy: string; }[]; items: ({ id: string; createdAt: number; createdBy: string; } & { title: string; type: string; params: { [x: string]: any; }; })[]; }[]; }" ], "path": "packages/kbn-investigation-shared/src/rest_specs/find.ts", "deprecated": false, @@ -195,7 +195,7 @@ "label": "GetInvestigationItemsResponse", "description": [], "signature": [ - "({ id: string; createdAt: number; createdBy: string; } & { title: string; type: \"esql\"; params: { esql: string; suggestion: any; }; })[]" + "({ id: string; createdAt: number; createdBy: string; } & { title: string; type: string; params: { [x: string]: any; }; })[]" ], "path": "packages/kbn-investigation-shared/src/rest_specs/get_items.ts", "deprecated": false, @@ -240,13 +240,43 @@ "label": "GetInvestigationResponse", "description": [], "signature": [ - "{ id: string; title: string; createdAt: number; createdBy: string; params: { timeRange: { from: number; to: number; }; }; origin: { type: \"alert\"; id: string; } | { type: \"blank\"; }; status: \"closed\" | \"ongoing\"; notes: { id: string; content: string; createdAt: number; createdBy: string; }[]; items: ({ id: string; createdAt: number; createdBy: string; } & { title: string; type: \"esql\"; params: { esql: string; suggestion: any; }; })[]; }" + "{ id: string; title: string; createdAt: number; createdBy: string; params: { timeRange: { from: number; to: number; }; }; origin: { type: \"alert\"; id: string; } | { type: \"blank\"; }; status: \"closed\" | \"ongoing\"; notes: { id: string; content: string; createdAt: number; createdBy: string; }[]; items: ({ id: string; createdAt: number; createdBy: string; } & { title: string; type: string; params: { [x: string]: any; }; })[]; }" ], "path": "packages/kbn-investigation-shared/src/rest_specs/get.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/investigation-shared", + "id": "def-common.InvestigationItem", + "type": "Type", + "tags": [], + "label": "InvestigationItem", + "description": [], + "signature": [ + "{ id: string; createdAt: number; createdBy: string; } & { title: string; type: string; params: { [x: string]: any; }; }" + ], + "path": "packages/kbn-investigation-shared/src/schema/investigation_item.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/investigation-shared", + "id": "def-common.InvestigationItemResponse", + "type": "Type", + "tags": [], + "label": "InvestigationItemResponse", + "description": [], + "signature": [ + "{ id: string; createdAt: number; createdBy: string; } & { title: string; type: string; params: { [x: string]: any; }; }" + ], + "path": "packages/kbn-investigation-shared/src/rest_specs/investigation_item.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/investigation-shared", "id": "def-common.InvestigationNoteResponse", @@ -261,6 +291,21 @@ "deprecated": false, "trackAdoption": false, "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/investigation-shared", + "id": "def-common.Item", + "type": "Type", + "tags": [], + "label": "Item", + "description": [], + "signature": [ + "{ title: string; type: string; params: { [x: string]: any; }; }" + ], + "path": "packages/kbn-investigation-shared/src/schema/investigation_item.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false } ], "objects": [ @@ -320,14 +365,14 @@ "<{ title: ", "StringC", "; type: ", - "LiteralC", - "<\"esql\">; params: ", - "TypeC", - "<{ esql: ", "StringC", - "; suggestion: ", + "; params: ", + "RecordC", + "<", + "StringC", + ", ", "AnyC", - "; }>; }>; }>" + ">; }>; }>" ], "path": "packages/kbn-investigation-shared/src/rest_specs/create_item.ts", "deprecated": false, @@ -356,14 +401,14 @@ "<{ title: ", "StringC", "; type: ", - "LiteralC", - "<\"esql\">; params: ", - "TypeC", - "<{ esql: ", "StringC", - "; suggestion: ", + "; params: ", + "RecordC", + "<", + "StringC", + ", ", "AnyC", - "; }>; }>]>" + ">; }>]>" ], "path": "packages/kbn-investigation-shared/src/rest_specs/create_item.ts", "deprecated": false, @@ -532,14 +577,14 @@ "<{ title: ", "StringC", "; type: ", - "LiteralC", - "<\"esql\">; params: ", - "TypeC", - "<{ esql: ", "StringC", - "; suggestion: ", + "; params: ", + "RecordC", + "<", + "StringC", + ", ", "AnyC", - "; }>; }>]>>; }>" + ">; }>]>>; }>" ], "path": "packages/kbn-investigation-shared/src/rest_specs/create.ts", "deprecated": false, @@ -610,32 +655,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "@kbn/investigation-shared", - "id": "def-common.esqlItemSchema", - "type": "Object", - "tags": [], - "label": "esqlItemSchema", - "description": [], - "signature": [ - "TypeC", - "<{ title: ", - "StringC", - "; type: ", - "LiteralC", - "<\"esql\">; params: ", - "TypeC", - "<{ esql: ", - "StringC", - "; suggestion: ", - "AnyC", - "; }>; }>" - ], - "path": "packages/kbn-investigation-shared/src/schema/investigation_item.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "@kbn/investigation-shared", "id": "def-common.findInvestigationsParamsSchema", @@ -742,14 +761,14 @@ "<{ title: ", "StringC", "; type: ", - "LiteralC", - "<\"esql\">; params: ", - "TypeC", - "<{ esql: ", "StringC", - "; suggestion: ", + "; params: ", + "RecordC", + "<", + "StringC", + ", ", "AnyC", - "; }>; }>]>>; }>>; }>" + ">; }>]>>; }>>; }>" ], "path": "packages/kbn-investigation-shared/src/rest_specs/find.ts", "deprecated": false, @@ -800,14 +819,14 @@ "<{ title: ", "StringC", "; type: ", - "LiteralC", - "<\"esql\">; params: ", - "TypeC", - "<{ esql: ", "StringC", - "; suggestion: ", + "; params: ", + "RecordC", + "<", + "StringC", + ", ", "AnyC", - "; }>; }>]>>" + ">; }>]>>" ], "path": "packages/kbn-investigation-shared/src/rest_specs/get_items.ts", "deprecated": false, @@ -952,14 +971,14 @@ "<{ title: ", "StringC", "; type: ", - "LiteralC", - "<\"esql\">; params: ", - "TypeC", - "<{ esql: ", "StringC", - "; suggestion: ", + "; params: ", + "RecordC", + "<", + "StringC", + ", ", "AnyC", - "; }>; }>]>>; }>" + ">; }>]>>; }>" ], "path": "packages/kbn-investigation-shared/src/rest_specs/get.ts", "deprecated": false, @@ -968,10 +987,10 @@ }, { "parentPluginId": "@kbn/investigation-shared", - "id": "def-common.investigationItemSchema", + "id": "def-common.investigationItemResponseSchema", "type": "Object", "tags": [], - "label": "investigationItemSchema", + "label": "investigationItemResponseSchema", "description": [], "signature": [ "IntersectionC", @@ -988,40 +1007,50 @@ "<{ title: ", "StringC", "; type: ", - "LiteralC", - "<\"esql\">; params: ", - "TypeC", - "<{ esql: ", "StringC", - "; suggestion: ", + "; params: ", + "RecordC", + "<", + "StringC", + ", ", "AnyC", - "; }>; }>]>" + ">; }>]>" ], - "path": "packages/kbn-investigation-shared/src/schema/investigation_item.ts", + "path": "packages/kbn-investigation-shared/src/rest_specs/investigation_item.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "@kbn/investigation-shared", - "id": "def-common.investigationItemsSchema", + "id": "def-common.investigationItemSchema", "type": "Object", "tags": [], - "label": "investigationItemsSchema", + "label": "investigationItemSchema", "description": [], "signature": [ + "IntersectionC", + "<[", + "TypeC", + "<{ id: ", + "StringC", + "; createdAt: ", + "NumberC", + "; createdBy: ", + "StringC", + "; }>, ", "TypeC", "<{ title: ", "StringC", "; type: ", - "LiteralC", - "<\"esql\">; params: ", - "TypeC", - "<{ esql: ", "StringC", - "; suggestion: ", + "; params: ", + "RecordC", + "<", + "StringC", + ", ", "AnyC", - "; }>; }>" + ">; }>]>" ], "path": "packages/kbn-investigation-shared/src/schema/investigation_item.ts", "deprecated": false, @@ -1148,19 +1177,45 @@ "<{ title: ", "StringC", "; type: ", - "LiteralC", - "<\"esql\">; params: ", - "TypeC", - "<{ esql: ", "StringC", - "; suggestion: ", + "; params: ", + "RecordC", + "<", + "StringC", + ", ", "AnyC", - "; }>; }>]>>; }>" + ">; }>]>>; }>" ], "path": "packages/kbn-investigation-shared/src/schema/investigation.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/investigation-shared", + "id": "def-common.itemSchema", + "type": "Object", + "tags": [], + "label": "itemSchema", + "description": [], + "signature": [ + "TypeC", + "<{ title: ", + "StringC", + "; type: ", + "StringC", + "; params: ", + "RecordC", + "<", + "StringC", + ", ", + "AnyC", + ">; }>" + ], + "path": "packages/kbn-investigation-shared/src/schema/investigation_item.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false } ] } diff --git a/api_docs/kbn_investigation_shared.mdx b/api_docs/kbn_investigation_shared.mdx index ac1933bb3dd1b..38096d13d9bf2 100644 --- a/api_docs/kbn_investigation_shared.mdx +++ b/api_docs/kbn_investigation_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-investigation-shared title: "@kbn/investigation-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/investigation-shared plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/investigation-shared'] --- import kbnInvestigationSharedObj from './kbn_investigation_shared.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/ | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 41 | 0 | 41 | 0 | +| 44 | 0 | 44 | 0 | ## Common diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index d0f6f93a36eac..6e35fb413f63d 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_ipynb.mdx b/api_docs/kbn_ipynb.mdx index 8cec6e84ef1ba..a2484264bcc02 100644 --- a/api_docs/kbn_ipynb.mdx +++ b/api_docs/kbn_ipynb.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ipynb title: "@kbn/ipynb" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ipynb plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ipynb'] --- import kbnIpynbObj from './kbn_ipynb.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index df2e9c7a23301..4ac4665e1810e 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_journeys.mdx b/api_docs/kbn_journeys.mdx index 1d5b84f2a194e..6aac219ecd6ff 100644 --- a/api_docs/kbn_journeys.mdx +++ b/api_docs/kbn_journeys.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-journeys title: "@kbn/journeys" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/journeys plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/journeys'] --- import kbnJourneysObj from './kbn_journeys.devdocs.json'; diff --git a/api_docs/kbn_json_ast.mdx b/api_docs/kbn_json_ast.mdx index 7d3fafdc2db73..fd0aa1074c2a5 100644 --- a/api_docs/kbn_json_ast.mdx +++ b/api_docs/kbn_json_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-ast title: "@kbn/json-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-ast plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/json-ast'] --- import kbnJsonAstObj from './kbn_json_ast.devdocs.json'; diff --git a/api_docs/kbn_json_schemas.mdx b/api_docs/kbn_json_schemas.mdx index 79935fd0d6a0f..eb029f92511cd 100644 --- a/api_docs/kbn_json_schemas.mdx +++ b/api_docs/kbn_json_schemas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-schemas title: "@kbn/json-schemas" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-schemas plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/json-schemas'] --- import kbnJsonSchemasObj from './kbn_json_schemas.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index fe033bedeb821..f4b80da9910ef 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_language_documentation_popover.mdx b/api_docs/kbn_language_documentation_popover.mdx index d0946f8d0e8ac..7e26a327a2491 100644 --- a/api_docs/kbn_language_documentation_popover.mdx +++ b/api_docs/kbn_language_documentation_popover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation-popover title: "@kbn/language-documentation-popover" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation-popover plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation-popover'] --- import kbnLanguageDocumentationPopoverObj from './kbn_language_documentation_popover.devdocs.json'; diff --git a/api_docs/kbn_lens_embeddable_utils.mdx b/api_docs/kbn_lens_embeddable_utils.mdx index d8aef714d9841..9fcbc65b75935 100644 --- a/api_docs/kbn_lens_embeddable_utils.mdx +++ b/api_docs/kbn_lens_embeddable_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-lens-embeddable-utils title: "@kbn/lens-embeddable-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/lens-embeddable-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-embeddable-utils'] --- import kbnLensEmbeddableUtilsObj from './kbn_lens_embeddable_utils.devdocs.json'; diff --git a/api_docs/kbn_lens_formula_docs.mdx b/api_docs/kbn_lens_formula_docs.mdx index 7a747c70900fa..786b29b546990 100644 --- a/api_docs/kbn_lens_formula_docs.mdx +++ b/api_docs/kbn_lens_formula_docs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-lens-formula-docs title: "@kbn/lens-formula-docs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/lens-formula-docs plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-formula-docs'] --- import kbnLensFormulaDocsObj from './kbn_lens_formula_docs.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index e486986a1d1b1..5f612b59fca0e 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] --- import kbnLoggingObj from './kbn_logging.devdocs.json'; diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index 6df141252cea5..da39b938ca78b 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_content_badge.mdx b/api_docs/kbn_managed_content_badge.mdx index 1068a46bdf200..c7aa445c0c585 100644 --- a/api_docs/kbn_managed_content_badge.mdx +++ b/api_docs/kbn_managed_content_badge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-content-badge title: "@kbn/managed-content-badge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-content-badge plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-content-badge'] --- import kbnManagedContentBadgeObj from './kbn_managed_content_badge.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index a86b9da564a60..a22bafb8698ac 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_management_cards_navigation.mdx b/api_docs/kbn_management_cards_navigation.mdx index 482a1affe0697..1a4f05dfd6ef3 100644 --- a/api_docs/kbn_management_cards_navigation.mdx +++ b/api_docs/kbn_management_cards_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-cards-navigation title: "@kbn/management-cards-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-cards-navigation plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-cards-navigation'] --- import kbnManagementCardsNavigationObj from './kbn_management_cards_navigation.devdocs.json'; diff --git a/api_docs/kbn_management_settings_application.mdx b/api_docs/kbn_management_settings_application.mdx index b8b07cc1545ad..bdb39d72399d2 100644 --- a/api_docs/kbn_management_settings_application.mdx +++ b/api_docs/kbn_management_settings_application.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-application title: "@kbn/management-settings-application" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-application plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-application'] --- import kbnManagementSettingsApplicationObj from './kbn_management_settings_application.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_category.mdx b/api_docs/kbn_management_settings_components_field_category.mdx index 8c96d2c16a813..92c8b82597bda 100644 --- a/api_docs/kbn_management_settings_components_field_category.mdx +++ b/api_docs/kbn_management_settings_components_field_category.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-category title: "@kbn/management-settings-components-field-category" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-category plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-category'] --- import kbnManagementSettingsComponentsFieldCategoryObj from './kbn_management_settings_components_field_category.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_input.mdx b/api_docs/kbn_management_settings_components_field_input.mdx index 154e4bc028289..c9c6d6cf6430d 100644 --- a/api_docs/kbn_management_settings_components_field_input.mdx +++ b/api_docs/kbn_management_settings_components_field_input.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-input title: "@kbn/management-settings-components-field-input" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-input plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-input'] --- import kbnManagementSettingsComponentsFieldInputObj from './kbn_management_settings_components_field_input.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_row.mdx b/api_docs/kbn_management_settings_components_field_row.mdx index 32813dd411a99..5056d5af28e5e 100644 --- a/api_docs/kbn_management_settings_components_field_row.mdx +++ b/api_docs/kbn_management_settings_components_field_row.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-row title: "@kbn/management-settings-components-field-row" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-row plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-row'] --- import kbnManagementSettingsComponentsFieldRowObj from './kbn_management_settings_components_field_row.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_form.mdx b/api_docs/kbn_management_settings_components_form.mdx index 33e21f4205d2f..decd973e6e0d2 100644 --- a/api_docs/kbn_management_settings_components_form.mdx +++ b/api_docs/kbn_management_settings_components_form.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-form title: "@kbn/management-settings-components-form" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-form plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-form'] --- import kbnManagementSettingsComponentsFormObj from './kbn_management_settings_components_form.devdocs.json'; diff --git a/api_docs/kbn_management_settings_field_definition.mdx b/api_docs/kbn_management_settings_field_definition.mdx index ad0c52760082f..a92a0487eb089 100644 --- a/api_docs/kbn_management_settings_field_definition.mdx +++ b/api_docs/kbn_management_settings_field_definition.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-field-definition title: "@kbn/management-settings-field-definition" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-field-definition plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-field-definition'] --- import kbnManagementSettingsFieldDefinitionObj from './kbn_management_settings_field_definition.devdocs.json'; diff --git a/api_docs/kbn_management_settings_ids.devdocs.json b/api_docs/kbn_management_settings_ids.devdocs.json index f5662d441bdc0..02da2b2d9b18f 100644 --- a/api_docs/kbn_management_settings_ids.devdocs.json +++ b/api_docs/kbn_management_settings_ids.devdocs.json @@ -1087,21 +1087,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "@kbn/management-settings-ids", - "id": "def-common.OBSERVABILITY_AI_ASSISTANT_RESPONSE_LANGUAGE", - "type": "string", - "tags": [], - "label": "OBSERVABILITY_AI_ASSISTANT_RESPONSE_LANGUAGE", - "description": [], - "signature": [ - "\"observability:aiAssistantResponseLanguage\"" - ], - "path": "packages/kbn-management/settings/setting_ids/index.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "@kbn/management-settings-ids", "id": "def-common.OBSERVABILITY_AI_ASSISTANT_SEARCH_CONNECTOR_INDEX_PATTERN", diff --git a/api_docs/kbn_management_settings_ids.mdx b/api_docs/kbn_management_settings_ids.mdx index 980f56f1f6bb2..90bc63858011c 100644 --- a/api_docs/kbn_management_settings_ids.mdx +++ b/api_docs/kbn_management_settings_ids.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-ids title: "@kbn/management-settings-ids" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-ids plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-ids'] --- import kbnManagementSettingsIdsObj from './kbn_management_settings_ids.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/appex-sharedux @elastic/kibana-management](https://github.com/ | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 143 | 0 | 141 | 0 | +| 142 | 0 | 140 | 0 | ## Common diff --git a/api_docs/kbn_management_settings_section_registry.mdx b/api_docs/kbn_management_settings_section_registry.mdx index e4bd5c7f40094..26f9bd5c39902 100644 --- a/api_docs/kbn_management_settings_section_registry.mdx +++ b/api_docs/kbn_management_settings_section_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-section-registry title: "@kbn/management-settings-section-registry" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-section-registry plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-section-registry'] --- import kbnManagementSettingsSectionRegistryObj from './kbn_management_settings_section_registry.devdocs.json'; diff --git a/api_docs/kbn_management_settings_types.mdx b/api_docs/kbn_management_settings_types.mdx index 89444186dd490..10393d78ee0b4 100644 --- a/api_docs/kbn_management_settings_types.mdx +++ b/api_docs/kbn_management_settings_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-types title: "@kbn/management-settings-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-types plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-types'] --- import kbnManagementSettingsTypesObj from './kbn_management_settings_types.devdocs.json'; diff --git a/api_docs/kbn_management_settings_utilities.mdx b/api_docs/kbn_management_settings_utilities.mdx index 6fa1f251b0fc7..f3b6dd57105f9 100644 --- a/api_docs/kbn_management_settings_utilities.mdx +++ b/api_docs/kbn_management_settings_utilities.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-utilities title: "@kbn/management-settings-utilities" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-utilities plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-utilities'] --- import kbnManagementSettingsUtilitiesObj from './kbn_management_settings_utilities.devdocs.json'; diff --git a/api_docs/kbn_management_storybook_config.mdx b/api_docs/kbn_management_storybook_config.mdx index 7f6fab807b5f6..7bf380e91cc7b 100644 --- a/api_docs/kbn_management_storybook_config.mdx +++ b/api_docs/kbn_management_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-storybook-config title: "@kbn/management-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-storybook-config plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-storybook-config'] --- import kbnManagementStorybookConfigObj from './kbn_management_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index 5baf3af31bdb0..261b0172ddaf4 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_maps_vector_tile_utils.mdx b/api_docs/kbn_maps_vector_tile_utils.mdx index caf901e9b2adf..8c646c25cb3ff 100644 --- a/api_docs/kbn_maps_vector_tile_utils.mdx +++ b/api_docs/kbn_maps_vector_tile_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-maps-vector-tile-utils title: "@kbn/maps-vector-tile-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/maps-vector-tile-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/maps-vector-tile-utils'] --- import kbnMapsVectorTileUtilsObj from './kbn_maps_vector_tile_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index 0788af076a72c..3fc1e37fbe925 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_anomaly_utils.mdx b/api_docs/kbn_ml_anomaly_utils.mdx index 37b3106e80804..847b398ec3cb3 100644 --- a/api_docs/kbn_ml_anomaly_utils.mdx +++ b/api_docs/kbn_ml_anomaly_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-anomaly-utils title: "@kbn/ml-anomaly-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-anomaly-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-anomaly-utils'] --- import kbnMlAnomalyUtilsObj from './kbn_ml_anomaly_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_cancellable_search.mdx b/api_docs/kbn_ml_cancellable_search.mdx index 84d5d09e14d3b..9ed2c18cc6ef6 100644 --- a/api_docs/kbn_ml_cancellable_search.mdx +++ b/api_docs/kbn_ml_cancellable_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-cancellable-search title: "@kbn/ml-cancellable-search" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-cancellable-search plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-cancellable-search'] --- import kbnMlCancellableSearchObj from './kbn_ml_cancellable_search.devdocs.json'; diff --git a/api_docs/kbn_ml_category_validator.mdx b/api_docs/kbn_ml_category_validator.mdx index 21643d9c482c1..51b814cf7a8dd 100644 --- a/api_docs/kbn_ml_category_validator.mdx +++ b/api_docs/kbn_ml_category_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-category-validator title: "@kbn/ml-category-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-category-validator plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-category-validator'] --- import kbnMlCategoryValidatorObj from './kbn_ml_category_validator.devdocs.json'; diff --git a/api_docs/kbn_ml_chi2test.mdx b/api_docs/kbn_ml_chi2test.mdx index 8e5cbb35a5dbc..dfc1835a0c168 100644 --- a/api_docs/kbn_ml_chi2test.mdx +++ b/api_docs/kbn_ml_chi2test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-chi2test title: "@kbn/ml-chi2test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-chi2test plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-chi2test'] --- import kbnMlChi2testObj from './kbn_ml_chi2test.devdocs.json'; diff --git a/api_docs/kbn_ml_data_frame_analytics_utils.mdx b/api_docs/kbn_ml_data_frame_analytics_utils.mdx index 55b4bc658e837..e12e56f7e1ffd 100644 --- a/api_docs/kbn_ml_data_frame_analytics_utils.mdx +++ b/api_docs/kbn_ml_data_frame_analytics_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-frame-analytics-utils title: "@kbn/ml-data-frame-analytics-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-frame-analytics-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-frame-analytics-utils'] --- import kbnMlDataFrameAnalyticsUtilsObj from './kbn_ml_data_frame_analytics_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_data_grid.mdx b/api_docs/kbn_ml_data_grid.mdx index bbaf79051310f..66e553b9b63be 100644 --- a/api_docs/kbn_ml_data_grid.mdx +++ b/api_docs/kbn_ml_data_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-grid title: "@kbn/ml-data-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-grid plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-grid'] --- import kbnMlDataGridObj from './kbn_ml_data_grid.devdocs.json'; diff --git a/api_docs/kbn_ml_date_picker.mdx b/api_docs/kbn_ml_date_picker.mdx index d199168f0da7d..1fc6ac99df933 100644 --- a/api_docs/kbn_ml_date_picker.mdx +++ b/api_docs/kbn_ml_date_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-picker title: "@kbn/ml-date-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-picker plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-picker'] --- import kbnMlDatePickerObj from './kbn_ml_date_picker.devdocs.json'; diff --git a/api_docs/kbn_ml_date_utils.mdx b/api_docs/kbn_ml_date_utils.mdx index e48ca364a2e2d..5f01e8448d063 100644 --- a/api_docs/kbn_ml_date_utils.mdx +++ b/api_docs/kbn_ml_date_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-utils title: "@kbn/ml-date-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-utils'] --- import kbnMlDateUtilsObj from './kbn_ml_date_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_error_utils.mdx b/api_docs/kbn_ml_error_utils.mdx index 91f4f290961ad..bb3e3320938b4 100644 --- a/api_docs/kbn_ml_error_utils.mdx +++ b/api_docs/kbn_ml_error_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-error-utils title: "@kbn/ml-error-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-error-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-error-utils'] --- import kbnMlErrorUtilsObj from './kbn_ml_error_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_in_memory_table.mdx b/api_docs/kbn_ml_in_memory_table.mdx index a28085aa353b4..5a7f0c243cb27 100644 --- a/api_docs/kbn_ml_in_memory_table.mdx +++ b/api_docs/kbn_ml_in_memory_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-in-memory-table title: "@kbn/ml-in-memory-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-in-memory-table plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-in-memory-table'] --- import kbnMlInMemoryTableObj from './kbn_ml_in_memory_table.devdocs.json'; diff --git a/api_docs/kbn_ml_is_defined.mdx b/api_docs/kbn_ml_is_defined.mdx index af6d69d9c079c..6a453a82a5b2a 100644 --- a/api_docs/kbn_ml_is_defined.mdx +++ b/api_docs/kbn_ml_is_defined.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-defined title: "@kbn/ml-is-defined" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-defined plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-defined'] --- import kbnMlIsDefinedObj from './kbn_ml_is_defined.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index b62cc5822b671..b109a87ebbfd8 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] --- import kbnMlIsPopulatedObjectObj from './kbn_ml_is_populated_object.devdocs.json'; diff --git a/api_docs/kbn_ml_kibana_theme.mdx b/api_docs/kbn_ml_kibana_theme.mdx index 422e5c60201a6..ecc633f5a09c3 100644 --- a/api_docs/kbn_ml_kibana_theme.mdx +++ b/api_docs/kbn_ml_kibana_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-kibana-theme title: "@kbn/ml-kibana-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-kibana-theme plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-kibana-theme'] --- import kbnMlKibanaThemeObj from './kbn_ml_kibana_theme.devdocs.json'; diff --git a/api_docs/kbn_ml_local_storage.mdx b/api_docs/kbn_ml_local_storage.mdx index cc204d9d961ec..f11a95cbc0114 100644 --- a/api_docs/kbn_ml_local_storage.mdx +++ b/api_docs/kbn_ml_local_storage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-local-storage title: "@kbn/ml-local-storage" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-local-storage plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-local-storage'] --- import kbnMlLocalStorageObj from './kbn_ml_local_storage.devdocs.json'; diff --git a/api_docs/kbn_ml_nested_property.mdx b/api_docs/kbn_ml_nested_property.mdx index 85197b205df74..2e0063282349a 100644 --- a/api_docs/kbn_ml_nested_property.mdx +++ b/api_docs/kbn_ml_nested_property.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-nested-property title: "@kbn/ml-nested-property" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-nested-property plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-nested-property'] --- import kbnMlNestedPropertyObj from './kbn_ml_nested_property.devdocs.json'; diff --git a/api_docs/kbn_ml_number_utils.mdx b/api_docs/kbn_ml_number_utils.mdx index a431ba883a067..781a843de0663 100644 --- a/api_docs/kbn_ml_number_utils.mdx +++ b/api_docs/kbn_ml_number_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-number-utils title: "@kbn/ml-number-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-number-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-number-utils'] --- import kbnMlNumberUtilsObj from './kbn_ml_number_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_query_utils.mdx b/api_docs/kbn_ml_query_utils.mdx index 6e1b48a2118d9..d58c528713709 100644 --- a/api_docs/kbn_ml_query_utils.mdx +++ b/api_docs/kbn_ml_query_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-query-utils title: "@kbn/ml-query-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-query-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-query-utils'] --- import kbnMlQueryUtilsObj from './kbn_ml_query_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_random_sampler_utils.mdx b/api_docs/kbn_ml_random_sampler_utils.mdx index def110412a8da..dd86793573528 100644 --- a/api_docs/kbn_ml_random_sampler_utils.mdx +++ b/api_docs/kbn_ml_random_sampler_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-random-sampler-utils title: "@kbn/ml-random-sampler-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-random-sampler-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-random-sampler-utils'] --- import kbnMlRandomSamplerUtilsObj from './kbn_ml_random_sampler_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_route_utils.mdx b/api_docs/kbn_ml_route_utils.mdx index 52b74aed2dcf2..c01fa8f45b8bf 100644 --- a/api_docs/kbn_ml_route_utils.mdx +++ b/api_docs/kbn_ml_route_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-route-utils title: "@kbn/ml-route-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-route-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-route-utils'] --- import kbnMlRouteUtilsObj from './kbn_ml_route_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_runtime_field_utils.mdx b/api_docs/kbn_ml_runtime_field_utils.mdx index ef36e23dff982..e50ae41a97513 100644 --- a/api_docs/kbn_ml_runtime_field_utils.mdx +++ b/api_docs/kbn_ml_runtime_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-runtime-field-utils title: "@kbn/ml-runtime-field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-runtime-field-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-runtime-field-utils'] --- import kbnMlRuntimeFieldUtilsObj from './kbn_ml_runtime_field_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index cb20c7911f56e..94b44d9e6afa4 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_ml_time_buckets.mdx b/api_docs/kbn_ml_time_buckets.mdx index a442b83f178de..0622698eb074b 100644 --- a/api_docs/kbn_ml_time_buckets.mdx +++ b/api_docs/kbn_ml_time_buckets.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-time-buckets title: "@kbn/ml-time-buckets" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-time-buckets plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-time-buckets'] --- import kbnMlTimeBucketsObj from './kbn_ml_time_buckets.devdocs.json'; diff --git a/api_docs/kbn_ml_trained_models_utils.mdx b/api_docs/kbn_ml_trained_models_utils.mdx index 58bf4daeca916..3b67041a0000d 100644 --- a/api_docs/kbn_ml_trained_models_utils.mdx +++ b/api_docs/kbn_ml_trained_models_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-trained-models-utils title: "@kbn/ml-trained-models-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-trained-models-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-trained-models-utils'] --- import kbnMlTrainedModelsUtilsObj from './kbn_ml_trained_models_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_ui_actions.mdx b/api_docs/kbn_ml_ui_actions.mdx index 411ec82b9b901..d51e24f4da8b3 100644 --- a/api_docs/kbn_ml_ui_actions.mdx +++ b/api_docs/kbn_ml_ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-ui-actions title: "@kbn/ml-ui-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-ui-actions plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-ui-actions'] --- import kbnMlUiActionsObj from './kbn_ml_ui_actions.devdocs.json'; diff --git a/api_docs/kbn_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index ea636c6b29a2a..4501a64f31031 100644 --- a/api_docs/kbn_ml_url_state.mdx +++ b/api_docs/kbn_ml_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-url-state title: "@kbn/ml-url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-url-state plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_mock_idp_utils.mdx b/api_docs/kbn_mock_idp_utils.mdx index 71c861ce26287..45dc4347a7198 100644 --- a/api_docs/kbn_mock_idp_utils.mdx +++ b/api_docs/kbn_mock_idp_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mock-idp-utils title: "@kbn/mock-idp-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mock-idp-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mock-idp-utils'] --- import kbnMockIdpUtilsObj from './kbn_mock_idp_utils.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 952cea5ca675a..b061d4c89f82c 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_object_versioning.mdx b/api_docs/kbn_object_versioning.mdx index 5a9b39313757f..c20cbde4516e4 100644 --- a/api_docs/kbn_object_versioning.mdx +++ b/api_docs/kbn_object_versioning.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-object-versioning title: "@kbn/object-versioning" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/object-versioning plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/object-versioning'] --- import kbnObjectVersioningObj from './kbn_object_versioning.devdocs.json'; diff --git a/api_docs/kbn_observability_alert_details.mdx b/api_docs/kbn_observability_alert_details.mdx index 22424f19ffeec..ffb5c6ef7bbbb 100644 --- a/api_docs/kbn_observability_alert_details.mdx +++ b/api_docs/kbn_observability_alert_details.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alert-details title: "@kbn/observability-alert-details" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alert-details plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alert-details'] --- import kbnObservabilityAlertDetailsObj from './kbn_observability_alert_details.devdocs.json'; diff --git a/api_docs/kbn_observability_alerting_rule_utils.mdx b/api_docs/kbn_observability_alerting_rule_utils.mdx index a7f3bfdfc78de..cf6367fa59d88 100644 --- a/api_docs/kbn_observability_alerting_rule_utils.mdx +++ b/api_docs/kbn_observability_alerting_rule_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alerting-rule-utils title: "@kbn/observability-alerting-rule-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alerting-rule-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alerting-rule-utils'] --- import kbnObservabilityAlertingRuleUtilsObj from './kbn_observability_alerting_rule_utils.devdocs.json'; diff --git a/api_docs/kbn_observability_alerting_test_data.mdx b/api_docs/kbn_observability_alerting_test_data.mdx index 45b4e9439fab2..936795814ad7a 100644 --- a/api_docs/kbn_observability_alerting_test_data.mdx +++ b/api_docs/kbn_observability_alerting_test_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alerting-test-data title: "@kbn/observability-alerting-test-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alerting-test-data plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alerting-test-data'] --- import kbnObservabilityAlertingTestDataObj from './kbn_observability_alerting_test_data.devdocs.json'; diff --git a/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx b/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx index 8765cfb145649..8590f019a303d 100644 --- a/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx +++ b/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-get-padded-alert-time-range-util title: "@kbn/observability-get-padded-alert-time-range-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-get-padded-alert-time-range-util plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-get-padded-alert-time-range-util'] --- import kbnObservabilityGetPaddedAlertTimeRangeUtilObj from './kbn_observability_get_padded_alert_time_range_util.devdocs.json'; diff --git a/api_docs/kbn_openapi_bundler.mdx b/api_docs/kbn_openapi_bundler.mdx index 49b07d4e68f06..07add5a4da06d 100644 --- a/api_docs/kbn_openapi_bundler.mdx +++ b/api_docs/kbn_openapi_bundler.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-bundler title: "@kbn/openapi-bundler" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-bundler plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-bundler'] --- import kbnOpenapiBundlerObj from './kbn_openapi_bundler.devdocs.json'; diff --git a/api_docs/kbn_openapi_generator.mdx b/api_docs/kbn_openapi_generator.mdx index 310ce0e970f3e..fcc8468a531bf 100644 --- a/api_docs/kbn_openapi_generator.mdx +++ b/api_docs/kbn_openapi_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-generator title: "@kbn/openapi-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-generator plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-generator'] --- import kbnOpenapiGeneratorObj from './kbn_openapi_generator.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index ca28901736540..35feb1923a817 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] --- import kbnOptimizerObj from './kbn_optimizer.devdocs.json'; diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index 8374769babe61..06a26caf7f3cb 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_osquery_io_ts_types.mdx b/api_docs/kbn_osquery_io_ts_types.mdx index c623a747d1f92..34002bfc45bdd 100644 --- a/api_docs/kbn_osquery_io_ts_types.mdx +++ b/api_docs/kbn_osquery_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-osquery-io-ts-types title: "@kbn/osquery-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/osquery-io-ts-types plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/osquery-io-ts-types'] --- import kbnOsqueryIoTsTypesObj from './kbn_osquery_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_panel_loader.mdx b/api_docs/kbn_panel_loader.mdx index 561225ef84ba3..91a90d3fadbd5 100644 --- a/api_docs/kbn_panel_loader.mdx +++ b/api_docs/kbn_panel_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-panel-loader title: "@kbn/panel-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/panel-loader plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/panel-loader'] --- import kbnPanelLoaderObj from './kbn_panel_loader.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index d5f9db4ad3c1f..0135893bb9d8b 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_check.mdx b/api_docs/kbn_plugin_check.mdx index 01125bfede9ef..564e6e759f403 100644 --- a/api_docs/kbn_plugin_check.mdx +++ b/api_docs/kbn_plugin_check.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-check title: "@kbn/plugin-check" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-check plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-check'] --- import kbnPluginCheckObj from './kbn_plugin_check.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index 8452e5b00c94b..5f99c4d37c974 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] --- import kbnPluginGeneratorObj from './kbn_plugin_generator.devdocs.json'; diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index fb46a0911997f..7358cca85b376 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_presentation_containers.devdocs.json b/api_docs/kbn_presentation_containers.devdocs.json index d3adf3e03080d..3216e399f98ba 100644 --- a/api_docs/kbn_presentation_containers.devdocs.json +++ b/api_docs/kbn_presentation_containers.devdocs.json @@ -1751,9 +1751,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.Reference", + "section": "def-server.Reference", "text": "Reference" }, "[] | undefined" diff --git a/api_docs/kbn_presentation_containers.mdx b/api_docs/kbn_presentation_containers.mdx index 09aca35c8c683..3eefd985c6cb8 100644 --- a/api_docs/kbn_presentation_containers.mdx +++ b/api_docs/kbn_presentation_containers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-presentation-containers title: "@kbn/presentation-containers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/presentation-containers plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/presentation-containers'] --- import kbnPresentationContainersObj from './kbn_presentation_containers.devdocs.json'; diff --git a/api_docs/kbn_presentation_publishing.mdx b/api_docs/kbn_presentation_publishing.mdx index 6cdbb1935fb7f..c7cc88a83203c 100644 --- a/api_docs/kbn_presentation_publishing.mdx +++ b/api_docs/kbn_presentation_publishing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-presentation-publishing title: "@kbn/presentation-publishing" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/presentation-publishing plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/presentation-publishing'] --- import kbnPresentationPublishingObj from './kbn_presentation_publishing.devdocs.json'; diff --git a/api_docs/kbn_profiling_utils.mdx b/api_docs/kbn_profiling_utils.mdx index 437c50eb2858e..356e737bb41c3 100644 --- a/api_docs/kbn_profiling_utils.mdx +++ b/api_docs/kbn_profiling_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-profiling-utils title: "@kbn/profiling-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/profiling-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/profiling-utils'] --- import kbnProfilingUtilsObj from './kbn_profiling_utils.devdocs.json'; diff --git a/api_docs/kbn_random_sampling.mdx b/api_docs/kbn_random_sampling.mdx index 5d9f7f858bf04..f02397fd1b03a 100644 --- a/api_docs/kbn_random_sampling.mdx +++ b/api_docs/kbn_random_sampling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-random-sampling title: "@kbn/random-sampling" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/random-sampling plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/random-sampling'] --- import kbnRandomSamplingObj from './kbn_random_sampling.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index c5f428f42e982..9daf5a9531cce 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_react_hooks.mdx b/api_docs/kbn_react_hooks.mdx index b86335808cbff..f87fb2ff68eed 100644 --- a/api_docs/kbn_react_hooks.mdx +++ b/api_docs/kbn_react_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-hooks title: "@kbn/react-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-hooks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-hooks'] --- import kbnReactHooksObj from './kbn_react_hooks.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_common.mdx b/api_docs/kbn_react_kibana_context_common.mdx index 99051444ed653..416fb1f972a6c 100644 --- a/api_docs/kbn_react_kibana_context_common.mdx +++ b/api_docs/kbn_react_kibana_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-common title: "@kbn/react-kibana-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-common'] --- import kbnReactKibanaContextCommonObj from './kbn_react_kibana_context_common.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_render.mdx b/api_docs/kbn_react_kibana_context_render.mdx index a85b1ebcff194..899fc3515fb5b 100644 --- a/api_docs/kbn_react_kibana_context_render.mdx +++ b/api_docs/kbn_react_kibana_context_render.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-render title: "@kbn/react-kibana-context-render" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-render plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-render'] --- import kbnReactKibanaContextRenderObj from './kbn_react_kibana_context_render.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_root.mdx b/api_docs/kbn_react_kibana_context_root.mdx index 445f551fc2abd..dc9a1e114a38d 100644 --- a/api_docs/kbn_react_kibana_context_root.mdx +++ b/api_docs/kbn_react_kibana_context_root.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-root title: "@kbn/react-kibana-context-root" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-root plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-root'] --- import kbnReactKibanaContextRootObj from './kbn_react_kibana_context_root.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_styled.mdx b/api_docs/kbn_react_kibana_context_styled.mdx index 0ae9eb3256543..e30b190449d88 100644 --- a/api_docs/kbn_react_kibana_context_styled.mdx +++ b/api_docs/kbn_react_kibana_context_styled.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-styled title: "@kbn/react-kibana-context-styled" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-styled plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-styled'] --- import kbnReactKibanaContextStyledObj from './kbn_react_kibana_context_styled.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_theme.mdx b/api_docs/kbn_react_kibana_context_theme.mdx index 115d877788967..57d8e88f75b90 100644 --- a/api_docs/kbn_react_kibana_context_theme.mdx +++ b/api_docs/kbn_react_kibana_context_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-theme title: "@kbn/react-kibana-context-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-theme plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-theme'] --- import kbnReactKibanaContextThemeObj from './kbn_react_kibana_context_theme.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_mount.devdocs.json b/api_docs/kbn_react_kibana_mount.devdocs.json index b26c6e53f7459..9340067e42c1e 100644 --- a/api_docs/kbn_react_kibana_mount.devdocs.json +++ b/api_docs/kbn_react_kibana_mount.devdocs.json @@ -152,7 +152,7 @@ "label": "useIfMounted", "description": [], "signature": [ - "() => (func: any) => void" + "() => (func?: (() => void) | undefined) => void" ], "path": "packages/react/kibana_mount/utils.ts", "deprecated": false, diff --git a/api_docs/kbn_react_kibana_mount.mdx b/api_docs/kbn_react_kibana_mount.mdx index 9efcf620e87fc..694b7656dd42d 100644 --- a/api_docs/kbn_react_kibana_mount.mdx +++ b/api_docs/kbn_react_kibana_mount.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-mount title: "@kbn/react-kibana-mount" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-mount plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-mount'] --- import kbnReactKibanaMountObj from './kbn_react_kibana_mount.devdocs.json'; diff --git a/api_docs/kbn_recently_accessed.mdx b/api_docs/kbn_recently_accessed.mdx index acc96f83709d1..a907261cc9d4a 100644 --- a/api_docs/kbn_recently_accessed.mdx +++ b/api_docs/kbn_recently_accessed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-recently-accessed title: "@kbn/recently-accessed" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/recently-accessed plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/recently-accessed'] --- import kbnRecentlyAccessedObj from './kbn_recently_accessed.devdocs.json'; diff --git a/api_docs/kbn_repo_file_maps.mdx b/api_docs/kbn_repo_file_maps.mdx index 8844145592be1..15757f00ac4ce 100644 --- a/api_docs/kbn_repo_file_maps.mdx +++ b/api_docs/kbn_repo_file_maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-file-maps title: "@kbn/repo-file-maps" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-file-maps plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-file-maps'] --- import kbnRepoFileMapsObj from './kbn_repo_file_maps.devdocs.json'; diff --git a/api_docs/kbn_repo_linter.mdx b/api_docs/kbn_repo_linter.mdx index 7b82fde6b2d1a..0a18a3eb773da 100644 --- a/api_docs/kbn_repo_linter.mdx +++ b/api_docs/kbn_repo_linter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-linter title: "@kbn/repo-linter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-linter plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-linter'] --- import kbnRepoLinterObj from './kbn_repo_linter.devdocs.json'; diff --git a/api_docs/kbn_repo_path.mdx b/api_docs/kbn_repo_path.mdx index 31c062c852f83..f0b05ed30f3f3 100644 --- a/api_docs/kbn_repo_path.mdx +++ b/api_docs/kbn_repo_path.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-path title: "@kbn/repo-path" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-path plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-path'] --- import kbnRepoPathObj from './kbn_repo_path.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index 87aba75095c4d..4551e5d8b7162 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_reporting_common.mdx b/api_docs/kbn_reporting_common.mdx index 007843217d3cc..7b3e3f7e5b0c1 100644 --- a/api_docs/kbn_reporting_common.mdx +++ b/api_docs/kbn_reporting_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-common title: "@kbn/reporting-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-common'] --- import kbnReportingCommonObj from './kbn_reporting_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_csv_share_panel.mdx b/api_docs/kbn_reporting_csv_share_panel.mdx index e9a64666f306e..d71f19fbc4a14 100644 --- a/api_docs/kbn_reporting_csv_share_panel.mdx +++ b/api_docs/kbn_reporting_csv_share_panel.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-csv-share-panel title: "@kbn/reporting-csv-share-panel" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-csv-share-panel plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-csv-share-panel'] --- import kbnReportingCsvSharePanelObj from './kbn_reporting_csv_share_panel.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_csv.devdocs.json b/api_docs/kbn_reporting_export_types_csv.devdocs.json index 42fd45ce66450..8fe9f3243962b 100644 --- a/api_docs/kbn_reporting_export_types_csv.devdocs.json +++ b/api_docs/kbn_reporting_export_types_csv.devdocs.json @@ -168,7 +168,7 @@ "section": "def-server.CoreSetup", "text": "CoreSetup" }, - ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -176,7 +176,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", { "pluginId": "@kbn/logging", "scope": "common", @@ -192,7 +192,7 @@ "section": "def-server.PluginInitializerContext", "text": "PluginInitializerContext" }, - "; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + "; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -200,7 +200,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" ], "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", "deprecated": false, @@ -569,7 +569,7 @@ "section": "def-server.CoreSetup", "text": "CoreSetup" }, - ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -577,7 +577,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", { "pluginId": "@kbn/logging", "scope": "common", @@ -593,7 +593,7 @@ "section": "def-server.PluginInitializerContext", "text": "PluginInitializerContext" }, - "; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + "; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -601,7 +601,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" ], "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", "deprecated": false, @@ -917,7 +917,7 @@ "section": "def-server.CoreSetup", "text": "CoreSetup" }, - ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -925,7 +925,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", { "pluginId": "@kbn/logging", "scope": "common", @@ -941,7 +941,7 @@ "section": "def-server.PluginInitializerContext", "text": "PluginInitializerContext" }, - "; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + "; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -949,7 +949,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" ], "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", "deprecated": false, diff --git a/api_docs/kbn_reporting_export_types_csv.mdx b/api_docs/kbn_reporting_export_types_csv.mdx index ef16397fb63c5..1730b8aba0734 100644 --- a/api_docs/kbn_reporting_export_types_csv.mdx +++ b/api_docs/kbn_reporting_export_types_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-csv title: "@kbn/reporting-export-types-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-csv plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv'] --- import kbnReportingExportTypesCsvObj from './kbn_reporting_export_types_csv.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_csv_common.mdx b/api_docs/kbn_reporting_export_types_csv_common.mdx index 84bf57f43d8f9..1dd6e8c0fa8ff 100644 --- a/api_docs/kbn_reporting_export_types_csv_common.mdx +++ b/api_docs/kbn_reporting_export_types_csv_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-csv-common title: "@kbn/reporting-export-types-csv-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-csv-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv-common'] --- import kbnReportingExportTypesCsvCommonObj from './kbn_reporting_export_types_csv_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_pdf.devdocs.json b/api_docs/kbn_reporting_export_types_pdf.devdocs.json index 3a4986f51971f..b6c461c57acfa 100644 --- a/api_docs/kbn_reporting_export_types_pdf.devdocs.json +++ b/api_docs/kbn_reporting_export_types_pdf.devdocs.json @@ -176,7 +176,7 @@ "section": "def-server.CoreSetup", "text": "CoreSetup" }, - ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -184,7 +184,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", { "pluginId": "@kbn/logging", "scope": "common", @@ -200,7 +200,7 @@ "section": "def-server.PluginInitializerContext", "text": "PluginInitializerContext" }, - "; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + "; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -208,7 +208,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" ], "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", "deprecated": false, @@ -597,7 +597,7 @@ "section": "def-server.CoreSetup", "text": "CoreSetup" }, - ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -605,7 +605,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", { "pluginId": "@kbn/logging", "scope": "common", @@ -621,7 +621,7 @@ "section": "def-server.PluginInitializerContext", "text": "PluginInitializerContext" }, - "; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + "; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -629,7 +629,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" ], "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", "deprecated": false, diff --git a/api_docs/kbn_reporting_export_types_pdf.mdx b/api_docs/kbn_reporting_export_types_pdf.mdx index 7ffb4afa20566..861933893658b 100644 --- a/api_docs/kbn_reporting_export_types_pdf.mdx +++ b/api_docs/kbn_reporting_export_types_pdf.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-pdf title: "@kbn/reporting-export-types-pdf" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-pdf plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf'] --- import kbnReportingExportTypesPdfObj from './kbn_reporting_export_types_pdf.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_pdf_common.mdx b/api_docs/kbn_reporting_export_types_pdf_common.mdx index 13c7b558aecc9..a7addd095fe23 100644 --- a/api_docs/kbn_reporting_export_types_pdf_common.mdx +++ b/api_docs/kbn_reporting_export_types_pdf_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-pdf-common title: "@kbn/reporting-export-types-pdf-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-pdf-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf-common'] --- import kbnReportingExportTypesPdfCommonObj from './kbn_reporting_export_types_pdf_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_png.devdocs.json b/api_docs/kbn_reporting_export_types_png.devdocs.json index aba2f914b2974..f8c2e8f045ec2 100644 --- a/api_docs/kbn_reporting_export_types_png.devdocs.json +++ b/api_docs/kbn_reporting_export_types_png.devdocs.json @@ -176,7 +176,7 @@ "section": "def-server.CoreSetup", "text": "CoreSetup" }, - ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -184,7 +184,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", { "pluginId": "@kbn/logging", "scope": "common", @@ -200,7 +200,7 @@ "section": "def-server.PluginInitializerContext", "text": "PluginInitializerContext" }, - "; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + "; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -208,7 +208,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" ], "path": "packages/kbn-reporting/export_types/png/png_v2.ts", "deprecated": false, diff --git a/api_docs/kbn_reporting_export_types_png.mdx b/api_docs/kbn_reporting_export_types_png.mdx index c7df4f2a35bda..9ee324b8b3402 100644 --- a/api_docs/kbn_reporting_export_types_png.mdx +++ b/api_docs/kbn_reporting_export_types_png.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-png title: "@kbn/reporting-export-types-png" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-png plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png'] --- import kbnReportingExportTypesPngObj from './kbn_reporting_export_types_png.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_png_common.mdx b/api_docs/kbn_reporting_export_types_png_common.mdx index 439f54983a057..cd09d6fc42e6d 100644 --- a/api_docs/kbn_reporting_export_types_png_common.mdx +++ b/api_docs/kbn_reporting_export_types_png_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-png-common title: "@kbn/reporting-export-types-png-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-png-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png-common'] --- import kbnReportingExportTypesPngCommonObj from './kbn_reporting_export_types_png_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_mocks_server.devdocs.json b/api_docs/kbn_reporting_mocks_server.devdocs.json index 008248db99552..e347bc511219a 100644 --- a/api_docs/kbn_reporting_mocks_server.devdocs.json +++ b/api_docs/kbn_reporting_mocks_server.devdocs.json @@ -29,7 +29,7 @@ "signature": [ "(overrides?: ", "_DeepPartialObject", - "; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + "; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -37,7 +37,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>) => Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>) => Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -45,7 +45,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>" + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>" ], "path": "packages/kbn-reporting/mocks_server/index.ts", "deprecated": false, @@ -60,7 +60,7 @@ "description": [], "signature": [ "_DeepPartialObject", - "; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + "; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -68,7 +68,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>" + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>" ], "path": "packages/kbn-reporting/mocks_server/index.ts", "deprecated": false, diff --git a/api_docs/kbn_reporting_mocks_server.mdx b/api_docs/kbn_reporting_mocks_server.mdx index 527ef257e206f..7c2ff8ebf5b2b 100644 --- a/api_docs/kbn_reporting_mocks_server.mdx +++ b/api_docs/kbn_reporting_mocks_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-mocks-server title: "@kbn/reporting-mocks-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-mocks-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-mocks-server'] --- import kbnReportingMocksServerObj from './kbn_reporting_mocks_server.devdocs.json'; diff --git a/api_docs/kbn_reporting_public.mdx b/api_docs/kbn_reporting_public.mdx index b0740c1f0780f..bee38532dfbf6 100644 --- a/api_docs/kbn_reporting_public.mdx +++ b/api_docs/kbn_reporting_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-public title: "@kbn/reporting-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-public plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-public'] --- import kbnReportingPublicObj from './kbn_reporting_public.devdocs.json'; diff --git a/api_docs/kbn_reporting_server.devdocs.json b/api_docs/kbn_reporting_server.devdocs.json index e9786a2dc0459..ecd948e6f0478 100644 --- a/api_docs/kbn_reporting_server.devdocs.json +++ b/api_docs/kbn_reporting_server.devdocs.json @@ -416,7 +416,7 @@ "label": "config", "description": [], "signature": [ - "Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + "Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -424,7 +424,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>" + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>" ], "path": "packages/kbn-reporting/server/export_type.ts", "deprecated": false, @@ -467,7 +467,7 @@ "section": "def-server.PluginInitializerContext", "text": "PluginInitializerContext" }, - "; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + "; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -475,7 +475,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>" + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>" ], "path": "packages/kbn-reporting/server/export_type.ts", "deprecated": false, @@ -949,7 +949,7 @@ "label": "getFullRedirectAppUrl", "description": [], "signature": [ - "(config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + "(config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -957,7 +957,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, serverInfo: ", + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, serverInfo: ", "ReportingServerInfo", ", spaceId: string | undefined, forceNow: string | undefined) => string" ], @@ -973,7 +973,7 @@ "label": "config", "description": [], "signature": [ - "Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + "Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -981,7 +981,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>" + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; capture: Readonly<{} & { maxAttempts: number; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>" ], "path": "packages/kbn-reporting/server/get_full_redirect_app_url.ts", "deprecated": false, @@ -1661,7 +1661,7 @@ "label": "ReportingConfigType", "description": [], "signature": [ - "{ readonly encryptionKey?: string | undefined; readonly enabled: boolean; readonly capture: Readonly<{} & { maxAttempts: number; }>; readonly roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; readonly kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; readonly queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; readonly csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + "{ readonly encryptionKey?: string | undefined; readonly enabled: boolean; readonly csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; strategy: \"scroll\" | \"pit\"; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -1669,7 +1669,7 @@ "section": "def-common.ByteSizeValue", "text": "ByteSizeValue" }, - "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; readonly poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; readonly export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; readonly statefulSettings: Readonly<{} & { enabled: boolean; }>; }" + "; useByteOrderMarkEncoding: boolean; maxConcurrentShardRequests: number; }>; readonly capture: Readonly<{} & { maxAttempts: number; }>; readonly roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; readonly kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; readonly queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; readonly poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; readonly export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; readonly statefulSettings: Readonly<{} & { enabled: boolean; }>; }" ], "path": "packages/kbn-reporting/server/types.ts", "deprecated": false, diff --git a/api_docs/kbn_reporting_server.mdx b/api_docs/kbn_reporting_server.mdx index 04ab2e2a811e6..ecf0978c05710 100644 --- a/api_docs/kbn_reporting_server.mdx +++ b/api_docs/kbn_reporting_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-server title: "@kbn/reporting-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-server'] --- import kbnReportingServerObj from './kbn_reporting_server.devdocs.json'; diff --git a/api_docs/kbn_resizable_layout.mdx b/api_docs/kbn_resizable_layout.mdx index 6f0c3bb8d8142..3ccaddda1f819 100644 --- a/api_docs/kbn_resizable_layout.mdx +++ b/api_docs/kbn_resizable_layout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-resizable-layout title: "@kbn/resizable-layout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/resizable-layout plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/resizable-layout'] --- import kbnResizableLayoutObj from './kbn_resizable_layout.devdocs.json'; diff --git a/api_docs/kbn_response_ops_feature_flag_service.mdx b/api_docs/kbn_response_ops_feature_flag_service.mdx index a52fa8da91fcc..27e778cfcceac 100644 --- a/api_docs/kbn_response_ops_feature_flag_service.mdx +++ b/api_docs/kbn_response_ops_feature_flag_service.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-response-ops-feature-flag-service title: "@kbn/response-ops-feature-flag-service" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/response-ops-feature-flag-service plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/response-ops-feature-flag-service'] --- import kbnResponseOpsFeatureFlagServiceObj from './kbn_response_ops_feature_flag_service.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index e46de85c77888..748288eb14184 100644 --- a/api_docs/kbn_rison.mdx +++ b/api_docs/kbn_rison.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rison title: "@kbn/rison" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rison plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_rollup.mdx b/api_docs/kbn_rollup.mdx index 60b97a50a443a..f2c82185226e0 100644 --- a/api_docs/kbn_rollup.mdx +++ b/api_docs/kbn_rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rollup title: "@kbn/rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rollup plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rollup'] --- import kbnRollupObj from './kbn_rollup.devdocs.json'; diff --git a/api_docs/kbn_router_to_openapispec.mdx b/api_docs/kbn_router_to_openapispec.mdx index d3f48e8d7d757..48fbaeece164a 100644 --- a/api_docs/kbn_router_to_openapispec.mdx +++ b/api_docs/kbn_router_to_openapispec.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-router-to-openapispec title: "@kbn/router-to-openapispec" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/router-to-openapispec plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/router-to-openapispec'] --- import kbnRouterToOpenapispecObj from './kbn_router_to_openapispec.devdocs.json'; diff --git a/api_docs/kbn_router_utils.mdx b/api_docs/kbn_router_utils.mdx index 4ecb903b21904..8b2aaf218d30f 100644 --- a/api_docs/kbn_router_utils.mdx +++ b/api_docs/kbn_router_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-router-utils title: "@kbn/router-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/router-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/router-utils'] --- import kbnRouterUtilsObj from './kbn_router_utils.devdocs.json'; diff --git a/api_docs/kbn_rrule.mdx b/api_docs/kbn_rrule.mdx index e5b9399563b7b..0db75685a1c29 100644 --- a/api_docs/kbn_rrule.mdx +++ b/api_docs/kbn_rrule.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rrule title: "@kbn/rrule" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rrule plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rrule'] --- import kbnRruleObj from './kbn_rrule.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 49957d43bb9f5..bc49d8f77b6c6 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_saved_objects_settings.mdx b/api_docs/kbn_saved_objects_settings.mdx index 7bfc27355d592..e6de3f110c023 100644 --- a/api_docs/kbn_saved_objects_settings.mdx +++ b/api_docs/kbn_saved_objects_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-saved-objects-settings title: "@kbn/saved-objects-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/saved-objects-settings plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/saved-objects-settings'] --- import kbnSavedObjectsSettingsObj from './kbn_saved_objects_settings.devdocs.json'; diff --git a/api_docs/kbn_screenshotting_server.mdx b/api_docs/kbn_screenshotting_server.mdx index a01abd70ab52a..6a1f75bcc8cc8 100644 --- a/api_docs/kbn_screenshotting_server.mdx +++ b/api_docs/kbn_screenshotting_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-screenshotting-server title: "@kbn/screenshotting-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/screenshotting-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/screenshotting-server'] --- import kbnScreenshottingServerObj from './kbn_screenshotting_server.devdocs.json'; diff --git a/api_docs/kbn_search_api_panels.mdx b/api_docs/kbn_search_api_panels.mdx index 652436cc2dc9d..08967a289b716 100644 --- a/api_docs/kbn_search_api_panels.mdx +++ b/api_docs/kbn_search_api_panels.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-api-panels title: "@kbn/search-api-panels" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-api-panels plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-panels'] --- import kbnSearchApiPanelsObj from './kbn_search_api_panels.devdocs.json'; diff --git a/api_docs/kbn_search_connectors.mdx b/api_docs/kbn_search_connectors.mdx index 22640dd1b1273..39f72e1e8cb18 100644 --- a/api_docs/kbn_search_connectors.mdx +++ b/api_docs/kbn_search_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-connectors title: "@kbn/search-connectors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-connectors plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-connectors'] --- import kbnSearchConnectorsObj from './kbn_search_connectors.devdocs.json'; diff --git a/api_docs/kbn_search_errors.mdx b/api_docs/kbn_search_errors.mdx index 573a1a2d7198c..67a2361579689 100644 --- a/api_docs/kbn_search_errors.mdx +++ b/api_docs/kbn_search_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-errors title: "@kbn/search-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-errors plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-errors'] --- import kbnSearchErrorsObj from './kbn_search_errors.devdocs.json'; diff --git a/api_docs/kbn_search_index_documents.mdx b/api_docs/kbn_search_index_documents.mdx index 2c623dd2691c8..80e09e4d6bbd8 100644 --- a/api_docs/kbn_search_index_documents.mdx +++ b/api_docs/kbn_search_index_documents.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-index-documents title: "@kbn/search-index-documents" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-index-documents plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-index-documents'] --- import kbnSearchIndexDocumentsObj from './kbn_search_index_documents.devdocs.json'; diff --git a/api_docs/kbn_search_response_warnings.mdx b/api_docs/kbn_search_response_warnings.mdx index f33aed11984d7..9c0f4e16a03a6 100644 --- a/api_docs/kbn_search_response_warnings.mdx +++ b/api_docs/kbn_search_response_warnings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-response-warnings title: "@kbn/search-response-warnings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-response-warnings plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-response-warnings'] --- import kbnSearchResponseWarningsObj from './kbn_search_response_warnings.devdocs.json'; diff --git a/api_docs/kbn_search_types.mdx b/api_docs/kbn_search_types.mdx index 4ac282e8ebca1..3953007209662 100644 --- a/api_docs/kbn_search_types.mdx +++ b/api_docs/kbn_search_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-types title: "@kbn/search-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-types plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-types'] --- import kbnSearchTypesObj from './kbn_search_types.devdocs.json'; diff --git a/api_docs/kbn_security_api_key_management.mdx b/api_docs/kbn_security_api_key_management.mdx index f6189b9954646..8ead181dd4930 100644 --- a/api_docs/kbn_security_api_key_management.mdx +++ b/api_docs/kbn_security_api_key_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-api-key-management title: "@kbn/security-api-key-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-api-key-management plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-api-key-management'] --- import kbnSecurityApiKeyManagementObj from './kbn_security_api_key_management.devdocs.json'; diff --git a/api_docs/kbn_security_authorization_core.mdx b/api_docs/kbn_security_authorization_core.mdx index 593238d47cb2c..c51c75c3b5491 100644 --- a/api_docs/kbn_security_authorization_core.mdx +++ b/api_docs/kbn_security_authorization_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-authorization-core title: "@kbn/security-authorization-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-authorization-core plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-authorization-core'] --- import kbnSecurityAuthorizationCoreObj from './kbn_security_authorization_core.devdocs.json'; diff --git a/api_docs/kbn_security_form_components.mdx b/api_docs/kbn_security_form_components.mdx index d8387aec6dcb2..775cc4344712f 100644 --- a/api_docs/kbn_security_form_components.mdx +++ b/api_docs/kbn_security_form_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-form-components title: "@kbn/security-form-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-form-components plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-form-components'] --- import kbnSecurityFormComponentsObj from './kbn_security_form_components.devdocs.json'; diff --git a/api_docs/kbn_security_hardening.mdx b/api_docs/kbn_security_hardening.mdx index 02b95af23522a..fb9b5e1ef9cb6 100644 --- a/api_docs/kbn_security_hardening.mdx +++ b/api_docs/kbn_security_hardening.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-hardening title: "@kbn/security-hardening" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-hardening plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-hardening'] --- import kbnSecurityHardeningObj from './kbn_security_hardening.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_common.mdx b/api_docs/kbn_security_plugin_types_common.mdx index 998678024f3fd..e628301da26df 100644 --- a/api_docs/kbn_security_plugin_types_common.mdx +++ b/api_docs/kbn_security_plugin_types_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-common title: "@kbn/security-plugin-types-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-common plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-common'] --- import kbnSecurityPluginTypesCommonObj from './kbn_security_plugin_types_common.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_public.devdocs.json b/api_docs/kbn_security_plugin_types_public.devdocs.json index 03955b2029ad2..3dee61c995c96 100644 --- a/api_docs/kbn_security_plugin_types_public.devdocs.json +++ b/api_docs/kbn_security_plugin_types_public.devdocs.json @@ -1,7 +1,76 @@ { "id": "@kbn/security-plugin-types-public", "client": { - "classes": [], + "classes": [ + { + "parentPluginId": "@kbn/security-plugin-types-public", + "id": "def-public.PrivilegesAPIClientPublicContract", + "type": "Class", + "tags": [], + "label": "PrivilegesAPIClientPublicContract", + "description": [], + "path": "x-pack/packages/security/plugin_types_public/src/privileges/privileges_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-plugin-types-public", + "id": "def-public.PrivilegesAPIClientPublicContract.getAll", + "type": "Function", + "tags": [], + "label": "getAll", + "description": [], + "signature": [ + "(args: ", + { + "pluginId": "@kbn/security-plugin-types-public", + "scope": "public", + "docId": "kibKbnSecurityPluginTypesPublicPluginApi", + "section": "def-public.PrivilegesAPIClientGetAllArgs", + "text": "PrivilegesAPIClientGetAllArgs" + }, + ") => Promise<", + { + "pluginId": "@kbn/security-authorization-core", + "scope": "server", + "docId": "kibKbnSecurityAuthorizationCorePluginApi", + "section": "def-server.RawKibanaPrivileges", + "text": "RawKibanaPrivileges" + }, + ">" + ], + "path": "x-pack/packages/security/plugin_types_public/src/privileges/privileges_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-plugin-types-public", + "id": "def-public.PrivilegesAPIClientPublicContract.getAll.$1", + "type": "Object", + "tags": [], + "label": "args", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-plugin-types-public", + "scope": "public", + "docId": "kibKbnSecurityPluginTypesPublicPluginApi", + "section": "def-public.PrivilegesAPIClientGetAllArgs", + "text": "PrivilegesAPIClientGetAllArgs" + } + ], + "path": "x-pack/packages/security/plugin_types_public/src/privileges/privileges_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], "functions": [], "interfaces": [ { @@ -112,6 +181,28 @@ "path": "x-pack/packages/security/plugin_types_public/src/authorization/authorization_service.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-public", + "id": "def-public.AuthorizationServiceSetup.privileges", + "type": "Object", + "tags": [], + "label": "privileges", + "description": [ + "\nA set of methods to work with Kibana role privileges" + ], + "signature": [ + { + "pluginId": "@kbn/security-plugin-types-public", + "scope": "public", + "docId": "kibKbnSecurityPluginTypesPublicPluginApi", + "section": "def-public.PrivilegesAPIClientPublicContract", + "text": "PrivilegesAPIClientPublicContract" + } + ], + "path": "x-pack/packages/security/plugin_types_public/src/authorization/authorization_service.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -187,6 +278,42 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/security-plugin-types-public", + "id": "def-public.PrivilegesAPIClientGetAllArgs", + "type": "Interface", + "tags": [], + "label": "PrivilegesAPIClientGetAllArgs", + "description": [], + "path": "x-pack/packages/security/plugin_types_public/src/privileges/privileges_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-plugin-types-public", + "id": "def-public.PrivilegesAPIClientGetAllArgs.includeActions", + "type": "boolean", + "tags": [], + "label": "includeActions", + "description": [], + "path": "x-pack/packages/security/plugin_types_public/src/privileges/privileges_api_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-public", + "id": "def-public.PrivilegesAPIClientGetAllArgs.respectLicenseLevel", + "type": "boolean", + "tags": [], + "label": "respectLicenseLevel", + "description": [], + "path": "x-pack/packages/security/plugin_types_public/src/privileges/privileges_api_client.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/security-plugin-types-public", "id": "def-public.RolePutPayload", diff --git a/api_docs/kbn_security_plugin_types_public.mdx b/api_docs/kbn_security_plugin_types_public.mdx index 07ec6782f80ed..1c721f890b421 100644 --- a/api_docs/kbn_security_plugin_types_public.mdx +++ b/api_docs/kbn_security_plugin_types_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-public title: "@kbn/security-plugin-types-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-public plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-public'] --- import kbnSecurityPluginTypesPublicObj from './kbn_security_plugin_types_public.devdocs.json'; @@ -21,10 +21,13 @@ Contact [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana- | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 51 | 0 | 25 | 0 | +| 58 | 0 | 31 | 0 | ## Client +### Classes + + ### Interfaces diff --git a/api_docs/kbn_security_plugin_types_server.mdx b/api_docs/kbn_security_plugin_types_server.mdx index a06bff9ce2b9e..27045f6d4b60f 100644 --- a/api_docs/kbn_security_plugin_types_server.mdx +++ b/api_docs/kbn_security_plugin_types_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-server title: "@kbn/security-plugin-types-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-server plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-server'] --- import kbnSecurityPluginTypesServerObj from './kbn_security_plugin_types_server.devdocs.json'; diff --git a/api_docs/kbn_security_role_management_model.mdx b/api_docs/kbn_security_role_management_model.mdx index f71acbae2bc64..ffe4ffe18eba6 100644 --- a/api_docs/kbn_security_role_management_model.mdx +++ b/api_docs/kbn_security_role_management_model.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-role-management-model title: "@kbn/security-role-management-model" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-role-management-model plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-role-management-model'] --- import kbnSecurityRoleManagementModelObj from './kbn_security_role_management_model.devdocs.json'; diff --git a/api_docs/kbn_security_solution_common.devdocs.json b/api_docs/kbn_security_solution_common.devdocs.json new file mode 100644 index 0000000000000..18ebfccd424ad --- /dev/null +++ b/api_docs/kbn_security_solution_common.devdocs.json @@ -0,0 +1,1025 @@ +{ + "id": "@kbn/security-solution-common", + "client": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPANDABLE_PANEL_CONTENT_TEST_ID", + "type": "Function", + "tags": [], + "label": "EXPANDABLE_PANEL_CONTENT_TEST_ID", + "description": [], + "signature": [ + "(dataTestSubj: string) => string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPANDABLE_PANEL_CONTENT_TEST_ID.$1", + "type": "string", + "tags": [], + "label": "dataTestSubj", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPANDABLE_PANEL_HEADER_LEFT_SECTION_TEST_ID", + "type": "Function", + "tags": [], + "label": "EXPANDABLE_PANEL_HEADER_LEFT_SECTION_TEST_ID", + "description": [], + "signature": [ + "(dataTestSubj: string) => string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPANDABLE_PANEL_HEADER_LEFT_SECTION_TEST_ID.$1", + "type": "string", + "tags": [], + "label": "dataTestSubj", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPANDABLE_PANEL_HEADER_RIGHT_SECTION_TEST_ID", + "type": "Function", + "tags": [], + "label": "EXPANDABLE_PANEL_HEADER_RIGHT_SECTION_TEST_ID", + "description": [], + "signature": [ + "(dataTestSubj: string) => string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPANDABLE_PANEL_HEADER_RIGHT_SECTION_TEST_ID.$1", + "type": "string", + "tags": [], + "label": "dataTestSubj", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPANDABLE_PANEL_HEADER_TITLE_ICON_TEST_ID", + "type": "Function", + "tags": [], + "label": "EXPANDABLE_PANEL_HEADER_TITLE_ICON_TEST_ID", + "description": [], + "signature": [ + "(dataTestSubj: string) => string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPANDABLE_PANEL_HEADER_TITLE_ICON_TEST_ID.$1", + "type": "string", + "tags": [], + "label": "dataTestSubj", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPANDABLE_PANEL_HEADER_TITLE_LINK_TEST_ID", + "type": "Function", + "tags": [], + "label": "EXPANDABLE_PANEL_HEADER_TITLE_LINK_TEST_ID", + "description": [], + "signature": [ + "(dataTestSubj: string) => string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPANDABLE_PANEL_HEADER_TITLE_LINK_TEST_ID.$1", + "type": "string", + "tags": [], + "label": "dataTestSubj", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID", + "type": "Function", + "tags": [], + "label": "EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID", + "description": [], + "signature": [ + "(dataTestSubj: string) => string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID.$1", + "type": "string", + "tags": [], + "label": "dataTestSubj", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPANDABLE_PANEL_LOADING_TEST_ID", + "type": "Function", + "tags": [], + "label": "EXPANDABLE_PANEL_LOADING_TEST_ID", + "description": [], + "signature": [ + "(dataTestSubj: string) => string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPANDABLE_PANEL_LOADING_TEST_ID.$1", + "type": "string", + "tags": [], + "label": "dataTestSubj", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID", + "type": "Function", + "tags": [], + "label": "EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID", + "description": [], + "signature": [ + "(dataTestSubj: string) => string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID.$1", + "type": "string", + "tags": [], + "label": "dataTestSubj", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.ExpandablePanel", + "type": "Function", + "tags": [], + "label": "ExpandablePanel", + "description": [ + "\nWrapper component that is composed of a header section and a content section.\nThe header can display an icon, a title (that can be a link), and an optional content section on the right.\nThe content section can display a loading spinner, an error message, or any other content.\nThe component can be expanded or collapsed by clicking on the chevron icon on the left of the title." + ], + "signature": [ + "{ ({ header: { title, link, iconType, headerContent }, content: { loading, error }, expand: { expandable, expandedOnFirstRender }, \"data-test-subj\": dataTestSubj, children, }: React.PropsWithChildren>): JSX.Element; displayName: string | undefined; }" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/components/expandable_panel.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.ExpandablePanel.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n header: { title, link, iconType, headerContent },\n content: { loading, error } = { loading: false, error: false },\n expand: { expandable, expandedOnFirstRender } = {\n expandable: false,\n expandedOnFirstRender: false,\n },\n 'data-test-subj': dataTestSubj,\n children,\n}", + "description": [], + "signature": [ + "React.PropsWithChildren>" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/components/expandable_panel.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutBody", + "type": "Function", + "tags": [], + "label": "FlyoutBody", + "description": [ + "\nWrapper of `EuiFlyoutBody`, setting the recommended `16px` padding using a EuiPanel." + ], + "signature": [ + "React.FunctionComponent" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/components/flyout_body.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutBody.$1", + "type": "CompoundType", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "P & { children?: React.ReactNode; }" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutBody.$2", + "type": "Any", + "tags": [], + "label": "context", + "description": [], + "signature": [ + "any" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutError", + "type": "Function", + "tags": [], + "label": "FlyoutError", + "description": [ + "\nUse this when you need to show an error state in the flyout" + ], + "signature": [ + "{ (): JSX.Element; displayName: string | undefined; }" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/components/flyout_error.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutFooter", + "type": "Function", + "tags": [], + "label": "FlyoutFooter", + "description": [ + "\nWrapper of `EuiFlyoutFooter`, setting the recommended `16px` padding using a EuiPanel." + ], + "signature": [ + "React.FunctionComponent" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/components/flyout_footer.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutFooter.$1", + "type": "CompoundType", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "P & { children?: React.ReactNode; }" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutFooter.$2", + "type": "Any", + "tags": [], + "label": "context", + "description": [], + "signature": [ + "any" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutHeader", + "type": "Function", + "tags": [], + "label": "FlyoutHeader", + "description": [ + "\nWrapper of `EuiFlyoutHeader`, setting the recommended `16px` padding using a EuiPanel." + ], + "signature": [ + "React.FunctionComponent" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/components/flyout_header.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutHeader.$1", + "type": "CompoundType", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "P & { children?: React.ReactNode; }" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutHeader.$2", + "type": "Any", + "tags": [], + "label": "context", + "description": [], + "signature": [ + "any" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutHeaderTabs", + "type": "Function", + "tags": [], + "label": "FlyoutHeaderTabs", + "description": [ + "\nWrapper of `EuiTabs`, setting bottom margin to align with the flyout header divider" + ], + "signature": [ + "React.FunctionComponent" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/components/flyout_header_tabs.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutHeaderTabs.$1", + "type": "CompoundType", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "P & { children?: React.ReactNode; }" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutHeaderTabs.$2", + "type": "Any", + "tags": [], + "label": "context", + "description": [], + "signature": [ + "any" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutLoading", + "type": "Function", + "tags": [], + "label": "FlyoutLoading", + "description": [ + "\nUse this when you need to show a loading state in the flyout" + ], + "signature": [ + "({ \"data-test-subj\": dataTestSubj, }: React.PropsWithChildren<", + "FlyoutLoadingProps", + ">) => JSX.Element" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/components/flyout_loading.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutLoading.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n 'data-test-subj': dataTestSubj = FLYOUT_LOADING_TEST_ID,\n}", + "description": [], + "signature": [ + "React.PropsWithChildren<", + "FlyoutLoadingProps", + ">" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/components/flyout_loading.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutNavigation", + "type": "Function", + "tags": [], + "label": "FlyoutNavigation", + "description": [ + "\nNavigation menu on the right panel only, with expand/collapse button and option to\npass in a list of actions to be displayed on top." + ], + "signature": [ + "React.FunctionComponent<", + "FlyoutNavigationProps", + ">" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/components/flyout_navigation.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutNavigation.$1", + "type": "CompoundType", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "P & { children?: React.ReactNode; }" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutNavigation.$2", + "type": "Any", + "tags": [], + "label": "context", + "description": [], + "signature": [ + "any" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutTitle", + "type": "Function", + "tags": [], + "label": "FlyoutTitle", + "description": [ + "\nTitle component with optional icon to indicate the type of document, can be used for text or a link" + ], + "signature": [ + "React.FunctionComponent<", + "FlyoutTitleProps", + ">" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/components/flyout_title.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutTitle.$1", + "type": "CompoundType", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "P & { children?: React.ReactNode; }" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FlyoutTitle.$2", + "type": "Any", + "tags": [], + "label": "context", + "description": [], + "signature": [ + "any" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.getDiscoverCellRenderer", + "type": "Function", + "tags": [], + "label": "getDiscoverCellRenderer", + "description": [], + "signature": [ + "({ fieldName }: GetRendererArgs) => ", + { + "pluginId": "@kbn/security-solution-common", + "scope": "public", + "docId": "kibKbnSecuritySolutionCommonPluginApi", + "section": "def-public.DiscoverCellRenderer", + "text": "DiscoverCellRenderer" + } + ], + "path": "x-pack/packages/security-solution/common/src/cells/renderers/discover.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.getDiscoverCellRenderer.$1", + "type": "Object", + "tags": [], + "label": "{ fieldName }", + "description": [], + "signature": [ + "GetRendererArgs" + ], + "path": "x-pack/packages/security-solution/common/src/cells/renderers/discover.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.HostDetailsButton", + "type": "Function", + "tags": [], + "label": "HostDetailsButton", + "description": [], + "signature": [ + "({ children, onClick, title, }: React.PropsWithChildren) => JSX.Element" + ], + "path": "x-pack/packages/security-solution/common/src/cells/renderers/host/button.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.HostDetailsButton.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n children,\n onClick,\n title,\n}", + "description": [], + "signature": [ + "React.PropsWithChildren" + ], + "path": "x-pack/packages/security-solution/common/src/cells/renderers/host/button.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.HostRightPanel", + "type": "Function", + "tags": [], + "label": "HostRightPanel", + "description": [], + "signature": [ + "(props: ", + "HostRightPanelParamProps", + ") => JSX.Element" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/panels/host/right/index.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.HostRightPanel.$1", + "type": "Object", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "HostRightPanelParamProps" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/panels/host/right/index.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.TITLE_HEADER_ICON_TEST_ID", + "type": "Function", + "tags": [], + "label": "TITLE_HEADER_ICON_TEST_ID", + "description": [], + "signature": [ + "(dataTestSubj: string) => string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.TITLE_HEADER_ICON_TEST_ID.$1", + "type": "string", + "tags": [], + "label": "dataTestSubj", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.TITLE_HEADER_TEXT_TEST_ID", + "type": "Function", + "tags": [], + "label": "TITLE_HEADER_TEXT_TEST_ID", + "description": [], + "signature": [ + "(dataTestSubj: string) => string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.TITLE_HEADER_TEXT_TEST_ID.$1", + "type": "string", + "tags": [], + "label": "dataTestSubj", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.TITLE_LINK_ICON_TEST_ID", + "type": "Function", + "tags": [], + "label": "TITLE_LINK_ICON_TEST_ID", + "description": [], + "signature": [ + "(dataTestSubj: string) => string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.TITLE_LINK_ICON_TEST_ID.$1", + "type": "string", + "tags": [], + "label": "dataTestSubj", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.COLLAPSE_DETAILS_BUTTON_TEST_ID", + "type": "string", + "tags": [], + "label": "COLLAPSE_DETAILS_BUTTON_TEST_ID", + "description": [], + "signature": [ + "\"securitySolutionFlyoutNavigationCollapseDetailButton\"" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.DiscoverCellRenderer", + "type": "Type", + "tags": [], + "label": "DiscoverCellRenderer", + "description": [], + "signature": [ + "React.ComponentClass, any> | React.FunctionComponent>" + ], + "path": "x-pack/packages/security-solution/common/src/cells/renderers/discover.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.EXPAND_DETAILS_BUTTON_TEST_ID", + "type": "string", + "tags": [], + "label": "EXPAND_DETAILS_BUTTON_TEST_ID", + "description": [], + "signature": [ + "\"securitySolutionFlyoutNavigationExpandDetailButton\"" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FLYOUT_ERROR_TEST_ID", + "type": "string", + "tags": [], + "label": "FLYOUT_ERROR_TEST_ID", + "description": [], + "signature": [ + "\"securitySolutionFlyoutError\"" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.FLYOUT_LOADING_TEST_ID", + "type": "string", + "tags": [], + "label": "FLYOUT_LOADING_TEST_ID", + "description": [], + "signature": [ + "\"securitySolutionFlyoutLoading\"" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.HEADER_ACTIONS_TEST_ID", + "type": "string", + "tags": [], + "label": "HEADER_ACTIONS_TEST_ID", + "description": [], + "signature": [ + "\"securitySolutionFlyoutNavigationActions\"" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.HEADER_NAVIGATION_BUTTON_TEST_ID", + "type": "string", + "tags": [], + "label": "HEADER_NAVIGATION_BUTTON_TEST_ID", + "description": [], + "signature": [ + "\"securitySolutionFlyoutNavigationButton\"" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-solution-common", + "id": "def-public.PREFIX", + "type": "string", + "tags": [], + "label": "PREFIX", + "description": [], + "signature": [ + "\"securitySolutionFlyout\"" + ], + "path": "x-pack/packages/security-solution/common/src/flyout/common/test_ids.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_security_solution_common.mdx b/api_docs/kbn_security_solution_common.mdx new file mode 100644 index 0000000000000..662dd064bb58d --- /dev/null +++ b/api_docs/kbn_security_solution_common.mdx @@ -0,0 +1,33 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnSecuritySolutionCommonPluginApi +slug: /kibana-dev-docs/api/kbn-security-solution-common +title: "@kbn/security-solution-common" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/security-solution-common plugin +date: 2024-08-29 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-common'] +--- +import kbnSecuritySolutionCommonObj from './kbn_security_solution_common.devdocs.json'; + + + +Contact [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 59 | 0 | 38 | 5 | + +## Client + +### Functions + + +### Consts, variables and types + + diff --git a/api_docs/kbn_security_solution_distribution_bar.mdx b/api_docs/kbn_security_solution_distribution_bar.mdx index 5bf0cd8b907ae..2833a865c42f0 100644 --- a/api_docs/kbn_security_solution_distribution_bar.mdx +++ b/api_docs/kbn_security_solution_distribution_bar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-distribution-bar title: "@kbn/security-solution-distribution-bar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-distribution-bar plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-distribution-bar'] --- import kbnSecuritySolutionDistributionBarObj from './kbn_security_solution_distribution_bar.devdocs.json'; diff --git a/api_docs/kbn_security_solution_features.mdx b/api_docs/kbn_security_solution_features.mdx index 88581262f9d03..dfe2677747d5f 100644 --- a/api_docs/kbn_security_solution_features.mdx +++ b/api_docs/kbn_security_solution_features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-features title: "@kbn/security-solution-features" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-features plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-features'] --- import kbnSecuritySolutionFeaturesObj from './kbn_security_solution_features.devdocs.json'; diff --git a/api_docs/kbn_security_solution_navigation.mdx b/api_docs/kbn_security_solution_navigation.mdx index d73e565c2d382..c259e0c5d0630 100644 --- a/api_docs/kbn_security_solution_navigation.mdx +++ b/api_docs/kbn_security_solution_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-navigation title: "@kbn/security-solution-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-navigation plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-navigation'] --- import kbnSecuritySolutionNavigationObj from './kbn_security_solution_navigation.devdocs.json'; diff --git a/api_docs/kbn_security_solution_side_nav.mdx b/api_docs/kbn_security_solution_side_nav.mdx index d55725ff48879..c99a74eb197a6 100644 --- a/api_docs/kbn_security_solution_side_nav.mdx +++ b/api_docs/kbn_security_solution_side_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-side-nav title: "@kbn/security-solution-side-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-side-nav plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-side-nav'] --- import kbnSecuritySolutionSideNavObj from './kbn_security_solution_side_nav.devdocs.json'; diff --git a/api_docs/kbn_security_solution_storybook_config.mdx b/api_docs/kbn_security_solution_storybook_config.mdx index 7511ee792f431..0c9d855ea008c 100644 --- a/api_docs/kbn_security_solution_storybook_config.mdx +++ b/api_docs/kbn_security_solution_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-storybook-config title: "@kbn/security-solution-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-storybook-config plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-storybook-config'] --- import kbnSecuritySolutionStorybookConfigObj from './kbn_security_solution_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_security_ui_components.devdocs.json b/api_docs/kbn_security_ui_components.devdocs.json new file mode 100644 index 0000000000000..9a0cd5098d114 --- /dev/null +++ b/api_docs/kbn_security_ui_components.devdocs.json @@ -0,0 +1,880 @@ +{ + "id": "@kbn/security-ui-components", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.FeatureTable", + "type": "Class", + "tags": [], + "label": "FeatureTable", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-ui-components", + "scope": "common", + "docId": "kibKbnSecurityUiComponentsPluginApi", + "section": "def-common.FeatureTable", + "text": "FeatureTable" + }, + " extends React.Component" + ], + "path": "x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.FeatureTable.defaultProps", + "type": "Object", + "tags": [], + "label": "defaultProps", + "description": [], + "path": "x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.FeatureTable.defaultProps.privilegeIndex", + "type": "number", + "tags": [], + "label": "privilegeIndex", + "description": [], + "path": "x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.FeatureTable.defaultProps.showLocks", + "type": "boolean", + "tags": [], + "label": "showLocks", + "description": [], + "path": "x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.tsx", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.FeatureTable.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.FeatureTable.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "Props" + ], + "path": "x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.FeatureTable.render", + "type": "Function", + "tags": [], + "label": "render", + "description": [], + "signature": [ + "() => JSX.Element" + ], + "path": "x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator", + "type": "Class", + "tags": [], + "label": "PrivilegeFormCalculator", + "description": [ + "\nCalculator responsible for determining the displayed and effective privilege values for the following interfaces:\n- and children\n- and children" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "kibanaPrivileges", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-role-management-model", + "scope": "common", + "docId": "kibKbnSecurityRoleManagementModelPluginApi", + "section": "def-common.KibanaPrivileges", + "text": "KibanaPrivileges" + } + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.Unnamed.$2", + "type": "Object", + "tags": [], + "label": "role", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.Role", + "text": "Role" + } + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.getBasePrivilege", + "type": "Function", + "tags": [], + "label": "getBasePrivilege", + "description": [ + "\nReturns the assigned base privilege.\nIf more than one base privilege is assigned, the most permissive privilege will be returned.\nIf no base privileges are assigned, then this will return `undefined`.\n" + ], + "signature": [ + "(privilegeIndex: number) => ", + { + "pluginId": "@kbn/security-role-management-model", + "scope": "common", + "docId": "kibKbnSecurityRoleManagementModelPluginApi", + "section": "def-common.KibanaPrivilege", + "text": "KibanaPrivilege" + }, + " | undefined" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.getBasePrivilege.$1", + "type": "number", + "tags": [], + "label": "privilegeIndex", + "description": [ + "the index of the kibana privileges role component" + ], + "signature": [ + "number" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.isWildcardBasePrivilege", + "type": "Function", + "tags": [], + "label": "isWildcardBasePrivilege", + "description": [ + "\nReturns true if it is base wildcard (*) privilege.\n" + ], + "signature": [ + "(privilegeIndex: number) => boolean" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.isWildcardBasePrivilege.$1", + "type": "number", + "tags": [], + "label": "privilegeIndex", + "description": [ + "the index of the kibana privileges role component" + ], + "signature": [ + "number" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.getDisplayedPrimaryFeaturePrivilegeId", + "type": "Function", + "tags": [], + "label": "getDisplayedPrimaryFeaturePrivilegeId", + "description": [ + "\nReturns the ID of the *displayed* Primary Feature Privilege for the indicated feature and privilege index.\nIf the effective primary feature privilege is a \"minimal\" version, then this returns the corresponding non-minimal version.\n" + ], + "signature": [ + "(featureId: string, privilegeIndex: number, allSpacesSelected: boolean) => string | undefined" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.getDisplayedPrimaryFeaturePrivilegeId.$1", + "type": "string", + "tags": [], + "label": "featureId", + "description": [ + "the feature id to get the Primary Feature KibanaPrivilege for." + ], + "signature": [ + "string" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.getDisplayedPrimaryFeaturePrivilegeId.$2", + "type": "number", + "tags": [], + "label": "privilegeIndex", + "description": [ + "the index of the kibana privileges role component" + ], + "signature": [ + "number" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.getDisplayedPrimaryFeaturePrivilegeId.$3", + "type": "boolean", + "tags": [], + "label": "allSpacesSelected", + "description": [ + "indicates if the privilege form is configured to grant access to all spaces." + ], + "signature": [ + "boolean" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.hasCustomizedSubFeaturePrivileges", + "type": "Function", + "tags": [], + "label": "hasCustomizedSubFeaturePrivileges", + "description": [ + "\nDetermines if the indicated feature has sub-feature privilege assignments which differ from the \"displayed\" primary feature privilege.\n" + ], + "signature": [ + "(featureId: string, privilegeIndex: number, allSpacesSelected: boolean) => boolean" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.hasCustomizedSubFeaturePrivileges.$1", + "type": "string", + "tags": [], + "label": "featureId", + "description": [ + "the feature id" + ], + "signature": [ + "string" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.hasCustomizedSubFeaturePrivileges.$2", + "type": "number", + "tags": [], + "label": "privilegeIndex", + "description": [ + "the index of the kibana privileges role component" + ], + "signature": [ + "number" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.hasCustomizedSubFeaturePrivileges.$3", + "type": "boolean", + "tags": [], + "label": "allSpacesSelected", + "description": [ + "indicates if the privilege form is configured to grant access to all spaces." + ], + "signature": [ + "boolean" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.getEffectivePrimaryFeaturePrivilege", + "type": "Function", + "tags": [], + "label": "getEffectivePrimaryFeaturePrivilege", + "description": [ + "\nReturns the most permissive effective Primary Feature KibanaPrivilege, including the minimal versions.\n" + ], + "signature": [ + "(featureId: string, privilegeIndex: number, allSpacesSelected?: boolean | undefined) => ", + { + "pluginId": "@kbn/security-role-management-model", + "scope": "common", + "docId": "kibKbnSecurityRoleManagementModelPluginApi", + "section": "def-common.PrimaryFeaturePrivilege", + "text": "PrimaryFeaturePrivilege" + }, + " | undefined" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.getEffectivePrimaryFeaturePrivilege.$1", + "type": "string", + "tags": [], + "label": "featureId", + "description": [ + "the feature id" + ], + "signature": [ + "string" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.getEffectivePrimaryFeaturePrivilege.$2", + "type": "number", + "tags": [], + "label": "privilegeIndex", + "description": [ + "the index of the kibana privileges role component" + ], + "signature": [ + "number" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.getEffectivePrimaryFeaturePrivilege.$3", + "type": "CompoundType", + "tags": [], + "label": "allSpacesSelected", + "description": [ + "indicates if the privilege form is configured to grant access to all spaces." + ], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.isIndependentSubFeaturePrivilegeGranted", + "type": "Function", + "tags": [], + "label": "isIndependentSubFeaturePrivilegeGranted", + "description": [ + "\nDetermines if the indicated sub-feature privilege is granted.\n" + ], + "signature": [ + "(featureId: string, privilegeId: string, privilegeIndex: number) => boolean" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.isIndependentSubFeaturePrivilegeGranted.$1", + "type": "string", + "tags": [], + "label": "featureId", + "description": [ + "the feature id" + ], + "signature": [ + "string" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.isIndependentSubFeaturePrivilegeGranted.$2", + "type": "string", + "tags": [], + "label": "privilegeId", + "description": [ + "the sub feature privilege id" + ], + "signature": [ + "string" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.isIndependentSubFeaturePrivilegeGranted.$3", + "type": "number", + "tags": [], + "label": "privilegeIndex", + "description": [ + "the index of the kibana privileges role component" + ], + "signature": [ + "number" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.getSelectedMutuallyExclusiveSubFeaturePrivilege", + "type": "Function", + "tags": [], + "label": "getSelectedMutuallyExclusiveSubFeaturePrivilege", + "description": [ + "\nReturns the most permissive effective privilege within the indicated mutually-exclusive sub feature privilege group.\n" + ], + "signature": [ + "(featureId: string, subFeatureGroup: ", + { + "pluginId": "@kbn/security-role-management-model", + "scope": "common", + "docId": "kibKbnSecurityRoleManagementModelPluginApi", + "section": "def-common.SubFeaturePrivilegeGroup", + "text": "SubFeaturePrivilegeGroup" + }, + ", privilegeIndex: number) => ", + { + "pluginId": "@kbn/security-role-management-model", + "scope": "common", + "docId": "kibKbnSecurityRoleManagementModelPluginApi", + "section": "def-common.SubFeaturePrivilege", + "text": "SubFeaturePrivilege" + }, + " | undefined" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.getSelectedMutuallyExclusiveSubFeaturePrivilege.$1", + "type": "string", + "tags": [], + "label": "featureId", + "description": [ + "the feature id" + ], + "signature": [ + "string" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.getSelectedMutuallyExclusiveSubFeaturePrivilege.$2", + "type": "Object", + "tags": [], + "label": "subFeatureGroup", + "description": [ + "the mutually-exclusive sub feature group" + ], + "signature": [ + { + "pluginId": "@kbn/security-role-management-model", + "scope": "common", + "docId": "kibKbnSecurityRoleManagementModelPluginApi", + "section": "def-common.SubFeaturePrivilegeGroup", + "text": "SubFeaturePrivilegeGroup" + } + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.getSelectedMutuallyExclusiveSubFeaturePrivilege.$3", + "type": "number", + "tags": [], + "label": "privilegeIndex", + "description": [ + "the index of the kibana privileges role component" + ], + "signature": [ + "number" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.canCustomizeSubFeaturePrivileges", + "type": "Function", + "tags": [], + "label": "canCustomizeSubFeaturePrivileges", + "description": [ + "\nDetermines if the indicated feature is capable of having its sub-feature privileges customized.\n" + ], + "signature": [ + "(featureId: string, privilegeIndex: number) => boolean" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.canCustomizeSubFeaturePrivileges.$1", + "type": "string", + "tags": [], + "label": "featureId", + "description": [ + "the feature id" + ], + "signature": [ + "string" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.canCustomizeSubFeaturePrivileges.$2", + "type": "number", + "tags": [], + "label": "privilegeIndex", + "description": [ + "the index of the kibana privileges role component" + ], + "signature": [ + "number" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.updateSelectedFeaturePrivilegesForCustomization", + "type": "Function", + "tags": [], + "label": "updateSelectedFeaturePrivilegesForCustomization", + "description": [ + "\nReturns an updated set of feature privileges based on the toggling of the \"Customize sub-feature privileges\" control.\n" + ], + "signature": [ + "(featureId: string, privilegeIndex: number, willBeCustomizing: boolean, allSpacesSelected: boolean) => string[]" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.updateSelectedFeaturePrivilegesForCustomization.$1", + "type": "string", + "tags": [], + "label": "featureId", + "description": [ + "the feature id" + ], + "signature": [ + "string" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.updateSelectedFeaturePrivilegesForCustomization.$2", + "type": "number", + "tags": [], + "label": "privilegeIndex", + "description": [ + "the index of the kibana privileges role component" + ], + "signature": [ + "number" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.updateSelectedFeaturePrivilegesForCustomization.$3", + "type": "boolean", + "tags": [], + "label": "willBeCustomizing", + "description": [ + "flag indicating if this feature is about to have its sub-feature privileges customized or not" + ], + "signature": [ + "boolean" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.updateSelectedFeaturePrivilegesForCustomization.$4", + "type": "boolean", + "tags": [], + "label": "allSpacesSelected", + "description": [ + "indicates if the privilege form is configured to grant access to all spaces." + ], + "signature": [ + "boolean" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.hasSupersededInheritedPrivileges", + "type": "Function", + "tags": [], + "label": "hasSupersededInheritedPrivileges", + "description": [ + "\nDetermines if the indicated privilege entry is less permissive than the configured \"global\" entry for the role." + ], + "signature": [ + "(privilegeIndex: number) => boolean" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.PrivilegeFormCalculator.hasSupersededInheritedPrivileges.$1", + "type": "number", + "tags": [], + "label": "privilegeIndex", + "description": [ + "the index of the kibana privileges role component" + ], + "signature": [ + "number" + ], + "path": "x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.FeatureTableCell", + "type": "Function", + "tags": [], + "label": "FeatureTableCell", + "description": [], + "signature": [ + "({ feature, className }: Props) => JSX.Element" + ], + "path": "x-pack/packages/security/ui_components/src/kibana_privilege_table/components/feature_table_cell.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-ui-components", + "id": "def-common.FeatureTableCell.$1", + "type": "Object", + "tags": [], + "label": "{ feature, className }", + "description": [], + "signature": [ + "Props" + ], + "path": "x-pack/packages/security/ui_components/src/kibana_privilege_table/components/feature_table_cell.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_security_ui_components.mdx b/api_docs/kbn_security_ui_components.mdx new file mode 100644 index 0000000000000..b7070467e24c4 --- /dev/null +++ b/api_docs/kbn_security_ui_components.mdx @@ -0,0 +1,33 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnSecurityUiComponentsPluginApi +slug: /kibana-dev-docs/api/kbn-security-ui-components +title: "@kbn/security-ui-components" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/security-ui-components plugin +date: 2024-08-29 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-ui-components'] +--- +import kbnSecurityUiComponentsObj from './kbn_security_ui_components.devdocs.json'; + + + +Contact [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 47 | 0 | 12 | 0 | + +## Common + +### Functions + + +### Classes + + diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 973abe9ee9af1..7e03a18016699 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_data_table.mdx b/api_docs/kbn_securitysolution_data_table.mdx index 8bafe23e3c1d5..e7ef6cfe9ce94 100644 --- a/api_docs/kbn_securitysolution_data_table.mdx +++ b/api_docs/kbn_securitysolution_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-data-table title: "@kbn/securitysolution-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-data-table plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-data-table'] --- import kbnSecuritysolutionDataTableObj from './kbn_securitysolution_data_table.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_ecs.mdx b/api_docs/kbn_securitysolution_ecs.mdx index f927981e3c76f..ce67b54e18ba3 100644 --- a/api_docs/kbn_securitysolution_ecs.mdx +++ b/api_docs/kbn_securitysolution_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-ecs title: "@kbn/securitysolution-ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-ecs plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-ecs'] --- import kbnSecuritysolutionEcsObj from './kbn_securitysolution_ecs.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 7144772c9980e..64ffb880b066e 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index 7c6f79c3c27f9..61237e7aa1951 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.mdx +++ b/api_docs/kbn_securitysolution_exception_list_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-exception-list-components title: "@kbn/securitysolution-exception-list-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-exception-list-components plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-exception-list-components'] --- import kbnSecuritysolutionExceptionListComponentsObj from './kbn_securitysolution_exception_list_components.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 534121d95f21b..6f1227ed88e75 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] --- import kbnSecuritysolutionHookUtilsObj from './kbn_securitysolution_hook_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index a358d827360c1..919429ebe2dfa 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] --- import kbnSecuritysolutionIoTsAlertingTypesObj from './kbn_securitysolution_io_ts_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index b8398b5a0ded0..7e2037ab690a6 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] --- import kbnSecuritysolutionIoTsListTypesObj from './kbn_securitysolution_io_ts_list_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index 425198e68fa64..5f9c758f86ca6 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] --- import kbnSecuritysolutionIoTsTypesObj from './kbn_securitysolution_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index 318da48ddaa26..29831dd98da6b 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] --- import kbnSecuritysolutionIoTsUtilsObj from './kbn_securitysolution_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index 65e5148a9331d..c00df870cd0b5 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] --- import kbnSecuritysolutionListApiObj from './kbn_securitysolution_list_api.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 6d573f6f5cc89..d06ae6b05210f 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] --- import kbnSecuritysolutionListConstantsObj from './kbn_securitysolution_list_constants.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index 1eab2bc0ed216..37a28104dee7e 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] --- import kbnSecuritysolutionListHooksObj from './kbn_securitysolution_list_hooks.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index 3468d526df5e8..db3290d407e4d 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index 05a4daffe5c6a..100f05e2ac102 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] --- import kbnSecuritysolutionRulesObj from './kbn_securitysolution_rules.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index b1ed44e073df3..d5ce15f435685 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] --- import kbnSecuritysolutionTGridObj from './kbn_securitysolution_t_grid.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index b51cc183606cf..3b704edbc3942 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_utils.devdocs.json'; diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index 5100bf9f97a93..89efb64226fd4 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] --- import kbnServerHttpToolsObj from './kbn_server_http_tools.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index 0d11189a3ef25..37c739b729532 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository_client.mdx b/api_docs/kbn_server_route_repository_client.mdx index 1d83cb20af3b9..bc8a03e6c6ffa 100644 --- a/api_docs/kbn_server_route_repository_client.mdx +++ b/api_docs/kbn_server_route_repository_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository-client title: "@kbn/server-route-repository-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository-client plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository-client'] --- import kbnServerRouteRepositoryClientObj from './kbn_server_route_repository_client.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository_utils.mdx b/api_docs/kbn_server_route_repository_utils.mdx index 23891106ad167..d8e21430895e9 100644 --- a/api_docs/kbn_server_route_repository_utils.mdx +++ b/api_docs/kbn_server_route_repository_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository-utils title: "@kbn/server-route-repository-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository-utils'] --- import kbnServerRouteRepositoryUtilsObj from './kbn_server_route_repository_utils.devdocs.json'; diff --git a/api_docs/kbn_serverless_common_settings.mdx b/api_docs/kbn_serverless_common_settings.mdx index 61dafac929b27..910aea6d0acb7 100644 --- a/api_docs/kbn_serverless_common_settings.mdx +++ b/api_docs/kbn_serverless_common_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-common-settings title: "@kbn/serverless-common-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-common-settings plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-common-settings'] --- import kbnServerlessCommonSettingsObj from './kbn_serverless_common_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_observability_settings.mdx b/api_docs/kbn_serverless_observability_settings.mdx index c1e8df59b84d8..d2a3e713f0254 100644 --- a/api_docs/kbn_serverless_observability_settings.mdx +++ b/api_docs/kbn_serverless_observability_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-observability-settings title: "@kbn/serverless-observability-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-observability-settings plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-observability-settings'] --- import kbnServerlessObservabilitySettingsObj from './kbn_serverless_observability_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_project_switcher.mdx b/api_docs/kbn_serverless_project_switcher.mdx index f70c33f9b8247..59f8a1fa2543a 100644 --- a/api_docs/kbn_serverless_project_switcher.mdx +++ b/api_docs/kbn_serverless_project_switcher.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-project-switcher title: "@kbn/serverless-project-switcher" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-project-switcher plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-project-switcher'] --- import kbnServerlessProjectSwitcherObj from './kbn_serverless_project_switcher.devdocs.json'; diff --git a/api_docs/kbn_serverless_search_settings.mdx b/api_docs/kbn_serverless_search_settings.mdx index 442c12f67f7f2..3b4a188a096ad 100644 --- a/api_docs/kbn_serverless_search_settings.mdx +++ b/api_docs/kbn_serverless_search_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-search-settings title: "@kbn/serverless-search-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-search-settings plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-search-settings'] --- import kbnServerlessSearchSettingsObj from './kbn_serverless_search_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_security_settings.mdx b/api_docs/kbn_serverless_security_settings.mdx index 45be2d441bb8a..1d623c28cbf9a 100644 --- a/api_docs/kbn_serverless_security_settings.mdx +++ b/api_docs/kbn_serverless_security_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-security-settings title: "@kbn/serverless-security-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-security-settings plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-security-settings'] --- import kbnServerlessSecuritySettingsObj from './kbn_serverless_security_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_storybook_config.mdx b/api_docs/kbn_serverless_storybook_config.mdx index 324655fc2323d..d0efe18378255 100644 --- a/api_docs/kbn_serverless_storybook_config.mdx +++ b/api_docs/kbn_serverless_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-storybook-config title: "@kbn/serverless-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-storybook-config plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-storybook-config'] --- import kbnServerlessStorybookConfigObj from './kbn_serverless_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index 2d3e2564915ef..6c4274c131c79 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-svg'] --- import kbnSharedSvgObj from './kbn_shared_svg.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_solution.mdx b/api_docs/kbn_shared_ux_avatar_solution.mdx index aae967f68a3f6..28bc0c39a6605 100644 --- a/api_docs/kbn_shared_ux_avatar_solution.mdx +++ b/api_docs/kbn_shared_ux_avatar_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-solution title: "@kbn/shared-ux-avatar-solution" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-solution plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-solution'] --- import kbnSharedUxAvatarSolutionObj from './kbn_shared_ux_avatar_solution.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index 094a565d51d2d..1d8f701bdebc0 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen title: "@kbn/shared-ux-button-exit-full-screen" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen'] --- import kbnSharedUxButtonExitFullScreenObj from './kbn_shared_ux_button_exit_full_screen.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 7640ea9e3ca91..2d66642d37ac3 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index f5c6d7eea87cb..2dd56b135b4c5 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] --- import kbnSharedUxCardNoDataObj from './kbn_shared_ux_card_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index 73601f7cdaddd..aa9b987e72f98 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data-mocks'] --- import kbnSharedUxCardNoDataMocksObj from './kbn_shared_ux_card_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_chrome_navigation.mdx b/api_docs/kbn_shared_ux_chrome_navigation.mdx index a377faa46c293..47c21b54c2e8c 100644 --- a/api_docs/kbn_shared_ux_chrome_navigation.mdx +++ b/api_docs/kbn_shared_ux_chrome_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-chrome-navigation title: "@kbn/shared-ux-chrome-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-chrome-navigation plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-chrome-navigation'] --- import kbnSharedUxChromeNavigationObj from './kbn_shared_ux_chrome_navigation.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_error_boundary.mdx b/api_docs/kbn_shared_ux_error_boundary.mdx index e32610fbef5e1..a5168e16b5be1 100644 --- a/api_docs/kbn_shared_ux_error_boundary.mdx +++ b/api_docs/kbn_shared_ux_error_boundary.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-error-boundary title: "@kbn/shared-ux-error-boundary" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-error-boundary plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-error-boundary'] --- import kbnSharedUxErrorBoundaryObj from './kbn_shared_ux_error_boundary.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index f57e2086cebd6..c61c717657bd2 100644 --- a/api_docs/kbn_shared_ux_file_context.mdx +++ b/api_docs/kbn_shared_ux_file_context.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-context title: "@kbn/shared-ux-file-context" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-context plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-context'] --- import kbnSharedUxFileContextObj from './kbn_shared_ux_file_context.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image.mdx b/api_docs/kbn_shared_ux_file_image.mdx index b5a4e93b87331..4a0a27cccc824 100644 --- a/api_docs/kbn_shared_ux_file_image.mdx +++ b/api_docs/kbn_shared_ux_file_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image title: "@kbn/shared-ux-file-image" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image'] --- import kbnSharedUxFileImageObj from './kbn_shared_ux_file_image.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image_mocks.mdx b/api_docs/kbn_shared_ux_file_image_mocks.mdx index 77c95a810948c..c3d7458252ee6 100644 --- a/api_docs/kbn_shared_ux_file_image_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_image_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image-mocks title: "@kbn/shared-ux-file-image-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image-mocks'] --- import kbnSharedUxFileImageMocksObj from './kbn_shared_ux_file_image_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_mocks.mdx b/api_docs/kbn_shared_ux_file_mocks.mdx index 917b5b2333728..907696ae66f8f 100644 --- a/api_docs/kbn_shared_ux_file_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-mocks title: "@kbn/shared-ux-file-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-mocks'] --- import kbnSharedUxFileMocksObj from './kbn_shared_ux_file_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_picker.mdx b/api_docs/kbn_shared_ux_file_picker.mdx index 5ab094f0c0998..6718522037261 100644 --- a/api_docs/kbn_shared_ux_file_picker.mdx +++ b/api_docs/kbn_shared_ux_file_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-picker title: "@kbn/shared-ux-file-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-picker plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-picker'] --- import kbnSharedUxFilePickerObj from './kbn_shared_ux_file_picker.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_types.mdx b/api_docs/kbn_shared_ux_file_types.mdx index 09de63ec5b353..7e2bb41331112 100644 --- a/api_docs/kbn_shared_ux_file_types.mdx +++ b/api_docs/kbn_shared_ux_file_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-types title: "@kbn/shared-ux-file-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-types plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-types'] --- import kbnSharedUxFileTypesObj from './kbn_shared_ux_file_types.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index a374a425114b1..82fc89af90a54 100644 --- a/api_docs/kbn_shared_ux_file_upload.mdx +++ b/api_docs/kbn_shared_ux_file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-upload title: "@kbn/shared-ux-file-upload" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-upload plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-upload'] --- import kbnSharedUxFileUploadObj from './kbn_shared_ux_file_upload.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_util.mdx b/api_docs/kbn_shared_ux_file_util.mdx index 1bdf08c90ee82..61d0288b5328d 100644 --- a/api_docs/kbn_shared_ux_file_util.mdx +++ b/api_docs/kbn_shared_ux_file_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-util title: "@kbn/shared-ux-file-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-util plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-util'] --- import kbnSharedUxFileUtilObj from './kbn_shared_ux_file_util.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app.mdx b/api_docs/kbn_shared_ux_link_redirect_app.mdx index 9c5ac68c6c303..d7f4205a22426 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app title: "@kbn/shared-ux-link-redirect-app" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app'] --- import kbnSharedUxLinkRedirectAppObj from './kbn_shared_ux_link_redirect_app.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx index bcf34b6ef3392..38c81d78d3878 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app-mocks'] --- import kbnSharedUxLinkRedirectAppMocksObj from './kbn_shared_ux_link_redirect_app_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown.mdx b/api_docs/kbn_shared_ux_markdown.mdx index d0aed0b2316a7..fcf77a278339a 100644 --- a/api_docs/kbn_shared_ux_markdown.mdx +++ b/api_docs/kbn_shared_ux_markdown.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown title: "@kbn/shared-ux-markdown" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown'] --- import kbnSharedUxMarkdownObj from './kbn_shared_ux_markdown.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown_mocks.mdx b/api_docs/kbn_shared_ux_markdown_mocks.mdx index 5b70a207847bd..4abbe8d05da72 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.mdx +++ b/api_docs/kbn_shared_ux_markdown_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown-mocks title: "@kbn/shared-ux-markdown-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown-mocks'] --- import kbnSharedUxMarkdownMocksObj from './kbn_shared_ux_markdown_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index 7a21b8493ca77..5709a2d7c0def 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] --- import kbnSharedUxPageAnalyticsNoDataObj from './kbn_shared_ux_page_analytics_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx index 0d1cf5386c1ca..ba5dc6db47fc0 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data-mocks'] --- import kbnSharedUxPageAnalyticsNoDataMocksObj from './kbn_shared_ux_page_analytics_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx index b5fac87442b4a..8941a26a324d7 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] --- import kbnSharedUxPageKibanaNoDataObj from './kbn_shared_ux_page_kibana_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx index 68321851bfd22..4b1c23b93a08e 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data-mocks'] --- import kbnSharedUxPageKibanaNoDataMocksObj from './kbn_shared_ux_page_kibana_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index 710fde66a173c..3510e566a2386 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template'] --- import kbnSharedUxPageKibanaTemplateObj from './kbn_shared_ux_page_kibana_template.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx index 8ee8c50122e85..c9e83d2f769e0 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template-mocks'] --- import kbnSharedUxPageKibanaTemplateMocksObj from './kbn_shared_ux_page_kibana_template_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index dc2d925b0b96f..5698e15842920 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data'] --- import kbnSharedUxPageNoDataObj from './kbn_shared_ux_page_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config.mdx b/api_docs/kbn_shared_ux_page_no_data_config.mdx index 85b6a53f72741..a808ca5dce15f 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config'] --- import kbnSharedUxPageNoDataConfigObj from './kbn_shared_ux_page_no_data_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx index 560c9d0489351..1ea8b0b0c2098 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config-mocks'] --- import kbnSharedUxPageNoDataConfigMocksObj from './kbn_shared_ux_page_no_data_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx index 428b867b21446..09e617adeaeca 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-mocks'] --- import kbnSharedUxPageNoDataMocksObj from './kbn_shared_ux_page_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index 7ffa3ea4574ff..237312a0443c9 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index d5c6199d4cc4c..a08a7442e1267 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] --- import kbnSharedUxPromptNoDataViewsObj from './kbn_shared_ux_prompt_no_data_views.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx index c9cdda33b1e55..6d3e8095360a0 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views-mocks'] --- import kbnSharedUxPromptNoDataViewsMocksObj from './kbn_shared_ux_prompt_no_data_views_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_not_found.mdx b/api_docs/kbn_shared_ux_prompt_not_found.mdx index 331eb2df1de59..f43bc4073d4e7 100644 --- a/api_docs/kbn_shared_ux_prompt_not_found.mdx +++ b/api_docs/kbn_shared_ux_prompt_not_found.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-not-found title: "@kbn/shared-ux-prompt-not-found" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-not-found plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-not-found'] --- import kbnSharedUxPromptNotFoundObj from './kbn_shared_ux_prompt_not_found.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index 422fe9392d236..1805977c0c728 100644 --- a/api_docs/kbn_shared_ux_router.mdx +++ b/api_docs/kbn_shared_ux_router.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router title: "@kbn/shared-ux-router" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router'] --- import kbnSharedUxRouterObj from './kbn_shared_ux_router.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router_mocks.mdx b/api_docs/kbn_shared_ux_router_mocks.mdx index 68881e7842119..9d3af376a71c4 100644 --- a/api_docs/kbn_shared_ux_router_mocks.mdx +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks title: "@kbn/shared-ux-router-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router-mocks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router-mocks'] --- import kbnSharedUxRouterMocksObj from './kbn_shared_ux_router_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_config.mdx b/api_docs/kbn_shared_ux_storybook_config.mdx index 5a6daa4d86af3..13be50b5d42b9 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-config'] --- import kbnSharedUxStorybookConfigObj from './kbn_shared_ux_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_mock.mdx b/api_docs/kbn_shared_ux_storybook_mock.mdx index fb7e548678b19..76049bbe16b05 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_tabbed_modal.mdx b/api_docs/kbn_shared_ux_tabbed_modal.mdx index 122ff503d0dd4..91d15cb263b88 100644 --- a/api_docs/kbn_shared_ux_tabbed_modal.mdx +++ b/api_docs/kbn_shared_ux_tabbed_modal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-tabbed-modal title: "@kbn/shared-ux-tabbed-modal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-tabbed-modal plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-tabbed-modal'] --- import kbnSharedUxTabbedModalObj from './kbn_shared_ux_tabbed_modal.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_table_persist.mdx b/api_docs/kbn_shared_ux_table_persist.mdx index 24d4af745e4de..5be2f5ee7f539 100644 --- a/api_docs/kbn_shared_ux_table_persist.mdx +++ b/api_docs/kbn_shared_ux_table_persist.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-table-persist title: "@kbn/shared-ux-table-persist" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-table-persist plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-table-persist'] --- import kbnSharedUxTablePersistObj from './kbn_shared_ux_table_persist.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 2856cf3fc5f1a..c402df512a212 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index de90e78bbe94b..ab99cb5ae6400 100644 --- a/api_docs/kbn_slo_schema.mdx +++ b/api_docs/kbn_slo_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-slo-schema title: "@kbn/slo-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/slo-schema plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 634de2e778da3..b32d746d8b468 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_sort_predicates.mdx b/api_docs/kbn_sort_predicates.mdx index 5605e34172e00..6884bc4e90033 100644 --- a/api_docs/kbn_sort_predicates.mdx +++ b/api_docs/kbn_sort_predicates.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sort-predicates title: "@kbn/sort-predicates" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sort-predicates plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-predicates'] --- import kbnSortPredicatesObj from './kbn_sort_predicates.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index 7d4509c2d6574..b45c8eb5da0ea 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] --- import kbnStdObj from './kbn_std.devdocs.json'; diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index f4db0b702a9ea..6e674db183b6d 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] --- import kbnStdioDevHelpersObj from './kbn_stdio_dev_helpers.devdocs.json'; diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index 891f3a4febf4c..c208d67b3da9d 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_synthetics_e2e.mdx b/api_docs/kbn_synthetics_e2e.mdx index 1e145f1a18644..a1d83d0ac7773 100644 --- a/api_docs/kbn_synthetics_e2e.mdx +++ b/api_docs/kbn_synthetics_e2e.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-synthetics-e2e title: "@kbn/synthetics-e2e" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/synthetics-e2e plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/synthetics-e2e'] --- import kbnSyntheticsE2eObj from './kbn_synthetics_e2e.devdocs.json'; diff --git a/api_docs/kbn_synthetics_private_location.mdx b/api_docs/kbn_synthetics_private_location.mdx index 84664ce4602b8..7d1e9327fc8f3 100644 --- a/api_docs/kbn_synthetics_private_location.mdx +++ b/api_docs/kbn_synthetics_private_location.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-synthetics-private-location title: "@kbn/synthetics-private-location" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/synthetics-private-location plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/synthetics-private-location'] --- import kbnSyntheticsPrivateLocationObj from './kbn_synthetics_private_location.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 2eb6cc14c7264..44c0386215ad4 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index a753af4adf4ba..09237dab27985 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_eui_helpers.mdx b/api_docs/kbn_test_eui_helpers.mdx index 2bd09dcd13d06..a232c83c23c3e 100644 --- a/api_docs/kbn_test_eui_helpers.mdx +++ b/api_docs/kbn_test_eui_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-eui-helpers title: "@kbn/test-eui-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-eui-helpers plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-eui-helpers'] --- import kbnTestEuiHelpersObj from './kbn_test_eui_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index ab7d1a7acb987..ff889ca1c4282 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] --- import kbnTestJestHelpersObj from './kbn_test_jest_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_subj_selector.mdx b/api_docs/kbn_test_subj_selector.mdx index e7f8d05bea5f8..69d04133cc166 100644 --- a/api_docs/kbn_test_subj_selector.mdx +++ b/api_docs/kbn_test_subj_selector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-subj-selector title: "@kbn/test-subj-selector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-subj-selector plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_text_based_editor.mdx b/api_docs/kbn_text_based_editor.mdx index 7915972645781..8adf93ce1c8de 100644 --- a/api_docs/kbn_text_based_editor.mdx +++ b/api_docs/kbn_text_based_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-text-based-editor title: "@kbn/text-based-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/text-based-editor plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/text-based-editor'] --- import kbnTextBasedEditorObj from './kbn_text_based_editor.devdocs.json'; diff --git a/api_docs/kbn_timerange.mdx b/api_docs/kbn_timerange.mdx index c4e829ee77482..652463023f2c9 100644 --- a/api_docs/kbn_timerange.mdx +++ b/api_docs/kbn_timerange.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-timerange title: "@kbn/timerange" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/timerange plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/timerange'] --- import kbnTimerangeObj from './kbn_timerange.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index df8071ff2bae3..3e9c62350d69a 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_triggers_actions_ui_types.mdx b/api_docs/kbn_triggers_actions_ui_types.mdx index 784c136482a24..eb871fb22f174 100644 --- a/api_docs/kbn_triggers_actions_ui_types.mdx +++ b/api_docs/kbn_triggers_actions_ui_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-triggers-actions-ui-types title: "@kbn/triggers-actions-ui-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/triggers-actions-ui-types plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/triggers-actions-ui-types'] --- import kbnTriggersActionsUiTypesObj from './kbn_triggers_actions_ui_types.devdocs.json'; diff --git a/api_docs/kbn_try_in_console.mdx b/api_docs/kbn_try_in_console.mdx index 56f7693e17141..a04cf5d0c7bdc 100644 --- a/api_docs/kbn_try_in_console.mdx +++ b/api_docs/kbn_try_in_console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-try-in-console title: "@kbn/try-in-console" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/try-in-console plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/try-in-console'] --- import kbnTryInConsoleObj from './kbn_try_in_console.devdocs.json'; diff --git a/api_docs/kbn_ts_projects.mdx b/api_docs/kbn_ts_projects.mdx index 01370ca6bc79c..1ab1f2f1a6cf8 100644 --- a/api_docs/kbn_ts_projects.mdx +++ b/api_docs/kbn_ts_projects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ts-projects title: "@kbn/ts-projects" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ts-projects plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ts-projects'] --- import kbnTsProjectsObj from './kbn_ts_projects.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index 37b85246847fe..39df983a6be2c 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] --- import kbnTypedReactRouterConfigObj from './kbn_typed_react_router_config.devdocs.json'; diff --git a/api_docs/kbn_ui_actions_browser.mdx b/api_docs/kbn_ui_actions_browser.mdx index 24885548ccb26..54fb7d2c63897 100644 --- a/api_docs/kbn_ui_actions_browser.mdx +++ b/api_docs/kbn_ui_actions_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-actions-browser title: "@kbn/ui-actions-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-actions-browser plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-actions-browser'] --- import kbnUiActionsBrowserObj from './kbn_ui_actions_browser.devdocs.json'; diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index 4745ae503988a..57c70570bee78 100644 --- a/api_docs/kbn_ui_shared_deps_src.mdx +++ b/api_docs/kbn_ui_shared_deps_src.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-shared-deps-src title: "@kbn/ui-shared-deps-src" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-shared-deps-src plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-shared-deps-src'] --- import kbnUiSharedDepsSrcObj from './kbn_ui_shared_deps_src.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index 32a3ec515d213..fb8c5cd2c51a6 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_unified_data_table.mdx b/api_docs/kbn_unified_data_table.mdx index c913eec4ea995..453cec4ce38f6 100644 --- a/api_docs/kbn_unified_data_table.mdx +++ b/api_docs/kbn_unified_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-data-table title: "@kbn/unified-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-data-table plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-data-table'] --- import kbnUnifiedDataTableObj from './kbn_unified_data_table.devdocs.json'; diff --git a/api_docs/kbn_unified_doc_viewer.mdx b/api_docs/kbn_unified_doc_viewer.mdx index 6645b4a75c39e..c0327ab3db776 100644 --- a/api_docs/kbn_unified_doc_viewer.mdx +++ b/api_docs/kbn_unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-doc-viewer title: "@kbn/unified-doc-viewer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-doc-viewer plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-doc-viewer'] --- import kbnUnifiedDocViewerObj from './kbn_unified_doc_viewer.devdocs.json'; diff --git a/api_docs/kbn_unified_field_list.mdx b/api_docs/kbn_unified_field_list.mdx index 6dda726eb2f67..eb4d919965710 100644 --- a/api_docs/kbn_unified_field_list.mdx +++ b/api_docs/kbn_unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-field-list title: "@kbn/unified-field-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-field-list plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-field-list'] --- import kbnUnifiedFieldListObj from './kbn_unified_field_list.devdocs.json'; diff --git a/api_docs/kbn_unsaved_changes_badge.mdx b/api_docs/kbn_unsaved_changes_badge.mdx index 8038c5607f6f2..5b0052e81fa67 100644 --- a/api_docs/kbn_unsaved_changes_badge.mdx +++ b/api_docs/kbn_unsaved_changes_badge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unsaved-changes-badge title: "@kbn/unsaved-changes-badge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unsaved-changes-badge plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unsaved-changes-badge'] --- import kbnUnsavedChangesBadgeObj from './kbn_unsaved_changes_badge.devdocs.json'; diff --git a/api_docs/kbn_unsaved_changes_prompt.mdx b/api_docs/kbn_unsaved_changes_prompt.mdx index 3a8e0c8bc43de..4f22b51f9cb4f 100644 --- a/api_docs/kbn_unsaved_changes_prompt.mdx +++ b/api_docs/kbn_unsaved_changes_prompt.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unsaved-changes-prompt title: "@kbn/unsaved-changes-prompt" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unsaved-changes-prompt plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unsaved-changes-prompt'] --- import kbnUnsavedChangesPromptObj from './kbn_unsaved_changes_prompt.devdocs.json'; diff --git a/api_docs/kbn_use_tracked_promise.mdx b/api_docs/kbn_use_tracked_promise.mdx index 3730028bc7038..ef237a66a07a3 100644 --- a/api_docs/kbn_use_tracked_promise.mdx +++ b/api_docs/kbn_use_tracked_promise.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-use-tracked-promise title: "@kbn/use-tracked-promise" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/use-tracked-promise plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/use-tracked-promise'] --- import kbnUseTrackedPromiseObj from './kbn_use_tracked_promise.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 6e23bd09e9281..cc11e11bd9702 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/user-profile-components'] --- import kbnUserProfileComponentsObj from './kbn_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index b5360f7bb8a9b..3f62d6b90f2d1 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index eba9cbe479837..a7630001fbdbe 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] --- import kbnUtilityTypesJestObj from './kbn_utility_types_jest.devdocs.json'; diff --git a/api_docs/kbn_utils.devdocs.json b/api_docs/kbn_utils.devdocs.json index f7fff669338a0..9ce76bbc13e33 100644 --- a/api_docs/kbn_utils.devdocs.json +++ b/api_docs/kbn_utils.devdocs.json @@ -9,19 +9,11 @@ "objects": [] }, "server": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - }, - "common": { "classes": [], "functions": [ { "parentPluginId": "@kbn/utils", - "id": "def-common.concatStreamProviders", + "id": "def-server.concatStreamProviders", "type": "Function", "tags": [ "return" @@ -44,7 +36,7 @@ "children": [ { "parentPluginId": "@kbn/utils", - "id": "def-common.concatStreamProviders.$1", + "id": "def-server.concatStreamProviders.$1", "type": "Array", "tags": [], "label": "sourceProviders", @@ -61,7 +53,7 @@ }, { "parentPluginId": "@kbn/utils", - "id": "def-common.concatStreamProviders.$2", + "id": "def-server.concatStreamProviders.$2", "type": "Object", "tags": [], "label": "options", @@ -85,7 +77,7 @@ }, { "parentPluginId": "@kbn/utils", - "id": "def-common.createConcatStream", + "id": "def-server.createConcatStream", "type": "Function", "tags": [ "return" @@ -104,7 +96,7 @@ "children": [ { "parentPluginId": "@kbn/utils", - "id": "def-common.createConcatStream.$1", + "id": "def-server.createConcatStream.$1", "type": "Uncategorized", "tags": [], "label": "initial", @@ -125,7 +117,7 @@ }, { "parentPluginId": "@kbn/utils", - "id": "def-common.createFilterStream", + "id": "def-server.createFilterStream", "type": "Function", "tags": [], "label": "createFilterStream", @@ -140,7 +132,7 @@ "children": [ { "parentPluginId": "@kbn/utils", - "id": "def-common.createFilterStream.$1", + "id": "def-server.createFilterStream.$1", "type": "Function", "tags": [], "label": "fn", @@ -159,7 +151,7 @@ }, { "parentPluginId": "@kbn/utils", - "id": "def-common.createIntersperseStream", + "id": "def-server.createIntersperseStream", "type": "Function", "tags": [ "return" @@ -178,7 +170,7 @@ "children": [ { "parentPluginId": "@kbn/utils", - "id": "def-common.createIntersperseStream.$1", + "id": "def-server.createIntersperseStream.$1", "type": "CompoundType", "tags": [], "label": "intersperseChunk", @@ -197,7 +189,7 @@ }, { "parentPluginId": "@kbn/utils", - "id": "def-common.createListStream", + "id": "def-server.createListStream", "type": "Function", "tags": [ "return" @@ -216,7 +208,7 @@ "children": [ { "parentPluginId": "@kbn/utils", - "id": "def-common.createListStream.$1", + "id": "def-server.createListStream.$1", "type": "CompoundType", "tags": [], "label": "items", @@ -237,7 +229,7 @@ }, { "parentPluginId": "@kbn/utils", - "id": "def-common.createMapStream", + "id": "def-server.createMapStream", "type": "Function", "tags": [], "label": "createMapStream", @@ -252,7 +244,7 @@ "children": [ { "parentPluginId": "@kbn/utils", - "id": "def-common.createMapStream.$1", + "id": "def-server.createMapStream.$1", "type": "Function", "tags": [], "label": "fn", @@ -271,7 +263,7 @@ }, { "parentPluginId": "@kbn/utils", - "id": "def-common.createPromiseFromStreams", + "id": "def-server.createPromiseFromStreams", "type": "Function", "tags": [], "label": "createPromiseFromStreams", @@ -289,7 +281,7 @@ "children": [ { "parentPluginId": "@kbn/utils", - "id": "def-common.createPromiseFromStreams.$1", + "id": "def-server.createPromiseFromStreams.$1", "type": "Object", "tags": [], "label": "streams", @@ -312,7 +304,7 @@ }, { "parentPluginId": "@kbn/utils", - "id": "def-common.createReduceStream", + "id": "def-server.createReduceStream", "type": "Function", "tags": [ "return" @@ -331,7 +323,7 @@ "children": [ { "parentPluginId": "@kbn/utils", - "id": "def-common.createReduceStream.$1", + "id": "def-server.createReduceStream.$1", "type": "Function", "tags": [], "label": "reducer", @@ -346,7 +338,7 @@ }, { "parentPluginId": "@kbn/utils", - "id": "def-common.createReduceStream.$2", + "id": "def-server.createReduceStream.$2", "type": "Uncategorized", "tags": [], "label": "initial", @@ -367,7 +359,7 @@ }, { "parentPluginId": "@kbn/utils", - "id": "def-common.createReplaceStream", + "id": "def-server.createReplaceStream", "type": "Function", "tags": [], "label": "createReplaceStream", @@ -382,7 +374,7 @@ "children": [ { "parentPluginId": "@kbn/utils", - "id": "def-common.createReplaceStream.$1", + "id": "def-server.createReplaceStream.$1", "type": "string", "tags": [], "label": "toReplace", @@ -397,7 +389,7 @@ }, { "parentPluginId": "@kbn/utils", - "id": "def-common.createReplaceStream.$2", + "id": "def-server.createReplaceStream.$2", "type": "CompoundType", "tags": [], "label": "replacement", @@ -416,7 +408,7 @@ }, { "parentPluginId": "@kbn/utils", - "id": "def-common.createSplitStream", + "id": "def-server.createSplitStream", "type": "Function", "tags": [ "return" @@ -435,7 +427,7 @@ "children": [ { "parentPluginId": "@kbn/utils", - "id": "def-common.createSplitStream.$1", + "id": "def-server.createSplitStream.$1", "type": "CompoundType", "tags": [], "label": "splitChunk", @@ -454,7 +446,7 @@ }, { "parentPluginId": "@kbn/utils", - "id": "def-common.prettyPrintAndSortKeys", + "id": "def-server.prettyPrintAndSortKeys", "type": "Function", "tags": [], "label": "prettyPrintAndSortKeys", @@ -470,7 +462,7 @@ "children": [ { "parentPluginId": "@kbn/utils", - "id": "def-common.prettyPrintAndSortKeys.$1", + "id": "def-server.prettyPrintAndSortKeys.$1", "type": "Uncategorized", "tags": [], "label": "object", @@ -493,7 +485,7 @@ "misc": [ { "parentPluginId": "@kbn/utils", - "id": "def-common.PathConfigType", + "id": "def-server.PathConfigType", "type": "Type", "tags": [], "label": "PathConfigType", @@ -508,5 +500,13 @@ } ], "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] } } \ No newline at end of file diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index d6ea70a2aed24..75b3510c24715 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; @@ -23,11 +23,11 @@ Contact [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kiban |-------------------|-----------|------------------------|-----------------| | 26 | 0 | 15 | 0 | -## Common +## Server ### Functions - + ### Consts, variables and types - + diff --git a/api_docs/kbn_visualization_ui_components.devdocs.json b/api_docs/kbn_visualization_ui_components.devdocs.json index 0ef41a076c1a0..684cd55d3dfae 100644 --- a/api_docs/kbn_visualization_ui_components.devdocs.json +++ b/api_docs/kbn_visualization_ui_components.devdocs.json @@ -47,7 +47,15 @@ "label": "ColorPicker", "description": [], "signature": [ - "({ overwriteColor, defaultColor, isClearable, setConfig, label, disableHelpTooltip, disabledMessage, showAlpha, }: { overwriteColor?: string | null | undefined; defaultColor?: string | null | undefined; isClearable?: boolean | undefined; setConfig: (config: { color?: string | undefined; }) => void; label?: string | undefined; disableHelpTooltip?: boolean | undefined; disabledMessage?: string | undefined; showAlpha?: boolean | undefined; }) => JSX.Element" + "({ overwriteColor, defaultColor, isClearable, setConfig, label, disableHelpTooltip, disabledMessage, showAlpha, }: ", + { + "pluginId": "@kbn/visualization-ui-components", + "scope": "public", + "docId": "kibKbnVisualizationUiComponentsPluginApi", + "section": "def-public.ColorPickerProps", + "text": "ColorPickerProps" + }, + ") => JSX.Element" ], "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", "deprecated": false, @@ -60,153 +68,19 @@ "tags": [], "label": "{\n overwriteColor,\n defaultColor,\n isClearable,\n setConfig,\n label,\n disableHelpTooltip,\n disabledMessage,\n showAlpha,\n}", "description": [], + "signature": [ + { + "pluginId": "@kbn/visualization-ui-components", + "scope": "public", + "docId": "kibKbnVisualizationUiComponentsPluginApi", + "section": "def-public.ColorPickerProps", + "text": "ColorPickerProps" + } + ], "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", "deprecated": false, "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.ColorPicker.$1.overwriteColor", - "type": "CompoundType", - "tags": [], - "label": "overwriteColor", - "description": [], - "signature": [ - "string | null | undefined" - ], - "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.ColorPicker.$1.defaultColor", - "type": "CompoundType", - "tags": [], - "label": "defaultColor", - "description": [], - "signature": [ - "string | null | undefined" - ], - "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.ColorPicker.$1.isClearable", - "type": "CompoundType", - "tags": [], - "label": "isClearable", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.ColorPicker.$1.setConfig", - "type": "Function", - "tags": [], - "label": "setConfig", - "description": [], - "signature": [ - "(config: { color?: string | undefined; }) => void" - ], - "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.ColorPicker.$1.setConfig.$1", - "type": "Object", - "tags": [], - "label": "config", - "description": [], - "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.ColorPicker.$1.setConfig.$1.color", - "type": "string", - "tags": [], - "label": "color", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "returnComment": [] - }, - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.ColorPicker.$1.label", - "type": "string", - "tags": [], - "label": "label", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.ColorPicker.$1.disableHelpTooltip", - "type": "CompoundType", - "tags": [], - "label": "disableHelpTooltip", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.ColorPicker.$1.disabledMessage", - "type": "string", - "tags": [], - "label": "disabledMessage", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.ColorPicker.$1.showAlpha", - "type": "CompoundType", - "tags": [], - "label": "showAlpha", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", - "deprecated": false, - "trackAdoption": false - } - ] + "isRequired": true } ], "returnComment": [], @@ -824,39 +698,9 @@ "label": "FilterQueryInput", "description": [], "signature": [ - "({\n inputFilter,\n onChange,\n dataView,\n helpMessage,\n label = filterByLabel,\n initiallyOpen,\n ['data-test-subj']: dataTestSubj,\n queryInputServices,\n appName,\n}: { inputFilter: ", - { - "pluginId": "@kbn/es-query", - "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.Query", - "text": "Query" - }, - " | undefined; onChange: (query: ", - { - "pluginId": "@kbn/es-query", - "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.Query", - "text": "Query" - }, - ") => void; dataView: ", - { - "pluginId": "@kbn/es-query", - "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.DataViewBase", - "text": "DataViewBase" - }, - "; helpMessage?: string | null | undefined; label?: string | undefined; initiallyOpen?: boolean | undefined; \"data-test-subj\"?: string | undefined; queryInputServices: ", - { - "pluginId": "@kbn/visualization-ui-components", - "scope": "public", - "docId": "kibKbnVisualizationUiComponentsPluginApi", - "section": "def-public.QueryInputServices", - "text": "QueryInputServices" - }, - "; appName: string; }) => JSX.Element" + "({\n inputFilter,\n onChange,\n dataView,\n helpMessage,\n label = filterByLabel,\n initiallyOpen,\n ['data-test-subj']: dataTestSubj,\n queryInputServices,\n appName,\n}: ", + "FilterQueryInputProps", + ") => JSX.Element" ], "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx", "deprecated": false, @@ -869,185 +713,13 @@ "tags": [], "label": "{\n inputFilter,\n onChange,\n dataView,\n helpMessage,\n label = filterByLabel,\n initiallyOpen,\n ['data-test-subj']: dataTestSubj,\n queryInputServices,\n appName,\n}", "description": [], + "signature": [ + "FilterQueryInputProps" + ], "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx", "deprecated": false, "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.FilterQueryInput.$1.inputFilter", - "type": "Object", - "tags": [], - "label": "inputFilter", - "description": [], - "signature": [ - { - "pluginId": "@kbn/es-query", - "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.Query", - "text": "Query" - }, - " | undefined" - ], - "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.FilterQueryInput.$1.onChange", - "type": "Function", - "tags": [], - "label": "onChange", - "description": [], - "signature": [ - "(query: ", - { - "pluginId": "@kbn/es-query", - "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.Query", - "text": "Query" - }, - ") => void" - ], - "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.FilterQueryInput.$1.onChange.$1", - "type": "Object", - "tags": [], - "label": "query", - "description": [], - "signature": [ - { - "pluginId": "@kbn/es-query", - "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.Query", - "text": "Query" - } - ], - "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.FilterQueryInput.$1.dataView", - "type": "Object", - "tags": [], - "label": "dataView", - "description": [], - "signature": [ - { - "pluginId": "@kbn/es-query", - "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.DataViewBase", - "text": "DataViewBase" - } - ], - "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.FilterQueryInput.$1.helpMessage", - "type": "CompoundType", - "tags": [], - "label": "helpMessage", - "description": [], - "signature": [ - "string | null | undefined" - ], - "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.FilterQueryInput.$1.label", - "type": "string", - "tags": [], - "label": "label", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.FilterQueryInput.$1.initiallyOpen", - "type": "CompoundType", - "tags": [], - "label": "initiallyOpen", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.FilterQueryInput.$1.datatestsubj", - "type": "string", - "tags": [], - "label": "['data-test-subj']", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.FilterQueryInput.$1.queryInputServices", - "type": "Object", - "tags": [], - "label": "queryInputServices", - "description": [], - "signature": [ - { - "pluginId": "@kbn/visualization-ui-components", - "scope": "public", - "docId": "kibKbnVisualizationUiComponentsPluginApi", - "section": "def-public.QueryInputServices", - "text": "QueryInputServices" - } - ], - "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.FilterQueryInput.$1.appName", - "type": "string", - "tags": [], - "label": "appName", - "description": [], - "path": "packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx", - "deprecated": false, - "trackAdoption": false - } - ] + "isRequired": true } ], "returnComment": [], @@ -2141,6 +1813,162 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/visualization-ui-components", + "id": "def-public.ColorPickerProps", + "type": "Interface", + "tags": [], + "label": "ColorPickerProps", + "description": [], + "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/visualization-ui-components", + "id": "def-public.ColorPickerProps.overwriteColor", + "type": "CompoundType", + "tags": [], + "label": "overwriteColor", + "description": [], + "signature": [ + "string | null | undefined" + ], + "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/visualization-ui-components", + "id": "def-public.ColorPickerProps.defaultColor", + "type": "CompoundType", + "tags": [], + "label": "defaultColor", + "description": [], + "signature": [ + "string | null | undefined" + ], + "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/visualization-ui-components", + "id": "def-public.ColorPickerProps.isClearable", + "type": "CompoundType", + "tags": [], + "label": "isClearable", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/visualization-ui-components", + "id": "def-public.ColorPickerProps.setConfig", + "type": "Function", + "tags": [], + "label": "setConfig", + "description": [], + "signature": [ + "(config: { color?: string | undefined; }) => void" + ], + "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/visualization-ui-components", + "id": "def-public.ColorPickerProps.setConfig.$1", + "type": "Object", + "tags": [], + "label": "config", + "description": [], + "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/visualization-ui-components", + "id": "def-public.ColorPickerProps.setConfig.$1.color", + "type": "string", + "tags": [], + "label": "color", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/visualization-ui-components", + "id": "def-public.ColorPickerProps.label", + "type": "string", + "tags": [], + "label": "label", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/visualization-ui-components", + "id": "def-public.ColorPickerProps.disableHelpTooltip", + "type": "CompoundType", + "tags": [], + "label": "disableHelpTooltip", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/visualization-ui-components", + "id": "def-public.ColorPickerProps.disabledMessage", + "type": "string", + "tags": [], + "label": "disabledMessage", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/visualization-ui-components", + "id": "def-public.ColorPickerProps.showAlpha", + "type": "CompoundType", + "tags": [], + "label": "showAlpha", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-visualization-ui-components/components/color_picker.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/visualization-ui-components", "id": "def-public.FieldOptionValue", diff --git a/api_docs/kbn_visualization_ui_components.mdx b/api_docs/kbn_visualization_ui_components.mdx index 6e44040dfdee4..2dbb03ea87c5a 100644 --- a/api_docs/kbn_visualization_ui_components.mdx +++ b/api_docs/kbn_visualization_ui_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-ui-components title: "@kbn/visualization-ui-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-ui-components plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-ui-components'] --- import kbnVisualizationUiComponentsObj from './kbn_visualization_ui_components.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 146 | 0 | 143 | 3 | +| 137 | 0 | 134 | 4 | ## Client diff --git a/api_docs/kbn_visualization_utils.mdx b/api_docs/kbn_visualization_utils.mdx index 31ad7698725dd..84c424613c5d8 100644 --- a/api_docs/kbn_visualization_utils.mdx +++ b/api_docs/kbn_visualization_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-utils title: "@kbn/visualization-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-utils'] --- import kbnVisualizationUtilsObj from './kbn_visualization_utils.devdocs.json'; diff --git a/api_docs/kbn_xstate_utils.mdx b/api_docs/kbn_xstate_utils.mdx index 00b688c24559a..c8b7b2d6d98ee 100644 --- a/api_docs/kbn_xstate_utils.mdx +++ b/api_docs/kbn_xstate_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-xstate-utils title: "@kbn/xstate-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/xstate-utils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/xstate-utils'] --- import kbnXstateUtilsObj from './kbn_xstate_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index 957417d1279bd..640e5022cf891 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kbn_zod.mdx b/api_docs/kbn_zod.mdx index 5ff1f59317f45..0ca21f7c420ab 100644 --- a/api_docs/kbn_zod.mdx +++ b/api_docs/kbn_zod.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-zod title: "@kbn/zod" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/zod plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/zod'] --- import kbnZodObj from './kbn_zod.devdocs.json'; diff --git a/api_docs/kbn_zod_helpers.mdx b/api_docs/kbn_zod_helpers.mdx index 6d577c60ef430..e721e4d5d9a55 100644 --- a/api_docs/kbn_zod_helpers.mdx +++ b/api_docs/kbn_zod_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-zod-helpers title: "@kbn/zod-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/zod-helpers plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/zod-helpers'] --- import kbnZodHelpersObj from './kbn_zod_helpers.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index c875f0cbc61de..5ccc8f599bb6f 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index 5b84c0375f740..758de17e062db 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index 0645ecabf59f2..96293527505b3 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index 1f6abaa25bc29..4ebc3e8b3e5ef 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.devdocs.json b/api_docs/lens.devdocs.json index a08955b55f968..f0eb9d0f9b29a 100644 --- a/api_docs/lens.devdocs.json +++ b/api_docs/lens.devdocs.json @@ -2510,7 +2510,7 @@ "section": "def-public.IncompleteColumn", "text": "IncompleteColumn" }, - "> | undefined" + " | undefined> | undefined" ], "path": "x-pack/plugins/lens/public/datasources/form_based/types.ts", "deprecated": false, @@ -8634,6 +8634,56 @@ ], "returnComment": [] }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.onDatasourceUpdate", + "type": "Function", + "tags": [], + "label": "onDatasourceUpdate", + "description": [], + "signature": [ + "((state: T, frame?: ", + "FramePublicAPI", + " | undefined) => T) | undefined" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "lens", + "id": "def-public.Visualization.onDatasourceUpdate.$1", + "type": "Uncategorized", + "tags": [], + "label": "state", + "description": [], + "signature": [ + "T" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.onDatasourceUpdate.$2", + "type": "Object", + "tags": [], + "label": "frame", + "description": [], + "signature": [ + "FramePublicAPI", + " | undefined" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, { "parentPluginId": "lens", "id": "def-public.Visualization.onIndexPatternChange", @@ -11726,7 +11776,7 @@ "section": "def-public.IncompleteColumn", "text": "IncompleteColumn" }, - "> | undefined; sampling?: number | undefined; }" + " | undefined> | undefined; sampling?: number | undefined; }" ], "path": "x-pack/plugins/lens/public/datasources/form_based/types.ts", "deprecated": false, diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index c43741ded505e..3607a91693376 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 685 | 0 | 583 | 62 | +| 688 | 0 | 586 | 62 | ## Client diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index 570168a8dd2b8..6bf76ab4b3fdd 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] --- import licenseApiGuardObj from './license_api_guard.devdocs.json'; diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index 82902a4f786e4..c49a73ef8cd74 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 1f5315779511a..bea9a5807e6ac 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/links.mdx b/api_docs/links.mdx index 72b49df0783f8..b2394f649cbe4 100644 --- a/api_docs/links.mdx +++ b/api_docs/links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/links title: "links" image: https://source.unsplash.com/400x175/?github description: API docs for the links plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'links'] --- import linksObj from './links.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index 53a054d43fb22..7ac2612f89469 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/logs_data_access.mdx b/api_docs/logs_data_access.mdx index 512a59d0cf859..db7adb4c1753d 100644 --- a/api_docs/logs_data_access.mdx +++ b/api_docs/logs_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsDataAccess title: "logsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the logsDataAccess plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsDataAccess'] --- import logsDataAccessObj from './logs_data_access.devdocs.json'; diff --git a/api_docs/logs_explorer.mdx b/api_docs/logs_explorer.mdx index 0973459c59bba..8e7882305bab1 100644 --- a/api_docs/logs_explorer.mdx +++ b/api_docs/logs_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsExplorer title: "logsExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the logsExplorer plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsExplorer'] --- import logsExplorerObj from './logs_explorer.devdocs.json'; diff --git a/api_docs/logs_shared.devdocs.json b/api_docs/logs_shared.devdocs.json index 32758ecf4558d..e3cf1d13960f4 100644 --- a/api_docs/logs_shared.devdocs.json +++ b/api_docs/logs_shared.devdocs.json @@ -3173,6 +3173,137 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "logsShared", + "id": "def-public.UpdatedDateRange", + "type": "Interface", + "tags": [], + "label": "UpdatedDateRange", + "description": [], + "path": "x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "logsShared", + "id": "def-public.UpdatedDateRange.startDateExpression", + "type": "string", + "tags": [], + "label": "startDateExpression", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "logsShared", + "id": "def-public.UpdatedDateRange.endDateExpression", + "type": "string", + "tags": [], + "label": "endDateExpression", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "logsShared", + "id": "def-public.VisibleInterval", + "type": "Interface", + "tags": [], + "label": "VisibleInterval", + "description": [], + "path": "x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "logsShared", + "id": "def-public.VisibleInterval.pagesBeforeStart", + "type": "number", + "tags": [], + "label": "pagesBeforeStart", + "description": [], + "path": "x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "logsShared", + "id": "def-public.VisibleInterval.pagesAfterEnd", + "type": "number", + "tags": [], + "label": "pagesAfterEnd", + "description": [], + "path": "x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "logsShared", + "id": "def-public.VisibleInterval.startKey", + "type": "CompoundType", + "tags": [], + "label": "startKey", + "description": [], + "signature": [ + "({ time: string; tiebreaker: number; } & { gid?: string | undefined; fromAutoReload?: boolean | undefined; }) | null" + ], + "path": "x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "logsShared", + "id": "def-public.VisibleInterval.middleKey", + "type": "CompoundType", + "tags": [], + "label": "middleKey", + "description": [], + "signature": [ + "({ time: string; tiebreaker: number; } & { gid?: string | undefined; fromAutoReload?: boolean | undefined; }) | null" + ], + "path": "x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "logsShared", + "id": "def-public.VisibleInterval.endKey", + "type": "CompoundType", + "tags": [], + "label": "endKey", + "description": [], + "signature": [ + "({ time: string; tiebreaker: number; } & { gid?: string | undefined; fromAutoReload?: boolean | undefined; }) | null" + ], + "path": "x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "logsShared", + "id": "def-public.VisibleInterval.fromScroll", + "type": "boolean", + "tags": [], + "label": "fromScroll", + "description": [], + "path": "x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "logsShared", "id": "def-public.WithSummaryProps", diff --git a/api_docs/logs_shared.mdx b/api_docs/logs_shared.mdx index 2eb3bc8027c02..e5d481908839f 100644 --- a/api_docs/logs_shared.mdx +++ b/api_docs/logs_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsShared title: "logsShared" image: https://source.unsplash.com/400x175/?github description: API docs for the logsShared plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsShared'] --- import logsSharedObj from './logs_shared.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 300 | 0 | 272 | 32 | +| 310 | 0 | 282 | 32 | ## Client diff --git a/api_docs/management.mdx b/api_docs/management.mdx index da12ff0f537aa..c00d73cc44d76 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index d8a4b185e9580..2b129cee2a56d 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index 65ae1ecf2b5d3..bdc4c5267b84c 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/metrics_data_access.mdx b/api_docs/metrics_data_access.mdx index 21983f6f07d17..0360707eb9fe4 100644 --- a/api_docs/metrics_data_access.mdx +++ b/api_docs/metrics_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/metricsDataAccess title: "metricsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the metricsDataAccess plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'metricsDataAccess'] --- import metricsDataAccessObj from './metrics_data_access.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 5c00beaa1f2f0..4ac951d3fcf9d 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/mock_idp_plugin.mdx b/api_docs/mock_idp_plugin.mdx index 6df6f57ef01ab..bf6178562bf88 100644 --- a/api_docs/mock_idp_plugin.mdx +++ b/api_docs/mock_idp_plugin.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mockIdpPlugin title: "mockIdpPlugin" image: https://source.unsplash.com/400x175/?github description: API docs for the mockIdpPlugin plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mockIdpPlugin'] --- import mockIdpPluginObj from './mock_idp_plugin.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index 12bef159b0c21..4857bbdd475f5 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index 9db57429f5cfd..bb4c3c8a863be 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] --- import monitoringCollectionObj from './monitoring_collection.devdocs.json'; diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index 7e06a0834bf6d..6157119d10d6d 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] --- import navigationObj from './navigation.devdocs.json'; diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index 1eb4d22046907..ace8fd60efdbc 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/no_data_page.mdx b/api_docs/no_data_page.mdx index 8d474055489c5..635563244ce1d 100644 --- a/api_docs/no_data_page.mdx +++ b/api_docs/no_data_page.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/noDataPage title: "noDataPage" image: https://source.unsplash.com/400x175/?github description: API docs for the noDataPage plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'noDataPage'] --- import noDataPageObj from './no_data_page.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index 6651a704fce86..71110305478bf 100644 --- a/api_docs/notifications.mdx +++ b/api_docs/notifications.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/notifications title: "notifications" image: https://source.unsplash.com/400x175/?github description: API docs for the notifications plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'notifications'] --- import notificationsObj from './notifications.devdocs.json'; diff --git a/api_docs/observability.devdocs.json b/api_docs/observability.devdocs.json index eaa4e3814d3d8..9be924035f454 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -8913,7 +8913,11 @@ "StringC", "; }>, ", "PartialC", - "<{ 'service.name': ", + "<{ alert_rule_parameter_time_size: ", + "StringC", + "; alert_rule_parameter_time_unit: ", + "StringC", + "; 'service.name': ", "StringC", "; 'service.environment': ", "StringC", @@ -8935,7 +8939,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params: { query: { alert_started_at: string; } & { 'service.name'?: string | undefined; 'service.environment'?: string | undefined; 'transaction.type'?: string | undefined; 'transaction.name'?: string | undefined; 'host.name'?: string | undefined; 'container.id'?: string | undefined; 'kubernetes.pod.name'?: string | undefined; }; }; }) => Promise<{ alertContext: ", + " & { params: { query: { alert_started_at: string; } & { alert_rule_parameter_time_size?: string | undefined; alert_rule_parameter_time_unit?: string | undefined; 'service.name'?: string | undefined; 'service.environment'?: string | undefined; 'transaction.type'?: string | undefined; 'transaction.name'?: string | undefined; 'host.name'?: string | undefined; 'container.id'?: string | undefined; 'kubernetes.pod.name'?: string | undefined; }; }; }) => Promise<{ alertContext: ", "AlertDetailsContextualInsight", "[]; }>; } & ", { @@ -9037,7 +9041,11 @@ "StringC", "; }>, ", "PartialC", - "<{ 'service.name': ", + "<{ alert_rule_parameter_time_size: ", + "StringC", + "; alert_rule_parameter_time_unit: ", + "StringC", + "; 'service.name': ", "StringC", "; 'service.environment': ", "StringC", @@ -9059,7 +9067,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params: { query: { alert_started_at: string; } & { 'service.name'?: string | undefined; 'service.environment'?: string | undefined; 'transaction.type'?: string | undefined; 'transaction.name'?: string | undefined; 'host.name'?: string | undefined; 'container.id'?: string | undefined; 'kubernetes.pod.name'?: string | undefined; }; }; }) => Promise<{ alertContext: ", + " & { params: { query: { alert_started_at: string; } & { alert_rule_parameter_time_size?: string | undefined; alert_rule_parameter_time_unit?: string | undefined; 'service.name'?: string | undefined; 'service.environment'?: string | undefined; 'transaction.type'?: string | undefined; 'transaction.name'?: string | undefined; 'host.name'?: string | undefined; 'container.id'?: string | undefined; 'kubernetes.pod.name'?: string | undefined; }; }; }) => Promise<{ alertContext: ", "AlertDetailsContextualInsight", "[]; }>; } & ", { diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 0061af2708ea7..582d435eca404 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant.devdocs.json b/api_docs/observability_a_i_assistant.devdocs.json index a1383e4f2ba6f..2315816499755 100644 --- a/api_docs/observability_a_i_assistant.devdocs.json +++ b/api_docs/observability_a_i_assistant.devdocs.json @@ -1606,7 +1606,7 @@ "section": "def-common.Message", "text": "Message" }, - "[]; persist: boolean; disableFunctions: boolean | { except: string[]; }; signal: AbortSignal; responseLanguage?: string | undefined; instructions?: ", + "[]; persist: boolean; disableFunctions: boolean | { except: string[]; }; signal: AbortSignal; instructions?: ", "AdHocInstruction", "[] | undefined; }) => ", "Observable", @@ -1738,20 +1738,6 @@ "deprecated": false, "trackAdoption": false }, - { - "parentPluginId": "observabilityAIAssistant", - "id": "def-public.ObservabilityAIAssistantChatService.complete.$1.responseLanguage", - "type": "string", - "tags": [], - "label": "responseLanguage", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "x-pack/plugins/observability_solution/observability_ai_assistant/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, { "parentPluginId": "observabilityAIAssistant", "id": "def-public.ObservabilityAIAssistantChatService.complete.$1.instructions", @@ -2526,8 +2512,6 @@ "StringC", "; title: ", "StringC", - "; responseLanguage: ", - "StringC", "; disableFunctions: ", "UnionC", "<[", @@ -2592,7 +2576,7 @@ "section": "def-common.Message", "text": "Message" }, - "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; responseLanguage?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body?: { actions?: ({ name: string; description: string; } & { parameters?: any; })[] | undefined; } | undefined; query?: { format?: \"default\" | \"openai\" | undefined; } | undefined; }; }) => Promise<", + "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body?: { actions?: ({ name: string; description: string; } & { parameters?: any; })[] | undefined; } | undefined; query?: { format?: \"default\" | \"openai\" | undefined; } | undefined; }; }) => Promise<", "Readable", ">; } & ", "ObservabilityAIAssistantRouteCreateOptions", @@ -2634,8 +2618,6 @@ "StringC", "; title: ", "StringC", - "; responseLanguage: ", - "StringC", "; disableFunctions: ", "UnionC", "<[", @@ -2686,7 +2668,7 @@ "section": "def-common.Message", "text": "Message" }, - "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; responseLanguage?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body: { screenContexts: ", + "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body: { screenContexts: ", "ObservabilityAIAssistantScreenContextRequest", "[]; }; }; }) => Promise<", "Readable", @@ -3232,8 +3214,6 @@ "StringC", "; title: ", "StringC", - "; responseLanguage: ", - "StringC", "; disableFunctions: ", "UnionC", "<[", @@ -3298,7 +3278,7 @@ "section": "def-common.Message", "text": "Message" }, - "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; responseLanguage?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body?: { actions?: ({ name: string; description: string; } & { parameters?: any; })[] | undefined; } | undefined; query?: { format?: \"default\" | \"openai\" | undefined; } | undefined; }; }) => Promise<", + "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body?: { actions?: ({ name: string; description: string; } & { parameters?: any; })[] | undefined; } | undefined; query?: { format?: \"default\" | \"openai\" | undefined; } | undefined; }; }) => Promise<", "Readable", ">; } & ", "ObservabilityAIAssistantRouteCreateOptions", @@ -3340,8 +3320,6 @@ "StringC", "; title: ", "StringC", - "; responseLanguage: ", - "StringC", "; disableFunctions: ", "UnionC", "<[", @@ -3392,7 +3370,7 @@ "section": "def-common.Message", "text": "Message" }, - "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; responseLanguage?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body: { screenContexts: ", + "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body: { screenContexts: ", "ObservabilityAIAssistantScreenContextRequest", "[]; }; }; }) => Promise<", "Readable", @@ -4060,13 +4038,13 @@ }, { "parentPluginId": "observabilityAIAssistant", - "id": "def-public.aiAssistantResponseLanguage", + "id": "def-public.aiAssistantPreferredAIAssistantType", "type": "string", "tags": [], - "label": "aiAssistantResponseLanguage", + "label": "aiAssistantPreferredAIAssistantType", "description": [], "signature": [ - "\"observability:aiAssistantResponseLanguage\"" + "\"aiAssistant:preferredAIAssistantType\"" ], "path": "x-pack/plugins/observability_solution/observability_ai_assistant/common/ui_settings/settings_keys.ts", "deprecated": false, @@ -4565,8 +4543,6 @@ "StringC", "; title: ", "StringC", - "; responseLanguage: ", - "StringC", "; disableFunctions: ", "UnionC", "<[", @@ -4631,7 +4607,7 @@ "section": "def-common.Message", "text": "Message" }, - "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; responseLanguage?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body?: { actions?: ({ name: string; description: string; } & { parameters?: any; })[] | undefined; } | undefined; query?: { format?: \"default\" | \"openai\" | undefined; } | undefined; }; }) => Promise<", + "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body?: { actions?: ({ name: string; description: string; } & { parameters?: any; })[] | undefined; } | undefined; query?: { format?: \"default\" | \"openai\" | undefined; } | undefined; }; }) => Promise<", "Readable", ">; } & ", "ObservabilityAIAssistantRouteCreateOptions", @@ -4673,8 +4649,6 @@ "StringC", "; title: ", "StringC", - "; responseLanguage: ", - "StringC", "; disableFunctions: ", "UnionC", "<[", @@ -4725,7 +4699,7 @@ "section": "def-common.Message", "text": "Message" }, - "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; responseLanguage?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body: { screenContexts: ", + "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body: { screenContexts: ", "ObservabilityAIAssistantScreenContextRequest", "[]; }; }; }) => Promise<", "Readable", @@ -5032,21 +5006,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "observabilityAIAssistant", - "id": "def-public.LANGUAGE_OPTIONS", - "type": "Array", - "tags": [], - "label": "LANGUAGE_OPTIONS", - "description": [], - "signature": [ - "{ value: string; label: string; }[]" - ], - "path": "x-pack/plugins/observability_solution/observability_ai_assistant/common/ui_settings/language_options.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "observabilityAIAssistant", "id": "def-public.ObservabilityAIAssistantAPIClientRequestParamsOf", @@ -5509,8 +5468,6 @@ "StringC", "; title: ", "StringC", - "; responseLanguage: ", - "StringC", "; disableFunctions: ", "UnionC", "<[", @@ -5575,7 +5532,7 @@ "section": "def-common.Message", "text": "Message" }, - "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; responseLanguage?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body?: { actions?: ({ name: string; description: string; } & { parameters?: any; })[] | undefined; } | undefined; query?: { format?: \"default\" | \"openai\" | undefined; } | undefined; }; }) => Promise<", + "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body?: { actions?: ({ name: string; description: string; } & { parameters?: any; })[] | undefined; } | undefined; query?: { format?: \"default\" | \"openai\" | undefined; } | undefined; }; }) => Promise<", "Readable", ">; } & ", "ObservabilityAIAssistantRouteCreateOptions", @@ -5617,8 +5574,6 @@ "StringC", "; title: ", "StringC", - "; responseLanguage: ", - "StringC", "; disableFunctions: ", "UnionC", "<[", @@ -5669,7 +5624,7 @@ "section": "def-common.Message", "text": "Message" }, - "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; responseLanguage?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body: { screenContexts: ", + "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body: { screenContexts: ", "ObservabilityAIAssistantScreenContextRequest", "[]; }; }; }) => Promise<", "Readable", @@ -6030,21 +5985,6 @@ } ], "initialIsOpen": false - }, - { - "parentPluginId": "observabilityAIAssistant", - "id": "def-public.DEFAULT_LANGUAGE_OPTION", - "type": "Object", - "tags": [], - "label": "DEFAULT_LANGUAGE_OPTION", - "description": [], - "signature": [ - "{ value: string; label: string; }" - ], - "path": "x-pack/plugins/observability_solution/observability_ai_assistant/common/ui_settings/language_options.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false } ], "setup": { @@ -6274,22 +6214,6 @@ } ] }, - { - "parentPluginId": "observabilityAIAssistant", - "id": "def-public.ObservabilityAIAssistantPublicStart.useUserPreferredLanguage", - "type": "Function", - "tags": [], - "label": "useUserPreferredLanguage", - "description": [], - "signature": [ - "() => { selectedLanguage: string; getPreferredLanguage: () => string; }" - ], - "path": "x-pack/plugins/observability_solution/observability_ai_assistant/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, { "parentPluginId": "observabilityAIAssistant", "id": "def-public.ObservabilityAIAssistantPublicStart.getContextualInsightMessages", @@ -6498,21 +6422,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "observabilityAIAssistant", - "id": "def-server.aiAssistantResponseLanguage", - "type": "string", - "tags": [], - "label": "aiAssistantResponseLanguage", - "description": [], - "signature": [ - "\"observability:aiAssistantResponseLanguage\"" - ], - "path": "x-pack/plugins/observability_solution/observability_ai_assistant/common/ui_settings/settings_keys.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "observabilityAIAssistant", "id": "def-server.aiAssistantSearchConnectorIndexPattern", @@ -7005,8 +6914,6 @@ "StringC", "; title: ", "StringC", - "; responseLanguage: ", - "StringC", "; disableFunctions: ", "UnionC", "<[", @@ -7071,7 +6978,7 @@ "section": "def-common.Message", "text": "Message" }, - "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; responseLanguage?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body?: { actions?: ({ name: string; description: string; } & { parameters?: any; })[] | undefined; } | undefined; query?: { format?: \"default\" | \"openai\" | undefined; } | undefined; }; }) => Promise<", + "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body?: { actions?: ({ name: string; description: string; } & { parameters?: any; })[] | undefined; } | undefined; query?: { format?: \"default\" | \"openai\" | undefined; } | undefined; }; }) => Promise<", "Readable", ">; } & ", "ObservabilityAIAssistantRouteCreateOptions", @@ -7113,8 +7020,6 @@ "StringC", "; title: ", "StringC", - "; responseLanguage: ", - "StringC", "; disableFunctions: ", "UnionC", "<[", @@ -7165,7 +7070,7 @@ "section": "def-common.Message", "text": "Message" }, - "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; responseLanguage?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body: { screenContexts: ", + "[]; connectorId: string; persist: boolean; } & { conversationId?: string | undefined; title?: string | undefined; disableFunctions?: boolean | { except: string[]; } | undefined; instructions?: ({ doc_id?: string | undefined; } & { text: string; instruction_type: \"user_instruction\" | \"application_instruction\"; })[] | undefined; }; } & { body: { screenContexts: ", "ObservabilityAIAssistantScreenContextRequest", "[]; }; }; }) => Promise<", "Readable", @@ -8427,21 +8332,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "observabilityAIAssistant", - "id": "def-common.aiAssistantResponseLanguage", - "type": "string", - "tags": [], - "label": "aiAssistantResponseLanguage", - "description": [], - "signature": [ - "\"observability:aiAssistantResponseLanguage\"" - ], - "path": "x-pack/plugins/observability_solution/observability_ai_assistant/common/ui_settings/settings_keys.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "observabilityAIAssistant", "id": "def-common.aiAssistantSearchConnectorIndexPattern", @@ -8713,21 +8603,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "observabilityAIAssistant", - "id": "def-common.LANGUAGE_OPTIONS", - "type": "Array", - "tags": [], - "label": "LANGUAGE_OPTIONS", - "description": [], - "signature": [ - "{ value: string; label: string; }[]" - ], - "path": "x-pack/plugins/observability_solution/observability_ai_assistant/common/ui_settings/language_options.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "observabilityAIAssistant", "id": "def-common.MessageAddEvent", @@ -8884,22 +8759,6 @@ "initialIsOpen": false } ], - "objects": [ - { - "parentPluginId": "observabilityAIAssistant", - "id": "def-common.DEFAULT_LANGUAGE_OPTION", - "type": "Object", - "tags": [], - "label": "DEFAULT_LANGUAGE_OPTION", - "description": [], - "signature": [ - "{ value: string; label: string; }" - ], - "path": "x-pack/plugins/observability_solution/observability_ai_assistant/common/ui_settings/language_options.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - } - ] + "objects": [] } } \ No newline at end of file diff --git a/api_docs/observability_a_i_assistant.mdx b/api_docs/observability_a_i_assistant.mdx index e39ad294021e9..4a7da59c69bcb 100644 --- a/api_docs/observability_a_i_assistant.mdx +++ b/api_docs/observability_a_i_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAIAssistant title: "observabilityAIAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAIAssistant plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistant'] --- import observabilityAIAssistantObj from './observability_a_i_assistant.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 294 | 1 | 292 | 27 | +| 286 | 1 | 284 | 27 | ## Client @@ -65,9 +65,6 @@ Contact [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai ## Common -### Objects - - ### Functions diff --git a/api_docs/observability_a_i_assistant_app.mdx b/api_docs/observability_a_i_assistant_app.mdx index 8cbaaa872d4cb..14baf68ab7485 100644 --- a/api_docs/observability_a_i_assistant_app.mdx +++ b/api_docs/observability_a_i_assistant_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAIAssistantApp title: "observabilityAIAssistantApp" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAIAssistantApp plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistantApp'] --- import observabilityAIAssistantAppObj from './observability_a_i_assistant_app.devdocs.json'; diff --git a/api_docs/observability_ai_assistant_management.mdx b/api_docs/observability_ai_assistant_management.mdx index 9441612794ad0..8b9a2c32a5282 100644 --- a/api_docs/observability_ai_assistant_management.mdx +++ b/api_docs/observability_ai_assistant_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAiAssistantManagement title: "observabilityAiAssistantManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAiAssistantManagement plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAiAssistantManagement'] --- import observabilityAiAssistantManagementObj from './observability_ai_assistant_management.devdocs.json'; diff --git a/api_docs/observability_logs_explorer.mdx b/api_docs/observability_logs_explorer.mdx index 2740655f8fa99..2c7b4a9e66168 100644 --- a/api_docs/observability_logs_explorer.mdx +++ b/api_docs/observability_logs_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityLogsExplorer title: "observabilityLogsExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityLogsExplorer plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityLogsExplorer'] --- import observabilityLogsExplorerObj from './observability_logs_explorer.devdocs.json'; diff --git a/api_docs/observability_onboarding.mdx b/api_docs/observability_onboarding.mdx index f9dfd904a907b..5840bf8d71821 100644 --- a/api_docs/observability_onboarding.mdx +++ b/api_docs/observability_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityOnboarding title: "observabilityOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityOnboarding plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityOnboarding'] --- import observabilityOnboardingObj from './observability_onboarding.devdocs.json'; diff --git a/api_docs/observability_shared.mdx b/api_docs/observability_shared.mdx index df83c7a009637..1a75342881719 100644 --- a/api_docs/observability_shared.mdx +++ b/api_docs/observability_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityShared title: "observabilityShared" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityShared plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityShared'] --- import observabilitySharedObj from './observability_shared.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index d28a5118490df..3f8c919c8232f 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/painless_lab.mdx b/api_docs/painless_lab.mdx index 2ce6c1982def4..eb9c1cf036374 100644 --- a/api_docs/painless_lab.mdx +++ b/api_docs/painless_lab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/painlessLab title: "painlessLab" image: https://source.unsplash.com/400x175/?github description: API docs for the painlessLab plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'painlessLab'] --- import painlessLabObj from './painless_lab.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 908398da629f7..a34bf2ec6cf3f 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -15,19 +15,19 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Count | Plugins or Packages with a
public API | Number of teams | |--------------|----------|------------------------| -| 846 | 719 | 46 | +| 849 | 723 | 46 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 52632 | 243 | 39544 | 1932 | +| 52833 | 243 | 39672 | 1940 | ## Plugin Directory | Plugin name           | Maintaining team | Description | API Cnt | Any Cnt | Missing
comments | Missing
exports | |--------------|----------------|-----------|--------------|----------|---------------|--------| -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 307 | 0 | 301 | 32 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 314 | 0 | 308 | 33 | | | [@elastic/appex-sharedux @elastic/kibana-management](https://github.com/orgs/elastic/teams/appex-sharedux ) | - | 2 | 0 | 2 | 0 | | | [@elastic/obs-knowledge-team](https://github.com/orgs/elastic/teams/obs-knowledge-team) | - | 4 | 0 | 4 | 1 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | AIOps plugin maintained by ML team. | 74 | 0 | 9 | 2 | @@ -119,16 +119,16 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 4 | 0 | 4 | 0 | | inputControlVis | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds Input Control visualization to Kibana | 0 | 0 | 0 | 0 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | - | 127 | 2 | 100 | 4 | -| | [@elastic/security-scalability](https://github.com/orgs/elastic/teams/security-scalability) | Plugin implementing the Integration Assistant API and UI | 49 | 0 | 41 | 3 | +| | [@elastic/security-scalability](https://github.com/orgs/elastic/teams/security-scalability) | Plugin implementing the Integration Assistant API and UI | 54 | 0 | 46 | 3 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides UI and APIs for the interactive setup mode. | 28 | 0 | 18 | 0 | -| | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 92 | 0 | 92 | 5 | +| | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 43 | 0 | 43 | 4 | | | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 5 | 0 | 5 | 2 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 6 | 0 | 6 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 153 | 0 | 121 | 3 | | kibanaUsageCollection | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 610 | 3 | 417 | 9 | | | [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) | - | 5 | 0 | 5 | 1 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana. | 685 | 0 | 583 | 62 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana. | 688 | 0 | 586 | 62 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 8 | 0 | 8 | 0 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 4 | 0 | 4 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 117 | 0 | 42 | 10 | @@ -136,7 +136,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 226 | 0 | 97 | 52 | | | [@elastic/obs-knowledge-team](https://github.com/orgs/elastic/teams/obs-knowledge-team) | - | 13 | 0 | 11 | 7 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | This plugin provides a LogsExplorer component using the Discover customization framework, offering several affordances specifically designed for log consumption. | 122 | 4 | 122 | 23 | -| | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | Exposes the shared components and APIs to access and visualize logs. | 300 | 0 | 272 | 32 | +| | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | Exposes the shared components and APIs to access and visualize logs. | 310 | 0 | 282 | 32 | | logstash | [@elastic/logstash](https://github.com/orgs/elastic/teams/logstash) | - | 0 | 0 | 0 | 0 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 44 | 0 | 44 | 7 | | | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | - | 209 | 0 | 205 | 28 | @@ -151,7 +151,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 3 | 0 | 3 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 2 | 1 | | | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 702 | 2 | 695 | 22 | -| | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 294 | 1 | 292 | 27 | +| | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 286 | 1 | 284 | 27 | | | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 4 | 0 | 4 | 0 | | | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 2 | 0 | 2 | 0 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | This plugin exposes and registers observability log consumption features. | 19 | 0 | 19 | 1 | @@ -184,7 +184,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | Plugin to provide access to and rendering of python notebooks for use in the persistent developer console. | 10 | 0 | 10 | 1 | | | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 17 | 0 | 11 | 1 | | searchprofiler | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 0 | 0 | 0 | 0 | -| | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides authentication and authorization features, and exposes functionality to understand the capabilities of the currently authenticated user. | 447 | 0 | 231 | 0 | +| | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides authentication and authorization features, and exposes functionality to understand the capabilities of the currently authenticated user. | 448 | 0 | 231 | 0 | | | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | - | 192 | 0 | 123 | 33 | | | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | ESS customizations for Security Solution. | 6 | 0 | 6 | 0 | | | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | Serverless customizations for security. | 7 | 0 | 7 | 0 | @@ -220,7 +220,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 12 | 0 | 12 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 52 | 0 | 14 | 5 | | | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 2 | 0 | 2 | 0 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | The default editor used in most aggregation-based visualizations. | 56 | 0 | 49 | 4 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | The default editor used in most aggregation-based visualizations. | 70 | 0 | 63 | 4 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Contains the gauge chart implementation using the elastic-charts library. The goal is to eventually deprecate the old implementation and keep only this. Until then, the library used is defined by the Legacy charts library advanced setting. | 7 | 0 | 7 | 2 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Contains the heatmap implementation using the elastic-charts library. The goal is to eventually deprecate the old implementation and keep only this. Until then, the library used is defined by the Legacy heatmap charts library advanced setting. | 3 | 0 | 3 | 2 | | visTypeMarkdown | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds a markdown visualization type | 0 | 0 | 0 | 0 | @@ -268,16 +268,18 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 19 | 0 | 16 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 9 | 2 | 9 | 0 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 44 | 1 | 30 | 1 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 23 | 0 | 19 | 0 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 25 | 0 | 21 | 0 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 84 | 0 | 84 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 7 | 0 | 2 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 3 | 0 | 3 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 62 | 0 | 17 | 1 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 2 | 0 | 2 | 0 | +| | [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) | - | 22 | 0 | 22 | 0 | +| | [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) | - | 49 | 0 | 49 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 41 | 0 | 17 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 2 | 0 | | | [@elastic/appex-qa](https://github.com/orgs/elastic/teams/appex-qa) | - | 8 | 0 | 4 | 0 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 217 | 0 | 180 | 9 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 227 | 0 | 188 | 9 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 79 | 0 | 50 | 9 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 24 | 0 | 24 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 149 | 2 | 143 | 20 | @@ -479,7 +481,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 3 | 0 | 3 | 0 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 4 | 0 | 4 | 0 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 3 | 0 | 3 | 0 | -| | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | - | 56 | 0 | 44 | 0 | +| | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | - | 61 | 0 | 49 | 0 | | | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 17 | 0 | 17 | 0 | | | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | - | 5 | 0 | 5 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 2 | 0 | @@ -491,12 +493,12 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 102 | 0 | 86 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 15 | 0 | 9 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 38 | 2 | 33 | 0 | -| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 133 | 0 | 106 | 1 | +| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 136 | 0 | 109 | 1 | | | [@elastic/docs](https://github.com/orgs/elastic/teams/docs) | - | 78 | 0 | 78 | 2 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 5 | 0 | 5 | 1 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 41 | 0 | 27 | 6 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 57 | 0 | 30 | 6 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 33 | 0 | 24 | 1 | -| | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 14 | 0 | 6 | 0 | +| | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 16 | 0 | 8 | 0 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | - | 35 | 0 | 34 | 0 | | | [@elastic/security-generative-ai](https://github.com/orgs/elastic/teams/security-generative-ai) | - | 156 | 0 | 130 | 9 | | | [@elastic/security-generative-ai](https://github.com/orgs/elastic/teams/security-generative-ai) | - | 346 | 0 | 320 | 0 | @@ -512,7 +514,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-esql](https://github.com/orgs/elastic/teams/kibana-esql) | - | 196 | 0 | 184 | 10 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 40 | 0 | 40 | 0 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 52 | 0 | 52 | 1 | -| | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 39 | 0 | 14 | 1 | +| | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 42 | 0 | 17 | 2 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 22 | 0 | 18 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 49 | 0 | 40 | 2 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 2 | 0 | 0 | 0 | @@ -523,7 +525,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 1 | 0 | 1 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 26 | 0 | 26 | 1 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | - | 16 | 0 | 16 | 1 | -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 17 | 0 | 12 | 10 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 17 | 0 | 12 | 11 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 49 | 0 | 47 | 0 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 33 | 3 | 24 | 6 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 3 | 0 | 3 | 0 | @@ -537,7 +539,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 7 | 1 | 7 | 1 | | | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 9 | 0 | 9 | 0 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 52 | 12 | 43 | 0 | -| | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 41 | 0 | 41 | 0 | +| | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 44 | 0 | 44 | 0 | | | [@elastic/obs-knowledge-team](https://github.com/orgs/elastic/teams/obs-knowledge-team) | - | 60 | 0 | 60 | 4 | | | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 44 | 0 | 44 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 13 | 0 | 13 | 0 | @@ -559,7 +561,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 23 | 0 | 7 | 0 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 8 | 0 | 2 | 3 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 45 | 0 | 0 | 0 | -| | [@elastic/appex-sharedux @elastic/kibana-management](https://github.com/orgs/elastic/teams/appex-sharedux ) | - | 143 | 0 | 141 | 0 | +| | [@elastic/appex-sharedux @elastic/kibana-management](https://github.com/orgs/elastic/teams/appex-sharedux ) | - | 142 | 0 | 140 | 0 | | | [@elastic/appex-sharedux @elastic/kibana-management](https://github.com/orgs/elastic/teams/appex-sharedux ) | - | 20 | 0 | 11 | 0 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 88 | 0 | 10 | 0 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 56 | 0 | 6 | 0 | @@ -658,14 +660,16 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 35 | 0 | 25 | 0 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 7 | 0 | 7 | 0 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 118 | 0 | 59 | 0 | -| | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 51 | 0 | 25 | 0 | +| | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 58 | 0 | 31 | 0 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 275 | 1 | 154 | 0 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 75 | 0 | 74 | 0 | +| | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 59 | 0 | 38 | 5 | | | [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) | - | 6 | 0 | 0 | 0 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 15 | 0 | 15 | 7 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 54 | 0 | 49 | 0 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 30 | 0 | 24 | 0 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 2 | 0 | 0 | 0 | +| | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 47 | 0 | 12 | 0 | | | [@elastic/security-detection-engine](https://github.com/orgs/elastic/teams/security-detection-engine) | - | 56 | 1 | 41 | 1 | | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 92 | 0 | 70 | 6 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 341 | 1 | 337 | 32 | @@ -767,7 +771,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 37 | 0 | 16 | 1 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 2 | 0 | 2 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 26 | 0 | 15 | 0 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 146 | 0 | 143 | 3 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 137 | 0 | 134 | 4 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 19 | 0 | 17 | 1 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | - | 13 | 0 | 13 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 9 | 0 | 4 | 0 | diff --git a/api_docs/presentation_panel.mdx b/api_docs/presentation_panel.mdx index 26d7c9c969ddc..50676fdbb1a64 100644 --- a/api_docs/presentation_panel.mdx +++ b/api_docs/presentation_panel.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationPanel title: "presentationPanel" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationPanel plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationPanel'] --- import presentationPanelObj from './presentation_panel.devdocs.json'; diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 923fe76dbc464..c9d34a56be7da 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index c30d5f49f61ce..2f26ed770b75d 100644 --- a/api_docs/profiling.mdx +++ b/api_docs/profiling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profiling title: "profiling" image: https://source.unsplash.com/400x175/?github description: API docs for the profiling plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/profiling_data_access.mdx b/api_docs/profiling_data_access.mdx index 5e0fc31881f4b..90728ec9714c1 100644 --- a/api_docs/profiling_data_access.mdx +++ b/api_docs/profiling_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profilingDataAccess title: "profilingDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the profilingDataAccess plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profilingDataAccess'] --- import profilingDataAccessObj from './profiling_data_access.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index e3aecf65ea502..2362fe42aeac6 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index 719d6340a68cc..b95daa83b6cda 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.devdocs.json'; diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index 093bf4409da7f..5ca3cf1837623 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 8558cf0f6e0aa..a884d2bbc9dfd 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index 524d0519041a4..a83bc675efcfc 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index 55ffba4f93e71..04ba4249f63f2 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; diff --git a/api_docs/saved_objects_finder.devdocs.json b/api_docs/saved_objects_finder.devdocs.json index a5dfa604ab941..f23341ed4ab5d 100644 --- a/api_docs/saved_objects_finder.devdocs.json +++ b/api_docs/saved_objects_finder.devdocs.json @@ -549,9 +549,9 @@ "signature": [ { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "" diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index 7835452fc8e1b..b8e84dcd4e52c 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index 66a83f84b9ae8..c6a6ed4f277ee 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index da2d0665bab32..1cda315a00d0e 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index ce9d137330667..8b1f6099ceda2 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.devdocs.json b/api_docs/saved_search.devdocs.json index 13e1c29fa1214..60a67177b7129 100644 --- a/api_docs/saved_search.devdocs.json +++ b/api_docs/saved_search.devdocs.json @@ -182,9 +182,9 @@ ", \"description\"> & { description?: string | undefined; references: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.Reference", + "section": "def-server.Reference", "text": "Reference" }, "[]; }" @@ -304,9 +304,9 @@ ", \"description\"> & { description?: string | undefined; references: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.Reference", + "section": "def-server.Reference", "text": "Reference" }, "[]; }" @@ -422,9 +422,9 @@ "() => Promise<", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "<", diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index 6493c183bf1d7..7dbbe8861c4ec 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedSearch'] --- import savedSearchObj from './saved_search.devdocs.json'; diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index 7c9f3dac7cf17..2095c96e19773 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index de3a94a7d7cd9..50e86072d25e9 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/search_assistant.mdx b/api_docs/search_assistant.mdx index 91e578291858c..383be7af8fc16 100644 --- a/api_docs/search_assistant.mdx +++ b/api_docs/search_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchAssistant title: "searchAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the searchAssistant plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchAssistant'] --- import searchAssistantObj from './search_assistant.devdocs.json'; diff --git a/api_docs/search_connectors.mdx b/api_docs/search_connectors.mdx index e906c5523870a..01875d782b57f 100644 --- a/api_docs/search_connectors.mdx +++ b/api_docs/search_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchConnectors title: "searchConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the searchConnectors plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchConnectors'] --- import searchConnectorsObj from './search_connectors.devdocs.json'; diff --git a/api_docs/search_homepage.mdx b/api_docs/search_homepage.mdx index d14cd8e67279f..81c82c27a9176 100644 --- a/api_docs/search_homepage.mdx +++ b/api_docs/search_homepage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchHomepage title: "searchHomepage" image: https://source.unsplash.com/400x175/?github description: API docs for the searchHomepage plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchHomepage'] --- import searchHomepageObj from './search_homepage.devdocs.json'; diff --git a/api_docs/search_indices.mdx b/api_docs/search_indices.mdx index 1812f60b5c8b9..34168f89362a6 100644 --- a/api_docs/search_indices.mdx +++ b/api_docs/search_indices.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchIndices title: "searchIndices" image: https://source.unsplash.com/400x175/?github description: API docs for the searchIndices plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchIndices'] --- import searchIndicesObj from './search_indices.devdocs.json'; diff --git a/api_docs/search_inference_endpoints.mdx b/api_docs/search_inference_endpoints.mdx index f2ace37c453c9..880067105aa40 100644 --- a/api_docs/search_inference_endpoints.mdx +++ b/api_docs/search_inference_endpoints.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchInferenceEndpoints title: "searchInferenceEndpoints" image: https://source.unsplash.com/400x175/?github description: API docs for the searchInferenceEndpoints plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchInferenceEndpoints'] --- import searchInferenceEndpointsObj from './search_inference_endpoints.devdocs.json'; diff --git a/api_docs/search_notebooks.mdx b/api_docs/search_notebooks.mdx index 96eeb74884b60..11f9d38b84f58 100644 --- a/api_docs/search_notebooks.mdx +++ b/api_docs/search_notebooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchNotebooks title: "searchNotebooks" image: https://source.unsplash.com/400x175/?github description: API docs for the searchNotebooks plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchNotebooks'] --- import searchNotebooksObj from './search_notebooks.devdocs.json'; diff --git a/api_docs/search_playground.mdx b/api_docs/search_playground.mdx index 831135e7c8899..9a769f783a872 100644 --- a/api_docs/search_playground.mdx +++ b/api_docs/search_playground.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchPlayground title: "searchPlayground" image: https://source.unsplash.com/400x175/?github description: API docs for the searchPlayground plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchPlayground'] --- import searchPlaygroundObj from './search_playground.devdocs.json'; diff --git a/api_docs/security.devdocs.json b/api_docs/security.devdocs.json index bc5c1ffbd6fc9..b48e22603274b 100644 --- a/api_docs/security.devdocs.json +++ b/api_docs/security.devdocs.json @@ -253,6 +253,28 @@ "path": "x-pack/packages/security/plugin_types_public/src/authorization/authorization_service.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "security", + "id": "def-public.AuthorizationServiceSetup.privileges", + "type": "Object", + "tags": [], + "label": "privileges", + "description": [ + "\nA set of methods to work with Kibana role privileges" + ], + "signature": [ + { + "pluginId": "@kbn/security-plugin-types-public", + "scope": "public", + "docId": "kibKbnSecurityPluginTypesPublicPluginApi", + "section": "def-public.PrivilegesAPIClientPublicContract", + "text": "PrivilegesAPIClientPublicContract" + } + ], + "path": "x-pack/packages/security/plugin_types_public/src/authorization/authorization_service.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/security.mdx b/api_docs/security.mdx index e289d2ade1afa..5ad06d1d871a2 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana- | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 447 | 0 | 231 | 0 | +| 448 | 0 | 231 | 0 | ## Client diff --git a/api_docs/security_solution.devdocs.json b/api_docs/security_solution.devdocs.json index ae4e037e5e71d..9d4957972ff47 100644 --- a/api_docs/security_solution.devdocs.json +++ b/api_docs/security_solution.devdocs.json @@ -485,7 +485,7 @@ "\nExperimental flag needed to enable the link" ], "signature": [ - "\"assistantKnowledgeBaseByDefault\" | \"assistantModelEvaluation\" | \"assistantBedrockChat\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"extendedRuleExecutionLoggingEnabled\" | \"socTrendsEnabled\" | \"responseActionUploadEnabled\" | \"automatedProcessActionsEnabled\" | \"responseActionsSentinelOneV1Enabled\" | \"responseActionsSentinelOneV2Enabled\" | \"responseActionsSentinelOneGetFileEnabled\" | \"responseActionsSentinelOneKillProcessEnabled\" | \"responseActionsSentinelOneProcessesEnabled\" | \"responseActionsCrowdstrikeManualHostIsolationEnabled\" | \"responseActionScanEnabled\" | \"securitySolutionNotesEnabled\" | \"entityAlertPreviewDisabled\" | \"newUserDetailsFlyoutManagedUser\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"esqlRulesDisabled\" | \"protectionUpdatesEnabled\" | \"disableTimelineSaveTour\" | \"riskEnginePrivilegesRouteEnabled\" | \"sentinelOneDataInAnalyzerEnabled\" | \"sentinelOneManualHostActionsEnabled\" | \"crowdstrikeDataInAnalyzerEnabled\" | \"jamfDataInAnalyzerEnabled\" | \"timelineEsqlTabDisabled\" | \"unifiedComponentsInTimelineDisabled\" | \"analyzerDatePickersAndSourcererDisabled\" | \"prebuiltRulesCustomizationEnabled\" | \"malwareOnWriteScanOptionAvailable\" | \"unifiedManifestEnabled\" | \"valueListItemsModalEnabled\" | \"manualRuleRunEnabled\" | \"filterProcessDescendantsForEventFiltersEnabled\" | \"dataIngestionHubEnabled\" | undefined" + "\"assistantKnowledgeBaseByDefault\" | \"assistantModelEvaluation\" | \"assistantBedrockChat\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"extendedRuleExecutionLoggingEnabled\" | \"socTrendsEnabled\" | \"responseActionUploadEnabled\" | \"automatedProcessActionsEnabled\" | \"responseActionsSentinelOneV1Enabled\" | \"responseActionsSentinelOneV2Enabled\" | \"responseActionsSentinelOneGetFileEnabled\" | \"responseActionsSentinelOneKillProcessEnabled\" | \"responseActionsSentinelOneProcessesEnabled\" | \"responseActionsCrowdstrikeManualHostIsolationEnabled\" | \"securitySolutionNotesEnabled\" | \"entityAlertPreviewDisabled\" | \"newUserDetailsFlyoutManagedUser\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"esqlRulesDisabled\" | \"protectionUpdatesEnabled\" | \"disableTimelineSaveTour\" | \"riskEnginePrivilegesRouteEnabled\" | \"sentinelOneDataInAnalyzerEnabled\" | \"sentinelOneManualHostActionsEnabled\" | \"crowdstrikeDataInAnalyzerEnabled\" | \"jamfDataInAnalyzerEnabled\" | \"timelineEsqlTabDisabled\" | \"unifiedComponentsInTimelineDisabled\" | \"analyzerDatePickersAndSourcererDisabled\" | \"prebuiltRulesCustomizationEnabled\" | \"malwareOnWriteScanOptionAvailable\" | \"unifiedManifestEnabled\" | \"valueListItemsModalEnabled\" | \"manualRuleRunEnabled\" | \"filterProcessDescendantsForEventFiltersEnabled\" | \"dataIngestionHubEnabled\" | undefined" ], "path": "x-pack/plugins/security_solution/public/common/links/types.ts", "deprecated": false, @@ -565,7 +565,7 @@ "\nExperimental flag needed to disable the link. Opposite of experimentalKey" ], "signature": [ - "\"assistantKnowledgeBaseByDefault\" | \"assistantModelEvaluation\" | \"assistantBedrockChat\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"extendedRuleExecutionLoggingEnabled\" | \"socTrendsEnabled\" | \"responseActionUploadEnabled\" | \"automatedProcessActionsEnabled\" | \"responseActionsSentinelOneV1Enabled\" | \"responseActionsSentinelOneV2Enabled\" | \"responseActionsSentinelOneGetFileEnabled\" | \"responseActionsSentinelOneKillProcessEnabled\" | \"responseActionsSentinelOneProcessesEnabled\" | \"responseActionsCrowdstrikeManualHostIsolationEnabled\" | \"responseActionScanEnabled\" | \"securitySolutionNotesEnabled\" | \"entityAlertPreviewDisabled\" | \"newUserDetailsFlyoutManagedUser\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"esqlRulesDisabled\" | \"protectionUpdatesEnabled\" | \"disableTimelineSaveTour\" | \"riskEnginePrivilegesRouteEnabled\" | \"sentinelOneDataInAnalyzerEnabled\" | \"sentinelOneManualHostActionsEnabled\" | \"crowdstrikeDataInAnalyzerEnabled\" | \"jamfDataInAnalyzerEnabled\" | \"timelineEsqlTabDisabled\" | \"unifiedComponentsInTimelineDisabled\" | \"analyzerDatePickersAndSourcererDisabled\" | \"prebuiltRulesCustomizationEnabled\" | \"malwareOnWriteScanOptionAvailable\" | \"unifiedManifestEnabled\" | \"valueListItemsModalEnabled\" | \"manualRuleRunEnabled\" | \"filterProcessDescendantsForEventFiltersEnabled\" | \"dataIngestionHubEnabled\" | undefined" + "\"assistantKnowledgeBaseByDefault\" | \"assistantModelEvaluation\" | \"assistantBedrockChat\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"extendedRuleExecutionLoggingEnabled\" | \"socTrendsEnabled\" | \"responseActionUploadEnabled\" | \"automatedProcessActionsEnabled\" | \"responseActionsSentinelOneV1Enabled\" | \"responseActionsSentinelOneV2Enabled\" | \"responseActionsSentinelOneGetFileEnabled\" | \"responseActionsSentinelOneKillProcessEnabled\" | \"responseActionsSentinelOneProcessesEnabled\" | \"responseActionsCrowdstrikeManualHostIsolationEnabled\" | \"securitySolutionNotesEnabled\" | \"entityAlertPreviewDisabled\" | \"newUserDetailsFlyoutManagedUser\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"esqlRulesDisabled\" | \"protectionUpdatesEnabled\" | \"disableTimelineSaveTour\" | \"riskEnginePrivilegesRouteEnabled\" | \"sentinelOneDataInAnalyzerEnabled\" | \"sentinelOneManualHostActionsEnabled\" | \"crowdstrikeDataInAnalyzerEnabled\" | \"jamfDataInAnalyzerEnabled\" | \"timelineEsqlTabDisabled\" | \"unifiedComponentsInTimelineDisabled\" | \"analyzerDatePickersAndSourcererDisabled\" | \"prebuiltRulesCustomizationEnabled\" | \"malwareOnWriteScanOptionAvailable\" | \"unifiedManifestEnabled\" | \"valueListItemsModalEnabled\" | \"manualRuleRunEnabled\" | \"filterProcessDescendantsForEventFiltersEnabled\" | \"dataIngestionHubEnabled\" | undefined" ], "path": "x-pack/plugins/security_solution/public/common/links/types.ts", "deprecated": false, @@ -1931,7 +1931,7 @@ "label": "experimentalFeatures", "description": [], "signature": [ - "{ readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly automatedProcessActionsEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly responseActionsSentinelOneV2Enabled: boolean; readonly responseActionsSentinelOneGetFileEnabled: boolean; readonly responseActionsSentinelOneKillProcessEnabled: boolean; readonly responseActionsSentinelOneProcessesEnabled: boolean; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: boolean; readonly responseActionScanEnabled: boolean; readonly securitySolutionNotesEnabled: boolean; readonly entityAlertPreviewDisabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantKnowledgeBaseByDefault: boolean; readonly assistantBedrockChat: boolean; readonly newUserDetailsFlyoutManagedUser: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly crowdstrikeDataInAnalyzerEnabled: boolean; readonly jamfDataInAnalyzerEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; readonly unifiedComponentsInTimelineDisabled: boolean; readonly analyzerDatePickersAndSourcererDisabled: boolean; readonly prebuiltRulesCustomizationEnabled: boolean; readonly malwareOnWriteScanOptionAvailable: boolean; readonly unifiedManifestEnabled: boolean; readonly valueListItemsModalEnabled: boolean; readonly manualRuleRunEnabled: boolean; readonly filterProcessDescendantsForEventFiltersEnabled: boolean; readonly dataIngestionHubEnabled: boolean; }" + "{ readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly automatedProcessActionsEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly responseActionsSentinelOneV2Enabled: boolean; readonly responseActionsSentinelOneGetFileEnabled: boolean; readonly responseActionsSentinelOneKillProcessEnabled: boolean; readonly responseActionsSentinelOneProcessesEnabled: boolean; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: boolean; readonly securitySolutionNotesEnabled: boolean; readonly entityAlertPreviewDisabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantKnowledgeBaseByDefault: boolean; readonly assistantBedrockChat: boolean; readonly newUserDetailsFlyoutManagedUser: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly crowdstrikeDataInAnalyzerEnabled: boolean; readonly jamfDataInAnalyzerEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; readonly unifiedComponentsInTimelineDisabled: boolean; readonly analyzerDatePickersAndSourcererDisabled: boolean; readonly prebuiltRulesCustomizationEnabled: boolean; readonly malwareOnWriteScanOptionAvailable: boolean; readonly unifiedManifestEnabled: boolean; readonly valueListItemsModalEnabled: boolean; readonly manualRuleRunEnabled: boolean; readonly filterProcessDescendantsForEventFiltersEnabled: boolean; readonly dataIngestionHubEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/public/types.ts", "deprecated": false, @@ -3082,7 +3082,7 @@ "\nThe security solution generic experimental features" ], "signature": [ - "{ readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly automatedProcessActionsEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly responseActionsSentinelOneV2Enabled: boolean; readonly responseActionsSentinelOneGetFileEnabled: boolean; readonly responseActionsSentinelOneKillProcessEnabled: boolean; readonly responseActionsSentinelOneProcessesEnabled: boolean; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: boolean; readonly responseActionScanEnabled: boolean; readonly securitySolutionNotesEnabled: boolean; readonly entityAlertPreviewDisabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantKnowledgeBaseByDefault: boolean; readonly assistantBedrockChat: boolean; readonly newUserDetailsFlyoutManagedUser: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly crowdstrikeDataInAnalyzerEnabled: boolean; readonly jamfDataInAnalyzerEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; readonly unifiedComponentsInTimelineDisabled: boolean; readonly analyzerDatePickersAndSourcererDisabled: boolean; readonly prebuiltRulesCustomizationEnabled: boolean; readonly malwareOnWriteScanOptionAvailable: boolean; readonly unifiedManifestEnabled: boolean; readonly valueListItemsModalEnabled: boolean; readonly manualRuleRunEnabled: boolean; readonly filterProcessDescendantsForEventFiltersEnabled: boolean; readonly dataIngestionHubEnabled: boolean; }" + "{ readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly automatedProcessActionsEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly responseActionsSentinelOneV2Enabled: boolean; readonly responseActionsSentinelOneGetFileEnabled: boolean; readonly responseActionsSentinelOneKillProcessEnabled: boolean; readonly responseActionsSentinelOneProcessesEnabled: boolean; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: boolean; readonly securitySolutionNotesEnabled: boolean; readonly entityAlertPreviewDisabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantKnowledgeBaseByDefault: boolean; readonly assistantBedrockChat: boolean; readonly newUserDetailsFlyoutManagedUser: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly crowdstrikeDataInAnalyzerEnabled: boolean; readonly jamfDataInAnalyzerEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; readonly unifiedComponentsInTimelineDisabled: boolean; readonly analyzerDatePickersAndSourcererDisabled: boolean; readonly prebuiltRulesCustomizationEnabled: boolean; readonly malwareOnWriteScanOptionAvailable: boolean; readonly unifiedManifestEnabled: boolean; readonly valueListItemsModalEnabled: boolean; readonly manualRuleRunEnabled: boolean; readonly filterProcessDescendantsForEventFiltersEnabled: boolean; readonly dataIngestionHubEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/server/plugin_contract.ts", "deprecated": false, @@ -3258,7 +3258,7 @@ "label": "ExperimentalFeatures", "description": [], "signature": [ - "{ readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly automatedProcessActionsEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly responseActionsSentinelOneV2Enabled: boolean; readonly responseActionsSentinelOneGetFileEnabled: boolean; readonly responseActionsSentinelOneKillProcessEnabled: boolean; readonly responseActionsSentinelOneProcessesEnabled: boolean; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: boolean; readonly responseActionScanEnabled: boolean; readonly securitySolutionNotesEnabled: boolean; readonly entityAlertPreviewDisabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantKnowledgeBaseByDefault: boolean; readonly assistantBedrockChat: boolean; readonly newUserDetailsFlyoutManagedUser: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly crowdstrikeDataInAnalyzerEnabled: boolean; readonly jamfDataInAnalyzerEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; readonly unifiedComponentsInTimelineDisabled: boolean; readonly analyzerDatePickersAndSourcererDisabled: boolean; readonly prebuiltRulesCustomizationEnabled: boolean; readonly malwareOnWriteScanOptionAvailable: boolean; readonly unifiedManifestEnabled: boolean; readonly valueListItemsModalEnabled: boolean; readonly manualRuleRunEnabled: boolean; readonly filterProcessDescendantsForEventFiltersEnabled: boolean; readonly dataIngestionHubEnabled: boolean; }" + "{ readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly automatedProcessActionsEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly responseActionsSentinelOneV2Enabled: boolean; readonly responseActionsSentinelOneGetFileEnabled: boolean; readonly responseActionsSentinelOneKillProcessEnabled: boolean; readonly responseActionsSentinelOneProcessesEnabled: boolean; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: boolean; readonly securitySolutionNotesEnabled: boolean; readonly entityAlertPreviewDisabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantKnowledgeBaseByDefault: boolean; readonly assistantBedrockChat: boolean; readonly newUserDetailsFlyoutManagedUser: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly crowdstrikeDataInAnalyzerEnabled: boolean; readonly jamfDataInAnalyzerEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; readonly unifiedComponentsInTimelineDisabled: boolean; readonly analyzerDatePickersAndSourcererDisabled: boolean; readonly prebuiltRulesCustomizationEnabled: boolean; readonly malwareOnWriteScanOptionAvailable: boolean; readonly unifiedManifestEnabled: boolean; readonly valueListItemsModalEnabled: boolean; readonly manualRuleRunEnabled: boolean; readonly filterProcessDescendantsForEventFiltersEnabled: boolean; readonly dataIngestionHubEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/common/experimental_features.ts", "deprecated": false, @@ -3324,7 +3324,7 @@ "\nA list of allowed values that can be used in `xpack.securitySolution.enableExperimental`.\nThis object is then used to validate and parse the value entered." ], "signature": [ - "{ readonly excludePoliciesInFilterEnabled: false; readonly kubernetesEnabled: true; readonly donutChartEmbeddablesEnabled: false; readonly previewTelemetryUrlEnabled: false; readonly extendedRuleExecutionLoggingEnabled: false; readonly socTrendsEnabled: false; readonly responseActionUploadEnabled: true; readonly automatedProcessActionsEnabled: true; readonly responseActionsSentinelOneV1Enabled: true; readonly responseActionsSentinelOneV2Enabled: true; readonly responseActionsSentinelOneGetFileEnabled: true; readonly responseActionsSentinelOneKillProcessEnabled: true; readonly responseActionsSentinelOneProcessesEnabled: true; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: true; readonly responseActionScanEnabled: true; readonly securitySolutionNotesEnabled: false; readonly entityAlertPreviewDisabled: false; readonly assistantModelEvaluation: false; readonly assistantKnowledgeBaseByDefault: false; readonly assistantBedrockChat: true; readonly newUserDetailsFlyoutManagedUser: false; readonly riskScoringPersistence: true; readonly riskScoringRoutesEnabled: true; readonly esqlRulesDisabled: false; readonly protectionUpdatesEnabled: true; readonly disableTimelineSaveTour: false; readonly riskEnginePrivilegesRouteEnabled: true; readonly sentinelOneDataInAnalyzerEnabled: true; readonly sentinelOneManualHostActionsEnabled: true; readonly crowdstrikeDataInAnalyzerEnabled: true; readonly jamfDataInAnalyzerEnabled: true; readonly timelineEsqlTabDisabled: false; readonly unifiedComponentsInTimelineDisabled: false; readonly analyzerDatePickersAndSourcererDisabled: false; readonly prebuiltRulesCustomizationEnabled: false; readonly malwareOnWriteScanOptionAvailable: true; readonly unifiedManifestEnabled: true; readonly valueListItemsModalEnabled: true; readonly manualRuleRunEnabled: false; readonly filterProcessDescendantsForEventFiltersEnabled: true; readonly dataIngestionHubEnabled: false; }" + "{ readonly excludePoliciesInFilterEnabled: false; readonly kubernetesEnabled: true; readonly donutChartEmbeddablesEnabled: false; readonly previewTelemetryUrlEnabled: false; readonly extendedRuleExecutionLoggingEnabled: false; readonly socTrendsEnabled: false; readonly responseActionUploadEnabled: true; readonly automatedProcessActionsEnabled: true; readonly responseActionsSentinelOneV1Enabled: true; readonly responseActionsSentinelOneV2Enabled: true; readonly responseActionsSentinelOneGetFileEnabled: true; readonly responseActionsSentinelOneKillProcessEnabled: true; readonly responseActionsSentinelOneProcessesEnabled: true; readonly responseActionsCrowdstrikeManualHostIsolationEnabled: true; readonly securitySolutionNotesEnabled: false; readonly entityAlertPreviewDisabled: false; readonly assistantModelEvaluation: false; readonly assistantKnowledgeBaseByDefault: false; readonly assistantBedrockChat: true; readonly newUserDetailsFlyoutManagedUser: false; readonly riskScoringPersistence: true; readonly riskScoringRoutesEnabled: true; readonly esqlRulesDisabled: false; readonly protectionUpdatesEnabled: true; readonly disableTimelineSaveTour: false; readonly riskEnginePrivilegesRouteEnabled: true; readonly sentinelOneDataInAnalyzerEnabled: true; readonly sentinelOneManualHostActionsEnabled: true; readonly crowdstrikeDataInAnalyzerEnabled: true; readonly jamfDataInAnalyzerEnabled: true; readonly timelineEsqlTabDisabled: false; readonly unifiedComponentsInTimelineDisabled: false; readonly analyzerDatePickersAndSourcererDisabled: false; readonly prebuiltRulesCustomizationEnabled: false; readonly malwareOnWriteScanOptionAvailable: true; readonly unifiedManifestEnabled: true; readonly valueListItemsModalEnabled: true; readonly manualRuleRunEnabled: false; readonly filterProcessDescendantsForEventFiltersEnabled: true; readonly dataIngestionHubEnabled: false; }" ], "path": "x-pack/plugins/security_solution/common/experimental_features.ts", "deprecated": false, diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 77b452878fa70..a1ad9e8443082 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/security_solution_ess.mdx b/api_docs/security_solution_ess.mdx index 3d9049b43d2c2..7a7585d7f6cc8 100644 --- a/api_docs/security_solution_ess.mdx +++ b/api_docs/security_solution_ess.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionEss title: "securitySolutionEss" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionEss plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionEss'] --- import securitySolutionEssObj from './security_solution_ess.devdocs.json'; diff --git a/api_docs/security_solution_serverless.mdx b/api_docs/security_solution_serverless.mdx index 7f401033ab837..ce13bb0c0f255 100644 --- a/api_docs/security_solution_serverless.mdx +++ b/api_docs/security_solution_serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionServerless title: "securitySolutionServerless" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionServerless plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionServerless'] --- import securitySolutionServerlessObj from './security_solution_serverless.devdocs.json'; diff --git a/api_docs/serverless.mdx b/api_docs/serverless.mdx index 3a66ca3ae8c1b..cc365736103c2 100644 --- a/api_docs/serverless.mdx +++ b/api_docs/serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverless title: "serverless" image: https://source.unsplash.com/400x175/?github description: API docs for the serverless plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverless'] --- import serverlessObj from './serverless.devdocs.json'; diff --git a/api_docs/serverless_observability.mdx b/api_docs/serverless_observability.mdx index 7507c218b3ad9..3a27fcc3ef778 100644 --- a/api_docs/serverless_observability.mdx +++ b/api_docs/serverless_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessObservability title: "serverlessObservability" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessObservability plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessObservability'] --- import serverlessObservabilityObj from './serverless_observability.devdocs.json'; diff --git a/api_docs/serverless_search.mdx b/api_docs/serverless_search.mdx index 25f8e60fcd4bf..c6bb6d935251c 100644 --- a/api_docs/serverless_search.mdx +++ b/api_docs/serverless_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessSearch title: "serverlessSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessSearch plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessSearch'] --- import serverlessSearchObj from './serverless_search.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 81fa8b0bd5ccd..24748178e20c7 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.mdx b/api_docs/share.mdx index 8840b6fe9b7cf..0bd062c95b4fe 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/slo.mdx b/api_docs/slo.mdx index 44d6d76eec612..ca2de59b49cce 100644 --- a/api_docs/slo.mdx +++ b/api_docs/slo.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/slo title: "slo" image: https://source.unsplash.com/400x175/?github description: API docs for the slo plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'slo'] --- import sloObj from './slo.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index 7866c061cf7be..a36913156bfd6 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] --- import snapshotRestoreObj from './snapshot_restore.devdocs.json'; diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index 07eff2e32f515..a9ca9b751807b 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] --- import spacesObj from './spaces.devdocs.json'; diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index b8475bcdf867f..ef2b059626944 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/stack_connectors.mdx b/api_docs/stack_connectors.mdx index 82ebcf572b38c..1ee5237af92c0 100644 --- a/api_docs/stack_connectors.mdx +++ b/api_docs/stack_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackConnectors title: "stackConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the stackConnectors plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index 9975a683c2fc6..81c96e40ae1ae 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index 0092af0da949f..e21e0726714d7 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index 50b7b81a75760..ad8d152b80427 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index 08d7f118d0da8..ddfd3254cd6a0 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] --- import telemetryCollectionXpackObj from './telemetry_collection_xpack.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index 750e14de23137..ae5bd1d8b8e7b 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index ace667e6e035d..bbe2addd3235a 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.devdocs.json b/api_docs/timelines.devdocs.json index 0d8299cd0d6d7..b932cbc25538b 100644 --- a/api_docs/timelines.devdocs.json +++ b/api_docs/timelines.devdocs.json @@ -3696,14 +3696,6 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/body/column_headers/helpers.test.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.tsx" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.tsx" - }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/common/containers/source/mock.ts" @@ -3816,14 +3808,6 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/provider_item_badge.tsx" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx" - }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx" - }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/body/column_headers/index.tsx" @@ -3924,6 +3908,14 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/flyout/document_details/right/tabs/table_tab.tsx" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/flyout/document_details/right/utils/enriched_field_info.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/flyout/document_details/right/utils/enriched_field_info.ts" + }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/shared/utils.ts" diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index 7d2ca3e44137f..aadf2e54945fe 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] --- import timelinesObj from './timelines.devdocs.json'; diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index 4182ee2d921a7..21ae7f2a0a8b9 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index dd0573a7dad31..c0fb56e2b4415 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 147415a02455d..70ea44a5b54e1 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index bc047abd77f93..ee682e771cd3e 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_doc_viewer.mdx b/api_docs/unified_doc_viewer.mdx index 6e9dc36957bab..aac22fcc3d72a 100644 --- a/api_docs/unified_doc_viewer.mdx +++ b/api_docs/unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedDocViewer title: "unifiedDocViewer" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedDocViewer plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedDocViewer'] --- import unifiedDocViewerObj from './unified_doc_viewer.devdocs.json'; diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index 28ebf3b09f032..1d4f5be31e4d6 100644 --- a/api_docs/unified_histogram.mdx +++ b/api_docs/unified_histogram.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedHistogram title: "unifiedHistogram" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedHistogram plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 71c9f28b32724..cf7b573376f24 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_search.devdocs.json'; diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index 47c6345975227..47221077e8571 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/uptime.mdx b/api_docs/uptime.mdx index ddddde515e257..d53f7799ba24d 100644 --- a/api_docs/uptime.mdx +++ b/api_docs/uptime.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uptime title: "uptime" image: https://source.unsplash.com/400x175/?github description: API docs for the uptime plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uptime'] --- import uptimeObj from './uptime.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index fe41ec1fa440d..0ec70835ab6e6 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 1986d4cc93a16..7a113d4820f61 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] --- import usageCollectionObj from './usage_collection.devdocs.json'; diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index 52db8bff35a05..5dba909a8af17 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] --- import uxObj from './ux.devdocs.json'; diff --git a/api_docs/vis_default_editor.devdocs.json b/api_docs/vis_default_editor.devdocs.json index 8f8b1b408ffd1..24aa865bbefc2 100644 --- a/api_docs/vis_default_editor.devdocs.json +++ b/api_docs/vis_default_editor.devdocs.json @@ -477,7 +477,15 @@ "\nDo not use this component anymore.\nPlease, use NumberInputOption in 'required_number_input.tsx'.\nIt is required for compatibility with TS 3.7.0\nThis should be removed in the future" ], "signature": [ - "({\n disabled,\n error,\n isInvalid,\n label,\n max,\n min,\n paramName,\n step,\n value = '',\n setValue,\n 'data-test-subj': dataTestSubj,\n}: NumberInputOptionProps) => JSX.Element" + "({\n disabled,\n error,\n isInvalid,\n label,\n max,\n min,\n paramName,\n step,\n value = '',\n setValue,\n 'data-test-subj': dataTestSubj,\n}: ", + { + "pluginId": "visDefaultEditor", + "scope": "public", + "docId": "kibVisDefaultEditorPluginApi", + "section": "def-public.NumberInputOptionProps", + "text": "NumberInputOptionProps" + }, + ") => JSX.Element" ], "path": "src/plugins/vis_default_editor/public/components/options/number_input.tsx", "deprecated": false, @@ -491,7 +499,14 @@ "label": "{\n disabled,\n error,\n isInvalid,\n label,\n max,\n min,\n paramName,\n step,\n value = '',\n setValue,\n 'data-test-subj': dataTestSubj,\n}", "description": [], "signature": [ - "NumberInputOptionProps" + { + "pluginId": "visDefaultEditor", + "scope": "public", + "docId": "kibVisDefaultEditorPluginApi", + "section": "def-public.NumberInputOptionProps", + "text": "NumberInputOptionProps" + }, + "" ], "path": "src/plugins/vis_default_editor/public/components/options/number_input.tsx", "deprecated": false, @@ -825,6 +840,217 @@ } ], "interfaces": [ + { + "parentPluginId": "visDefaultEditor", + "id": "def-public.NumberInputOptionProps", + "type": "Interface", + "tags": [], + "label": "NumberInputOptionProps", + "description": [], + "signature": [ + { + "pluginId": "visDefaultEditor", + "scope": "public", + "docId": "kibVisDefaultEditorPluginApi", + "section": "def-public.NumberInputOptionProps", + "text": "NumberInputOptionProps" + }, + "" + ], + "path": "src/plugins/vis_default_editor/public/components/options/number_input.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "visDefaultEditor", + "id": "def-public.NumberInputOptionProps.disabled", + "type": "CompoundType", + "tags": [], + "label": "disabled", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/vis_default_editor/public/components/options/number_input.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visDefaultEditor", + "id": "def-public.NumberInputOptionProps.error", + "type": "CompoundType", + "tags": [], + "label": "error", + "description": [], + "signature": [ + "boolean | React.ReactChild | React.ReactFragment | React.ReactPortal | null | undefined" + ], + "path": "src/plugins/vis_default_editor/public/components/options/number_input.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visDefaultEditor", + "id": "def-public.NumberInputOptionProps.isInvalid", + "type": "CompoundType", + "tags": [], + "label": "isInvalid", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/vis_default_editor/public/components/options/number_input.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visDefaultEditor", + "id": "def-public.NumberInputOptionProps.label", + "type": "CompoundType", + "tags": [], + "label": "label", + "description": [], + "signature": [ + "boolean | React.ReactChild | React.ReactFragment | React.ReactPortal | null | undefined" + ], + "path": "src/plugins/vis_default_editor/public/components/options/number_input.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visDefaultEditor", + "id": "def-public.NumberInputOptionProps.max", + "type": "number", + "tags": [], + "label": "max", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "src/plugins/vis_default_editor/public/components/options/number_input.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visDefaultEditor", + "id": "def-public.NumberInputOptionProps.min", + "type": "number", + "tags": [], + "label": "min", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "src/plugins/vis_default_editor/public/components/options/number_input.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visDefaultEditor", + "id": "def-public.NumberInputOptionProps.paramName", + "type": "Uncategorized", + "tags": [], + "label": "paramName", + "description": [], + "signature": [ + "ParamName" + ], + "path": "src/plugins/vis_default_editor/public/components/options/number_input.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visDefaultEditor", + "id": "def-public.NumberInputOptionProps.step", + "type": "number", + "tags": [], + "label": "step", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "src/plugins/vis_default_editor/public/components/options/number_input.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visDefaultEditor", + "id": "def-public.NumberInputOptionProps.value", + "type": "CompoundType", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "number | \"\" | undefined" + ], + "path": "src/plugins/vis_default_editor/public/components/options/number_input.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visDefaultEditor", + "id": "def-public.NumberInputOptionProps.datatestsubj", + "type": "string", + "tags": [], + "label": "'data-test-subj'", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/vis_default_editor/public/components/options/number_input.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visDefaultEditor", + "id": "def-public.NumberInputOptionProps.setValue", + "type": "Function", + "tags": [], + "label": "setValue", + "description": [], + "signature": [ + "(paramName: ParamName, value: number | \"\") => void" + ], + "path": "src/plugins/vis_default_editor/public/components/options/number_input.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "visDefaultEditor", + "id": "def-public.NumberInputOptionProps.setValue.$1", + "type": "Uncategorized", + "tags": [], + "label": "paramName", + "description": [], + "signature": [ + "ParamName" + ], + "path": "src/plugins/vis_default_editor/public/components/options/number_input.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "visDefaultEditor", + "id": "def-public.NumberInputOptionProps.setValue.$2", + "type": "CompoundType", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "number | \"\"" + ], + "path": "src/plugins/vis_default_editor/public/components/options/number_input.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, { "parentPluginId": "visDefaultEditor", "id": "def-public.RangeValues", diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index 9bc6e6e6365ad..298ed85fe74e0 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] --- import visDefaultEditorObj from './vis_default_editor.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 56 | 0 | 49 | 4 | +| 70 | 0 | 63 | 4 | ## Client diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index 7b5e9d38452bd..ff8f002ad94c5 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] --- import visTypeGaugeObj from './vis_type_gauge.devdocs.json'; diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index 0922ed4326778..672856eb4ddd2 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] --- import visTypeHeatmapObj from './vis_type_heatmap.devdocs.json'; diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index ff203dbd3293b..dfe12ab90299e 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] --- import visTypePieObj from './vis_type_pie.devdocs.json'; diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index 99d6c80770730..9080fa39b4721 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] --- import visTypeTableObj from './vis_type_table.devdocs.json'; diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index 1e4c96030615c..d6d7c4b1112f4 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] --- import visTypeTimelionObj from './vis_type_timelion.devdocs.json'; diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index 8400a667f3f2f..e8481e89fad53 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] --- import visTypeTimeseriesObj from './vis_type_timeseries.devdocs.json'; diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index b00f3eb7627c8..c49e00825f779 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] --- import visTypeVegaObj from './vis_type_vega.devdocs.json'; diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index a1abd27f4405a..0de2af428ced6 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] --- import visTypeVislibObj from './vis_type_vislib.devdocs.json'; diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index 23bbfa5922da0..5818791e9c649 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.devdocs.json b/api_docs/visualizations.devdocs.json index b49f7ebbcaa5f..e7df60cb03ea5 100644 --- a/api_docs/visualizations.devdocs.json +++ b/api_docs/visualizations.devdocs.json @@ -5671,9 +5671,9 @@ "(id: string) => Promise<{ item: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "; meta: { outcome: \"exactMatch\" | \"aliasMatch\" | \"conflict\"; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; }; }>" @@ -5719,17 +5719,17 @@ ">, \"contentTypeId\">) => Promise<{ item: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "; meta?: undefined; }>" @@ -5757,9 +5757,9 @@ ">, \"contentTypeId\">" @@ -5791,17 +5791,17 @@ ", Pick<", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SavedObjectUpdateOptions", + "section": "def-server.SavedObjectUpdateOptions", "text": "SavedObjectUpdateOptions" }, ", \"references\">>, \"contentTypeId\">) => Promise<{ item: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadataPartial", + "section": "def-server.SOWithMetadataPartial", "text": "SOWithMetadataPartial" }, "; meta?: undefined; }>" @@ -5829,9 +5829,9 @@ ", Pick<", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SavedObjectUpdateOptions", + "section": "def-server.SavedObjectUpdateOptions", "text": "SavedObjectUpdateOptions" }, ", \"references\">>, \"contentTypeId\">" @@ -5903,9 +5903,9 @@ ", options?: object | undefined) => Promise<{ hits: ", { "pluginId": "@kbn/content-management-utils", - "scope": "common", + "scope": "server", "docId": "kibKbnContentManagementUtilsPluginApi", - "section": "def-common.SOWithMetadata", + "section": "def-server.SOWithMetadata", "text": "SOWithMetadata" }, "[]; pagination: { total: number; cursor?: string | undefined; }; }>" diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index 4e0c973ce0fb9..e33967fce9626 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2024-08-27 +date: 2024-08-29 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; diff --git a/config/serverless.security.yml b/config/serverless.security.yml index b5922379f3c4b..6f39182d1e2e6 100644 --- a/config/serverless.security.yml +++ b/config/serverless.security.yml @@ -106,8 +106,3 @@ xpack.ml.compatibleModuleType: 'security' # Disable the embedded Dev Console console.ui.embeddedEnabled: false - -# mTLS cert paths for agentless-api calls -xpack.fleet.agentless.api.tls.certificate: "/mnt/elastic-internal/http-certs/tls.crt" -xpack.fleet.agentless.api.tls.key: "/mnt/elastic-internal/http-certs/tls.key" -xpack.fleet.agentless.api.tls.ca: "/mnt/elastic-internal/http-certs/ca.crt" diff --git a/docs/CHANGELOG.asciidoc b/docs/CHANGELOG.asciidoc index c095b28666d7a..c0c8d6ff5b934 100644 --- a/docs/CHANGELOG.asciidoc +++ b/docs/CHANGELOG.asciidoc @@ -111,6 +111,19 @@ Use the *Workflows* app in Microsoft Teams to create a new webhook URL, as descr Update your Microsoft Teams connector to use the new URL before the end of December 2024. ==== +[discrete] +[[known-189283]] +.Incorrect index errors related to inference endpoints +[%collapsible] +==== +*Details* + +In 8.15.1, we fixed a UI bug where an index error about the `semantic_text` field would be incorrectly displayed when the inference endpoint was configured and available. + +You can ignore this error if you've confirmed that the inference endpoint is configured and the model is deployed. + +This bug is fixed in {kibana-pull}189283[#189283]. +==== + [float] [[deprecations-8.15.0]] === Deprecations diff --git a/docs/maps/connect-to-ems.asciidoc b/docs/maps/connect-to-ems.asciidoc index 879d4846ef3f1..e41d544d64e4d 100644 --- a/docs/maps/connect-to-ems.asciidoc +++ b/docs/maps/connect-to-ems.asciidoc @@ -1,6 +1,6 @@ :ems: Elastic Maps Service -:ems-docker-repo: docker.elastic.co/elastic-maps-service/elastic-maps-server-ubi8 -:ems-docker-image: {ems-docker-repo}:{version} +:ems-docker-repo: docker.elastic.co/elastic-maps-service/elastic-maps-server +:ems-docker-image: {ems-docker-repo}:{version}-amd64 :ems-headers-url: https://deployment-host [[maps-connect-to-ems]] @@ -195,7 +195,7 @@ One way to configure {hosted-ems} is to provide `elastic-maps-server.yml` via bi -------------------------------------------- version: '2' services: - {hosted-ems}: + ems-server: image: {ems-docker-image} volumes: - ./elastic-maps-server.yml:/usr/src/app/server/config/elastic-maps-server.yml @@ -214,7 +214,7 @@ These variables can be set with +docker-compose+ like this: ---------------------------------------------------------- version: '2' services: - {hosted-ems}: + ems-server: image: {ems-docker-image} environment: ELASTICSEARCH_HOST: http://elasticsearch.example.org diff --git a/docs/setup/configuring-reporting.asciidoc b/docs/setup/configuring-reporting.asciidoc index 946ec1145d010..041012c8dba85 100644 --- a/docs/setup/configuring-reporting.asciidoc +++ b/docs/setup/configuring-reporting.asciidoc @@ -214,13 +214,13 @@ If using PNG/PDF {report-features}, make sure the {kib} server operating system If you are using RHEL operating systems, install the following packages: -* `ipa-gothic-fonts` * `xorg-x11-fonts-100dpi` * `xorg-x11-fonts-75dpi` * `xorg-x11-utils` * `xorg-x11-fonts-cyrillic` * `xorg-x11-fonts-Type1` * `xorg-x11-fonts-misc` +* `vlgothic-fonts` * `fontconfig` * `freetype` diff --git a/docs/setup/install/targz.asciidoc b/docs/setup/install/targz.asciidoc index 2dd6058106a56..8560b9a0102dd 100644 --- a/docs/setup/install/targz.asciidoc +++ b/docs/setup/install/targz.asciidoc @@ -15,6 +15,10 @@ link:/downloads/kibana[Download Kibana] page. Other versions can be found on the link:/downloads/past-releases[Past Releases page]. +[NOTE] +==== +macOS is supported for development purposes only and is not covered under the support SLA for link:https://www.elastic.co/support/matrix#kibana[production-supported operating systems]. +==== [[install-linux64]] ==== Download and install the Linux 64-bit package diff --git a/examples/grid_example/public/app.tsx b/examples/grid_example/public/app.tsx index 8c26ecf8f1e2a..c10d740b8dc3f 100644 --- a/examples/grid_example/public/app.tsx +++ b/examples/grid_example/public/app.tsx @@ -15,9 +15,9 @@ import { EuiPageTemplate, EuiProvider } from '@elastic/eui'; export const GridExample = () => { return ( - + - + { return
{id}
; @@ -41,7 +41,7 @@ export const GridExample = () => { { title: 'Small section', isCollapsed: false, - panels: { panel9: { column: 0, row: 0, width: 12, height: 6, id: 'panel9' } }, + panels: { panel9: { column: 0, row: 0, width: 12, height: 16, id: 'panel9' } }, }, { title: 'Another small section', diff --git a/oas_docs/.spectral.yaml b/oas_docs/.spectral.yaml index 7ff86442f9b9e..a3e5a469bc63b 100644 --- a/oas_docs/.spectral.yaml +++ b/oas_docs/.spectral.yaml @@ -47,6 +47,14 @@ rules: function: pattern functionOptions: notMatch: /(blacklist|whitelist|execute|kill)/i + property-description: + description: Properties should have descriptions. + message: "Each property should have a description" + severity: warn + given: $.components.schemas.*.properties.* + then: + field: description + function: defined # Examples operation-success-examples: formats: ['oas3_1'] diff --git a/oas_docs/kibana.info.serverless.yaml b/oas_docs/kibana.info.serverless.yaml index efc8955856de1..fca516d797f24 100644 --- a/oas_docs/kibana.info.serverless.yaml +++ b/oas_docs/kibana.info.serverless.yaml @@ -28,8 +28,8 @@ info: ``` version: "1.0.2" license: - name: Elastic License 2.0 - url: https://www.elastic.co/licensing/elastic-license + name: Attribution-NonCommercial-NoDerivatives 4.0 International + url: https://creativecommons.org/licenses/by-nc-nd/4.0/ contact: name: Kibana Team x-feedbackLink: diff --git a/oas_docs/kibana.info.yaml b/oas_docs/kibana.info.yaml index 13db5ef728833..40795333fcf44 100644 --- a/oas_docs/kibana.info.yaml +++ b/oas_docs/kibana.info.yaml @@ -26,8 +26,8 @@ info: For more information about the console, refer to [Run API requests](https://www.elastic.co/guide/en/kibana/current/console-kibana.html). version: '1.0.2' license: - name: Elastic License 2.0 - url: https://www.elastic.co/licensing/elastic-license + name: Attribution-NonCommercial-NoDerivatives 4.0 International + url: https://creativecommons.org/licenses/by-nc-nd/4.0/ contact: name: Kibana Team x-feedbackLink: diff --git a/oas_docs/makefile b/oas_docs/makefile index 78e082494e301..d64e296b795a6 100644 --- a/oas_docs/makefile +++ b/oas_docs/makefile @@ -35,6 +35,10 @@ api-docs-serverless: ## Generate only kibana.serverless.yaml api-docs-lint: ## Run spectral API docs linter @npx @stoplight/spectral-cli lint "output/*.yaml" --ruleset ".spectral.yaml" +.PHONY: api-docs-lint-errs +api-docs-lint-errs: ## Run spectral API docs linter and return only errors + @npx @stoplight/spectral-cli lint "output/*.yaml" --ruleset ".spectral.yaml" -D + .PHONY: api-docs-lint-stateful api-docs-lint-stateful: ## Run spectral API docs linter on kibana.yaml @npx @stoplight/spectral-cli lint "output/kibana.yaml" --ruleset ".spectral.yaml" diff --git a/oas_docs/output/kibana.serverless.yaml b/oas_docs/output/kibana.serverless.yaml index f7e0765267b29..8d81681f3789e 100644 --- a/oas_docs/output/kibana.serverless.yaml +++ b/oas_docs/output/kibana.serverless.yaml @@ -48,8 +48,8 @@ info: ``` license: - name: Elastic License 2.0 - url: 'https://www.elastic.co/licensing/elastic-license' + name: Attribution-NonCommercial-NoDerivatives 4.0 International + url: 'https://creativecommons.org/licenses/by-nc-nd/4.0/' title: Kibana Serverless APIs version: 1.0.2 x-feedbackLink: diff --git a/oas_docs/output/kibana.yaml b/oas_docs/output/kibana.yaml index a4bc05d9fb2e4..dfe69b9be3400 100644 --- a/oas_docs/output/kibana.yaml +++ b/oas_docs/output/kibana.yaml @@ -47,8 +47,8 @@ info: For more information about the console, refer to [Run API requests](https://www.elastic.co/guide/en/kibana/current/console-kibana.html). license: - name: Elastic License 2.0 - url: 'https://www.elastic.co/licensing/elastic-license' + name: Attribution-NonCommercial-NoDerivatives 4.0 International + url: 'https://creativecommons.org/licenses/by-nc-nd/4.0/' title: Kibana APIs version: 1.0.2 x-feedbackLink: diff --git a/package.json b/package.json index 78d2e97408fa0..ce1f760416eb0 100644 --- a/package.json +++ b/package.json @@ -107,11 +107,11 @@ "@dnd-kit/sortable": "^8.0.0", "@dnd-kit/utilities": "^3.2.2", "@elastic/apm-rum": "^5.16.1", - "@elastic/apm-rum-core": "^5.21.0", + "@elastic/apm-rum-core": "^5.21.1", "@elastic/apm-rum-react": "^2.0.3", "@elastic/charts": "66.1.1", "@elastic/datemath": "5.0.3", - "@elastic/ebt": "1.0.0", + "@elastic/ebt": "^1.1.1", "@elastic/ecs": "^8.11.1", "@elastic/elasticsearch": "^8.15.0", "@elastic/ems-client": "8.5.3", @@ -674,6 +674,7 @@ "@kbn/observability-onboarding-plugin": "link:x-pack/plugins/observability_solution/observability_onboarding", "@kbn/observability-plugin": "link:x-pack/plugins/observability_solution/observability", "@kbn/observability-shared-plugin": "link:x-pack/plugins/observability_solution/observability_shared", + "@kbn/observability-utils": "link:x-pack/packages/observability/observability_utils", "@kbn/oidc-provider-plugin": "link:x-pack/test/security_api_integration/plugins/oidc_provider", "@kbn/open-telemetry-instrumented-plugin": "link:test/common/plugins/otel_metrics", "@kbn/openapi-common": "link:packages/kbn-openapi-common", @@ -790,6 +791,7 @@ "@kbn/security-solution-storybook-config": "link:x-pack/packages/security-solution/storybook/config", "@kbn/security-solution-upselling": "link:x-pack/packages/security-solution/upselling", "@kbn/security-test-endpoints-plugin": "link:x-pack/test/security_functional/plugins/test_endpoints", + "@kbn/security-ui-components": "link:x-pack/packages/security/ui_components", "@kbn/securitysolution-autocomplete": "link:packages/kbn-securitysolution-autocomplete", "@kbn/securitysolution-data-table": "link:x-pack/packages/security-solution/data_table", "@kbn/securitysolution-ecs": "link:packages/kbn-securitysolution-ecs", @@ -1135,9 +1137,9 @@ "mime": "^2.4.4", "mime-types": "^2.1.27", "minimatch": "^3.1.2", - "moment": "^2.29.4", + "moment": "^2.30.1", "moment-duration-format": "^2.3.2", - "moment-timezone": "^0.5.43", + "moment-timezone": "^0.5.45", "monaco-editor": "^0.44.0", "monaco-yaml": "^5.1.0", "murmurhash": "^2.0.1", @@ -1477,6 +1479,7 @@ "@storybook/react": "^6.5.16", "@storybook/testing-react": "^1.3.0", "@storybook/theming": "^6.5.16", + "@testing-library/dom": "^8.19.0", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^12.1.5", "@testing-library/react-hooks": "^8.0.1", diff --git a/packages/deeplinks/observability/locators/dataset_quality.ts b/packages/deeplinks/observability/locators/dataset_quality.ts index e30648e3f129c..9e04e10e9933e 100644 --- a/packages/deeplinks/observability/locators/dataset_quality.ts +++ b/packages/deeplinks/observability/locators/dataset_quality.ts @@ -23,14 +23,6 @@ type TimeRangeConfig = { refresh: RefreshInterval; }; -// eslint-disable-next-line @typescript-eslint/consistent-type-definitions -type DatasetConfig = { - rawName: string; - type: string; - name: string; - namespace: string; -}; - // eslint-disable-next-line @typescript-eslint/consistent-type-definitions type Filters = { timeRange: TimeRangeConfig; @@ -38,7 +30,4 @@ type Filters = { export interface DataQualityLocatorParams extends SerializableRecord { filters?: Filters; - flyout?: { - dataset: DatasetConfig; - }; } diff --git a/packages/deeplinks/observability/locators/dataset_quality_details.ts b/packages/deeplinks/observability/locators/dataset_quality_details.ts new file mode 100644 index 0000000000000..6f51bbbfe7ce3 --- /dev/null +++ b/packages/deeplinks/observability/locators/dataset_quality_details.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { SerializableRecord } from '@kbn/utility-types'; + +export const DATA_QUALITY_DETAILS_LOCATOR_ID = 'DATA_QUALITY_DETAILS_LOCATOR'; + +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +type RefreshInterval = { + pause: boolean; + value: number; +}; + +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +type TimeRangeConfig = { + from: string; + to: string; + refresh: RefreshInterval; +}; + +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +type DegradedFieldsTable = { + page?: number; + rowsPerPage?: number; + sort?: { + field: string; + direction: 'asc' | 'desc'; + }; +}; + +export interface DataQualityDetailsLocatorParams extends SerializableRecord { + dataStream: string; + timeRange?: TimeRangeConfig; + breakdownField?: string; + degradedFields?: { + table?: DegradedFieldsTable; + }; +} diff --git a/packages/deeplinks/observability/locators/index.ts b/packages/deeplinks/observability/locators/index.ts index 67e79ecb577ea..48902c8f37cf4 100644 --- a/packages/deeplinks/observability/locators/index.ts +++ b/packages/deeplinks/observability/locators/index.ts @@ -7,6 +7,7 @@ */ export * from './dataset_quality'; +export * from './dataset_quality_details'; export * from './logs_explorer'; export * from './observability_logs_explorer'; export * from './observability_onboarding'; diff --git a/packages/kbn-check-mappings-update-cli/current_fields.json b/packages/kbn-check-mappings-update-cli/current_fields.json index aa84c709c655b..6138ac9d9eae1 100644 --- a/packages/kbn-check-mappings-update-cli/current_fields.json +++ b/packages/kbn-check-mappings-update-cli/current_fields.json @@ -544,6 +544,7 @@ ], "fleet-space-settings": [], "fleet-uninstall-tokens": [ + "namespaces", "policy_id", "token_plain" ], diff --git a/packages/kbn-check-mappings-update-cli/current_mappings.json b/packages/kbn-check-mappings-update-cli/current_mappings.json index 97e34c9b29341..8098f637b177f 100644 --- a/packages/kbn-check-mappings-update-cli/current_mappings.json +++ b/packages/kbn-check-mappings-update-cli/current_mappings.json @@ -1812,6 +1812,9 @@ "fleet-uninstall-tokens": { "dynamic": false, "properties": { + "namespaces": { + "type": "keyword" + }, "policy_id": { "type": "keyword" }, diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx index 290c549684f90..a9249d703d747 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/categorical_color_mapping.tsx @@ -15,22 +15,26 @@ import { Container } from './components/container/container'; import { ColorMapping } from './config'; import { uiReducer } from './state/ui'; +export interface ColorMappingInputCategoricalData { + type: 'categories'; + /** an ORDERED array of categories rendered in the visualization */ + categories: Array; +} + +export interface ColorMappingInputContinuousData { + type: 'ranges'; + min: number; + max: number; + bins: number; +} + /** * A configuration object that is required to populate correctly the visible categories * or the ranges in the CategoricalColorMapping component */ export type ColorMappingInputData = - | { - type: 'categories'; - /** an ORDERED array of categories rendered in the visualization */ - categories: Array; - } - | { - type: 'ranges'; - min: number; - max: number; - bins: number; - }; + | ColorMappingInputCategoricalData + | ColorMappingInputContinuousData; /** * The props of the CategoricalColorMapping component diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/color/color_handling.ts b/packages/kbn-coloring/src/shared_components/color_mapping/color/color_handling.ts index 8867b07572308..77aec76e68a4e 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/color/color_handling.ts +++ b/packages/kbn-coloring/src/shared_components/color_mapping/color/color_handling.ts @@ -74,7 +74,7 @@ export function getColorFactory( }) : []; - // find all categories that doesn't match with an assignment + // find all categories that don't match with an assignment const notAssignedCategories = data.type === 'categories' ? data.categories.filter((category) => { diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/color/rule_matching.ts b/packages/kbn-coloring/src/shared_components/color_mapping/color/rule_matching.ts index a157c7927747c..7bfc22691bb72 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/color/rule_matching.ts +++ b/packages/kbn-coloring/src/shared_components/color_mapping/color/rule_matching.ts @@ -41,7 +41,7 @@ export function rangeMatch(rule: ColorMapping.RuleRange, value: number) { } // TODO: move in some data/table related package -export const SPECIAL_TOKENS_STRING_CONVERTION = new Map([ +export const SPECIAL_TOKENS_STRING_CONVERSION = new Map([ [ '__other__', i18n.translate('coloring.colorMapping.terms.otherBucketLabel', { @@ -55,3 +55,9 @@ export const SPECIAL_TOKENS_STRING_CONVERTION = new Map([ }), ], ]); + +/** + * Returns special string for sake of color mapping/syncing + */ +export const getSpecialString = (value: string) => + SPECIAL_TOKENS_STRING_CONVERSION.get(value) ?? value; diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/assignment/assignment.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/assignment/assignment.tsx index 89c4375d4bc10..7e9e6869849c6 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/assignment/assignment.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/assignment/assignment.tsx @@ -121,7 +121,7 @@ export function Assignment({ css={ !disableDelete ? css` - color: ${euiThemeVars.euiTextSubduedColor}; + color: ${euiThemeVars.euiTextColor}; transition: ${euiThemeVars.euiAnimSpeedFast} ease-in-out; transition-property: color; &:hover, diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/assignment/match.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/assignment/match.tsx index bfef7a270e1a0..c10b3c0194cf7 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/assignment/match.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/assignment/match.tsx @@ -73,6 +73,7 @@ export const Match: React.FC<{ return ( diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/color_picker.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/color_picker.tsx index f576daa2096cc..ebce7b9749830 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/color_picker.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/color_picker.tsx @@ -7,14 +7,7 @@ */ import React, { useState } from 'react'; -import { - EuiButtonEmpty, - EuiPopoverTitle, - EuiTab, - EuiTabs, - EuiTitle, - EuiHorizontalRule, -} from '@elastic/eui'; +import { EuiButtonEmpty, EuiPopoverTitle, EuiTab, EuiTabs, EuiHorizontalRule } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ColorMapping } from '../../config'; import { getPalette } from '../../palettes'; @@ -56,22 +49,14 @@ export function ColorPicker({ > setTab('palette')} isSelected={tab === 'palette'}> - - - {i18n.translate('coloring.colorMapping.colorPicker.paletteTabLabel', { - defaultMessage: 'Colors', - })} - - + {i18n.translate('coloring.colorMapping.colorPicker.paletteTabLabel', { + defaultMessage: 'Colors', + })} setTab('custom')} isSelected={tab === 'custom'}> - - - {i18n.translate('coloring.colorMapping.colorPicker.customTabLabel', { - defaultMessage: 'Custom', - })} - - + {i18n.translate('coloring.colorMapping.colorPicker.customTabLabel', { + defaultMessage: 'Custom', + })} diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/color_swatch.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/color_swatch.tsx index 34ffbefeca30f..9b466810b069c 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/color_swatch.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/color_swatch.tsx @@ -124,15 +124,14 @@ export const ColorSwatch = ({ css={css` &::after { content: ''; - width: 0; - height: 0; - border-left: 3px solid transparent; - border-right: 3px solid transparent; - border-top: 4px solid ${colorIsDark ? 'white' : 'black'}; - margin: 0; - bottom: 2px; + background-color: ${colorIsDark ? 'white' : 'black'}; + // custom arrowDown svg + mask-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI3IiBoZWlnaHQ9IjQiIHZpZXdCb3g9IjAgMCA3IDQiPgogIDxwYXRoIGQ9Ik0uMTQ2LjE0N2EuNS41IDAgMCAxIC43MDggMEwzLjUgMi43OTQgNi4xNDYuMTQ3YS41LjUgMCAxIDEgLjcwOC43MDhsLTMgM2EuNS41IDAgMCAxLS43MDggMGwtMy0zYS41LjUgMCAwIDEgMC0uNzA4WiIvPgo8L3N2Zz4K'); + height: 4px; + width: 7px; + bottom: 6px; + right: 4px; position: absolute; - right: 2px; } `} /> diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/palette_colors.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/palette_colors.tsx index 77a8273654b89..48473fc191f25 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/palette_colors.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/color_picker/palette_colors.tsx @@ -12,8 +12,9 @@ import { EuiFlexItem, EuiHorizontalRule, EuiIcon, - EuiText, + EuiTitle, EuiToolTip, + EuiSpacer, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ColorMapping } from '../../config'; @@ -50,13 +51,14 @@ export function PaletteColors({ <> - - + +
{i18n.translate('coloring.colorMapping.colorPicker.paletteColorsLabel', { defaultMessage: 'Palette colors', })} - - +
+ + - - + +
{i18n.translate('coloring.colorMapping.colorPicker.themeAwareColorsLabel', { defaultMessage: 'Neutral colors', })} - - - - - + + + +
+ + @@ -214,7 +214,6 @@ export function AssignmentsConfig({ , @@ -228,13 +227,14 @@ export function AssignmentsConfig({ {assignments.length > 0 && } -
- {assignments.length > 0 && ( + + {assignments.length > 0 && ( +
{i18n.translate( 'coloring.colorMapping.container.clearAllAssignmentsButtonLabel', @@ -322,8 +325,8 @@ export function AssignmentsConfig({ )} - )} -
+
+ )} ); } diff --git a/packages/kbn-coloring/src/shared_components/color_mapping/components/container/container.tsx b/packages/kbn-coloring/src/shared_components/color_mapping/components/container/container.tsx index e3de3c0a24261..e8466e428ee88 100644 --- a/packages/kbn-coloring/src/shared_components/color_mapping/components/container/container.tsx +++ b/packages/kbn-coloring/src/shared_components/color_mapping/components/container/container.tsx @@ -81,6 +81,7 @@ export function Container({ > >( ({ target: { value: targetValue } }) => { - setLocalValue(targetValue); + setLocalValue(+targetValue); dispatch({ type: 'updateValue', payload: { index, value: targetValue, accessor, dataBounds, palettes }, @@ -138,7 +146,7 @@ export function ColorRangeItem({ ); const onUpdateColor = useCallback( - (color) => { + (color: string) => { dispatch({ type: 'updateColor', payload: { index, color, dataBounds, palettes } }); }, [dispatch, index, dataBounds, palettes] diff --git a/packages/kbn-coloring/src/shared_components/coloring/palette_picker.tsx b/packages/kbn-coloring/src/shared_components/coloring/palette_picker.tsx index 5cb2466d48421..ca7116142bfde 100644 --- a/packages/kbn-coloring/src/shared_components/coloring/palette_picker.tsx +++ b/packages/kbn-coloring/src/shared_components/coloring/palette_picker.tsx @@ -77,9 +77,9 @@ export function PalettePicker({ }) { const palettesToShow: EuiColorPalettePickerPaletteProps[] = palettes .getAll() - .filter(({ internal, canDynamicColoring }) => - showDynamicColorOnly ? canDynamicColoring : !internal - ) + .filter(({ internal, canDynamicColoring }) => { + return showDynamicColorOnly ? canDynamicColoring && !internal : !internal; + }) .map(({ id, title, getCategoricalColors }) => { const colors = getCategoricalColors( activePalette?.params?.steps || DEFAULT_COLOR_STEPS, diff --git a/packages/kbn-content-management-utils/kibana.jsonc b/packages/kbn-content-management-utils/kibana.jsonc index 06779896a47c4..0b0fa95451cd2 100644 --- a/packages/kbn-content-management-utils/kibana.jsonc +++ b/packages/kbn-content-management-utils/kibana.jsonc @@ -1,5 +1,5 @@ { - "type": "shared-common", + "type": "shared-server", "id": "@kbn/content-management-utils", "owner": "@elastic/kibana-data-discovery" } diff --git a/packages/kbn-dom-drag-drop/index.ts b/packages/kbn-dom-drag-drop/index.ts index f188b6c6659ad..f9e4f3f4f5bb9 100644 --- a/packages/kbn-dom-drag-drop/index.ts +++ b/packages/kbn-dom-drag-drop/index.ts @@ -14,6 +14,7 @@ export { type DraggingIdentifier, type DragDropAction, type DropOverlayWrapperProps, + type DroppableProps, Draggable, Droppable, useDragDropContext, diff --git a/packages/kbn-grid-layout/grid/grid_height_smoother.tsx b/packages/kbn-grid-layout/grid/grid_height_smoother.tsx new file mode 100644 index 0000000000000..238d8996ae15e --- /dev/null +++ b/packages/kbn-grid-layout/grid/grid_height_smoother.tsx @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { css } from '@emotion/react'; +import React, { PropsWithChildren, useEffect, useRef } from 'react'; +import { combineLatest } from 'rxjs'; +import { GridLayoutStateManager } from './types'; + +export const GridHeightSmoother = ({ + children, + gridLayoutStateManager, +}: PropsWithChildren<{ gridLayoutStateManager: GridLayoutStateManager }>) => { + // set the parent div size directly to smooth out height changes. + const smoothHeightRef = useRef(null); + useEffect(() => { + const subscription = combineLatest([ + gridLayoutStateManager.gridDimensions$, + gridLayoutStateManager.interactionEvent$, + ]).subscribe(([dimensions, interactionEvent]) => { + if (!smoothHeightRef.current) return; + if (!interactionEvent) { + smoothHeightRef.current.style.height = `${dimensions.height}px`; + return; + } + + /** + * When the user is interacting with an element, the page can grow, but it cannot + * shrink. This is to stop a behaviour where the page would scroll up automatically + * making the panel shrink or grow unpredictably. + */ + smoothHeightRef.current.style.height = `${Math.max( + dimensions.height ?? 0, + smoothHeightRef.current.getBoundingClientRect().height + )}px`; + }); + return () => subscription.unsubscribe(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( +
+ {children} +
+ ); +}; diff --git a/packages/kbn-grid-layout/grid/grid_layout.tsx b/packages/kbn-grid-layout/grid/grid_layout.tsx index 68650035f7b44..78259b1556c3e 100644 --- a/packages/kbn-grid-layout/grid/grid_layout.tsx +++ b/packages/kbn-grid-layout/grid/grid_layout.tsx @@ -6,11 +6,10 @@ * Side Public License, v 1. */ -import { EuiPortal, transparentize } from '@elastic/eui'; -import { css } from '@emotion/react'; import { useBatchedPublishingSubjects } from '@kbn/presentation-publishing'; -import { euiThemeVars } from '@kbn/ui-theme'; import React from 'react'; +import { GridHeightSmoother } from './grid_height_smoother'; +import { GridOverlay } from './grid_overlay'; import { GridRow } from './grid_row'; import { GridLayoutData, GridSettings } from './types'; import { useGridLayoutEvents } from './use_grid_layout_events'; @@ -23,7 +22,7 @@ export const GridLayout = ({ getCreationOptions: () => { initialLayout: GridLayoutData; gridSettings: GridSettings }; renderPanelContents: (panelId: string) => React.ReactNode; }) => { - const { gridLayoutStateManager, gridSizeRef } = useGridLayoutState({ + const { gridLayoutStateManager, setDimensionsRef } = useGridLayoutState({ getCreationOptions, }); useGridLayoutEvents({ gridLayoutStateManager }); @@ -35,58 +34,44 @@ export const GridLayout = ({ ); return ( -
- {gridLayout.map((rowData, rowIndex) => { - return ( - { - const currentLayout = gridLayoutStateManager.gridLayout$.value; - currentLayout[rowIndex].isCollapsed = !currentLayout[rowIndex].isCollapsed; - gridLayoutStateManager.gridLayout$.next(currentLayout); - }} - setInteractionEvent={(nextInteractionEvent) => { - if (!nextInteractionEvent) { - gridLayoutStateManager.hideDragPreview(); - } - gridLayoutStateManager.interactionEvent$.next(nextInteractionEvent); - }} - ref={(element) => (gridLayoutStateManager.rowRefs.current[rowIndex] = element)} - /> - ); - })} - + <> +
{ + setDimensionsRef(divElement); + }} > -
+ {gridLayout.map((rowData, rowIndex) => { + return ( + { + const currentLayout = gridLayoutStateManager.gridLayout$.value; + currentLayout[rowIndex].isCollapsed = !currentLayout[rowIndex].isCollapsed; + gridLayoutStateManager.gridLayout$.next(currentLayout); + }} + setInteractionEvent={(nextInteractionEvent) => { + if (!nextInteractionEvent) { + gridLayoutStateManager.hideDragPreview(); + } + gridLayoutStateManager.interactionEvent$.next(nextInteractionEvent); + }} + ref={(element) => (gridLayoutStateManager.rowRefs.current[rowIndex] = element)} + /> + ); + })}
- -
+
+ + ); }; diff --git a/packages/kbn-grid-layout/grid/grid_overlay.tsx b/packages/kbn-grid-layout/grid/grid_overlay.tsx new file mode 100644 index 0000000000000..3050b721abcb2 --- /dev/null +++ b/packages/kbn-grid-layout/grid/grid_overlay.tsx @@ -0,0 +1,134 @@ +/* + * 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 { EuiPortal, EuiText, transparentize } from '@elastic/eui'; +import { css } from '@emotion/react'; +import { i18n } from '@kbn/i18n'; +import { euiThemeVars } from '@kbn/ui-theme'; +import React, { useRef, useState } from 'react'; +import { GridLayoutStateManager, PanelInteractionEvent } from './types'; + +type ScrollDirection = 'up' | 'down'; + +const scrollLabels: { [key in ScrollDirection]: string } = { + up: i18n.translate('kbnGridLayout.overlays.scrollUpLabel', { defaultMessage: 'Scroll up' }), + down: i18n.translate('kbnGridLayout.overlays.scrollDownLabel', { defaultMessage: 'Scroll down' }), +}; + +const scrollOnInterval = (direction: ScrollDirection) => { + const interval = setInterval(() => { + window.scroll({ + top: window.scrollY + (direction === 'down' ? 50 : -50), + behavior: 'smooth', + }); + }, 100); + return interval; +}; + +const ScrollOnHover = ({ direction, hide }: { hide: boolean; direction: ScrollDirection }) => { + const [isActive, setIsActive] = useState(false); + const scrollInterval = useRef(null); + const stopScrollInterval = () => { + if (scrollInterval.current) { + clearInterval(scrollInterval.current); + } + }; + + return ( +
{ + setIsActive(true); + scrollInterval.current = scrollOnInterval(direction); + }} + onMouseLeave={() => { + setIsActive(false); + stopScrollInterval(); + }} + css={css` + width: 100%; + position: fixed; + display: flex; + align-items: center; + flex-direction: column; + justify-content: center; + opacity: ${hide ? 0 : 1}; + transition: opacity 100ms linear; + padding: ${euiThemeVars.euiSizeM}; + ${direction === 'down' ? 'bottom: 0;' : 'top: 0;'} + `} + > + {direction === 'up' && ( +
+ )} +
+ + {scrollLabels[direction]} + +
+
+ ); +}; + +export const GridOverlay = ({ + interactionEvent, + gridLayoutStateManager, +}: { + interactionEvent?: PanelInteractionEvent; + gridLayoutStateManager: GridLayoutStateManager; +}) => { + return ( + +
+ + +
+
+ + ); +}; diff --git a/packages/kbn-grid-layout/grid/grid_panel.tsx b/packages/kbn-grid-layout/grid/grid_panel.tsx index a0f53cef8869c..fc1ab5cb1e619 100644 --- a/packages/kbn-grid-layout/grid/grid_panel.tsx +++ b/packages/kbn-grid-layout/grid/grid_panel.tsx @@ -30,15 +30,13 @@ export const GridPanel = ({ setInteractionEvent: (interactionData?: Omit) => void; }) => { const panelRef = useRef(null); - const ghostRef = useRef(null); const thisPanelActive = activePanelId === panelData.id; const interactionStart = useCallback( - (type: 'drag' | 'resize', e: React.DragEvent) => { - if (!panelRef.current || !ghostRef.current) return; - e.dataTransfer.effectAllowed = 'move'; - e.dataTransfer.dropEffect = 'move'; - e.dataTransfer.setDragImage(ghostRef.current, 0, 0); + (type: 'drag' | 'resize', e: React.MouseEvent) => { + if (!panelRef.current) return; + e.preventDefault(); + e.stopPropagation(); const panelRect = panelRef.current.getBoundingClientRect(); setInteractionEvent({ type, @@ -83,22 +81,8 @@ export const GridPanel = ({ } `} > - {/* Hidden dragging ghost */} -
{/* drag handle */}
) => interactionStart('drag', e)} + onMouseDown={(e) => interactionStart('drag', e)} >
{/* Resize handle */}
interactionStart('resize', e)} + onMouseDown={(e) => interactionStart('resize', e)} css={css` right: 0; bottom: 0; diff --git a/packages/kbn-grid-layout/grid/grid_row.tsx b/packages/kbn-grid-layout/grid/grid_row.tsx index 3f2676a1db6ba..ce2d226fc2cb8 100644 --- a/packages/kbn-grid-layout/grid/grid_row.tsx +++ b/packages/kbn-grid-layout/grid/grid_row.tsx @@ -8,6 +8,7 @@ import { EuiButtonIcon, EuiFlexGroup, EuiSpacer, EuiTitle, transparentize } from '@elastic/eui'; import { css } from '@emotion/react'; +import { i18n } from '@kbn/i18n'; import { euiThemeVars } from '@kbn/ui-theme'; import React, { forwardRef, useMemo } from 'react'; import { GridPanel } from './grid_panel'; @@ -69,6 +70,9 @@ export const GridRow = forwardRef< diff --git a/packages/kbn-grid-layout/grid/types.ts b/packages/kbn-grid-layout/grid/types.ts index e3119f6e1cfd2..1ef9b69fc997e 100644 --- a/packages/kbn-grid-layout/grid/types.ts +++ b/packages/kbn-grid-layout/grid/types.ts @@ -7,6 +7,7 @@ */ import { BehaviorSubject } from 'rxjs'; +import type { ObservedSize } from 'use-resize-observer/polyfilled'; export interface GridCoordinate { column: number; row: number; @@ -53,6 +54,7 @@ export interface GridLayoutStateManager { right: number; }) => void; + gridDimensions$: BehaviorSubject; gridLayout$: BehaviorSubject; runtimeSettings$: BehaviorSubject; rowRefs: React.MutableRefObject>; diff --git a/packages/kbn-grid-layout/grid/use_grid_layout_events.ts b/packages/kbn-grid-layout/grid/use_grid_layout_events.ts index c8c1a505fc13a..11e514674f883 100644 --- a/packages/kbn-grid-layout/grid/use_grid_layout_events.ts +++ b/packages/kbn-grid-layout/grid/use_grid_layout_events.ts @@ -25,7 +25,7 @@ export const useGridLayoutEvents = ({ }: { gridLayoutStateManager: GridLayoutStateManager; }) => { - const dragEnterCount = useRef(0); + const mouseClientPosition = useRef({ x: 0, y: 0 }); const lastRequestedPanelPosition = useRef(undefined); // ----------------------------------------------------------------------------------------- @@ -33,7 +33,8 @@ export const useGridLayoutEvents = ({ // ----------------------------------------------------------------------------------------- useEffect(() => { const { runtimeSettings$, interactionEvent$, gridLayout$ } = gridLayoutStateManager; - const dragOver = (e: MouseEvent) => { + const calculateUserEvent = (e: Event) => { + if (!interactionEvent$.value) return; e.preventDefault(); e.stopPropagation(); @@ -51,17 +52,14 @@ export const useGridLayoutEvents = ({ } })(); - if ( - !runtimeSettings$.value || - !interactionEvent || - !previewElement || - !gridRowElements || - !currentGridData - ) { + if (!runtimeSettings$.value || !previewElement || !gridRowElements || !currentGridData) { return; } - const mouseTargetPixel = { x: e.clientX, y: e.clientY }; + const mouseTargetPixel = { + x: mouseClientPosition.current.x, + y: mouseClientPosition.current.y, + }; const panelRect = interactionEvent.panelDiv.getBoundingClientRect(); const previewRect = { left: isResize ? panelRect.left : mouseTargetPixel.x - interactionEvent.mouseOffsets.left, @@ -159,46 +157,27 @@ export const useGridLayoutEvents = ({ } }; - const onDrop = (e: MouseEvent) => { + const onMouseUp = (e: MouseEvent) => { + if (!interactionEvent$.value) return; e.preventDefault(); e.stopPropagation(); - if (!interactionEvent$.value) return; interactionEvent$.next(undefined); gridLayoutStateManager.hideDragPreview(); - dragEnterCount.current = 0; }; - const onDragEnter = (e: MouseEvent) => { - e.preventDefault(); - e.stopPropagation(); - if (!interactionEvent$.value) return; - - dragEnterCount.current++; - }; - - const onDragLeave = (e: MouseEvent) => { - e.preventDefault(); - e.stopPropagation(); - if (!interactionEvent$.value) return; - - dragEnterCount.current--; - if (dragEnterCount.current === 0) { - interactionEvent$.next(undefined); - gridLayoutStateManager.hideDragPreview(); - dragEnterCount.current = 0; - } + const onMouseMove = (e: MouseEvent) => { + mouseClientPosition.current = { x: e.clientX, y: e.clientY }; + calculateUserEvent(e); }; - window.addEventListener('drop', onDrop); - window.addEventListener('dragover', dragOver); - window.addEventListener('dragenter', onDragEnter); - window.addEventListener('dragleave', onDragLeave); + document.addEventListener('mouseup', onMouseUp); + document.addEventListener('mousemove', onMouseMove); + document.addEventListener('scroll', calculateUserEvent); return () => { - window.removeEventListener('drop', dragOver); - window.removeEventListener('dragover', dragOver); - window.removeEventListener('dragenter', onDragEnter); - window.removeEventListener('dragleave', onDragLeave); + document.removeEventListener('mouseup', onMouseUp); + document.removeEventListener('mousemove', onMouseMove); + document.removeEventListener('scroll', calculateUserEvent); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); diff --git a/packages/kbn-grid-layout/grid/use_grid_layout_state.ts b/packages/kbn-grid-layout/grid/use_grid_layout_state.ts index bad259b428892..182eb2a88cec8 100644 --- a/packages/kbn-grid-layout/grid/use_grid_layout_state.ts +++ b/packages/kbn-grid-layout/grid/use_grid_layout_state.ts @@ -6,10 +6,9 @@ * Side Public License, v 1. */ -import { debounce } from 'lodash'; -import { useMemo, useRef } from 'react'; -import { BehaviorSubject } from 'rxjs'; -import useResizeObserver from 'use-resize-observer/polyfilled'; +import { useEffect, useMemo, useRef } from 'react'; +import { BehaviorSubject, debounceTime } from 'rxjs'; +import useResizeObserver, { type ObservedSize } from 'use-resize-observer/polyfilled'; import { GridLayoutData, GridLayoutStateManager, @@ -24,71 +23,77 @@ export const useGridLayoutState = ({ getCreationOptions: () => { initialLayout: GridLayoutData; gridSettings: GridSettings }; }): { gridLayoutStateManager: GridLayoutStateManager; - gridSizeRef: (instance: HTMLDivElement | null) => void; + setDimensionsRef: (instance: HTMLDivElement | null) => void; } => { const rowRefs = useRef>([]); const dragPreviewRef = useRef(null); - const { gridLayoutStateManager, onWidthChange } = useMemo(() => { - const { initialLayout, gridSettings } = getCreationOptions(); + // eslint-disable-next-line react-hooks/exhaustive-deps + const { initialLayout, gridSettings } = useMemo(() => getCreationOptions(), []); + + const gridLayoutStateManager = useMemo(() => { const gridLayout$ = new BehaviorSubject(initialLayout); + const gridDimensions$ = new BehaviorSubject({ width: 0, height: 0 }); const interactionEvent$ = new BehaviorSubject(undefined); const runtimeSettings$ = new BehaviorSubject({ ...gridSettings, columnPixelWidth: 0, }); - // debounce width changes to avoid re-rendering too frequently when the browser is resizing - const widthChange = debounce((elementWidth: number) => { - const columnPixelWidth = - (elementWidth - gridSettings.gutterSize * (gridSettings.columnCount - 1)) / - gridSettings.columnCount; - runtimeSettings$.next({ ...gridSettings, columnPixelWidth }); - }, 250); - return { - gridLayoutStateManager: { - rowRefs, - gridLayout$, - dragPreviewRef, - runtimeSettings$, - interactionEvent$, - updatePreviewElement: (previewRect: { - top: number; - bottom: number; - left: number; - right: number; - }) => { - if (!dragPreviewRef.current) return; - dragPreviewRef.current.style.opacity = '1'; - dragPreviewRef.current.style.left = `${previewRect.left}px`; - dragPreviewRef.current.style.top = `${previewRect.top}px`; - dragPreviewRef.current.style.width = `${Math.max( - previewRect.right - previewRect.left, - runtimeSettings$.value.columnPixelWidth - )}px`; - dragPreviewRef.current.style.height = `${Math.max( - previewRect.bottom - previewRect.top, - runtimeSettings$.value.rowHeight - )}px`; - }, - hideDragPreview: () => { - if (!dragPreviewRef.current) return; - dragPreviewRef.current.style.opacity = '0'; - }, + rowRefs, + gridLayout$, + dragPreviewRef, + gridDimensions$, + runtimeSettings$, + interactionEvent$, + updatePreviewElement: (previewRect: { + top: number; + bottom: number; + left: number; + right: number; + }) => { + if (!dragPreviewRef.current) return; + dragPreviewRef.current.style.opacity = '1'; + dragPreviewRef.current.style.left = `${previewRect.left}px`; + dragPreviewRef.current.style.top = `${previewRect.top}px`; + dragPreviewRef.current.style.width = `${Math.max( + previewRect.right - previewRect.left, + runtimeSettings$.value.columnPixelWidth + )}px`; + dragPreviewRef.current.style.height = `${Math.max( + previewRect.bottom - previewRect.top, + runtimeSettings$.value.rowHeight + )}px`; + }, + hideDragPreview: () => { + if (!dragPreviewRef.current) return; + dragPreviewRef.current.style.opacity = '0'; }, - onWidthChange: widthChange, }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const { ref: gridSizeRef } = useResizeObserver({ + useEffect(() => { + // debounce width changes to avoid unnecessary column width recalculation. + const subscription = gridLayoutStateManager.gridDimensions$ + .pipe(debounceTime(250)) + .subscribe((dimensions) => { + const elementWidth = dimensions.width ?? 0; + const columnPixelWidth = + (elementWidth - gridSettings.gutterSize * (gridSettings.columnCount - 1)) / + gridSettings.columnCount; + gridLayoutStateManager.runtimeSettings$.next({ ...gridSettings, columnPixelWidth }); + }); + return () => subscription.unsubscribe(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const { ref: setDimensionsRef } = useResizeObserver({ onResize: (dimensions) => { - if (dimensions.width) { - onWidthChange(dimensions.width); - } + gridLayoutStateManager.gridDimensions$.next(dimensions); }, }); - return { gridLayoutStateManager, gridSizeRef }; + return { gridLayoutStateManager, setDimensionsRef }; }; diff --git a/packages/kbn-grid-layout/tsconfig.json b/packages/kbn-grid-layout/tsconfig.json index 3aff3ea3aa354..5a1888db0dc64 100644 --- a/packages/kbn-grid-layout/tsconfig.json +++ b/packages/kbn-grid-layout/tsconfig.json @@ -19,5 +19,6 @@ "kbn_references": [ "@kbn/presentation-publishing", "@kbn/ui-theme", + "@kbn/i18n", ] } diff --git a/packages/kbn-grouping/src/components/accordion_panel/index.tsx b/packages/kbn-grouping/src/components/accordion_panel/index.tsx index ae13509b51a9e..37a531b386b47 100644 --- a/packages/kbn-grouping/src/components/accordion_panel/index.tsx +++ b/packages/kbn-grouping/src/components/accordion_panel/index.tsx @@ -102,7 +102,7 @@ const GroupPanelComponent = ({ ); const onToggle = useCallback( - (isOpen) => { + (isOpen: boolean) => { if (onToggleGroup) { onToggleGroup(isOpen, groupBucket); } diff --git a/packages/kbn-grouping/src/hooks/use_grouping.tsx b/packages/kbn-grouping/src/hooks/use_grouping.tsx index 284343a29d748..f01dcc29aa790 100644 --- a/packages/kbn-grouping/src/hooks/use_grouping.tsx +++ b/packages/kbn-grouping/src/hooks/use_grouping.tsx @@ -56,7 +56,7 @@ export type DynamicGroupingProps = Pick< /** Interface for configuring grouping package where T is the consumer `GroupingAggregation` * @interface GroupingArgs */ -interface GroupingArgs { +export interface GroupingArgs { componentProps: StaticGroupingProps; defaultGroupingOptions: GroupOption[]; fields: FieldSpec[]; diff --git a/packages/kbn-investigation-shared/src/rest_specs/create_item.ts b/packages/kbn-investigation-shared/src/rest_specs/create_item.ts index c94673313a50c..a0696df4040d8 100644 --- a/packages/kbn-investigation-shared/src/rest_specs/create_item.ts +++ b/packages/kbn-investigation-shared/src/rest_specs/create_item.ts @@ -7,14 +7,14 @@ */ import * as t from 'io-ts'; -import { investigationItemsSchema } from '../schema'; +import { itemSchema } from '../schema'; import { investigationItemResponseSchema } from './investigation_item'; const createInvestigationItemParamsSchema = t.type({ path: t.type({ investigationId: t.string, }), - body: investigationItemsSchema, + body: itemSchema, }); const createInvestigationItemResponseSchema = investigationItemResponseSchema; diff --git a/packages/kbn-investigation-shared/src/rest_specs/index.ts b/packages/kbn-investigation-shared/src/rest_specs/index.ts index 50c1e300cd96a..cb13c11886481 100644 --- a/packages/kbn-investigation-shared/src/rest_specs/index.ts +++ b/packages/kbn-investigation-shared/src/rest_specs/index.ts @@ -17,6 +17,7 @@ export type * from './investigation_note'; export type * from './create_item'; export type * from './delete_item'; export type * from './get_items'; +export type * from './investigation_item'; export * from './create'; export * from './create_note'; @@ -29,3 +30,4 @@ export * from './investigation_note'; export * from './create_item'; export * from './delete_item'; export * from './get_items'; +export * from './investigation_item'; diff --git a/packages/kbn-investigation-shared/src/schema/investigation_item.ts b/packages/kbn-investigation-shared/src/schema/investigation_item.ts index 8689224960c52..717bf246e3590 100644 --- a/packages/kbn-investigation-shared/src/schema/investigation_item.ts +++ b/packages/kbn-investigation-shared/src/schema/investigation_item.ts @@ -8,20 +8,23 @@ import * as t from 'io-ts'; -const esqlItemSchema = t.type({ +const itemSchema = t.type({ title: t.string, - type: t.literal('esql'), - params: t.type({ - esql: t.string, - suggestion: t.any, - }), + type: t.string, + params: t.record(t.string, t.any), }); -const investigationItemsSchema = esqlItemSchema; // replace with union with various item types - const investigationItemSchema = t.intersection([ - t.type({ id: t.string, createdAt: t.number, createdBy: t.string }), - investigationItemsSchema, + t.type({ + id: t.string, + createdAt: t.number, + createdBy: t.string, + }), + itemSchema, ]); -export { investigationItemSchema, investigationItemsSchema, esqlItemSchema }; +type Item = t.TypeOf; +type InvestigationItem = t.TypeOf; + +export type { Item, InvestigationItem }; +export { investigationItemSchema, itemSchema }; diff --git a/packages/kbn-management/settings/components/field_input/code_editor.tsx b/packages/kbn-management/settings/components/field_input/code_editor.tsx index ac1ea672d8a15..397fd8b80492b 100644 --- a/packages/kbn-management/settings/components/field_input/code_editor.tsx +++ b/packages/kbn-management/settings/components/field_input/code_editor.tsx @@ -70,7 +70,7 @@ export const CodeEditor = ({ onChange, type, isReadOnly, name, ...props }: CodeE editorModel.setValue(trimmedValue); }, []); - const editorDidMount = useCallback( + const editorDidMount = useCallback>( (editor) => { setEditorCalculatedHeight(editor); diff --git a/packages/kbn-management/settings/components/field_input/input/array_input.tsx b/packages/kbn-management/settings/components/field_input/input/array_input.tsx index 0dc9b8ddc406e..f77c66f5f15e1 100644 --- a/packages/kbn-management/settings/components/field_input/input/array_input.tsx +++ b/packages/kbn-management/settings/components/field_input/input/array_input.tsx @@ -13,6 +13,7 @@ import { getFieldInputValue } from '@kbn/management-settings-utilities'; import { useUpdate } from '@kbn/management-settings-utilities'; import { debounce } from 'lodash'; +import { OnInputChangeFn } from '@kbn/management-settings-types'; import { useServices } from '../services'; import { InputProps } from '../types'; import { TEST_SUBJ_PREFIX_FIELD } from '.'; @@ -39,7 +40,7 @@ export const ArrayInput = ({ const onUpdate = useUpdate({ onInputChange, field }); const updateValue = useCallback( - async (newValue: string, onUpdateFn) => { + async (newValue: string, onUpdateFn: OnInputChangeFn<'array'>) => { const parsedValue = newValue .replace(REGEX, ',') .split(',') diff --git a/packages/kbn-management/settings/components/field_input/input/number_input.tsx b/packages/kbn-management/settings/components/field_input/input/number_input.tsx index 8a29429eff59f..303dfe3868664 100644 --- a/packages/kbn-management/settings/components/field_input/input/number_input.tsx +++ b/packages/kbn-management/settings/components/field_input/input/number_input.tsx @@ -12,6 +12,7 @@ import { EuiFieldNumber, EuiFieldNumberProps } from '@elastic/eui'; import { getFieldInputValue, useUpdate } from '@kbn/management-settings-utilities'; import { debounce } from 'lodash'; +import { OnInputChangeFn } from '@kbn/management-settings-types'; import { InputProps } from '../types'; import { TEST_SUBJ_PREFIX_FIELD } from '.'; import { useServices } from '../services'; @@ -36,7 +37,7 @@ export const NumberInput = ({ const onUpdate = useUpdate({ onInputChange, field }); const updateValue = useCallback( - async (newValue: number, onUpdateFn) => { + async (newValue: number, onUpdateFn: OnInputChangeFn<'number'>) => { const validationResponse = await validateChange(field.id, newValue); if (validationResponse.successfulValidation && !validationResponse.valid) { onUpdateFn({ diff --git a/packages/kbn-management/settings/setting_ids/index.ts b/packages/kbn-management/settings/setting_ids/index.ts index 2d09f5a2b2ad7..9f0c226717079 100644 --- a/packages/kbn-management/settings/setting_ids/index.ts +++ b/packages/kbn-management/settings/setting_ids/index.ts @@ -145,8 +145,6 @@ export const OBSERVABILITY_ENTITY_CENTRIC_EXPERIENCE = 'observability:entityCent export const OBSERVABILITY_LOGS_DATA_ACCESS_LOG_SOURCES_ID = 'observability:logSources'; export const OBSERVABILITY_AI_ASSISTANT_LOGS_INDEX_PATTERN_ID = 'observability:aiAssistantLogsIndexPattern'; -export const OBSERVABILITY_AI_ASSISTANT_RESPONSE_LANGUAGE = - 'observability:aiAssistantResponseLanguage'; export const OBSERVABILITY_AI_ASSISTANT_SIMULATED_FUNCTION_CALLING = 'observability:aiAssistantSimulatedFunctionCalling'; export const OBSERVABILITY_AI_ASSISTANT_SEARCH_CONNECTOR_INDEX_PATTERN = diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 3a56e7e75029b..aea38badef492 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -55,7 +55,7 @@ pageLoadAssetSize: expressionLegacyMetricVis: 23121 expressionMetric: 22238 expressionMetricVis: 23121 - expressionPartitionVis: 29700 + expressionPartitionVis: 44888 expressionRepeatImage: 22341 expressionRevealImage: 25675 expressions: 140958 diff --git a/packages/kbn-reporting/common/schema_utils.ts b/packages/kbn-reporting/common/schema_utils.ts index 6e3d193489ec1..d32f93b237977 100644 --- a/packages/kbn-reporting/common/schema_utils.ts +++ b/packages/kbn-reporting/common/schema_utils.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ByteSizeValue } from '@kbn/config-schema'; +import type { ByteSizeValue } from '@kbn/config-schema'; import moment from 'moment'; /* diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx index 75c7001c462d5..bf7f77837fee4 100644 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx +++ b/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx @@ -64,7 +64,7 @@ export const AutocompleteFieldListsComponent: React.FC name, []); + const getLabel = useCallback(({ name }: ListSchema) => name, []); const optionsMemo = useMemo( () => filterFieldToList(listData, selectedField), diff --git a/packages/kbn-securitysolution-autocomplete/src/operator/index.tsx b/packages/kbn-securitysolution-autocomplete/src/operator/index.tsx index 6d45d4d5ab37d..722bb33f9f303 100644 --- a/packages/kbn-securitysolution-autocomplete/src/operator/index.tsx +++ b/packages/kbn-securitysolution-autocomplete/src/operator/index.tsx @@ -44,7 +44,7 @@ export const OperatorComponent: React.FC = ({ selectedField, 'aria-label': ariaLabel, }): JSX.Element => { - const getLabel = useCallback(({ message }): string => message, []); + const getLabel = useCallback(({ message }: OperatorOption): string => message, []); const optionsMemo = useMemo( (): OperatorOption[] => operatorOptions != null && operatorOptions.length > 0 diff --git a/packages/kbn-securitysolution-exception-list-components/src/search_bar/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/search_bar/index.tsx index a40393bac8fcc..ab5c81d30eb5a 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/search_bar/index.tsx +++ b/packages/kbn-securitysolution-exception-list-components/src/search_bar/index.tsx @@ -9,7 +9,7 @@ import React, { useCallback } from 'react'; import type { FC } from 'react'; -import type { IconType, SearchFilterConfig } from '@elastic/eui'; +import type { EuiSearchBarProps, IconType, SearchFilterConfig } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiButton, EuiSearchBar } from '@elastic/eui'; import type { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; import type { GetExceptionItemProps } from '../types'; @@ -73,7 +73,7 @@ const SearchBarComponent: FC = ({ onSearch, onAddExceptionClick, }) => { - const handleOnSearch = useCallback( + const handleOnSearch = useCallback>( ({ queryText }): void => { onSearch({ search: queryText }); }, diff --git a/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts b/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts index 0da36d21f405b..76946be77fc3d 100644 --- a/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts +++ b/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts @@ -204,6 +204,26 @@ describe('Helpers', () => { ]) ).toBeTruthy(); }); + + test('it returns true if there are entries joined with an OR that have a wildcard and the wrong operator', () => { + expect( + hasWrongOperatorWithWildcard([ + { + description: '', + name: '', + type: 'simple', + entries: [{ type: 'match', value: 'withwildcard?', field: '', operator: 'included' }], + }, + { + description: '', + name: '', + type: 'simple', + entries: [{ type: 'match', value: 'withwildcard?*', field: '', operator: 'included' }], + }, + ]) + ).toBeTruthy(); + }); + test('it returns false if there are no exception entries with a wildcard and the wrong operator', () => { expect( hasWrongOperatorWithWildcard([ @@ -219,5 +239,25 @@ describe('Helpers', () => { ]) ).toBeFalsy(); }); + + test('it returns true if there are nested entries with a wildcard and the wrong operator', () => { + expect( + hasWrongOperatorWithWildcard([ + { + description: '', + name: '', + type: 'simple', + entries: [ + { type: 'match', value: 'nowildcard', field: '', operator: 'excluded' }, + { + field: '', + type: 'nested', + entries: [{ type: 'match', value: 'wildcard?', field: '', operator: 'excluded' }], + }, + ], + }, + ]) + ).toBeTruthy(); + }); }); }); diff --git a/packages/kbn-securitysolution-list-utils/src/helpers/index.ts b/packages/kbn-securitysolution-list-utils/src/helpers/index.ts index c969ac82c8a19..27598fb18110c 100644 --- a/packages/kbn-securitysolution-list-utils/src/helpers/index.ts +++ b/packages/kbn-securitysolution-list-utils/src/helpers/index.ts @@ -1032,7 +1032,16 @@ export const getMappingConflictsInfo = (field: DataViewField): FieldConflictsInf export const hasWrongOperatorWithWildcard = ( items: ExceptionsBuilderReturnExceptionItem[] ): boolean => { - const allEntries = items.flatMap((item) => item.entries); + // flattens array of multiple entries added with OR + const multipleEntries = items.flatMap((item) => item.entries); + // flattens nested entries + const allEntries = multipleEntries.flatMap((item) => { + if (item.type === 'nested') { + return item.entries; + } + return item; + }); + return allEntries.some((e) => { if (e.type !== 'list' && 'value' in e) { return validateHasWildcardWithWrongOperator({ diff --git a/packages/kbn-server-http-tools/kibana.jsonc b/packages/kbn-server-http-tools/kibana.jsonc index c2b6aae999c2f..f540a5be09123 100644 --- a/packages/kbn-server-http-tools/kibana.jsonc +++ b/packages/kbn-server-http-tools/kibana.jsonc @@ -1,5 +1,5 @@ { - "type": "shared-common", + "type": "shared-server", "id": "@kbn/server-http-tools", "owner": "@elastic/kibana-core" } diff --git a/packages/kbn-telemetry-tools/kibana.jsonc b/packages/kbn-telemetry-tools/kibana.jsonc index f36e6d272b81b..cf1d0def824e4 100644 --- a/packages/kbn-telemetry-tools/kibana.jsonc +++ b/packages/kbn-telemetry-tools/kibana.jsonc @@ -1,5 +1,5 @@ { - "type": "shared-common", + "type": "shared-server", "id": "@kbn/telemetry-tools", "devOnly": true, "owner": "@elastic/kibana-core" diff --git a/packages/kbn-telemetry-tools/src/tools/__fixture__/telemetry_collectors/externally_defined_usage_collector/index.ts b/packages/kbn-telemetry-tools/src/tools/__fixture__/telemetry_collectors/externally_defined_usage_collector/index.ts index 2b62900ae5c30..13f4a5bd8e281 100644 --- a/packages/kbn-telemetry-tools/src/tools/__fixture__/telemetry_collectors/externally_defined_usage_collector/index.ts +++ b/packages/kbn-telemetry-tools/src/tools/__fixture__/telemetry_collectors/externally_defined_usage_collector/index.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -// eslint-disable-next-line @kbn/imports/no_boundary_crossing import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import { getUsageCollector } from './get_usage_collector'; diff --git a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx index 326dc471a86c1..4fd0f994520d6 100644 --- a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx +++ b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx @@ -192,6 +192,14 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ setIsHistoryOpen(status); }, []); + const showSuggestionsIfEmptyQuery = useCallback(() => { + if (editorModel.current?.getValueLength() === 0) { + setImmediate(() => { + editor1.current?.trigger(undefined, 'editor.action.triggerSuggest', {}); + }); + } + }, []); + const openTimePickerPopover = useCallback(() => { const currentCursorPosition = editor1.current?.getPosition(); const editorCoords = editor1.current?.getDomNode()!.getBoundingClientRect(); @@ -275,7 +283,8 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ const onEditorFocus = useCallback(() => { setIsCodeEditorExpandedFocused(true); - }, []); + showSuggestionsIfEmptyQuery(); + }, [showSuggestionsIfEmptyQuery]); const { cache: esqlFieldsCache, memoizedFieldsFromESQL } = useMemo(() => { // need to store the timing of the first request so we can atomically clear the cache per query @@ -682,6 +691,8 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ editor.onDidLayoutChange((layoutInfoEvent) => { onLayoutChangeRef.current(layoutInfoEvent); }); + + editor.onDidChangeModelContent(showSuggestionsIfEmptyQuery); }} />
diff --git a/packages/kbn-unified-data-table/src/components/data_table_additional_display_settings.tsx b/packages/kbn-unified-data-table/src/components/data_table_additional_display_settings.tsx index cbead22b39997..9b6629d2c960b 100644 --- a/packages/kbn-unified-data-table/src/components/data_table_additional_display_settings.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table_additional_display_settings.tsx @@ -7,7 +7,7 @@ */ import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { EuiFormRow, EuiHorizontalRule, EuiRange } from '@elastic/eui'; +import { EuiFormRow, EuiHorizontalRule, EuiRange, EuiRangeProps } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { debounce } from 'lodash'; import { RowHeightSettings, RowHeightSettingsProps } from './row_height_settings'; @@ -63,9 +63,9 @@ export const UnifiedDataTableAdditionalDisplaySettings: React.FC< [onChangeSampleSize] ); - const onChangeActiveSampleSize = useCallback( + const onChangeActiveSampleSize = useCallback>( (event) => { - if (!event.target.value) { + if (!('value' in event.target) || !event.target.value) { setActiveSampleSize(''); return; } diff --git a/packages/kbn-utils/kibana.jsonc b/packages/kbn-utils/kibana.jsonc index 2c4efc0a67651..516d42bb2e8ba 100644 --- a/packages/kbn-utils/kibana.jsonc +++ b/packages/kbn-utils/kibana.jsonc @@ -1,5 +1,5 @@ { - "type": "shared-common", + "type": "shared-server", "id": "@kbn/utils", "owner": "@elastic/kibana-operations" } diff --git a/packages/kbn-visualization-ui-components/components/color_picker.tsx b/packages/kbn-visualization-ui-components/components/color_picker.tsx index 3a2613d16d665..442140e82c2b6 100644 --- a/packages/kbn-visualization-ui-components/components/color_picker.tsx +++ b/packages/kbn-visualization-ui-components/components/color_picker.tsx @@ -28,6 +28,17 @@ const tooltipContent = { }), }; +export interface ColorPickerProps { + overwriteColor?: string | null; + defaultColor?: string | null; + isClearable?: boolean; + setConfig: (config: { color?: string }) => void; + label?: string; + disableHelpTooltip?: boolean; + disabledMessage?: string; + showAlpha?: boolean; +} + export const ColorPicker = ({ overwriteColor, defaultColor, @@ -37,16 +48,7 @@ export const ColorPicker = ({ disableHelpTooltip, disabledMessage, showAlpha, -}: { - overwriteColor?: string | null; - defaultColor?: string | null; - isClearable?: boolean; - setConfig: (config: { color?: string }) => void; - label?: string; - disableHelpTooltip?: boolean; - disabledMessage?: string; - showAlpha?: boolean; -}) => { +}: ColorPickerProps) => { const [colorText, setColorText] = useState(overwriteColor || defaultColor); const [validatedColor, setValidatedColor] = useState(overwriteColor || defaultColor); const [currentColorAlpha, setCurrentColorAlpha] = useState(getColorAlpha(colorText)); diff --git a/packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx b/packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx index b954c37e3f7d1..3c031ac82da06 100644 --- a/packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx +++ b/packages/kbn-visualization-ui-components/components/query_input/filter_query_input.tsx @@ -33,6 +33,18 @@ export const defaultFilter: Query = { language: 'kuery', }; +export interface FilterQueryInputProps { + inputFilter: Query | undefined; + onChange: (query: Query) => void; + dataView: DataViewBase; + helpMessage?: string | null; + label?: string; + initiallyOpen?: boolean; + ['data-test-subj']?: string; + queryInputServices: QueryInputServices; + appName: string; +} + export function FilterQueryInput({ inputFilter, onChange, @@ -43,17 +55,7 @@ export function FilterQueryInput({ ['data-test-subj']: dataTestSubj, queryInputServices, appName, -}: { - inputFilter: Query | undefined; - onChange: (query: Query) => void; - dataView: DataViewBase; - helpMessage?: string | null; - label?: string; - initiallyOpen?: boolean; - ['data-test-subj']?: string; - queryInputServices: QueryInputServices; - appName: string; -}) { +}: FilterQueryInputProps) { const [filterPopoverOpen, setFilterPopoverOpen] = useState(Boolean(initiallyOpen)); const onClosePopup: EuiPopoverProps['closePopover'] = useCallback(() => { diff --git a/packages/kbn-visualization-ui-components/index.ts b/packages/kbn-visualization-ui-components/index.ts index 239849da05a50..c6d4d7a8c545c 100644 --- a/packages/kbn-visualization-ui-components/index.ts +++ b/packages/kbn-visualization-ui-components/index.ts @@ -40,6 +40,7 @@ export type { IconSet, AccessorConfig, QueryInputServices, + ColorPickerProps, } from './components'; export type { FormatFactory, LineStyle } from './types'; diff --git a/packages/react/kibana_mount/utils.ts b/packages/react/kibana_mount/utils.ts index d012a373f6a09..10294c8f0f818 100644 --- a/packages/react/kibana_mount/utils.ts +++ b/packages/react/kibana_mount/utils.ts @@ -17,7 +17,7 @@ export const useIfMounted = () => { [] ); - const ifMounted = useCallback((func) => { + const ifMounted = useCallback((func?: () => void) => { if (isMounted.current && func) { func(); } diff --git a/packages/serverless/settings/observability_project/index.ts b/packages/serverless/settings/observability_project/index.ts index 07a9c84e210ff..bcaab96e8bd0a 100644 --- a/packages/serverless/settings/observability_project/index.ts +++ b/packages/serverless/settings/observability_project/index.ts @@ -34,7 +34,6 @@ export const OBSERVABILITY_PROJECT_SETTINGS = [ settings.OBSERVABILITY_APM_ENABLE_SERVICE_INVENTORY_TABLE_SEARCH_BAR, settings.OBSERVABILITY_ENTITY_CENTRIC_EXPERIENCE, settings.OBSERVABILITY_AI_ASSISTANT_LOGS_INDEX_PATTERN_ID, - settings.OBSERVABILITY_AI_ASSISTANT_RESPONSE_LANGUAGE, settings.OBSERVABILITY_AI_ASSISTANT_SIMULATED_FUNCTION_CALLING, settings.OBSERVABILITY_AI_ASSISTANT_SEARCH_CONNECTOR_INDEX_PATTERN, ]; diff --git a/renovate.json b/renovate.json index 233505d4012de..774dce52e3515 100644 --- a/renovate.json +++ b/renovate.json @@ -1,24 +1,9 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "config:recommended", - "helpers:pinGitHubActionDigests", - "helpers:pinGitHubActionDigestsToSemver" - ], - "ignorePaths": [ - "**/__fixtures__/**", - "**/fixtures/**" - ], - "enabledManagers": [ - "npm", - "github-actions", - "custom.regex", - "devcontainer" - ], - "baseBranches": [ - "main", - "7.17" - ], + "extends": ["config:recommended", "helpers:pinGitHubActionDigests", "helpers:pinGitHubActionDigestsToSemver"], + "ignorePaths": ["**/__fixtures__/**", "**/fixtures/**"], + "enabledManagers": ["npm", "github-actions", "custom.regex", "devcontainer"], + "baseBranches": ["main", "7.17"], "prConcurrentLimit": 0, "prHourlyLimit": 0, "separateMajorMinor": false, @@ -32,51 +17,28 @@ }, "packageRules": [ { - "enabled": false, - "matchDepNames": [ - "/.*/" - ] + "matchDepPatterns": [".*"], + "enabled": false }, { "groupName": "devcontainer", - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip", - "backport:current-major" - ], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip", "backport:current-major"], "enabled": true, - "matchManagers": [ - "devcontainer" - ] + "matchManagers": ["devcontainer"] }, { "groupName": "chainguard", - "matchPackageNames": [ - "docker.elastic.co/wolfi/chainguard-base" - ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "matchPackageNames": ["docker.elastic.co/wolfi/chainguard-base"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "enabled": true }, { "groupName": "operations actions", - "matchManagers": [ - "github-actions" - ], + "matchManagers": ["github-actions"], "matchPackageNames": [ "actions/checkout", "elastic/github-actions/project-assigner", @@ -85,367 +47,168 @@ "sergeysova/jq-action", "sourenlouv/backport" ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "backport:all-open", - "release_note:skip" - ], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "backport:all-open", "release_note:skip"], "enabled": true }, { "groupName": "@elastic/charts", - "matchDepNames": [ - "@elastic/charts" - ], - "reviewers": [ - "team:visualizations", - "markov00", - "nickofthyme" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:skip", - "Team:Visualizations" - ], + "matchDepNames": ["@elastic/charts"], + "reviewers": ["team:visualizations", "markov00", "nickofthyme"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:skip", "Team:Visualizations"], "enabled": true }, { "groupName": "@elastic/elasticsearch", - "matchDepNames": [ - "@elastic/elasticsearch" - ], - "reviewers": [ - "team:kibana-operations", - "team:kibana-core" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:skip", - "Team:Operations", - "Team:Core" - ], + "matchDepNames": ["@elastic/elasticsearch"], + "reviewers": ["team:kibana-operations", "team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:skip", "Team:Operations", "Team:Core"], "enabled": true }, { "groupName": "@elastic/elasticsearch", - "matchDepNames": [ - "@elastic/elasticsearch" - ], - "reviewers": [ - "team:kibana-operations", - "team:kibana-core" - ], - "matchBaseBranches": [ - "7.17" - ], - "labels": [ - "release_note:skip", - "Team:Operations", - "Team:Core", - "backport:skip" - ], + "matchDepNames": ["@elastic/elasticsearch"], + "reviewers": ["team:kibana-operations", "team:kibana-core"], + "matchBaseBranches": ["7.17"], + "labels": ["release_note:skip", "Team:Operations", "Team:Core", "backport:skip"], "enabled": true }, { "groupName": "LaunchDarkly", - "matchDepNames": [ - "launchdarkly-js-client-sdk", - "@launchdarkly/node-server-sdk", - "launchdarkly/find-code-references" - ], - "reviewers": [ - "team:kibana-security", - "team:kibana-core" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "Team:Security", - "Team:Core", - "backport:prev-minor" - ], + "matchDepNames": ["launchdarkly-js-client-sdk", "@launchdarkly/node-server-sdk", "launchdarkly/find-code-references"], + "reviewers": ["team:kibana-security", "team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "Team:Security", "Team:Core", "backport:prev-minor"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "APM", - "matchDepNames": [ - "elastic-apm-node", - "@elastic/apm-rum", - "@elastic/apm-rum-react" - ], - "reviewers": [ - "team:kibana-core" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "Team:Core", - "backport:skip" - ], + "matchDepNames": ["elastic-apm-node", "@elastic/apm-rum", "@elastic/apm-rum-react"], + "reviewers": ["team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "Team:Core", "backport:skip"], "enabled": true }, { "groupName": "@elastic/ebt", - "matchDepNames": [ - "@elastic/ebt" - ], - "reviewers": [ - "team:kibana-core" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "Team:Core", - "backport:skip" - ], + "matchDepNames": ["@elastic/ebt"], + "reviewers": ["team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "Team:Core", "backport:skip"], "enabled": true }, { "groupName": "ansi-regex", - "matchDepNames": [ - "ansi-regex" - ], - "reviewers": [ - "team:kibana-core" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "Team:Core", - "backport:skip" - ], + "matchDepNames": ["ansi-regex"], + "reviewers": ["team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "Team:Core", "backport:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "OpenAPI Spec", - "matchDepNames": [ - "@redocly/cli" - ], - "reviewers": [ - "team:kibana-core" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "Team:Core", - "backport:skip" - ], + "matchDepNames": ["@redocly/cli"], + "reviewers": ["team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "Team:Core", "backport:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "babel", - "matchDepNames": [ - "@types/babel__core", - "/^@babel/", - "/^babel-plugin/" - ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "matchDepNames": ["@types/babel__core"], + "matchDepPatterns": ["^@babel", "^babel-plugin"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "typescript", - "matchDepNames": [ - "typescript", - "@types/jsdom" - ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "matchDepNames": ["typescript", "@types/jsdom"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "prettier", - "matchDepNames": [ - "prettier", - "eslint-plugin-prettier", - "eslint-config-prettier" - ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "matchDepNames": ["prettier", "eslint-plugin-prettier", "eslint-config-prettier"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "allowedVersions": "<3.0", "enabled": true }, { "groupName": "typescript-eslint", - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "matchDepPatterns": ["^@typescript-eslint"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", - "enabled": true, - "matchDepNames": [ - "/^@typescript-eslint/" - ] + "enabled": true }, { "groupName": "eslint-plugin-depend", - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "matchDepPatterns": ["eslint-plugin-depend"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", - "enabled": true, - "matchDepNames": [ - "/eslint-plugin-depend/" - ] + "enabled": true }, { "groupName": "polyfills", - "matchDepNames": [ - "core-js", - "/polyfill/" - ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "matchDepNames": ["core-js"], + "matchDepPatterns": ["polyfill"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "CLI tooling", - "matchDepNames": [ - "listr2" - ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "backport:all-open", - "release_note:skip" - ], + "matchDepNames": ["listr2"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "backport:all-open", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "vega related modules", - "matchDepNames": [ - "vega", - "vega-lite", - "vega-schema-url-parser", - "vega-tooltip" - ], - "reviewers": [ - "team:kibana-visualizations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Feature:Vega", - "Team:Visualizations" - ], + "matchDepNames": ["vega", "vega-lite", "vega-schema-url-parser", "vega-tooltip"], + "reviewers": ["team:kibana-visualizations"], + "matchBaseBranches": ["main"], + "labels": ["Feature:Vega", "Team:Visualizations"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "cypress", - "reviewers": [ - "Team:apm", - "Team: SecuritySolution" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "buildkite-ci", - "ci:all-cypress-suites" - ], + "matchDepPatterns": ["cypress"], + "reviewers": ["Team:apm", "Team: SecuritySolution"], + "matchBaseBranches": ["main"], + "labels": ["buildkite-ci", "ci:all-cypress-suites"], "minimumReleaseAge": "7 days", - "enabled": true, - "matchDepNames": [ - "/cypress/" - ] + "enabled": true }, { "groupName": "security solution modules", - "matchDepNames": [ - "zod", - "langchain" - ], - "reviewers": [ - "Team: SecuritySolution" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team: SecuritySolution" - ], + "matchDepNames": ["zod", "langchain"], + "reviewers": ["Team: SecuritySolution"], + "matchBaseBranches": ["main"], + "labels": ["Team: SecuritySolution"], "minimumReleaseAge": "7 days", "enabled": true }, @@ -463,17 +226,9 @@ "@types/xml-crypto", "@kayahr/text-encoding" ], - "reviewers": [ - "team:kibana-security" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Security", - "release_note:skip", - "backport:all-open" - ], + "reviewers": ["team:kibana-security"], + "matchBaseBranches": ["main"], + "labels": ["Team:Security", "release_note:skip", "backport:all-open"], "minimumReleaseAge": "7 days", "enabled": true }, @@ -483,17 +238,9 @@ "github/codeql-action/analyze", "github/codeql-action/init" ], - "reviewers": [ - "team:kibana-security" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Security", - "release_note:skip", - "backport:all-open" - ], + "reviewers": ["team:kibana-security"], + "matchBaseBranches": ["main"], + "labels": ["Team:Security", "release_note:skip", "backport:all-open"], "minimumReleaseAge": "7 days", "enabled": true }, @@ -507,54 +254,27 @@ "ms-chromium-edge-driver", "selenium-webdriver" ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "scss", - "matchDepNames": [ - "sass-embedded" - ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip", - "backport:all-open" - ], + "matchDepNames": ["sass-embedded"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip", "backport:all-open"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "minify", - "matchDepNames": [ - "gulp-terser", - "terser" - ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "matchDepNames": ["gulp-terser", "terser"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, @@ -568,16 +288,9 @@ "@testing-library/user-event", "@types/testing-library__jest-dom" ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, @@ -599,68 +312,36 @@ "jest-runtime", "jest-snapshot" ], - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip" - ], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "@storybook", - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Operations", - "release_note:skip", - "ci:build-storybooks", - "backport:skip" - ], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "matchDepPatterns": ["^@storybook"], + "excludeDepNames": ["@storybook/testing-react"], + "labels": ["Team:Operations", "release_note:skip", "ci:build-storybooks", "backport:skip"], "minimumReleaseAge": "7 days", "allowedVersions": "<7.0", - "enabled": true, - "matchDepNames": [ - "/^@storybook/", - "!@storybook/testing-react" - ] + "enabled": true }, { "groupName": "@storybook/testing-react", - "reviewers": [ - "team:kibana-operations" - ], - "matchBaseBranches": [ - "main" - ], - "matchDepNames": [ - "@storybook/testing-react" - ], - "labels": [ - "Team:Operations", - "release_note:skip", - "ci:build-storybooks", - "backport:skip" - ], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "matchDepNames": ["@storybook/testing-react"], + "labels": ["Team:Operations", "release_note:skip", "ci:build-storybooks", "backport:skip"], "minimumReleaseAge": "7 days", "allowedVersions": "<2.0", "enabled": true }, { "groupName": "react-query", - "matchDepNames": [ - "@tanstack/react-query", - "@tanstack/react-query-devtools" - ], + "matchDepNames": ["@tanstack/react-query", "@tanstack/react-query-devtools"], "reviewers": [ "team:response-ops", "team:kibana-cloud-security-posture", @@ -669,43 +350,23 @@ "team:awp-platform", "team:security-onboarding-and-lifecycle-mgt" ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:skip", - "ci:all-cypress-suites" - ], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:skip", "ci:all-cypress-suites"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "react-hook-form", - "matchDepNames": [ - "react-hook-form" - ], - "reviewers": [ - "team:security-asset-management", - "team:uptime" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:skip", - "ci:all-cypress-suites" - ], + "matchDepNames": ["react-hook-form"], + "reviewers": ["team:security-asset-management", "team:uptime"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:skip", "ci:all-cypress-suites"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "redux", - "matchDepNames": [ - "redux", - "react-redux" - ], + "matchDepNames": ["redux", "react-redux"], "reviewers": [ "team:search-kibana", "team:kibana-presentation", @@ -714,241 +375,115 @@ "team:kibana-gis", "team:security-solution" ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:skip", - "ci:all-cypress-suites" - ], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:skip", "ci:all-cypress-suites"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "Profiling", - "matchDepNames": [ - "peggy", - "@types/dagre" - ], - "reviewers": [ - "team:obs-ux-infra_services-team" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:skip" - ], + "matchDepNames": ["peggy", "@types/dagre"], + "reviewers": ["team:obs-ux-infra_services-team"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "TTY Output", - "matchDepNames": [ - "xterm", - "byte-size", - "@types/byte-size" - ], - "reviewers": [ - "team:sec-cloudnative-integrations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team: AWP: Visualization", - "release_note:skip", - "backport:skip" - ], + "matchDepNames": ["xterm", "byte-size", "@types/byte-size"], + "reviewers": ["team:sec-cloudnative-integrations"], + "matchBaseBranches": ["main"], + "labels": ["Team: AWP: Visualization", "release_note:skip", "backport:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "Cloud Defend", - "matchDepNames": [ - "monaco-yaml" - ], - "reviewers": [ - "team:sec-cloudnative-integrations" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team: Cloud Native Integrations", - "release_note:skip", - "backport:skip" - ], + "matchDepNames": ["monaco-yaml"], + "reviewers": ["team:sec-cloudnative-integrations"], + "matchBaseBranches": ["main"], + "labels": ["Team: Cloud Native Integrations", "release_note:skip", "backport:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "JSON Web Token", - "matchDepNames": [ - "jsonwebtoken" - ], - "reviewers": [ - "team:response-ops", - "team:kibana-core" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:all-open" - ], + "matchDepNames": ["jsonwebtoken"], + "reviewers": ["team:response-ops", "team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:all-open"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "XState", - "matchDepNames": [ - "xstate", - "@xstate/{/,}**" - ], - "reviewers": [ - "team:obs-ux-logs-team" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Obs UX Logs", - "release_note:skip" - ], + "matchDepNames": ["xstate"], + "matchDepPrefixes": ["@xstate/"], + "reviewers": ["team:obs-ux-logs-team"], + "matchBaseBranches": ["main"], + "labels": ["Team:Obs UX Logs", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "OpenTelemetry modules", - "reviewers": [ - "team:stack-monitoring" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:Monitoring" - ], + "matchDepPrefixes": ["@opentelemetry/"], + "reviewers": ["team:stack-monitoring"], + "matchBaseBranches": ["main"], + "labels": ["Team:Monitoring"], "minimumReleaseAge": "7 days", - "enabled": true, - "matchDepNames": [ - "@opentelemetry/{/,}**" - ] + "enabled": true }, { "groupName": "csp", - "matchDepNames": [ - "content-security-policy-parser" - ], - "reviewers": [ - "team:kibana-security", - "team:kibana-core" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:skip", - "ci:serverless-test-all" - ], + "matchDepNames": ["content-security-policy-parser"], + "reviewers": ["team:kibana-security", "team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:skip", "ci:serverless-test-all"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "AlertingEmails", - "matchDepNames": [ - "nodemailer" - ], - "reviewers": [ - "team:response-ops" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:prev-minor" - ], + "matchDepNames": ["nodemailer"], + "reviewers": ["team:response-ops"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:prev-minor"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "Kibana ES|QL Team", - "matchDepNames": [ - "recast" - ], - "reviewers": [ - "team:kibana-esql" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team:ESQL", - "release_note:skip" - ], + "matchDepNames": ["recast"], + "reviewers": ["team:kibana-esql"], + "matchBaseBranches": ["main"], + "labels": ["Team:ESQL", "release_note:skip"], "minimumReleaseAge": "7 days", "enabled": true }, { "groupName": "MSW", - "matchPackageNames": [ - "msw" - ], - "reviewers": [ - "team:kibana-cloud-security-posture" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "Team: Cloud Security", - "release_note:skip", - "backport:skip" - ], + "matchPackageNames": ["msw"], + "reviewers": ["team:kibana-cloud-security-posture"], + "matchBaseBranches": ["main"], + "labels": ["Team: Cloud Security", "release_note:skip", "backport:skip"], "enabled": true }, { "groupName": "re2js", - "matchDepNames": [ - "re2js" - ], - "reviewers": [ - "team:visualizations", - "dej611" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "backport:all-open", - "Team:Visualizations" - ], + "matchDepNames": ["re2js"], + "reviewers": ["team:visualizations", "dej611"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "backport:all-open", "Team:Visualizations"], "enabled": true }, { "groupName": "Serve swagger docs", - "matchDepNames": [ - "express", - "swagger-jsdoc", - "swagger-ui-express" - ], - "reviewers": [ - "team:obs-entities" - ], - "matchBaseBranches": [ - "main" - ], - "labels": [ - "release_note:skip", - "team:obs-entities" - ], + "matchDepNames": ["express", "swagger-jsdoc", "swagger-ui-express"], + "reviewers": ["team:obs-entities"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "team:obs-entities"], "enabled": true } ], @@ -977,4 +512,4 @@ "datasourceTemplate": "docker" } ] -} \ No newline at end of file +} diff --git a/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts b/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts index bcc7d33f38c39..4c9a9fad340c8 100644 --- a/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts +++ b/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts @@ -110,7 +110,7 @@ describe('checking migration metadata changes on all registered SO types', () => "fleet-proxy": "6cb688f0d2dd856400c1dbc998b28704ff70363d", "fleet-setup-lock": "0dc784792c79b5af5a6e6b5dcac06b0dbaa90bde", "fleet-space-settings": "b278e82a33978900e53a1253884b5bdbd929c9bb", - "fleet-uninstall-tokens": "ed8aa37e3cdd69e4360709e64944bb81cae0c025", + "fleet-uninstall-tokens": "371a691206845b364bcf6d3693ca7905ffdb71a4", "graph-workspace": "5cc6bb1455b078fd848c37324672163f09b5e376", "guided-onboarding-guide-state": "d338972ed887ac480c09a1a7fbf582d6a3827c91", "guided-onboarding-plugin-state": "bc109e5ef46ca594fdc179eda15f3095ca0a37a4", diff --git a/src/core/server/integration_tests/saved_objects/migrations/group2/multiple_kibana_nodes.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group2/multiple_kibana_nodes.test.ts index 8d6f83736d010..1a8806e8dd707 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group2/multiple_kibana_nodes.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group2/multiple_kibana_nodes.test.ts @@ -106,7 +106,8 @@ async function createRoot({ logFileName }: CreateRootConfig) { // suite is very long, the 10mins default can cause timeouts jest.setTimeout(15 * 60 * 1000); -describe('migration v2', () => { +// FLAKY: https://github.com/elastic/kibana/issues/156117 +describe.skip('migration v2', () => { let esServer: TestElasticsearchUtils; let rootA: Root; let rootB: Root; diff --git a/src/plugins/chart_expressions/common/color_categories.test.ts b/src/plugins/chart_expressions/common/color_categories.test.ts new file mode 100644 index 0000000000000..cbd02e149ecdc --- /dev/null +++ b/src/plugins/chart_expressions/common/color_categories.test.ts @@ -0,0 +1,71 @@ +/* + * 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 { DatatableRow } from '@kbn/expressions-plugin/common'; +import { getColorCategories } from './color_categories'; + +const extensions = ['gz', 'css', '', 'rpm', 'deb', 'zip', null]; +const getExtension = (i: number) => extensions[i % extensions.length]; + +const basicDatatableRows: DatatableRow[] = Array.from({ length: 30 }).map((_, i) => ({ + count: i, + extension: getExtension(i), +})); + +const isTransposedDatatableRows: DatatableRow[] = Array.from({ length: 30 }).map((_, i) => ({ + count: i, + ['safari---extension']: getExtension(i), + ['chrome---extension']: getExtension(i + 1), + ['firefox---extension']: getExtension(i + 2), +})); + +describe('getColorCategories', () => { + it('should return all categories from datatable rows', () => { + expect(getColorCategories(basicDatatableRows, 'extension')).toEqual([ + 'gz', + 'css', + '', + 'rpm', + 'deb', + 'zip', + 'null', + ]); + }); + + it('should exclude selected categories from datatable rows', () => { + expect(getColorCategories(basicDatatableRows, 'extension', false, ['', null])).toEqual([ + 'gz', + 'css', + 'rpm', + 'deb', + 'zip', + ]); + }); + + it('should return categories across all transpose columns of datatable rows', () => { + expect(getColorCategories(isTransposedDatatableRows, 'extension', true)).toEqual([ + 'gz', + 'css', + '', + 'rpm', + 'deb', + 'zip', + 'null', + ]); + }); + + it('should exclude selected categories across all transpose columns of datatable rows', () => { + expect(getColorCategories(isTransposedDatatableRows, 'extension', true, ['', null])).toEqual([ + 'gz', + 'css', + 'rpm', + 'deb', + 'zip', + ]); + }); +}); diff --git a/src/plugins/chart_expressions/common/color_categories.ts b/src/plugins/chart_expressions/common/color_categories.ts index 0bb8811f2701a..3699c89d2c8ce 100644 --- a/src/plugins/chart_expressions/common/color_categories.ts +++ b/src/plugins/chart_expressions/common/color_categories.ts @@ -15,27 +15,38 @@ import { isMultiFieldKey } from '@kbn/data-plugin/common'; */ export function getColorCategories( rows: DatatableRow[], - accessor?: string + accessor?: string, + isTransposed?: boolean, + exclude?: any[] ): Array { - return accessor - ? rows.reduce<{ keys: Set; categories: Array }>( - (acc, r) => { - const value = r[accessor]; - if (value === undefined) { - return acc; - } + const ids = isTransposed + ? Object.keys(rows[0]).filter((key) => accessor && key.endsWith(accessor)) + : accessor + ? [accessor] + : []; + + return rows + .flatMap((r) => + ids + .map((id) => r[id]) + .filter((v) => !(v === undefined || exclude?.includes(v))) + .map((v) => { // The categories needs to be stringified in their unformatted version. // We can't distinguish between a number and a string from a text input and the match should // work with both numeric field values and string values. - const key = (isMultiFieldKey(value) ? [...value.keys] : [value]).map(String); + const key = (isMultiFieldKey(v) ? v.keys : [v]).map(String); const stringifiedKeys = key.join(','); - if (!acc.keys.has(stringifiedKeys)) { - acc.keys.add(stringifiedKeys); - acc.categories.push(key.length === 1 ? key[0] : key); - } - return acc; - }, - { keys: new Set(), categories: [] } - ).categories - : []; + return { key, stringifiedKeys }; + }) + ) + .reduce<{ keys: Set; categories: Array }>( + (acc, { key, stringifiedKeys }) => { + if (!acc.keys.has(stringifiedKeys)) { + acc.keys.add(stringifiedKeys); + acc.categories.push(key.length === 1 ? key[0] : key); + } + return acc; + }, + { keys: new Set(), categories: [] } + ).categories; } diff --git a/src/plugins/chart_expressions/expression_gauge/public/components/gauge_component.tsx b/src/plugins/chart_expressions/expression_gauge/public/components/gauge_component.tsx index 0e1ebe988e602..145571da11022 100644 --- a/src/plugins/chart_expressions/expression_gauge/public/components/gauge_component.tsx +++ b/src/plugins/chart_expressions/expression_gauge/public/components/gauge_component.tsx @@ -194,7 +194,7 @@ export const GaugeComponent: FC = ({ const getColor = useCallback( ( - value, + value: number, paletteConfig: PaletteOutput, bands: number[], percentageMode?: boolean diff --git a/src/plugins/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx b/src/plugins/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx index 0c7f855c66390..b76bc5ec611b7 100644 --- a/src/plugins/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx +++ b/src/plugins/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx @@ -18,6 +18,8 @@ import { Wordcloud, RenderChangeListener, LEGACY_LIGHT_THEME, + ElementClickListener, + WordCloudElementEvent, } from '@elastic/charts'; import { EmptyPlaceholder } from '@kbn/charts-plugin/public'; import { @@ -190,13 +192,13 @@ export const TagCloudChart = ({ [] ); - const handleWordClick = useCallback( + const handleWordClick = useCallback( (elements) => { if (!bucket) { return; } const termsBucketId = getColumnByAccessor(bucket, visData.columns)!.id; - const clickedValue = elements[0][0].text; + const clickedValue = (elements[0] as WordCloudElementEvent)[0].text; const columnIndex = visData.columns.findIndex((col) => col.id === termsBucketId); if (columnIndex < 0) { diff --git a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap index b983bc6047077..789878ac673fa 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap +++ b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap @@ -1747,8 +1747,8 @@ exports[`XYChart component it renders area 1`] = ` minBarHeight={1} paletteService={ Object { - "get": [Function], - "getAll": [Function], + "get": [MockFunction], + "getAll": [MockFunction], } } shouldShowValueLabels={true} @@ -3302,8 +3302,8 @@ exports[`XYChart component it renders bar 1`] = ` minBarHeight={1} paletteService={ Object { - "get": [Function], - "getAll": [Function], + "get": [MockFunction], + "getAll": [MockFunction], } } shouldShowValueLabels={true} @@ -4857,8 +4857,8 @@ exports[`XYChart component it renders horizontal bar 1`] = ` minBarHeight={1} paletteService={ Object { - "get": [Function], - "getAll": [Function], + "get": [MockFunction], + "getAll": [MockFunction], } } shouldShowValueLabels={true} @@ -6412,8 +6412,8 @@ exports[`XYChart component it renders line 1`] = ` minBarHeight={1} paletteService={ Object { - "get": [Function], - "getAll": [Function], + "get": [MockFunction], + "getAll": [MockFunction], } } shouldShowValueLabels={true} @@ -7967,8 +7967,8 @@ exports[`XYChart component it renders stacked area 1`] = ` minBarHeight={1} paletteService={ Object { - "get": [Function], - "getAll": [Function], + "get": [MockFunction], + "getAll": [MockFunction], } } shouldShowValueLabels={true} @@ -9522,8 +9522,8 @@ exports[`XYChart component it renders stacked bar 1`] = ` minBarHeight={1} paletteService={ Object { - "get": [Function], - "getAll": [Function], + "get": [MockFunction], + "getAll": [MockFunction], } } shouldShowValueLabels={true} @@ -11077,8 +11077,8 @@ exports[`XYChart component it renders stacked horizontal bar 1`] = ` minBarHeight={1} paletteService={ Object { - "get": [Function], - "getAll": [Function], + "get": [MockFunction], + "getAll": [MockFunction], } } shouldShowValueLabels={true} @@ -12858,8 +12858,8 @@ exports[`XYChart component split chart should render split chart if both, splitR minBarHeight={1} paletteService={ Object { - "get": [Function], - "getAll": [Function], + "get": [MockFunction], + "getAll": [MockFunction], } } shouldShowValueLabels={true} @@ -14646,8 +14646,8 @@ exports[`XYChart component split chart should render split chart if splitColumnA minBarHeight={1} paletteService={ Object { - "get": [Function], - "getAll": [Function], + "get": [MockFunction], + "getAll": [MockFunction], } } shouldShowValueLabels={true} @@ -16432,8 +16432,8 @@ exports[`XYChart component split chart should render split chart if splitRowAcce minBarHeight={1} paletteService={ Object { - "get": [Function], - "getAll": [Function], + "get": [MockFunction], + "getAll": [MockFunction], } } shouldShowValueLabels={true} diff --git a/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx b/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx index c5223a270eadd..ffdb868ecff53 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx @@ -48,8 +48,8 @@ interface Props { endValue?: EndValue | undefined; paletteService: PaletteRegistry; formattedDatatables: DatatablesWithFormatInfo; - syncColors?: boolean; - timeZone?: string; + syncColors: boolean; + timeZone: string; emphasizeFitting?: boolean; fillOpacity?: number; minBarHeight: number; diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/color_assignment.ts b/src/plugins/chart_expressions/expression_xy/public/helpers/color_assignment.ts index 990d1ab93a1bc..0dd7ca05a2c9d 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/color_assignment.ts +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/color_assignment.ts @@ -98,7 +98,6 @@ export const getAllSeries = ( /** * This function joins every data series name available on each layer by the same color palette. * The returned function `getRank` should return the position of a series name in this unified list by palette. - * */ export function getColorAssignments( layers: CommonXYLayerConfig[], diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx b/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx index b3684217d137f..406c498c15bba 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx @@ -28,7 +28,7 @@ import { getPalette, AVAILABLE_PALETTES, NeutralPalette, - SPECIAL_TOKENS_STRING_CONVERTION, + SPECIAL_TOKENS_STRING_CONVERSION, } from '@kbn/coloring'; import { getColorCategories } from '@kbn/chart-expressions-common'; import { isDataLayer } from '../../common/utils/layer_types_guards'; @@ -53,10 +53,10 @@ type GetSeriesPropsFn = (config: { colorAssignments: ColorAssignments; columnToLabelMap: Record; paletteService: PaletteRegistry; - syncColors?: boolean; yAxis?: GroupsConfiguration[number]; xAxis?: GroupsConfiguration[number]; - timeZone?: string; + syncColors: boolean; + timeZone: string; emphasizeFitting?: boolean; fillOpacity?: number; formattedDatatableInfo: DatatableWithFormatInfo; @@ -324,7 +324,7 @@ const getColor: GetColorFn = ( series, { layer, colorAssignments, paletteService, syncColors, getSeriesNameFn }, uiState, - singleTable + isSingleTable ) => { const overwriteColor = getSeriesColor(layer, series.yAccessor as string); if (overwriteColor !== null) { @@ -333,7 +333,7 @@ const getColor: GetColorFn = ( const name = getSeriesNameFn(series)?.toString() || ''; - const overwriteColors: Record = uiState?.get ? uiState.get('vis.colors', {}) : {}; + const overwriteColors: Record = uiState?.get?.('vis.colors', {}) ?? {}; if (Object.keys(overwriteColors).includes(name)) { return overwriteColors[name]; @@ -344,7 +344,7 @@ const getColor: GetColorFn = ( { name, totalSeriesAtDepth: colorAssignment.totalSeriesCount, - rankAtDepth: colorAssignment.getRank(singleTable ? 'commonLayerId' : layer.layerId, name), + rankAtDepth: colorAssignment.getRank(isSingleTable ? 'commonLayerId' : layer.layerId, name), }, ]; return paletteService.get(layer.palette.name).getCategoricalColor( @@ -493,7 +493,7 @@ export const getSeriesProps: GetSeriesPropsFn = ({ // if colorMapping exist then we can apply it, if not let's use the legacy coloring method layer.colorMapping && splitColumnIds.length > 0 ? getColorSeriesAccessorFn( - JSON.parse(layer.colorMapping), // the color mapping is at this point just a strinfigied JSON + JSON.parse(layer.colorMapping), // the color mapping is at this point just a stringified JSON getPalette(AVAILABLE_PALETTES, NeutralPalette), isDarkMode, { @@ -501,7 +501,7 @@ export const getSeriesProps: GetSeriesPropsFn = ({ categories: getColorCategories(table.rows, splitColumnIds[0]), }, splitColumnIds[0], - SPECIAL_TOKENS_STRING_CONVERTION + SPECIAL_TOKENS_STRING_CONVERSION ) : (series) => getColor( diff --git a/src/plugins/charts/public/services/active_cursor/use_active_cursor.ts b/src/plugins/charts/public/services/active_cursor/use_active_cursor.ts index e06c6096664c8..aff01a5871ad6 100644 --- a/src/plugins/charts/public/services/active_cursor/use_active_cursor.ts +++ b/src/plugins/charts/public/services/active_cursor/use_active_cursor.ts @@ -11,7 +11,7 @@ import { animationFrameScheduler } from 'rxjs'; import { useCallback, useEffect, RefObject } from 'react'; import { filter, debounceTime } from 'rxjs'; -import type { Chart } from '@elastic/charts'; +import type { Chart, PointerUpdateListener } from '@elastic/charts'; import { parseSyncOptions } from './active_cursor_utils'; @@ -24,9 +24,9 @@ export const useActiveCursor = ( activeCursor: ActiveCursor, chartRef: RefObject, syncOptions: ActiveCursorSyncOption -) => { +): PointerUpdateListener => { const { accessors, isDateHistogram } = parseSyncOptions(syncOptions); - const handleCursorUpdate = useCallback( + const handleCursorUpdate = useCallback( (cursor) => { activeCursor.activeCursor$?.next({ cursor, diff --git a/src/plugins/charts/public/services/palettes/mock.ts b/src/plugins/charts/public/services/palettes/mock.ts index 8d7007f96529b..2d1ee87e385ca 100644 --- a/src/plugins/charts/public/services/palettes/mock.ts +++ b/src/plugins/charts/public/services/palettes/mock.ts @@ -74,9 +74,10 @@ export const getPaletteRegistry = () => { }; return { - get: (name: string) => - name === 'custom' ? mockPalette3 : name !== 'default' ? mockPalette2 : mockPalette1, - getAll: () => [mockPalette1, mockPalette2, mockPalette3], + get: jest.fn((name: string) => + name === 'custom' ? mockPalette3 : name !== 'default' ? mockPalette2 : mockPalette1 + ), + getAll: jest.fn(() => [mockPalette1, mockPalette2, mockPalette3]), }; }; diff --git a/src/plugins/controls/common/options_list/types.ts b/src/plugins/controls/common/options_list/types.ts index 4192cc6aac26d..f84b1a85f857f 100644 --- a/src/plugins/controls/common/options_list/types.ts +++ b/src/plugins/controls/common/options_list/types.ts @@ -81,6 +81,7 @@ export interface OptionsListRequestBody > { runtimeFieldMap?: Record; allowExpensiveQueries: boolean; + ignoreValidations?: boolean; filters?: Array<{ bool: BoolQuery }>; runPastTimeout?: boolean; searchString?: string; diff --git a/src/plugins/controls/public/options_list/components/options_list_popover_suggestions.tsx b/src/plugins/controls/public/options_list/components/options_list_popover_suggestions.tsx index 486978b63ec5e..f0398d1bf60fd 100644 --- a/src/plugins/controls/public/options_list/components/options_list_popover_suggestions.tsx +++ b/src/plugins/controls/public/options_list/components/options_list_popover_suggestions.tsx @@ -157,7 +157,7 @@ export const OptionsListPopoverSuggestions = ({ }, [loadMoreSuggestions, totalCardinality]); const renderOption = useCallback( - (option, searchStringValue) => { + (option: EuiSelectableOption, searchStringValue: string) => { if (!allowExpensiveQueries || searchTechnique === 'exact') return option.label; return ( diff --git a/src/plugins/controls/public/react_controls/controls/data_controls/options_list_control/fetch_and_validate.tsx b/src/plugins/controls/public/react_controls/controls/data_controls/options_list_control/fetch_and_validate.tsx index f3633b13d3d1a..c03acb4fceafa 100644 --- a/src/plugins/controls/public/react_controls/controls/data_controls/options_list_control/fetch_and_validate.tsx +++ b/src/plugins/controls/public/react_controls/controls/data_controls/options_list_control/fetch_and_validate.tsx @@ -55,6 +55,7 @@ export function fetchAndValidate$({ api.field$, api.controlFetch$, api.parentApi.allowExpensiveQueries$, + api.parentApi.ignoreParentSettings$, api.debouncedSearchString, stateManager.sort, stateManager.searchTechnique, @@ -86,6 +87,7 @@ export function fetchAndValidate$({ field, controlFetchContext, allowExpensiveQueries, + ignoreParentSettings, searchString, sort, searchTechnique, @@ -116,6 +118,7 @@ export function fetchAndValidate$({ field: field.toSpec(), size: requestSize, allowExpensiveQueries, + ignoreValidations: ignoreParentSettings?.ignoreValidations, ...controlFetchContext, }; diff --git a/src/plugins/controls/public/react_controls/controls/data_controls/options_list_control/options_list_fetch_cache.ts b/src/plugins/controls/public/react_controls/controls/data_controls/options_list_control/options_list_fetch_cache.ts index 6a4bc779a61a2..4e6e0aa779b48 100644 --- a/src/plugins/controls/public/react_controls/controls/data_controls/options_list_control/options_list_fetch_cache.ts +++ b/src/plugins/controls/public/react_controls/controls/data_controls/options_list_control/options_list_fetch_cache.ts @@ -51,6 +51,7 @@ export class OptionsListFetchCache { runPastTimeout, selectedOptions, searchTechnique, + ignoreValidations, field: { name: fieldName }, dataView: { title: dataViewTitle }, } = request; @@ -67,6 +68,7 @@ export class OptionsListFetchCache { query, sort, searchTechnique, + ignoreValidations, runPastTimeout, dataViewTitle, searchString: searchString ?? '', diff --git a/src/plugins/controls/server/options_list/options_list_suggestions_route.ts b/src/plugins/controls/server/options_list/options_list_suggestions_route.ts index b31c4feb6bf0f..abe6cb536289b 100644 --- a/src/plugins/controls/server/options_list/options_list_suggestions_route.ts +++ b/src/plugins/controls/server/options_list/options_list_suggestions_route.ts @@ -48,6 +48,7 @@ export const setupOptionsListSuggestionsRoute = ( filters: schema.maybe(schema.any()), fieldSpec: schema.maybe(schema.any()), allowExpensiveQueries: schema.boolean(), + ignoreValidations: schema.maybe(schema.boolean()), searchString: schema.maybe(schema.string()), searchTechnique: schema.maybe( schema.oneOf([ @@ -102,7 +103,7 @@ export const setupOptionsListSuggestionsRoute = ( /** * Build ES Query */ - const { runPastTimeout, filters, runtimeFieldMap } = request; + const { runPastTimeout, filters, runtimeFieldMap, ignoreValidations } = request; const { terminateAfter, timeout } = getAutocompleteSettings(); const timeoutSettings = runPastTimeout ? {} @@ -112,7 +113,9 @@ export const setupOptionsListSuggestionsRoute = ( const validationBuilder = getValidationAggregationBuilder(); const suggestionAggregation: any = suggestionBuilder.buildAggregation(request) ?? {}; - const validationAggregation: any = validationBuilder.buildAggregation(request); + const validationAggregation: any = ignoreValidations + ? {} + : validationBuilder.buildAggregation(request); const body: SearchRequest['body'] = { size: 0, @@ -141,7 +144,9 @@ export const setupOptionsListSuggestionsRoute = ( */ const results = suggestionBuilder.parse(rawEsResult, request); const totalCardinality = results.totalCardinality; - const invalidSelections = validationBuilder.parse(rawEsResult, request); + const invalidSelections = ignoreValidations + ? [] + : validationBuilder.parse(rawEsResult, request); return { suggestions: results.suggestions, diff --git a/src/plugins/dashboard/common/content_management/v1/index.ts b/src/plugins/dashboard/common/content_management/v1/index.ts index 4fb96a584691e..72271a64a3e57 100644 --- a/src/plugins/dashboard/common/content_management/v1/index.ts +++ b/src/plugins/dashboard/common/content_management/v1/index.ts @@ -13,10 +13,3 @@ export type { DashboardAttributes, SavedDashboardPanel, } from './types'; - -export { - serviceDefinition, - dashboardSavedObjectSchema, - controlGroupInputSchema, - dashboardAttributesSchema, -} from './cm_services'; diff --git a/src/plugins/dashboard/common/content_management/v2/index.ts b/src/plugins/dashboard/common/content_management/v2/index.ts index 15105c60d5aba..27ba4a2c2ef61 100644 --- a/src/plugins/dashboard/common/content_management/v2/index.ts +++ b/src/plugins/dashboard/common/content_management/v2/index.ts @@ -6,11 +6,5 @@ * Side Public License, v 1. */ -export { - serviceDefinition, - dashboardSavedObjectSchema, - dashboardAttributesSchema, -} from './cm_services'; - export type { GridData, DashboardItem, SavedDashboardPanel } from '../v1/types'; // no changes made to types from v1 to v2 export type { DashboardCrudTypes, DashboardAttributes } from './types'; diff --git a/src/plugins/dashboard/common/content_management/v2/types.ts b/src/plugins/dashboard/common/content_management/v2/types.ts index dcb45f9b44c54..3ecee5fe8f43e 100644 --- a/src/plugins/dashboard/common/content_management/v2/types.ts +++ b/src/plugins/dashboard/common/content_management/v2/types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { +import type { ContentManagementCrudTypes, SavedObjectCreateOptions, SavedObjectUpdateOptions, diff --git a/src/plugins/dashboard/public/dashboard_container/component/settings/settings_flyout.tsx b/src/plugins/dashboard/public/dashboard_container/component/settings/settings_flyout.tsx index 339d4d4bda10b..750056691cfb5 100644 --- a/src/plugins/dashboard/public/dashboard_container/component/settings/settings_flyout.tsx +++ b/src/plugins/dashboard/public/dashboard_container/component/settings/settings_flyout.tsx @@ -24,6 +24,8 @@ import { EuiTitle, EuiCallOut, EuiSwitch, + EuiText, + EuiIconTip, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { DashboardContainerInput } from '../../../../common'; @@ -269,12 +271,47 @@ export const DashboardSettings = ({ onClose }: DashboardSettingsProps) => { <> + {i18n.translate( + 'dashboard.embeddableApi.showSettings.flyout.form.syncColorsBetweenPanelsSwitchLabel', + { + defaultMessage: 'Sync color palettes across panels', + } + )}{' '} + + {i18n.translate('dashboard.palettes.defaultPaletteLabel', { + defaultMessage: 'Default', + })} + + ), + compatibility: ( + + {i18n.translate('dashboard.palettes.kibanaPaletteLabel', { + defaultMessage: 'Compatibility', + })} + + ), + }} + /> + } + iconProps={{ + className: 'eui-alignTop', + }} + position="top" + size="s" + type="questionInCircle" + /> + + } checked={dashboardSettingsState.syncColors} onChange={(event) => updateDashboardSetting({ syncColors: event.target.checked })} data-test-subj="dashboardSyncColorsCheckbox" diff --git a/src/plugins/dashboard/server/content_management/dashboard_storage.ts b/src/plugins/dashboard/server/content_management/dashboard_storage.ts index 4391aeaa90563..e9b5479dea90c 100644 --- a/src/plugins/dashboard/server/content_management/dashboard_storage.ts +++ b/src/plugins/dashboard/server/content_management/dashboard_storage.ts @@ -11,7 +11,7 @@ import { SavedObjectsFindOptions } from '@kbn/core-saved-objects-api-server'; import type { Logger } from '@kbn/logging'; import { CONTENT_ID } from '../../common/content_management'; -import { cmServicesDefinition } from '../../common/content_management/cm_services'; +import { cmServicesDefinition } from './schema/cm_services'; import type { DashboardCrudTypes } from '../../common/content_management'; const searchArgsToSOFindOptions = ( diff --git a/src/plugins/dashboard/common/content_management/cm_services.ts b/src/plugins/dashboard/server/content_management/schema/cm_services.ts similarity index 100% rename from src/plugins/dashboard/common/content_management/cm_services.ts rename to src/plugins/dashboard/server/content_management/schema/cm_services.ts diff --git a/src/plugins/dashboard/common/content_management/v1/cm_services.ts b/src/plugins/dashboard/server/content_management/schema/v1/cm_services.ts similarity index 100% rename from src/plugins/dashboard/common/content_management/v1/cm_services.ts rename to src/plugins/dashboard/server/content_management/schema/v1/cm_services.ts diff --git a/src/plugins/dashboard/server/content_management/schema/v1/index.ts b/src/plugins/dashboard/server/content_management/schema/v1/index.ts new file mode 100644 index 0000000000000..3e4684ab64cfb --- /dev/null +++ b/src/plugins/dashboard/server/content_management/schema/v1/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { + serviceDefinition, + dashboardSavedObjectSchema, + controlGroupInputSchema, + dashboardAttributesSchema, +} from './cm_services'; diff --git a/src/plugins/dashboard/common/content_management/v2/cm_services.ts b/src/plugins/dashboard/server/content_management/schema/v2/cm_services.ts similarity index 100% rename from src/plugins/dashboard/common/content_management/v2/cm_services.ts rename to src/plugins/dashboard/server/content_management/schema/v2/cm_services.ts diff --git a/src/plugins/dashboard/server/content_management/schema/v2/index.ts b/src/plugins/dashboard/server/content_management/schema/v2/index.ts new file mode 100644 index 0000000000000..b20dfef423801 --- /dev/null +++ b/src/plugins/dashboard/server/content_management/schema/v2/index.ts @@ -0,0 +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 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 { + serviceDefinition, + dashboardSavedObjectSchema, + dashboardAttributesSchema, +} from './cm_services'; diff --git a/src/plugins/dashboard/server/dashboard_saved_object/dashboard_saved_object.ts b/src/plugins/dashboard/server/dashboard_saved_object/dashboard_saved_object.ts index 2cf913919b912..688dce1d0687d 100644 --- a/src/plugins/dashboard/server/dashboard_saved_object/dashboard_saved_object.ts +++ b/src/plugins/dashboard/server/dashboard_saved_object/dashboard_saved_object.ts @@ -9,8 +9,8 @@ import { ANALYTICS_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; import { SavedObjectsType } from '@kbn/core/server'; -import { dashboardAttributesSchema as dashboardAttributesSchemaV1 } from '../../common/content_management/v1'; -import { dashboardAttributesSchema as dashboardAttributesSchemaV2 } from '../../common/content_management/v2'; +import { dashboardAttributesSchema as dashboardAttributesSchemaV1 } from '../content_management/schema/v1'; +import { dashboardAttributesSchema as dashboardAttributesSchemaV2 } from '../content_management/schema/v2'; import { createDashboardSavedObjectTypeMigrations, DashboardSavedObjectTypeMigrationsDeps, diff --git a/src/plugins/data/common/search/expressions/esql.ts b/src/plugins/data/common/search/expressions/esql.ts index d7af8ac5ffed1..34ac9a1ccffc5 100644 --- a/src/plugins/data/common/search/expressions/esql.ts +++ b/src/plugins/data/common/search/expressions/esql.ts @@ -9,22 +9,32 @@ import type { KibanaRequest } from '@kbn/core/server'; import { esFieldTypeToKibanaFieldType } from '@kbn/field-types'; import { i18n } from '@kbn/i18n'; -import type { IKibanaSearchResponse, IKibanaSearchRequest } from '@kbn/search-types'; +import type { + IKibanaSearchRequest, + IKibanaSearchResponse, + ISearchGeneric, +} from '@kbn/search-types'; import type { Datatable, ExpressionFunctionDefinition } from '@kbn/expressions-plugin/common'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; import { getStartEndParams } from '@kbn/esql-utils'; - import { zipObject } from 'lodash'; -import { Observable, defer, throwError } from 'rxjs'; -import { catchError, map, switchMap, tap } from 'rxjs'; -import { buildEsQuery } from '@kbn/es-query'; -import type { ISearchGeneric } from '@kbn/search-types'; -import type { ESQLSearchResponse, ESQLSearchParams } from '@kbn/es-types'; +import { catchError, defer, map, Observable, switchMap, tap, throwError } from 'rxjs'; +import { buildEsQuery, type Filter } from '@kbn/es-query'; +import type { ESQLSearchParams, ESQLSearchResponse } from '@kbn/es-types'; import { getEsQueryConfig } from '../../es_query'; import { getTime } from '../../query'; -import { ESQL_ASYNC_SEARCH_STRATEGY, KibanaContext, ESQL_TABLE_TYPE } from '..'; +import { ESQL_ASYNC_SEARCH_STRATEGY, ESQL_TABLE_TYPE, KibanaContext } from '..'; import { UiSettingsCommon } from '../..'; +declare global { + interface Window { + /** + * Debug setting to make requests complete slower than normal. Only available on snapshots where `error_query` is enabled in ES. + */ + ELASTIC_ESQL_DELAY_SECONDS?: number; + } +} + type Input = KibanaContext | null; type Output = Observable; @@ -166,12 +176,31 @@ export const getEsqlFn = ({ getStartDependencies }: EsqlFnArguments) => { fieldName: timeField, }); - params.filter = buildEsQuery( - undefined, - input.query || [], - [...(input.filters ?? []), ...(timeFilter ? [timeFilter] : [])], - esQueryConfigs - ); + // Used for debugging & inside automated tests to simulate a slow query + const delayFilter: Filter | undefined = window.ELASTIC_ESQL_DELAY_SECONDS + ? { + meta: {}, + query: { + error_query: { + indices: [ + { + name: '*', + error_type: 'warning', + stall_time_seconds: window.ELASTIC_ESQL_DELAY_SECONDS, + }, + ], + }, + }, + } + : undefined; + + const filters = [ + ...(input.filters ?? []), + ...(timeFilter ? [timeFilter] : []), + ...(delayFilter ? [delayFilter] : []), + ]; + + params.filter = buildEsQuery(undefined, input.query || [], filters, esQueryConfigs); } let startTime = Date.now(); diff --git a/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx b/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx index 98897ed4472de..22ed26e702eb4 100644 --- a/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx +++ b/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx @@ -196,7 +196,7 @@ const IndexPatternEditorFlyoutContentComponent = ({ const getRollupIndices = (rollupCaps: RollupIndicesCapsResponse) => Object.keys(rollupCaps); const onTypeChange = useCallback( - (newType) => { + (newType: INDEX_PATTERN_TYPE) => { form.setFieldValue('title', ''); form.setFieldValue('name', ''); form.setFieldValue('timestampField', ''); diff --git a/src/plugins/data_views/server/content_management/data_views_storage.ts b/src/plugins/data_views/server/content_management/data_views_storage.ts index bb01064d59956..c0f7f287a7f92 100644 --- a/src/plugins/data_views/server/content_management/data_views_storage.ts +++ b/src/plugins/data_views/server/content_management/data_views_storage.ts @@ -11,7 +11,7 @@ import type { Logger } from '@kbn/logging'; import type { DataViewCrudTypes } from '../../common/content_management'; import { DataViewSOType } from '../../common/content_management'; -import { cmServicesDefinition } from '../../common/content_management/cm_services'; +import { cmServicesDefinition } from './schema/cm_services'; export class DataViewsStorage extends SOContentStorage { constructor({ diff --git a/src/plugins/data_views/common/content_management/cm_services.ts b/src/plugins/data_views/server/content_management/schema/cm_services.ts similarity index 100% rename from src/plugins/data_views/common/content_management/cm_services.ts rename to src/plugins/data_views/server/content_management/schema/cm_services.ts diff --git a/src/plugins/data_views/common/content_management/v1/cm_services.ts b/src/plugins/data_views/server/content_management/schema/v1/cm_services.ts similarity index 95% rename from src/plugins/data_views/common/content_management/v1/cm_services.ts rename to src/plugins/data_views/server/content_management/schema/v1/cm_services.ts index 7b70a4c103457..71e73135b5e59 100644 --- a/src/plugins/data_views/common/content_management/v1/cm_services.ts +++ b/src/plugins/data_views/server/content_management/schema/v1/cm_services.ts @@ -16,9 +16,9 @@ import { createResultSchema, searchOptionsSchemas, } from '@kbn/content-management-utils'; -import { DataViewType } from '../..'; -import { MAX_DATA_VIEW_FIELD_DESCRIPTION_LENGTH } from '../../constants'; -import { serializedFieldFormatSchema, fieldSpecSchema } from '../../schemas'; +import { DataViewType } from '../../../../common'; +import { MAX_DATA_VIEW_FIELD_DESCRIPTION_LENGTH } from '../../../../common/constants'; +import { serializedFieldFormatSchema, fieldSpecSchema } from '../../../schemas'; const dataViewAttributesSchema = schema.object( { diff --git a/src/plugins/data_views/server/rest_api_routes/public/fields/update_fields.ts b/src/plugins/data_views/server/rest_api_routes/public/fields/update_fields.ts index a8d2e7d0a5247..2ef80e8cbf68d 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/fields/update_fields.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/fields/update_fields.ts @@ -12,7 +12,7 @@ import { IRouter, StartServicesAccessor } from '@kbn/core/server'; import { SerializedFieldFormat } from '@kbn/field-formats-plugin/common'; import { DataViewsService } from '../../../../common'; import { handleErrors } from '../util/handle_errors'; -import { serializedFieldFormatSchema } from '../../../../common/schemas'; +import { serializedFieldFormatSchema } from '../../../schemas'; import { MAX_DATA_VIEW_FIELD_DESCRIPTION_LENGTH } from '../../../../common/constants'; import { dataViewSpecSchema } from '../../schema'; import { DataViewSpecRestResponse } from '../../route_types'; diff --git a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/create_runtime_field.ts b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/create_runtime_field.ts index ff446f76c885a..49f928dd863a5 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/create_runtime_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/create_runtime_field.ts @@ -12,7 +12,7 @@ import { IRouter, StartServicesAccessor } from '@kbn/core/server'; import { DataViewsService } from '../../../../common/data_views'; import { RuntimeField } from '../../../../common/types'; import { handleErrors } from '../util/handle_errors'; -import { runtimeFieldSchema } from '../../../../common/schemas'; +import { runtimeFieldSchema } from '../../../schemas'; import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies, diff --git a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/put_runtime_field.ts b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/put_runtime_field.ts index 7105d8ea8413b..30076183ce6e8 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/put_runtime_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/put_runtime_field.ts @@ -12,7 +12,7 @@ import { IRouter, StartServicesAccessor } from '@kbn/core/server'; import { DataViewsService } from '../../../../common/data_views'; import { RuntimeField } from '../../../../common/types'; import { handleErrors } from '../util/handle_errors'; -import { runtimeFieldSchema } from '../../../../common/schemas'; +import { runtimeFieldSchema } from '../../../schemas'; import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies, diff --git a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/update_runtime_field.ts b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/update_runtime_field.ts index 485551c866eef..85887582804ad 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/update_runtime_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/update_runtime_field.ts @@ -13,7 +13,7 @@ import { DataViewsService } from '../../../../common/data_views'; import { RuntimeField } from '../../../../common/types'; import { ErrorIndexPatternFieldNotFound } from '../../../error'; import { handleErrors } from '../util/handle_errors'; -import { runtimeFieldSchemaUpdate } from '../../../../common/schemas'; +import { runtimeFieldSchemaUpdate } from '../../../schemas'; import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies, diff --git a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/create_scripted_field.ts b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/create_scripted_field.ts index ed6716b1684ba..6ed3bbf5e84d0 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/create_scripted_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/create_scripted_field.ts @@ -9,7 +9,7 @@ import { schema } from '@kbn/config-schema'; import { IRouter, StartServicesAccessor } from '@kbn/core/server'; import { handleErrors } from '../util/handle_errors'; -import { fieldSpecSchema } from '../../../../common/schemas'; +import { fieldSpecSchema } from '../../../schemas'; import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies, diff --git a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/get_scripted_field.ts b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/get_scripted_field.ts index 7023fba31b589..d5083b01070ba 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/get_scripted_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/get_scripted_field.ts @@ -15,7 +15,7 @@ import type { DataViewsServerPluginStartDependencies, } from '../../../types'; import { INITIAL_REST_VERSION } from '../../../constants'; -import { fieldSpecSchemaFields } from '../../../../common/schemas'; +import { fieldSpecSchemaFields } from '../../../schemas'; import { FieldSpecRestResponse } from '../../route_types'; export const registerGetScriptedFieldRoute = ( diff --git a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/put_scripted_field.ts b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/put_scripted_field.ts index 20e828009f2a1..00875773a8049 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/put_scripted_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/put_scripted_field.ts @@ -9,7 +9,7 @@ import { schema } from '@kbn/config-schema'; import { IRouter, StartServicesAccessor } from '@kbn/core/server'; import { handleErrors } from '../util/handle_errors'; -import { fieldSpecSchema } from '../../../../common/schemas'; +import { fieldSpecSchema } from '../../../schemas'; import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies, diff --git a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/update_scripted_field.ts b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/update_scripted_field.ts index 53e9d165814b5..9589c1c9e7a8d 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/update_scripted_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/update_scripted_field.ts @@ -11,7 +11,7 @@ import { IRouter, StartServicesAccessor } from '@kbn/core/server'; import { FieldSpec } from '../../../../common'; import { ErrorIndexPatternFieldNotFound } from '../../../error'; import { handleErrors } from '../util/handle_errors'; -import { fieldSpecSchemaFields } from '../../../../common/schemas'; +import { fieldSpecSchemaFields } from '../../../schemas'; import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies, diff --git a/src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts b/src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts index 0c7c66a0a1fec..ad830c7c809f2 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts @@ -13,11 +13,7 @@ import { DataViewSpecRestResponse } from '../route_types'; import { DataViewsService } from '../../../common/data_views'; import { DataViewSpec } from '../../../common/types'; import { handleErrors } from './util/handle_errors'; -import { - fieldSpecSchema, - runtimeFieldSchema, - serializedFieldFormatSchema, -} from '../../../common/schemas'; +import { fieldSpecSchema, runtimeFieldSchema, serializedFieldFormatSchema } from '../../schemas'; import { dataViewSpecSchema } from '../schema'; import type { DataViewsServerPluginStartDependencies, diff --git a/src/plugins/data_views/server/rest_api_routes/schema.ts b/src/plugins/data_views/server/rest_api_routes/schema.ts index c4f4a4c70b826..f9518ca8099b2 100644 --- a/src/plugins/data_views/server/rest_api_routes/schema.ts +++ b/src/plugins/data_views/server/rest_api_routes/schema.ts @@ -14,7 +14,7 @@ import { runtimeFieldSchema, serializedFieldFormatSchema, fieldSpecSchemaFields, -} from '../../common/schemas'; +} from '../schemas'; import { MAX_DATA_VIEW_FIELD_DESCRIPTION_LENGTH } from '../../common/constants'; export const dataViewSpecSchema = schema.object({ diff --git a/src/plugins/data_views/common/schemas.ts b/src/plugins/data_views/server/schemas.ts similarity index 97% rename from src/plugins/data_views/common/schemas.ts rename to src/plugins/data_views/server/schemas.ts index b780118414044..1eae6d09ee7de 100644 --- a/src/plugins/data_views/common/schemas.ts +++ b/src/plugins/data_views/server/schemas.ts @@ -7,8 +7,8 @@ */ import { schema, Type } from '@kbn/config-schema'; -import { MAX_DATA_VIEW_FIELD_DESCRIPTION_LENGTH } from './constants'; -import { RuntimeType } from '.'; +import { MAX_DATA_VIEW_FIELD_DESCRIPTION_LENGTH } from '../common/constants'; +import { RuntimeType } from '../common'; export const serializedFieldFormatSchema = schema.object({ id: schema.maybe(schema.string()), diff --git a/src/plugins/discover/public/application/context/context_app_content.tsx b/src/plugins/discover/public/application/context/context_app_content.tsx index 4d6d815fd796b..e0f0dbbd820cb 100644 --- a/src/plugins/discover/public/application/context/context_app_content.tsx +++ b/src/plugins/discover/public/application/context/context_app_content.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import React, { Fragment, useCallback, useMemo, useState, FC, PropsWithChildren } from 'react'; +import React, { Fragment, useCallback, useMemo, useState, FC } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiSpacer, EuiText, useEuiPaddingSize } from '@elastic/eui'; import { css } from '@emotion/react'; @@ -241,7 +241,7 @@ export function ContextAppContent({ ); } -const WrapperWithPadding: FC> = ({ children }) => { +const WrapperWithPadding: FC = ({ children }) => { const padding = useEuiPaddingSize('s'); return ( diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx index fa8128c0b95ec..ac71b1a437038 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx @@ -250,7 +250,7 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) // As unifiedFieldListSidebarContainerRef ref can be empty in the beginning, // we need to fetch the data once API becomes available and after documents are fetched const initializeUnifiedFieldListSidebarContainerApi = useCallback( - (api) => { + (api: UnifiedFieldListSidebarContainerApi) => { if (!api) { return; } diff --git a/src/plugins/es_ui_shared/static/forms/components/fields/select_field.tsx b/src/plugins/es_ui_shared/static/forms/components/fields/select_field.tsx index b09215146a59b..3794f605e4e64 100644 --- a/src/plugins/es_ui_shared/static/forms/components/fields/select_field.tsx +++ b/src/plugins/es_ui_shared/static/forms/components/fields/select_field.tsx @@ -11,7 +11,7 @@ import { EuiFormRow, EuiSelect } from '@elastic/eui'; import { FieldHook, getFieldValidityAndErrorMessage } from '../../hook_form_lib'; -interface Props { +export interface Props { field: FieldHook; euiFieldProps: { options: Array< diff --git a/src/plugins/event_annotation/common/content_management/v1/types.ts b/src/plugins/event_annotation/common/content_management/v1/types.ts index d85250e3883fa..6e2ee48e010f9 100644 --- a/src/plugins/event_annotation/common/content_management/v1/types.ts +++ b/src/plugins/event_annotation/common/content_management/v1/types.ts @@ -18,7 +18,7 @@ import { CreateResult, UpdateResult, } from '@kbn/content-management-plugin/common'; -import { ContentManagementCrudTypes } from '@kbn/content-management-utils'; +import type { ContentManagementCrudTypes } from '@kbn/content-management-utils'; import type { DataViewSpec } from '@kbn/data-views-plugin/common'; import type { EventAnnotationConfig } from '@kbn/event-annotation-common'; diff --git a/src/plugins/event_annotation/server/content_management/event_annotation_group_storage.ts b/src/plugins/event_annotation/server/content_management/event_annotation_group_storage.ts index 49a5b516c1d24..ea92e9ac0fa10 100644 --- a/src/plugins/event_annotation/server/content_management/event_annotation_group_storage.ts +++ b/src/plugins/event_annotation/server/content_management/event_annotation_group_storage.ts @@ -9,7 +9,7 @@ import { SOContentStorage } from '@kbn/content-management-utils'; import { EVENT_ANNOTATION_GROUP_TYPE } from '@kbn/event-annotation-common'; import { Logger } from '@kbn/logging'; -import { cmServicesDefinition } from '../../common/content_management/cm_services'; +import { cmServicesDefinition } from './schema/cm_services'; import type { EventAnnotationGroupCrudTypes } from '../../common/content_management'; export class EventAnnotationGroupStorage extends SOContentStorage { diff --git a/src/plugins/event_annotation/common/content_management/cm_services.ts b/src/plugins/event_annotation/server/content_management/schema/cm_services.ts similarity index 100% rename from src/plugins/event_annotation/common/content_management/cm_services.ts rename to src/plugins/event_annotation/server/content_management/schema/cm_services.ts diff --git a/src/plugins/event_annotation/common/content_management/v1/cm_services.ts b/src/plugins/event_annotation/server/content_management/schema/v1/cm_services.ts similarity index 100% rename from src/plugins/event_annotation/common/content_management/v1/cm_services.ts rename to src/plugins/event_annotation/server/content_management/schema/v1/cm_services.ts diff --git a/src/plugins/field_formats/public/lib/converters/_string.scss b/src/plugins/field_formats/public/lib/converters/_string.scss index 9d97f0195780c..dd27bded25083 100644 --- a/src/plugins/field_formats/public/lib/converters/_string.scss +++ b/src/plugins/field_formats/public/lib/converters/_string.scss @@ -1,3 +1,7 @@ .ffString__emptyValue { color: $euiColorDarkShade; } + +.lnsTableCell--colored .ffString__emptyValue { + color: unset; +} diff --git a/src/plugins/interactive_setup/server/verification_code.ts b/src/plugins/interactive_setup/server/verification_code.ts index d14cdb85e0204..47c3ba73c174d 100644 --- a/src/plugins/interactive_setup/server/verification_code.ts +++ b/src/plugins/interactive_setup/server/verification_code.ts @@ -69,20 +69,24 @@ Your verification code is: ${highlightedCode} /** * Returns a cryptographically secure and random 6-digit code. - * - * Implementation notes: `secureRandomNumber` returns a random number like `0.05505769583xxxx`. To - * turn that into a 6 digit code we multiply it by `10^6` and result is `055057`. */ private static generate(length: number) { - return Math.floor(secureRandomNumber() * Math.pow(10, length)) - .toString() - .padStart(length, '0'); + return secureRandomNumber(length).join(''); } } /** * Cryptographically secure equivalent of `Math.random()`. */ -function secureRandomNumber() { - return crypto.randomBytes(4).readUInt32LE() / 0x100000000; +function secureRandomNumber(length: number) { + const digits = []; + while (digits.length < length) { + const byte = crypto.randomBytes(1)[0]; + if (byte >= 250) { + continue; + } + digits.push(byte % 10); + } + + return digits; } diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts index 3a8c0b9b6076a..8bc81a6f1d497 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts @@ -487,10 +487,6 @@ export const stackManagementSchema: MakeSchemaFrom = { type: 'keyword', _meta: { description: 'Non-default value of setting.' }, }, - 'observability:aiAssistantResponseLanguage': { - type: 'keyword', - _meta: { description: 'Non-default value of setting.' }, - }, 'observability:aiAssistantSimulatedFunctionCalling': { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts index 92e507ebef855..9821fd1bad43f 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts @@ -55,7 +55,6 @@ export interface UsageStats { 'observability:logsExplorer:allowedDataViews': string[]; 'observability:logSources': string[]; 'observability:aiAssistantLogsIndexPattern': string; - 'observability:aiAssistantResponseLanguage': string; 'observability:aiAssistantSimulatedFunctionCalling': boolean; 'observability:aiAssistantSearchConnectorIndexPattern': string; 'visualization:heatmap:maxBuckets': number; diff --git a/src/plugins/links/common/persistable_state/references.ts b/src/plugins/links/common/persistable_state/references.ts index 3c527465a2868..93dc152949289 100644 --- a/src/plugins/links/common/persistable_state/references.ts +++ b/src/plugins/links/common/persistable_state/references.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { Reference } from '@kbn/content-management-utils'; +import type { Reference } from '@kbn/content-management-utils'; import { omit } from 'lodash'; import { DASHBOARD_LINK_TYPE, LinksAttributes } from '../content_management'; diff --git a/src/plugins/links/public/components/dashboard_link/dashboard_link_destination_picker.tsx b/src/plugins/links/public/components/dashboard_link/dashboard_link_destination_picker.tsx index 8868dd1a2776a..30bd3d3879da9 100644 --- a/src/plugins/links/public/components/dashboard_link/dashboard_link_destination_picker.tsx +++ b/src/plugins/links/public/components/dashboard_link/dashboard_link_destination_picker.tsx @@ -94,7 +94,7 @@ export const DashboardLinkDestinationPicker = ({ ); const renderOption = useCallback( - (option, searchValue, contentClassName) => { + (option: DashboardComboBoxOption, searchValue: string, contentClassName: string) => { const { label, key: dashboardId } = option; return ( diff --git a/src/plugins/links/public/components/editor/links_editor.tsx b/src/plugins/links/public/components/editor/links_editor.tsx index 0ee31cd841521..ac8879d1dd850 100644 --- a/src/plugins/links/public/components/editor/links_editor.tsx +++ b/src/plugins/links/public/components/editor/links_editor.tsx @@ -10,6 +10,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import useMountedState from 'react-use/lib/useMountedState'; import { + DropResult, EuiButton, EuiButtonEmpty, EuiButtonGroup, @@ -101,7 +102,7 @@ const LinksEditor = ({ }, [initialLinks]); const onDragEnd = useCallback( - ({ source, destination }) => { + ({ source, destination }: DropResult) => { if (source && destination) { const newList = euiDragDropReorder(orderedLinks, source.index, destination.index).map( (link, i) => { diff --git a/src/plugins/links/public/lib/deserialize_from_library.ts b/src/plugins/links/public/lib/deserialize_from_library.ts index 859a988954a1b..2640540b6e49c 100644 --- a/src/plugins/links/public/lib/deserialize_from_library.ts +++ b/src/plugins/links/public/lib/deserialize_from_library.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { SOWithMetadata } from '@kbn/content-management-utils'; +import type { SOWithMetadata } from '@kbn/content-management-utils'; import { LinksAttributes } from '../../common/content_management'; import { injectReferences } from '../../common/persistable_state'; import { LinksByReferenceSerializedState, LinksRuntimeState, LinksSerializedState } from '../types'; diff --git a/src/plugins/links/server/content_management/links_storage.ts b/src/plugins/links/server/content_management/links_storage.ts index 21a5e4aa0de0d..ca403efcd099e 100644 --- a/src/plugins/links/server/content_management/links_storage.ts +++ b/src/plugins/links/server/content_management/links_storage.ts @@ -10,7 +10,7 @@ import type { Logger } from '@kbn/logging'; import { SOContentStorage } from '@kbn/content-management-utils'; import { CONTENT_ID } from '../../common'; import type { LinksCrudTypes } from '../../common/content_management'; -import { cmServicesDefinition } from '../../common/content_management/cm_services'; +import { cmServicesDefinition } from './schema/cm_services'; export class LinksStorage extends SOContentStorage { constructor({ diff --git a/src/plugins/links/common/content_management/cm_services.ts b/src/plugins/links/server/content_management/schema/cm_services.ts similarity index 100% rename from src/plugins/links/common/content_management/cm_services.ts rename to src/plugins/links/server/content_management/schema/cm_services.ts diff --git a/src/plugins/links/common/content_management/v1/cm_services.ts b/src/plugins/links/server/content_management/schema/v1/cm_services.ts similarity index 93% rename from src/plugins/links/common/content_management/v1/cm_services.ts rename to src/plugins/links/server/content_management/schema/v1/cm_services.ts index 597fcfe0d8451..16a8b1209b22b 100644 --- a/src/plugins/links/common/content_management/v1/cm_services.ts +++ b/src/plugins/links/server/content_management/schema/v1/cm_services.ts @@ -15,8 +15,11 @@ import { createOptionsSchemas, objectTypeToGetResultSchema, } from '@kbn/content-management-utils'; -import { DASHBOARD_LINK_TYPE, EXTERNAL_LINK_TYPE } from '.'; -import { LINKS_HORIZONTAL_LAYOUT, LINKS_VERTICAL_LAYOUT } from './constants'; +import { DASHBOARD_LINK_TYPE, EXTERNAL_LINK_TYPE } from '../../../../common/content_management/v1'; +import { + LINKS_HORIZONTAL_LAYOUT, + LINKS_VERTICAL_LAYOUT, +} from '../../../../common/content_management/v1/constants'; const baseLinkSchema = { id: schema.string(), diff --git a/src/plugins/saved_search/server/content_management/saved_search_storage.ts b/src/plugins/saved_search/server/content_management/saved_search_storage.ts index 3982bca7cf932..de17c9e9cf5de 100644 --- a/src/plugins/saved_search/server/content_management/saved_search_storage.ts +++ b/src/plugins/saved_search/server/content_management/saved_search_storage.ts @@ -11,7 +11,7 @@ import type { Logger } from '@kbn/logging'; import type { SavedSearchCrudTypes } from '../../common/content_management'; import { SavedSearchType } from '../../common/content_management'; -import { cmServicesDefinition } from '../../common/content_management/cm_services'; +import { cmServicesDefinition } from './schema/cm_services'; export class SavedSearchStorage extends SOContentStorage { constructor({ diff --git a/src/plugins/saved_search/common/content_management/cm_services.ts b/src/plugins/saved_search/server/content_management/schema/cm_services.ts similarity index 100% rename from src/plugins/saved_search/common/content_management/cm_services.ts rename to src/plugins/saved_search/server/content_management/schema/cm_services.ts diff --git a/src/plugins/saved_search/common/content_management/v1/cm_services.ts b/src/plugins/saved_search/server/content_management/schema/v1/cm_services.ts similarity index 97% rename from src/plugins/saved_search/common/content_management/v1/cm_services.ts rename to src/plugins/saved_search/server/content_management/schema/v1/cm_services.ts index 7a3f8eb6d5e9d..53df9882afd70 100644 --- a/src/plugins/saved_search/common/content_management/v1/cm_services.ts +++ b/src/plugins/saved_search/server/content_management/schema/v1/cm_services.ts @@ -15,7 +15,10 @@ import { updateOptionsSchema, createResultSchema, } from '@kbn/content-management-utils'; -import { MIN_SAVED_SEARCH_SAMPLE_SIZE, MAX_SAVED_SEARCH_SAMPLE_SIZE } from '../../constants'; +import { + MIN_SAVED_SEARCH_SAMPLE_SIZE, + MAX_SAVED_SEARCH_SAMPLE_SIZE, +} from '../../../../common/constants'; const sortSchema = schema.arrayOf(schema.string(), { maxSize: 2 }); diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index ebd98b2190c12..8563b5beaf57c 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -10456,12 +10456,6 @@ "description": "Non-default value of setting." } }, - "observability:aiAssistantResponseLanguage": { - "type": "keyword", - "_meta": { - "description": "Non-default value of setting." - } - }, "observability:aiAssistantSimulatedFunctionCalling": { "type": "boolean", "_meta": { diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview_degraded_fields.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview_degraded_fields.tsx index 976ef71c6b647..2ff0d6a224af2 100644 --- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview_degraded_fields.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview_degraded_fields.tsx @@ -23,7 +23,10 @@ import { import { i18n } from '@kbn/i18n'; import { orderBy } from 'lodash'; import { getRouterLinkProps } from '@kbn/router-utils'; -import { DATA_QUALITY_LOCATOR_ID, DataQualityLocatorParams } from '@kbn/deeplinks-observability'; +import { + DATA_QUALITY_DETAILS_LOCATOR_ID, + DataQualityDetailsLocatorParams, +} from '@kbn/deeplinks-observability'; import { BrowserUrlService } from '@kbn/share-plugin/public'; import { getUnifiedDocViewerServices } from '../../plugin'; @@ -39,13 +42,6 @@ interface DegradedField { values: string[]; } -interface ParamsForLocator { - dataStreamType: string; - dataStreamName: string; - dataStreamNamespace: string; - rawName: string; -} - interface TableOptions { page: { index: number; @@ -117,7 +113,7 @@ export const LogsOverviewDegradedFields = ({ rawDoc }: { rawDoc: DataTableRecord const columns = getDegradedFieldsColumns(); const tableData = getDataFormattedForTable(ignoredFieldValues); - const paramsForLocator = getParamsForLocator(sourceFields); + const dataStream = getDataStreamRawName(sourceFields); const accordionId = useGeneratedHtmlId({ prefix: qualityIssuesAccordionTitle, @@ -194,9 +190,7 @@ export const LogsOverviewDegradedFields = ({ rawDoc }: { rawDoc: DataTableRecord buttonContent={accordionTitle} paddingSize="m" initialIsOpen={false} - extraAction={ - - } + extraAction={} data-test-subj="unifiedDocViewLogsOverviewDegradedFieldsAccordion" > { +): string | undefined => { if (sourceFields) { const dataStreamTypeArr = sourceFields['data_stream.type']; const dataStreamType = dataStreamTypeArr ? dataStreamTypeArr[0] : undefined; @@ -256,49 +250,35 @@ const getParamsForLocator = ( const dataStreamName = dataStreamNameArr ? dataStreamNameArr[0] : undefined; const dataStreamNamespaceArr = sourceFields['data_stream.namespace']; const dataStreamNamespace = dataStreamNamespaceArr ? dataStreamNamespaceArr[0] : undefined; - let rawName; + let dataStream; if (dataStreamType && dataStreamName && dataStreamNamespace) { - rawName = `${dataStreamType}-${dataStreamName}-${dataStreamNamespace}`; + dataStream = `${dataStreamType}-${dataStreamName}-${dataStreamNamespace}`; } - if (rawName) { - return { - dataStreamType, - dataStreamName, - dataStreamNamespace, - rawName, - }; - } + return dataStream; } }; const DatasetQualityLink = React.memo( ({ urlService, - paramsForLocator, + dataStream, }: { urlService: BrowserUrlService; - paramsForLocator?: ParamsForLocator; + dataStream: string | undefined; }) => { - const locator = urlService.locators.get(DATA_QUALITY_LOCATOR_ID); - const locatorParams: DataQualityLocatorParams = paramsForLocator - ? { - flyout: { - dataset: { - rawName: paramsForLocator.rawName, - type: paramsForLocator.dataStreamType, - name: paramsForLocator.dataStreamName, - namespace: paramsForLocator.dataStreamNamespace, - }, - }, - } - : {}; - - const datasetQualityUrl = locator?.getRedirectUrl(locatorParams); + if (!dataStream) { + return null; + } + const locator = urlService.locators.get( + DATA_QUALITY_DETAILS_LOCATOR_ID + ); + + const datasetQualityUrl = locator?.getRedirectUrl({ dataStream }); const navigateToDatasetQuality = () => { - locator?.navigate(locatorParams); + locator?.navigate({ dataStream }); }; const datasetQualityLinkProps = getRouterLinkProps({ @@ -306,7 +286,7 @@ const DatasetQualityLink = React.memo( onClick: navigateToDatasetQuality, }); - return paramsForLocator ? ( + return ( {datasetQualityLinkTitle} - ) : null; + ); } ); diff --git a/src/plugins/unified_histogram/public/chart/chart_config_panel.tsx b/src/plugins/unified_histogram/public/chart/chart_config_panel.tsx index 1c598d06a143c..00d1eee9bcba0 100644 --- a/src/plugins/unified_histogram/public/chart/chart_config_panel.tsx +++ b/src/plugins/unified_histogram/public/chart/chart_config_panel.tsx @@ -5,12 +5,13 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import React, { useCallback, useEffect, useRef, useState } from 'react'; +import React, { ComponentProps, useCallback, useEffect, useRef, useState } from 'react'; import type { Observable } from 'rxjs'; import type { AggregateQuery, Query } from '@kbn/es-query'; -import { isEqual } from 'lodash'; +import { isEqual, isObject } from 'lodash'; import type { LensEmbeddableOutput, Suggestion } from '@kbn/lens-plugin/public'; import type { Datatable } from '@kbn/expressions-plugin/common'; +import { EditLensConfigPanelComponent } from '@kbn/lens-plugin/public/plugin'; import { deriveLensSuggestionFromLensAttributes } from '../utils/external_vis_context'; import { @@ -49,13 +50,16 @@ export function ChartConfigPanel({ const previousAdapters = useRef | undefined>(undefined); const previousQuery = useRef(undefined); - const updatePanelState = useCallback( + const updatePanelState = useCallback< + ComponentProps['updatePanelState'] + >( (datasourceState, visualizationState, visualizationId) => { const updatedSuggestion: Suggestion = { - ...currentSuggestionContext?.suggestion, - visualizationId: visualizationId ?? currentSuggestionContext?.suggestion?.visualizationId, - ...(datasourceState && { datasourceState }), - ...(visualizationState && { visualizationState }), + ...currentSuggestionContext.suggestion!, + visualizationId: + visualizationId ?? currentSuggestionContext.suggestion?.visualizationId ?? '', + ...(isObject(datasourceState) && { datasourceState }), + ...(isObject(visualizationState) && { visualizationState }), }; onSuggestionContextEdit({ ...currentSuggestionContext, @@ -65,7 +69,9 @@ export function ChartConfigPanel({ [currentSuggestionContext, onSuggestionContextEdit] ); - const updateSuggestion = useCallback( + const updateSuggestion = useCallback< + NonNullable['updateSuggestion']> + >( (attributes) => { const updatedSuggestion = deriveLensSuggestionFromLensAttributes({ externalVisContext: { diff --git a/src/plugins/unified_histogram/public/chart/toolbar_selector.tsx b/src/plugins/unified_histogram/public/chart/toolbar_selector.tsx index b9115847b7b03..58d6b5db00234 100644 --- a/src/plugins/unified_histogram/public/chart/toolbar_selector.tsx +++ b/src/plugins/unified_histogram/public/chart/toolbar_selector.tsx @@ -60,9 +60,11 @@ export const ToolbarSelector: React.FC = ({ [] ); - const onSelectionChange = useCallback( + const onSelectionChange = useCallback< + NonNullable['onChange']> + >( (newOptions) => { - const chosenOption = newOptions.find(({ checked }: SelectableEntry) => checked === 'on'); + const chosenOption = newOptions.find(({ checked }) => checked === 'on'); onChange?.( chosenOption?.value && chosenOption?.value !== EMPTY_OPTION ? chosenOption : undefined @@ -139,7 +141,7 @@ export const ToolbarSelector: React.FC = ({ anchorPosition="downLeft" > {popoverTitle} - id={`${dataTestSubj}Selectable`} singleSelection aria-label={popoverTitle} diff --git a/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts b/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts index 44a216178f6d5..1491556fc37d3 100644 --- a/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts +++ b/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts @@ -7,10 +7,9 @@ */ import { DataView, DataViewField, DataViewType } from '@kbn/data-views-plugin/common'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; -import { Suggestion } from '@kbn/lens-plugin/public'; import { renderHook } from '@testing-library/react-hooks'; import { act } from 'react-test-renderer'; -import { UnifiedHistogramFetchStatus } from '../../types'; +import { UnifiedHistogramFetchStatus, UnifiedHistogramSuggestionContext } from '../../types'; import { dataViewMock } from '../../__mocks__/data_view'; import { dataViewWithTimefieldMock } from '../../__mocks__/data_view_with_timefield'; import { lensAdaptersMock } from '../../__mocks__/lens_adapters'; @@ -451,10 +450,12 @@ describe('useStateProps', () => { expect(stateService.setBreakdownField).toHaveBeenLastCalledWith('field'); act(() => { - onSuggestionContextChange({ title: 'Stacked Bar' } as Suggestion); + onSuggestionContextChange({ + suggestion: { title: 'Stacked Bar' }, + } as UnifiedHistogramSuggestionContext); }); expect(stateService.setCurrentSuggestionContext).toHaveBeenLastCalledWith({ - title: 'Stacked Bar', + suggestion: { title: 'Stacked Bar' }, }); }); diff --git a/src/plugins/unified_histogram/public/container/hooks/use_state_props.ts b/src/plugins/unified_histogram/public/container/hooks/use_state_props.ts index f5c8e8e3bc025..58ec13fd5d1a7 100644 --- a/src/plugins/unified_histogram/public/container/hooks/use_state_props.ts +++ b/src/plugins/unified_histogram/public/container/hooks/use_state_props.ts @@ -10,7 +10,11 @@ import { DataView, DataViewField, DataViewType } from '@kbn/data-views-plugin/co import { AggregateQuery, isOfAggregateQueryType, Query } from '@kbn/es-query'; import type { RequestAdapter } from '@kbn/inspector-plugin/public'; import { useCallback, useEffect, useMemo } from 'react'; -import { UnifiedHistogramChartLoadEvent, UnifiedHistogramFetchStatus } from '../../types'; +import { + UnifiedHistogramChartLoadEvent, + UnifiedHistogramFetchStatus, + UnifiedHistogramSuggestionContext, +} from '../../types'; import type { UnifiedHistogramStateService } from '../services/state_service'; import { breakdownFieldSelector, @@ -150,7 +154,7 @@ export const useStateProps = ({ ); const onSuggestionContextChange = useCallback( - (suggestionContext) => { + (suggestionContext: UnifiedHistogramSuggestionContext | undefined) => { stateService?.setCurrentSuggestionContext(suggestionContext); }, [stateService] diff --git a/src/plugins/unified_search/public/dataview_picker/dataview_list.tsx b/src/plugins/unified_search/public/dataview_picker/dataview_list.tsx index 559174711af3b..1b32952c15679 100644 --- a/src/plugins/unified_search/public/dataview_picker/dataview_list.tsx +++ b/src/plugins/unified_search/public/dataview_picker/dataview_list.tsx @@ -16,6 +16,7 @@ import { EuiPanel, EuiButtonGroup, toSentenceCase, + Direction, } from '@elastic/eui'; import type { DataViewListItem } from '@kbn/data-views-plugin/public'; import { i18n } from '@kbn/i18n'; @@ -107,8 +108,8 @@ export function DataViewsList({ ); const onChangeSortDirection = useCallback( - (value) => { - sortingService.setDirection(value); + (value: string) => { + sortingService.setDirection(value as Direction); setSortedDataViewsList((dataViews) => sortingService.sortData(dataViews)); }, [sortingService] diff --git a/src/plugins/unified_search/public/filters_builder/filter_item/params_editor.tsx b/src/plugins/unified_search/public/filters_builder/filter_item/params_editor.tsx index b51defaf2282e..4dac0d33163dd 100644 --- a/src/plugins/unified_search/public/filters_builder/filter_item/params_editor.tsx +++ b/src/plugins/unified_search/public/filters_builder/filter_item/params_editor.tsx @@ -10,10 +10,11 @@ import React, { useCallback, useContext } from 'react'; import { DataView, DataViewField } from '@kbn/data-views-plugin/common'; import type { Filter } from '@kbn/es-query'; import { EuiToolTip, EuiFormRow } from '@elastic/eui'; +import { FilterMetaParams } from '@kbn/es-query/src/filters/build_filters'; import type { Operator } from '../../filter_bar/filter_editor'; import { getFieldValidityAndErrorMessage } from '../../filter_bar/filter_editor/lib'; import { FiltersBuilderContextType } from '../context'; -import { ParamsEditorInput } from './params_editor_input'; +import { ParamsEditorInput, ParamsEditorInputProps } from './params_editor_input'; interface ParamsEditorProps { dataView: DataView; @@ -37,15 +38,15 @@ export function ParamsEditor({ filtersForSuggestions, }: ParamsEditorProps) { const { disabled, suggestionsAbstraction } = useContext(FiltersBuilderContextType); - const onParamsChange = useCallback( + const onParamsChange = useCallback( (selectedParams) => { - onHandleParamsChange(selectedParams); + onHandleParamsChange(selectedParams as FilterMetaParams); }, [onHandleParamsChange] ); - const onParamsUpdate = useCallback( - (value) => { + const onParamsUpdate = useCallback( + (value: any) => { onHandleParamsUpdate(value); }, [onHandleParamsUpdate] diff --git a/src/plugins/unified_search/public/filters_builder/filter_item/params_editor_input.tsx b/src/plugins/unified_search/public/filters_builder/filter_item/params_editor_input.tsx index c3138f7a14e24..d59ffa9782e35 100644 --- a/src/plugins/unified_search/public/filters_builder/filter_item/params_editor_input.tsx +++ b/src/plugins/unified_search/public/filters_builder/filter_item/params_editor_input.tsx @@ -34,7 +34,7 @@ export const strings = { }), }; -interface ParamsEditorInputProps { +export interface ParamsEditorInputProps { dataView: DataView; params: unknown; onParamsChange: (params: unknown) => void; diff --git a/src/plugins/unified_search/public/saved_query_form/save_query_form.tsx b/src/plugins/unified_search/public/saved_query_form/save_query_form.tsx index e9d7a548fadaa..09a55047d2777 100644 --- a/src/plugins/unified_search/public/saved_query_form/save_query_form.tsx +++ b/src/plugins/unified_search/public/saved_query_form/save_query_form.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import React, { useState, useCallback } from 'react'; +import React, { useState, useCallback, ChangeEventHandler } from 'react'; import { EuiButton, EuiForm, EuiFormRow, EuiFieldText, EuiSwitch } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { isEqual } from 'lodash'; @@ -117,7 +117,7 @@ export function SaveQueryForm({ shouldIncludeTimefilter, ]); - const onInputChange = useCallback((event) => { + const onInputChange = useCallback>((event) => { setFormErrors([]); setTitle(event.target.value); }, []); diff --git a/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.tsx b/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.tsx index d62061d7d6cf6..825b158849120 100644 --- a/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.tsx +++ b/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.tsx @@ -24,6 +24,7 @@ import { EuiHorizontalRule, EuiProgress, PrettyDuration, + EuiSelectableProps, } from '@elastic/eui'; import { EuiContextMenuClass } from '@elastic/eui/src/components/context_menu/context_menu'; import { i18n } from '@kbn/i18n'; @@ -282,9 +283,17 @@ export const SavedQueryManagementList = ({ } }, [onLoad, selectedSavedQuery, onClose]); - const handleSelect = useCallback((savedQueryToSelect) => { - setSelectedSavedQuery(savedQueryToSelect); - }, []); + const handleSelect = useCallback['onChange']>>( + (choices) => { + const choice = choices.find(({ checked }) => checked); + if (choice) { + setSelectedSavedQuery( + currentPageQueries.find((savedQuery) => savedQuery.id === choice.value) + ); + } + }, + [currentPageQueries] + ); const handleDelete = useCallback((savedQueryToDelete: SavedQuery) => { setShowDeletionConfirmationModal(true); @@ -439,14 +448,7 @@ export const SavedQueryManagementList = ({ {noSavedQueriesDescriptionText} } - onChange={(choices) => { - const choice = choices.find(({ checked }) => checked); - if (choice) { - handleSelect( - currentPageQueries.find((savedQuery) => savedQuery.id === choice.value) - ); - } - }} + onChange={handleSelect} renderOption={renderOption} css={{ '.euiSelectableList__list': { diff --git a/src/plugins/vis_default_editor/public/components/agg_params.tsx b/src/plugins/vis_default_editor/public/components/agg_params.tsx index aa1fe36d797e4..8e67a2624501f 100644 --- a/src/plugins/vis_default_editor/public/components/agg_params.tsx +++ b/src/plugins/vis_default_editor/public/components/agg_params.tsx @@ -11,7 +11,7 @@ import { EuiForm, EuiAccordion, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import useUnmount from 'react-use/lib/useUnmount'; -import { IAggConfig, AggGroupNames } from '@kbn/data-plugin/public'; +import { IAggConfig, AggGroupNames, IAggType } from '@kbn/data-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { Schema } from '@kbn/visualizations-plugin/public'; @@ -124,7 +124,7 @@ function DefaultEditorAggParams({ !!error || isInvalidParamsTouched(agg.type, aggType, paramsState); const onAggSelect = useCallback( - (value) => { + (value: IAggType) => { if (agg.type !== value) { onAggTypeChange(agg.id, value); // reset touched and valid of params diff --git a/src/plugins/vis_default_editor/public/components/agg_select.tsx b/src/plugins/vis_default_editor/public/components/agg_select.tsx index 09aee4b217266..e65b56753ab1b 100644 --- a/src/plugins/vis_default_editor/public/components/agg_select.tsx +++ b/src/plugins/vis_default_editor/public/components/agg_select.tsx @@ -104,14 +104,14 @@ function DefaultEditorAggSelect({ }, [setValue] ); - const onSearchChange = useCallback((searchValue) => setIsDirty(Boolean(searchValue)), []); + const onSearchChange = useCallback((searchValue: string) => setIsDirty(Boolean(searchValue)), []); const setTouched = useCallback( () => onChangeAggType({ type: AGG_TYPE_ACTION_KEYS.TOUCHED, payload: true }), [onChangeAggType] ); const setValidity = useCallback( - (valid) => onChangeAggType({ type: AGG_TYPE_ACTION_KEYS.VALID, payload: valid }), + (valid: boolean) => onChangeAggType({ type: AGG_TYPE_ACTION_KEYS.VALID, payload: valid }), [onChangeAggType] ); diff --git a/src/plugins/vis_default_editor/public/components/controls/components/from_to_list.tsx b/src/plugins/vis_default_editor/public/components/controls/components/from_to_list.tsx index 89a6109c52fc7..699dbe3470273 100644 --- a/src/plugins/vis_default_editor/public/components/controls/components/from_to_list.tsx +++ b/src/plugins/vis_default_editor/public/components/controls/components/from_to_list.tsx @@ -67,7 +67,7 @@ const defaultConfig = { }; function FromToList({ showValidation, onBlur, ...rest }: FromToListProps) { - const renderInputRow = useCallback( + const renderInputRow = useCallback( (item: FromToModel, index, onChangeValue) => ( <> diff --git a/src/plugins/vis_default_editor/public/components/controls/components/mask_list.tsx b/src/plugins/vis_default_editor/public/components/controls/components/mask_list.tsx index a63848c1d14ce..ca42f1bd23f02 100644 --- a/src/plugins/vis_default_editor/public/components/controls/components/mask_list.tsx +++ b/src/plugins/vis_default_editor/public/components/controls/components/mask_list.tsx @@ -63,7 +63,7 @@ const defaultConfig = { }; function MaskList({ showValidation, onBlur, ...rest }: MaskListProps) { - const renderInputRow = useCallback( + const renderInputRow = useCallback( ({ mask }: MaskModel, index, onChangeValue) => ( setIsDirty(Boolean(searchValue)), []); + const onSearchChange = useCallback((searchValue: string) => setIsDirty(Boolean(searchValue)), []); return ( setValue(ev.target.value), [setValue]); + const onChange = useCallback>( + (e) => setValue(e.target.value), + [setValue] + ); return ( setStateParamValue(PARAMS.NAME, optionId === PARAMS.ROWS), + (optionId: string) => setStateParamValue(PARAMS.NAME, optionId === PARAMS.ROWS), [setStateParamValue] ); diff --git a/src/plugins/vis_default_editor/public/components/controls/string.tsx b/src/plugins/vis_default_editor/public/components/controls/string.tsx index 254c299180662..90b47ebf5c0d4 100644 --- a/src/plugins/vis_default_editor/public/components/controls/string.tsx +++ b/src/plugins/vis_default_editor/public/components/controls/string.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import React, { useEffect, useCallback } from 'react'; +import React, { useEffect, useCallback, ChangeEventHandler } from 'react'; import { EuiFieldText, EuiFormRow } from '@elastic/eui'; import { AggParamEditorProps } from '../agg_param_props'; @@ -26,7 +26,10 @@ function StringParamEditor({ setValidity(isValid); }, [isValid, setValidity]); - const onChange = useCallback((ev) => setValue(ev.target.value), [setValue]); + const onChange = useCallback>( + (e) => setValue(e.target.value), + [setValue] + ); return ( void; @@ -18,9 +19,9 @@ function useSubAggParamsHandlers( aggParam: AggParamType, subAgg: IAggConfig, setValue: SetValue -) { - const setAggParamValue = useCallback( - (aggId, paramName, val) => { +): Pick { + const setAggParamValue = useCallback( + (_, paramName, val) => { const parsedParams = subAgg.serialize(); const params = { ...parsedParams, @@ -35,13 +36,13 @@ function useSubAggParamsHandlers( [agg, aggParam, setValue, subAgg] ); - const onAggTypeChange = useCallback( - (aggId, aggType) => { + const onAggTypeChange = useCallback( + (_, aggType) => { const parsedAgg = subAgg.serialize(); const parsedAggParams = parsedAgg.params as SerializableRecord; // we should share between aggs only field and base params: json, label, time shift. - const params = { + const params: AggConfigSerialized = { ...parsedAgg, params: { field: parsedAggParams.field, @@ -49,6 +50,7 @@ function useSubAggParamsHandlers( customLabel: parsedAggParams.customLabel, timeShift: parsedAggParams.timeShift, }, + // @ts-ignore - Need to verify type type: aggType, }; diff --git a/src/plugins/vis_default_editor/public/components/options/color_ranges.tsx b/src/plugins/vis_default_editor/public/components/options/color_ranges.tsx index 67a6c9c6e8f40..059518926a3e8 100644 --- a/src/plugins/vis_default_editor/public/components/options/color_ranges.tsx +++ b/src/plugins/vis_default_editor/public/components/options/color_ranges.tsx @@ -39,8 +39,8 @@ function ColorRanges({ }, [colorsRange]); const validateRange = useCallback( - ({ from, to }, index) => { - if (!colorsRange[index]) { + ({ from, to }: RangeValues, index: number) => { + if (from === undefined || to === undefined || !colorsRange[index]) { return [false, false]; } diff --git a/src/plugins/vis_default_editor/public/components/options/index.ts b/src/plugins/vis_default_editor/public/components/options/index.ts index 09373dc64eb85..fa2aab1568610 100644 --- a/src/plugins/vis_default_editor/public/components/options/index.ts +++ b/src/plugins/vis_default_editor/public/components/options/index.ts @@ -9,11 +9,9 @@ export { BasicOptions } from './basic_options'; export { SwitchOption } from './switch'; export { SelectOption } from './select'; -export type { SetColorRangeValue } from './color_ranges'; -export { ColorRanges } from './color_ranges'; -export type { SetColorSchemaOptionsValue } from './color_schema'; -export { ColorSchemaOptions } from './color_schema'; -export { NumberInputOption } from './number_input'; +export { ColorRanges, type SetColorRangeValue } from './color_ranges'; +export { ColorSchemaOptions, type SetColorSchemaOptionsValue } from './color_schema'; +export { NumberInputOption, type NumberInputOptionProps } from './number_input'; export { RangeOption } from './range'; export { RequiredNumberInputOption } from './required_number_input'; export { TextInputOption } from './text_input'; diff --git a/src/plugins/vis_default_editor/public/components/options/legend_size_settings.tsx b/src/plugins/vis_default_editor/public/components/options/legend_size_settings.tsx index bbe47295c99e6..43d6b6d230b5d 100644 --- a/src/plugins/vis_default_editor/public/components/options/legend_size_settings.tsx +++ b/src/plugins/vis_default_editor/public/components/options/legend_size_settings.tsx @@ -71,7 +71,7 @@ export const LegendSizeSettings = ({ }, [isVerticalLegend, legendSize, onLegendSizeChange]); const onLegendSizeOptionChange = useCallback( - (option) => onLegendSizeChange(option === DEFAULT_LEGEND_SIZE ? undefined : option), + (size: LegendSize) => onLegendSizeChange(size === DEFAULT_LEGEND_SIZE ? undefined : size), [onLegendSizeChange] ); diff --git a/src/plugins/vis_default_editor/public/components/options/number_input.tsx b/src/plugins/vis_default_editor/public/components/options/number_input.tsx index 604a5896308ae..643d4ad60890e 100644 --- a/src/plugins/vis_default_editor/public/components/options/number_input.tsx +++ b/src/plugins/vis_default_editor/public/components/options/number_input.tsx @@ -62,4 +62,4 @@ function NumberInputOption({ ); } -export { NumberInputOption }; +export { NumberInputOption, type NumberInputOptionProps }; diff --git a/src/plugins/vis_default_editor/public/components/sidebar/controls.tsx b/src/plugins/vis_default_editor/public/components/sidebar/controls.tsx index 678a6c2edaf97..4b14ade5ef431 100644 --- a/src/plugins/vis_default_editor/public/components/sidebar/controls.tsx +++ b/src/plugins/vis_default_editor/public/components/sidebar/controls.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import React, { useCallback, useState } from 'react'; +import React, { SetStateAction, useCallback, useState } from 'react'; import { EuiFlexGroup, EuiFlexItem, @@ -42,7 +42,7 @@ function DefaultEditorControls({ const { enableAutoApply } = vis.type.editorConfig; const [autoApplyEnabled, setAutoApplyEnabled] = useState(false); const toggleAutoApply = useCallback( - (nextAutoApplyEnabled) => setAutoApplyEnabled(nextAutoApplyEnabled), + (nextAutoApplyEnabled: SetStateAction) => setAutoApplyEnabled(nextAutoApplyEnabled), [] ); const onClickDiscard = useCallback(() => dispatch(discardChanges(vis)), [dispatch, vis]); diff --git a/src/plugins/vis_default_editor/public/index.ts b/src/plugins/vis_default_editor/public/index.ts index ffa5e5f88e661..1e251976d30a9 100644 --- a/src/plugins/vis_default_editor/public/index.ts +++ b/src/plugins/vis_default_editor/public/index.ts @@ -27,6 +27,7 @@ export { ColorRanges, BasicOptions, type SetColorRangeValue, + type NumberInputOptionProps, type SetColorSchemaOptionsValue, } from './components/options'; export type { RangeValues } from './components/controls/ranges'; diff --git a/src/plugins/vis_types/heatmap/public/editor/components/heatmap.tsx b/src/plugins/vis_types/heatmap/public/editor/components/heatmap.tsx index 14f09472df752..de483e34f7b11 100644 --- a/src/plugins/vis_types/heatmap/public/editor/components/heatmap.tsx +++ b/src/plugins/vis_types/heatmap/public/editor/components/heatmap.tsx @@ -69,7 +69,10 @@ const HeatmapOptions = (props: HeatmapOptionsProps) => { } }, [stateParams]); - const handleLegendSizeChange = useCallback((size) => setValue('legendSize', size), [setValue]); + const handleLegendSizeChange = useCallback( + (size?: LegendSize) => setValue('legendSize', size), + [setValue] + ); return ( <> diff --git a/src/plugins/vis_types/heatmap/public/editor/components/labels_panel.tsx b/src/plugins/vis_types/heatmap/public/editor/components/labels_panel.tsx index 0b16e538fb481..0134d8d056ec8 100644 --- a/src/plugins/vis_types/heatmap/public/editor/components/labels_panel.tsx +++ b/src/plugins/vis_types/heatmap/public/editor/components/labels_panel.tsx @@ -47,7 +47,10 @@ function LabelsPanel({ valueAxis, setValue, isNewLibrary }: LabelsPanelProps) { [setValueAxisLabels] ); - const setColor = useCallback((value) => setValueAxisLabels('color', value), [setValueAxisLabels]); + const setColor = useCallback( + (value: string) => setValueAxisLabels('color', value), + [setValueAxisLabels] + ); return ( diff --git a/src/plugins/vis_types/pie/public/editor/components/pie.tsx b/src/plugins/vis_types/pie/public/editor/components/pie.tsx index b1369e4e90929..8b5a6bdd7c490 100644 --- a/src/plugins/vis_types/pie/public/editor/components/pie.tsx +++ b/src/plugins/vis_types/pie/public/editor/components/pie.tsx @@ -117,14 +117,17 @@ const PieOptions = (props: PieOptionsProps) => { }, [props.palettes]); const handleEmptySizeRatioChange = useCallback( - (sizeId) => { + (sizeId: string) => { const emptySizeRatio = emptySizeRatioOptions.find(({ id }) => id === sizeId)?.value; setValue('emptySizeRatio', emptySizeRatio); }, [setValue] ); - const handleLegendSizeChange = useCallback((size) => setValue('legendSize', size), [setValue]); + const handleLegendSizeChange = useCallback( + (size?: LegendSize) => setValue('legendSize', size), + [setValue] + ); const handleLegendDisplayChange = useCallback( (name: keyof PartitionVisParams, show: boolean) => { diff --git a/src/plugins/vis_types/timeseries/public/application/components/annotations_editor.tsx b/src/plugins/vis_types/timeseries/public/application/components/annotations_editor.tsx index b1c4adae3859b..9af19c8dc18f7 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/annotations_editor.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/annotations_editor.tsx @@ -74,7 +74,7 @@ export const AnnotationsEditor = (props: AnnotationsEditorProps) => { ); const handleDelete = useCallback( - (annotation) => () => + (annotation: Annotation) => () => collectionActions.handleDelete(getCollectionActionsProps(props), annotation), [props] ); diff --git a/src/plugins/vis_types/vega/public/vega_inspector/components/inspector_data_grid.tsx b/src/plugins/vis_types/vega/public/vega_inspector/components/inspector_data_grid.tsx index 688247c5eb6d5..e9341ec5a4a2e 100644 --- a/src/plugins/vis_types/vega/public/vega_inspector/components/inspector_data_grid.tsx +++ b/src/plugins/vis_types/vega/public/vega_inspector/components/inspector_data_grid.tsx @@ -19,12 +19,12 @@ interface InspectorDataGridProps extends VegaRuntimeData { export const InspectorDataGrid = ({ columns, data, dataGridAriaLabel }: InspectorDataGridProps) => { const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: DEFAULT_PAGE_SIZE }); const onChangeItemsPerPage = useCallback( - (pageSize) => setPagination((p) => ({ ...p, pageSize, pageIndex: 0 })), + (pageSize: number) => setPagination((p) => ({ ...p, pageSize, pageIndex: 0 })), [setPagination] ); const onChangePage = useCallback( - (pageIndex) => setPagination((p) => ({ ...p, pageIndex })), + (pageIndex: number) => setPagination((p) => ({ ...p, pageIndex })), [setPagination] ); diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/chart_options.tsx b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/chart_options.tsx index 1d609187f83c5..8611f17d585dd 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/chart_options.tsx +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/chart_options.tsx @@ -47,7 +47,7 @@ function ChartOptions({ ); const setValueAxis = useCallback( - (paramName, value) => { + (paramName: 'valueAxis', value: string) => { changeValueAxis(index, paramName, value); }, [changeValueAxis, index] diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/y_extents.tsx b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/y_extents.tsx index 5b37ae97a1966..e8baea3ed4da1 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/y_extents.tsx +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/y_extents.tsx @@ -10,7 +10,7 @@ import React, { useEffect, useCallback } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { NumberInputOption } from '@kbn/vis-default-editor-plugin/public'; +import { NumberInputOption, NumberInputOptionProps } from '@kbn/vis-default-editor-plugin/public'; import { Scale, ScaleType } from '../../../../types'; import { SetScale } from './value_axis_options'; @@ -54,7 +54,7 @@ function YExtents({ scale, setScale, setMultipleValidity }: YExtentsProps) { const isValid = !errors.length; - const setExtents = useCallback( + const setExtents = useCallback['setValue']>( (paramName, value) => { setScale(paramName, value === '' ? null : value); }, diff --git a/src/plugins/vis_types/xy/public/editor/components/options/point_series/point_series.tsx b/src/plugins/vis_types/xy/public/editor/components/options/point_series/point_series.tsx index f38471d2ae24e..fe997ead61eb5 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/point_series/point_series.tsx +++ b/src/plugins/vis_types/xy/public/editor/components/options/point_series/point_series.tsx @@ -46,7 +46,10 @@ export function PointSeriesOptions(props: ValidationVisOptionsProps) const [hadAutoLegendSize] = useState(() => legendSize === LegendSize.AUTO); - const handleLegendSizeChange = useCallback((size) => setValue('legendSize', size), [setValue]); + const handleLegendSizeChange = useCallback( + (size?: LegendSize) => setValue('legendSize', size), + [setValue] + ); return ( <> diff --git a/src/plugins/visualizations/common/content_management/v1/types.ts b/src/plugins/visualizations/common/content_management/v1/types.ts index 80159165d97d9..02ab5f762051f 100644 --- a/src/plugins/visualizations/common/content_management/v1/types.ts +++ b/src/plugins/visualizations/common/content_management/v1/types.ts @@ -18,7 +18,7 @@ import { CreateResult, UpdateResult, } from '@kbn/content-management-plugin/common'; -import { ContentManagementCrudTypes } from '@kbn/content-management-utils'; +import type { ContentManagementCrudTypes } from '@kbn/content-management-utils'; import { VisualizationContentType } from '../types'; diff --git a/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts b/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts index f736455faf046..1144f4519490c 100644 --- a/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts +++ b/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts @@ -8,7 +8,7 @@ import { SearchQuery } from '@kbn/content-management-plugin/common'; import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public'; -import { +import type { ContentManagementCrudTypes, SavedObjectCreateOptions, SavedObjectUpdateOptions, diff --git a/test/functional/apps/console/monaco/_misc_console_behavior.ts b/test/functional/apps/console/monaco/_misc_console_behavior.ts index f9b93872740ad..b952533c71a07 100644 --- a/test/functional/apps/console/monaco/_misc_console_behavior.ts +++ b/test/functional/apps/console/monaco/_misc_console_behavior.ts @@ -91,7 +91,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(await PageObjects.console.monaco.getCurrentLineNumber()).to.be(4); }); - describe('open documentation', () => { + // FLAKY: https://github.com/elastic/kibana/issues/190321 + describe.skip('open documentation', () => { const requests = ['GET _search', 'GET test_index/_search', 'GET /_search']; requests.forEach((request) => { it('should open documentation when Ctrl+/ is pressed', async () => { diff --git a/test/functional/services/filter_bar.ts b/test/functional/services/filter_bar.ts index be4abf4e0daf2..c508410739db0 100644 --- a/test/functional/services/filter_bar.ts +++ b/test/functional/services/filter_bar.ts @@ -133,10 +133,11 @@ export class FilterBarService extends FtrService { * @param key field name */ public async removeFilter(key: string): Promise { - await this.retry.try(async () => { + await this.retry.waitFor('filter pill context menu is open', async () => { await this.testSubjects.click(`~filter & ~filter-key-${key}`); - await this.testSubjects.click(`deleteFilter`); + return await this.testSubjects.exists('deleteFilter'); }); + await this.testSubjects.click(`deleteFilter`); await this.header.awaitGlobalLoadingIndicatorHidden(); } diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis/self_changing_editor.tsx b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis/self_changing_editor.tsx index 2ffe694e37b5e..7b92509ed53cf 100644 --- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis/self_changing_editor.tsx +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis/self_changing_editor.tsx @@ -16,7 +16,7 @@ interface CounterParams { } export class SelfChangingEditor extends React.Component> { - onCounterChange = (ev: any) => { + onCounterChange = (ev: React.ChangeEvent) => { this.props.setValue('counter', parseInt(ev.target.value, 10)); }; diff --git a/test/plugin_functional/test_suites/saved_objects_management/hidden_types.ts b/test/plugin_functional/test_suites/saved_objects_management/hidden_types.ts index 8e7adb504ebee..1eac63022d6d6 100644 --- a/test/plugin_functional/test_suites/saved_objects_management/hidden_types.ts +++ b/test/plugin_functional/test_suites/saved_objects_management/hidden_types.ts @@ -8,6 +8,7 @@ import path from 'path'; import expect from '@kbn/expect'; +import { byIdAscComparator } from '@kbn/core-saved-objects-import-export-server-internal/src/export/utils'; import { PluginFunctionalProviderContext } from '../../services'; const fixturePaths = { @@ -47,11 +48,13 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide .expect(200) .then((resp) => { expect( - resp.body.saved_objects.map((obj: any) => ({ - id: obj.id, - type: obj.type, - hidden: obj.meta.hiddenType, - })) + resp.body.saved_objects + .map((obj: any) => ({ + id: obj.id, + type: obj.type, + hidden: obj.meta.hiddenType, + })) + .sort(byIdAscComparator) ).to.eql([ { id: 'obj_1', diff --git a/test/tsconfig.json b/test/tsconfig.json index b03067c0440ae..9f9f062a16492 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -78,5 +78,6 @@ "@kbn/default-nav-analytics", "@kbn/default-nav-management", "@kbn/default-nav-devtools", + "@kbn/core-saved-objects-import-export-server-internal", ] } diff --git a/tsconfig.base.json b/tsconfig.base.json index d6b0733743929..ab942aab15550 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1278,6 +1278,8 @@ "@kbn/observability-plugin/*": ["x-pack/plugins/observability_solution/observability/*"], "@kbn/observability-shared-plugin": ["x-pack/plugins/observability_solution/observability_shared"], "@kbn/observability-shared-plugin/*": ["x-pack/plugins/observability_solution/observability_shared/*"], + "@kbn/observability-utils": ["x-pack/packages/observability/observability_utils"], + "@kbn/observability-utils/*": ["x-pack/packages/observability/observability_utils/*"], "@kbn/oidc-provider-plugin": ["x-pack/test/security_api_integration/plugins/oidc_provider"], "@kbn/oidc-provider-plugin/*": ["x-pack/test/security_api_integration/plugins/oidc_provider/*"], "@kbn/open-telemetry-instrumented-plugin": ["test/common/plugins/otel_metrics"], @@ -1542,6 +1544,8 @@ "@kbn/security-solution-upselling/*": ["x-pack/packages/security-solution/upselling/*"], "@kbn/security-test-endpoints-plugin": ["x-pack/test/security_functional/plugins/test_endpoints"], "@kbn/security-test-endpoints-plugin/*": ["x-pack/test/security_functional/plugins/test_endpoints/*"], + "@kbn/security-ui-components": ["x-pack/packages/security/ui_components"], + "@kbn/security-ui-components/*": ["x-pack/packages/security/ui_components/*"], "@kbn/securitysolution-autocomplete": ["packages/kbn-securitysolution-autocomplete"], "@kbn/securitysolution-autocomplete/*": ["packages/kbn-securitysolution-autocomplete/*"], "@kbn/securitysolution-data-table": ["x-pack/packages/security-solution/data_table"], diff --git a/x-pack/examples/testing_embedded_lens/public/app.tsx b/x-pack/examples/testing_embedded_lens/public/app.tsx index c3d4d103a9a4e..9aa6a40fe20cf 100644 --- a/x-pack/examples/testing_embedded_lens/public/app.tsx +++ b/x-pack/examples/testing_embedded_lens/public/app.tsx @@ -470,7 +470,7 @@ export const App = (props: { const currentSO = useRef(initialAttributes); const [currentValid, saveValidSO] = useState(initialAttributes); const switchChartPreset = useCallback( - (newIndex) => { + (newIndex: number) => { const newChart = charts[newIndex]; const newAttributes = JSON.stringify(newChart.attributes, null, 2); currentSO.current = newAttributes; @@ -694,7 +694,7 @@ export const App = (props: { ({ value: i, text: id }))} value={undefined} - onChange={(e) => switchChartPreset(Number(e.target.value))} + onChange={(e) => switchChartPreset(+e.target.value)} aria-label="Load from a preset" prepend={'Load preset'} /> diff --git a/x-pack/packages/kbn-cloud-security-posture-common/index.ts b/x-pack/packages/kbn-cloud-security-posture-common/index.ts index f4d7ac2e34dd9..66a98d5e398c3 100644 --- a/x-pack/packages/kbn-cloud-security-posture-common/index.ts +++ b/x-pack/packages/kbn-cloud-security-posture-common/index.ts @@ -16,7 +16,8 @@ export type { BaseCspSetupBothPolicy, BaseCspSetupStatus, CspSetupStatus, - CspFinding, -} from './types'; +} from './types/status'; +export type { CspFinding } from './types/findings'; +export type { BenchmarksCisId } from './types/benchmark'; export * from './constants'; -export type { CspBenchmarkRuleMetadata, CspBenchmarkRulesStates } from './schema/rules'; +export { extractErrorMessage, buildMutedRulesFilter } from './utils/helpers'; diff --git a/x-pack/packages/kbn-cloud-security-posture-common/jest.config.js b/x-pack/packages/kbn-cloud-security-posture-common/jest.config.js new file mode 100644 index 0000000000000..d6f06d2bcc21c --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture-common/jest.config.js @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../..', + roots: ['/x-pack/packages/kbn-cloud-security-posture-common'], +}; diff --git a/x-pack/packages/kbn-cloud-security-posture-common/schema/rules.ts b/x-pack/packages/kbn-cloud-security-posture-common/schema/rules.ts deleted file mode 100644 index 67bb37e4e1702..0000000000000 --- a/x-pack/packages/kbn-cloud-security-posture-common/schema/rules.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { TypeOf, schema } from '@kbn/config-schema'; -import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../constants'; - -export type CspBenchmarkRuleMetadata = TypeOf; - -export const cspBenchmarkRuleMetadataSchema = schema.object({ - audit: schema.string(), - benchmark: schema.object({ - name: schema.string(), - posture_type: schema.maybe( - schema.oneOf([schema.literal(CSPM_POLICY_TEMPLATE), schema.literal(KSPM_POLICY_TEMPLATE)]) - ), - id: schema.string(), - version: schema.string(), - rule_number: schema.maybe(schema.string()), - }), - default_value: schema.maybe(schema.string()), - description: schema.string(), - id: schema.string(), - impact: schema.maybe(schema.string()), - name: schema.string(), - profile_applicability: schema.string(), - rationale: schema.string(), - references: schema.maybe(schema.string()), - rego_rule_id: schema.string(), - remediation: schema.string(), - section: schema.string(), - tags: schema.arrayOf(schema.string()), - version: schema.string(), -}); - -export const ruleStateAttributes = schema.object({ - muted: schema.boolean(), - benchmark_id: schema.string(), - benchmark_version: schema.string(), - rule_number: schema.string(), - rule_id: schema.string(), -}); - -export const rulesStates = schema.recordOf(schema.string(), ruleStateAttributes); - -export type CspBenchmarkRulesStates = TypeOf; diff --git a/x-pack/packages/kbn-cloud-security-posture-common/schema/rules/index.ts b/x-pack/packages/kbn-cloud-security-posture-common/schema/rules/index.ts new file mode 100644 index 0000000000000..b8b927b3d1c5f --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture-common/schema/rules/index.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * as rulesV1 from './v1'; +export * as rulesV2 from './v2'; +export * as rulesV3 from './v3'; +export * as rulesV4 from './v4'; +export * as rulesV5 from './v5'; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/index.tsx b/x-pack/packages/kbn-cloud-security-posture-common/schema/rules/latest.ts similarity index 90% rename from x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/index.tsx rename to x-pack/packages/kbn-cloud-security-posture-common/schema/rules/latest.ts index 6a2c75f0054a7..b56fab649ade5 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/index.tsx +++ b/x-pack/packages/kbn-cloud-security-posture-common/schema/rules/latest.ts @@ -5,4 +5,4 @@ * 2.0. */ -export * from './flyout'; +export * from './v5'; diff --git a/x-pack/plugins/cloud_security_posture/common/types/rules/v1.ts b/x-pack/packages/kbn-cloud-security-posture-common/schema/rules/v1.ts similarity index 100% rename from x-pack/plugins/cloud_security_posture/common/types/rules/v1.ts rename to x-pack/packages/kbn-cloud-security-posture-common/schema/rules/v1.ts diff --git a/x-pack/plugins/cloud_security_posture/common/types/rules/v2.ts b/x-pack/packages/kbn-cloud-security-posture-common/schema/rules/v2.ts similarity index 100% rename from x-pack/plugins/cloud_security_posture/common/types/rules/v2.ts rename to x-pack/packages/kbn-cloud-security-posture-common/schema/rules/v2.ts diff --git a/x-pack/plugins/cloud_security_posture/common/types/rules/v3.ts b/x-pack/packages/kbn-cloud-security-posture-common/schema/rules/v3.ts similarity index 73% rename from x-pack/plugins/cloud_security_posture/common/types/rules/v3.ts rename to x-pack/packages/kbn-cloud-security-posture-common/schema/rules/v3.ts index 7c0a536de79a5..a00bf1a8077e6 100644 --- a/x-pack/plugins/cloud_security_posture/common/types/rules/v3.ts +++ b/x-pack/packages/kbn-cloud-security-posture-common/schema/rules/v3.ts @@ -6,8 +6,7 @@ */ import { schema, TypeOf } from '@kbn/config-schema'; - -import { cspBenchmarkRuleMetadataSchema } from '@kbn/cloud-security-posture-common/schema'; +import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../../constants'; export const DEFAULT_BENCHMARK_RULES_PER_PAGE = 25; @@ -15,8 +14,36 @@ export const DEFAULT_BENCHMARK_RULES_PER_PAGE = 25; export type FindCspBenchmarkRuleRequest = TypeOf; +export type CspBenchmarkRuleMetadata = TypeOf; + export type CspBenchmarkRule = TypeOf; +export const cspBenchmarkRuleMetadataSchema = schema.object({ + audit: schema.string(), + benchmark: schema.object({ + name: schema.string(), + posture_type: schema.maybe( + schema.oneOf([schema.literal(CSPM_POLICY_TEMPLATE), schema.literal(KSPM_POLICY_TEMPLATE)]) + ), + id: schema.string(), + version: schema.string(), + rule_number: schema.maybe(schema.string()), + }), + default_value: schema.maybe(schema.string()), + description: schema.string(), + id: schema.string(), + impact: schema.maybe(schema.string()), + name: schema.string(), + profile_applicability: schema.string(), + rationale: schema.string(), + references: schema.maybe(schema.string()), + rego_rule_id: schema.string(), + remediation: schema.string(), + section: schema.string(), + tags: schema.arrayOf(schema.string()), + version: schema.string(), +}); + export const cspBenchmarkRuleSchema = schema.object({ metadata: cspBenchmarkRuleMetadataSchema, }); diff --git a/x-pack/plugins/cloud_security_posture/common/types/rules/v4.ts b/x-pack/packages/kbn-cloud-security-posture-common/schema/rules/v4.ts similarity index 86% rename from x-pack/plugins/cloud_security_posture/common/types/rules/v4.ts rename to x-pack/packages/kbn-cloud-security-posture-common/schema/rules/v4.ts index 231fb4c65a9bb..4f05a15f555b5 100644 --- a/x-pack/plugins/cloud_security_posture/common/types/rules/v4.ts +++ b/x-pack/packages/kbn-cloud-security-posture-common/schema/rules/v4.ts @@ -6,11 +6,15 @@ */ import { schema, TypeOf } from '@kbn/config-schema'; -import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common'; -import { ruleStateAttributes, rulesStates } from '@kbn/cloud-security-posture-common/schema'; -import { BenchmarksCisId } from '../latest'; +import { BenchmarksCisId } from '../../types/benchmark'; import { DEFAULT_BENCHMARK_RULES_PER_PAGE } from './v3'; -export type { cspBenchmarkRuleSchema, CspBenchmarkRule, FindCspBenchmarkRuleResponse } from './v3'; +export type { + cspBenchmarkRuleMetadataSchema, + CspBenchmarkRuleMetadata, + cspBenchmarkRuleSchema, + CspBenchmarkRule, + FindCspBenchmarkRuleResponse, +} from './v3'; export type FindCspBenchmarkRuleRequest = TypeOf; @@ -22,6 +26,8 @@ export type CspBenchmarkRulesBulkActionRequestSchema = TypeOf< export type RuleStateAttributes = TypeOf; +export type CspBenchmarkRulesStates = TypeOf; + export type CspSettings = TypeOf; export const findCspBenchmarkRuleRequestSchema = schema.object({ @@ -137,6 +143,16 @@ export interface CspBenchmarkRulesBulkActionResponse { message: string; } +const ruleStateAttributes = schema.object({ + muted: schema.boolean(), + benchmark_id: schema.string(), + benchmark_version: schema.string(), + rule_number: schema.string(), + rule_id: schema.string(), +}); + +const rulesStates = schema.recordOf(schema.string(), ruleStateAttributes); + export const cspSettingsSchema = schema.object({ rules: rulesStates, }); diff --git a/x-pack/plugins/cloud_security_posture/common/types/rules/v5.ts b/x-pack/packages/kbn-cloud-security-posture-common/schema/rules/v5.ts similarity index 93% rename from x-pack/plugins/cloud_security_posture/common/types/rules/v5.ts rename to x-pack/packages/kbn-cloud-security-posture-common/schema/rules/v5.ts index 1d70528d457ea..6f30ed446531a 100644 --- a/x-pack/plugins/cloud_security_posture/common/types/rules/v5.ts +++ b/x-pack/packages/kbn-cloud-security-posture-common/schema/rules/v5.ts @@ -7,13 +7,20 @@ import { schema, TypeOf } from '@kbn/config-schema'; import { DEFAULT_BENCHMARK_RULES_PER_PAGE } from './v3'; -export type { cspBenchmarkRuleSchema, CspBenchmarkRule, FindCspBenchmarkRuleResponse } from './v3'; +export type { + cspBenchmarkRuleMetadataSchema, + CspBenchmarkRuleMetadata, + cspBenchmarkRuleSchema, + CspBenchmarkRule, + FindCspBenchmarkRuleResponse, +} from './v3'; export type { PageUrlParams, rulesToUpdate, CspBenchmarkRulesBulkActionRequestSchema, CspBenchmarkRulesBulkActionResponse, RuleStateAttributes, + CspBenchmarkRulesStates, cspSettingsSchema, CspSettings, BulkActionBenchmarkRulesResponse, diff --git a/x-pack/packages/kbn-cloud-security-posture-common/tsconfig.json b/x-pack/packages/kbn-cloud-security-posture-common/tsconfig.json index 1eb47d23c1542..17961df586258 100644 --- a/x-pack/packages/kbn-cloud-security-posture-common/tsconfig.json +++ b/x-pack/packages/kbn-cloud-security-posture-common/tsconfig.json @@ -16,5 +16,7 @@ ], "kbn_references": [ "@kbn/config-schema", + "@kbn/data-views-plugin", + "@kbn/i18n", ] } diff --git a/x-pack/packages/kbn-cloud-security-posture-common/types/benchmark.ts b/x-pack/packages/kbn-cloud-security-posture-common/types/benchmark.ts new file mode 100644 index 0000000000000..ed661879558e7 --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture-common/types/benchmark.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +export type BenchmarksCisId = 'cis_k8s' | 'cis_azure' | 'cis_aws' | 'cis_eks' | 'cis_gcp'; diff --git a/x-pack/packages/kbn-cloud-security-posture-common/types.ts b/x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts similarity index 54% rename from x-pack/packages/kbn-cloud-security-posture-common/types.ts rename to x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts index 7a9d5fee09c8f..8a7a563fb26c7 100644 --- a/x-pack/packages/kbn-cloud-security-posture-common/types.ts +++ b/x-pack/packages/kbn-cloud-security-posture-common/types/findings.ts @@ -4,46 +4,15 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { EcsDataStream, EcsEvent } from '@elastic/ecs'; -import type { CspBenchmarkRuleMetadata } from './schema/rules'; - -export type CspStatusCode = - | 'indexed' // latest findings index exists and has results - | 'indexing' // index timeout was not surpassed since installation, assumes data is being indexed - | 'unprivileged' // user lacks privileges for the latest findings index - | 'index-timeout' // index timeout was surpassed since installation - | 'not-deployed' // no healthy agents were deployed - | 'not-installed' // number of installed csp integrations is 0; - | 'waiting_for_results'; // have healthy agents but no findings at all, assumes data is being indexed for the 1st time - -export type IndexStatus = - | 'not-empty' // Index contains documents - | 'empty' // Index doesn't contain documents (or doesn't exist) - | 'unprivileged'; // User doesn't have access to query the index - -export interface IndexDetails { - index: string; - status: IndexStatus; -} - -export interface BaseCspSetupBothPolicy { - status: CspStatusCode; - installedPackagePolicies: number; - healthyAgents: number; -} - -export interface BaseCspSetupStatus { - indicesDetails: IndexDetails[]; - latestPackageVersion: string; - cspm: BaseCspSetupBothPolicy; - kspm: BaseCspSetupBothPolicy; - vuln_mgmt: BaseCspSetupBothPolicy; - isPluginInitialized: boolean; - installedPackageVersion?: string | undefined; - hasMisconfigurationsFindings?: boolean; -} -export type CspSetupStatus = BaseCspSetupStatus; +/* + * 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 { EcsDataStream, EcsEvent } from '@elastic/ecs'; +import type { CspBenchmarkRuleMetadata } from '../schema/rules/latest'; export interface CspFinding { '@timestamp': string; diff --git a/x-pack/packages/kbn-cloud-security-posture-common/types/status.ts b/x-pack/packages/kbn-cloud-security-posture-common/types/status.ts new file mode 100644 index 0000000000000..92ad6ee126b8a --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture-common/types/status.ts @@ -0,0 +1,51 @@ +/* + * 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. + */ + +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export type CspStatusCode = + | 'indexed' // latest findings index exists and has results + | 'indexing' // index timeout was not surpassed since installation, assumes data is being indexed + | 'unprivileged' // user lacks privileges for the latest findings index + | 'index-timeout' // index timeout was surpassed since installation + | 'not-deployed' // no healthy agents were deployed + | 'not-installed' // number of installed csp integrations is 0; + | 'waiting_for_results'; // have healthy agents but no findings at all, assumes data is being indexed for the 1st time + +export type IndexStatus = + | 'not-empty' // Index contains documents + | 'empty' // Index doesn't contain documents (or doesn't exist) + | 'unprivileged'; // User doesn't have access to query the index + +export interface IndexDetails { + index: string; + status: IndexStatus; +} + +export interface BaseCspSetupBothPolicy { + status: CspStatusCode; + installedPackagePolicies: number; + healthyAgents: number; +} + +export interface BaseCspSetupStatus { + indicesDetails: IndexDetails[]; + latestPackageVersion: string; + cspm: BaseCspSetupBothPolicy; + kspm: BaseCspSetupBothPolicy; + vuln_mgmt: BaseCspSetupBothPolicy; + isPluginInitialized: boolean; + installedPackageVersion?: string | undefined; + hasMisconfigurationsFindings?: boolean; +} + +export type CspSetupStatus = BaseCspSetupStatus; diff --git a/x-pack/packages/kbn-cloud-security-posture-common/utils/helpers.test.ts b/x-pack/packages/kbn-cloud-security-posture-common/utils/helpers.test.ts new file mode 100644 index 0000000000000..7e5f4f1d8120a --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture-common/utils/helpers.test.ts @@ -0,0 +1,141 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { extractErrorMessage, defaultErrorMessage, buildMutedRulesFilter } from './helpers'; + +const fallbackMessage = 'thisIsAFallBackMessage'; + +describe('test helper methods', () => { + describe('extractErrorMessage Test', () => { + it('should return error message if input is instance of Error', () => { + const errorMessage = 'thisIsInstanceOfErrorMessage'; + const error = new Error(errorMessage); + const extractedErrorMessage = extractErrorMessage(error, fallbackMessage); + + expect(extractedErrorMessage).toMatch(errorMessage); + }); + + it('should return string if input is string', () => { + const error: string = 'thisIsAString'; + const extractedErrorMessage = extractErrorMessage(error, fallbackMessage); + + expect(extractedErrorMessage).toMatch(error); + }); + + it('should return fallbackMessage is input is not string nor instance of Error', () => { + const error: number = 12345; + const extractedErrorMessage = extractErrorMessage(error, fallbackMessage); + + expect(extractedErrorMessage).toMatch(fallbackMessage); + }); + + it('should return default message when input is not string nor instance of Error and fallbackMessage is not provided', () => { + const error: number = 12345; + const extractedErrorMessage = extractErrorMessage(error); + + expect(extractedErrorMessage).toMatch(defaultErrorMessage); + }); + }); + + describe('buildMutedRulesFilter Test', () => { + it('should return an empty array if no rules are muted', () => { + const rulesStates = { + rule1: { + muted: false, + benchmark_id: '1', + benchmark_version: '1.0', + rule_number: '1', + rule_id: '11', + }, + rule2: { + muted: false, + benchmark_id: '2', + benchmark_version: '1.0', + rule_number: '2', + rule_id: '22', + }, + }; + + expect(buildMutedRulesFilter(rulesStates)).toEqual([]); + }); + + it('should return the correct query for a single muted rule', () => { + const rulesStates = { + rule1: { + muted: true, + benchmark_id: '1', + benchmark_version: '1.0', + rule_number: '1', + rule_id: '11', + }, + rule2: { + muted: false, + benchmark_id: '2', + benchmark_version: '1.0', + rule_number: '2', + rule_id: '22', + }, + }; + + const expectedQuery = [ + { + bool: { + must: [ + { term: { 'rule.benchmark.id': '1' } }, + { term: { 'rule.benchmark.version': '1.0' } }, + { term: { 'rule.benchmark.rule_number': '1' } }, + ], + }, + }, + ]; + + expect(buildMutedRulesFilter(rulesStates)).toEqual(expectedQuery); + }); + + it('should return the correct queries for multiple muted rules', () => { + const rulesStates = { + rule1: { + muted: true, + benchmark_id: '1', + benchmark_version: '1.0', + rule_number: '1', + rule_id: '11', + }, + rule2: { + muted: true, + benchmark_id: '2', + benchmark_version: '1.0', + rule_number: '2', + rule_id: '22', + }, + }; + + const expectedQuery = [ + { + bool: { + must: [ + { term: { 'rule.benchmark.id': '1' } }, + { term: { 'rule.benchmark.version': '1.0' } }, + { term: { 'rule.benchmark.rule_number': '1' } }, + ], + }, + }, + { + bool: { + must: [ + { term: { 'rule.benchmark.id': '2' } }, + { term: { 'rule.benchmark.version': '1.0' } }, + { term: { 'rule.benchmark.rule_number': '2' } }, + ], + }, + }, + ]; + + expect(buildMutedRulesFilter(rulesStates)).toEqual(expectedQuery); + }); + }); +}); diff --git a/x-pack/packages/kbn-cloud-security-posture-common/utils/helpers.ts b/x-pack/packages/kbn-cloud-security-posture-common/utils/helpers.ts new file mode 100644 index 0000000000000..7c26c61778137 --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture-common/utils/helpers.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { QueryDslQueryContainer } from '@kbn/data-views-plugin/common/types'; +import { i18n } from '@kbn/i18n'; +import type { CspBenchmarkRulesStates } from '../schema/rules/latest'; + +export const defaultErrorMessage = i18n.translate('xpack.csp.common.utils.helpers.unknownError', { + defaultMessage: 'Unknown Error', +}); + +export const extractErrorMessage = (e: unknown, fallbackMessage?: string): string => { + if (e instanceof Error) return e.message; + if (typeof e === 'string') return e; + + return fallbackMessage ?? defaultErrorMessage; +}; + +export const buildMutedRulesFilter = ( + rulesStates: CspBenchmarkRulesStates +): QueryDslQueryContainer[] => { + const mutedRules = Object.fromEntries( + Object.entries(rulesStates).filter(([key, value]) => value.muted === true) + ); + + const mutedRulesFilterQuery = Object.keys(mutedRules).map((key) => { + const rule = mutedRules[key]; + return { + bool: { + must: [ + { term: { 'rule.benchmark.id': rule.benchmark_id } }, + { term: { 'rule.benchmark.version': rule.benchmark_version } }, + { term: { 'rule.benchmark.rule_number': rule.rule_number } }, + ], + }, + }; + }); + + return mutedRulesFilterQuery; +}; diff --git a/x-pack/packages/kbn-cloud-security-posture/index.ts b/x-pack/packages/kbn-cloud-security-posture/index.ts index a0e4ba8dbc1b2..bb40ae57eca2a 100644 --- a/x-pack/packages/kbn-cloud-security-posture/index.ts +++ b/x-pack/packages/kbn-cloud-security-posture/index.ts @@ -6,3 +6,4 @@ */ export * from './type'; +export { showErrorToast } from './src/utils/show_error_toast'; diff --git a/x-pack/plugins/cloud_security_posture/public/common/api/use_setup_status_api.ts b/x-pack/packages/kbn-cloud-security-posture/src/hooks/use_csp_setup_status_api.ts similarity index 84% rename from x-pack/plugins/cloud_security_posture/public/common/api/use_setup_status_api.ts rename to x-pack/packages/kbn-cloud-security-posture/src/hooks/use_csp_setup_status_api.ts index 003f841772285..f77e1e5c12c8d 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/api/use_setup_status_api.ts +++ b/x-pack/packages/kbn-cloud-security-posture/src/hooks/use_csp_setup_status_api.ts @@ -6,16 +6,17 @@ */ import { useQuery, type UseQueryOptions } from '@tanstack/react-query'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import type { CoreStart } from '@kbn/core/public'; import { STATUS_API_CURRENT_VERSION, STATUS_ROUTE_PATH } from '@kbn/cloud-security-posture-common'; import type { CspSetupStatus } from '@kbn/cloud-security-posture-common'; -import { useKibana } from '../hooks/use_kibana'; const getCspSetupStatusQueryKey = 'csp_status_key'; export const useCspSetupStatusApi = ( options?: UseQueryOptions ) => { - const { http } = useKibana().services; + const { http } = useKibana().services; return useQuery( [getCspSetupStatusQueryKey], () => http.get(STATUS_ROUTE_PATH, { version: STATUS_API_CURRENT_VERSION }), diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_get_benchmark_rules_state_api.ts b/x-pack/packages/kbn-cloud-security-posture/src/hooks/use_get_benchmark_rules_state_api.ts similarity index 81% rename from x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_get_benchmark_rules_state_api.ts rename to x-pack/packages/kbn-cloud-security-posture/src/hooks/use_get_benchmark_rules_state_api.ts index cf79ef80b1196..06270d9bc710a 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_get_benchmark_rules_state_api.ts +++ b/x-pack/packages/kbn-cloud-security-posture/src/hooks/use_get_benchmark_rules_state_api.ts @@ -10,13 +10,14 @@ import { CSP_GET_BENCHMARK_RULES_STATE_API_CURRENT_VERSION, CSP_GET_BENCHMARK_RULES_STATE_ROUTE_PATH, } from '@kbn/cloud-security-posture-common'; -import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common'; -import { useKibana } from '../../../common/hooks/use_kibana'; +import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common/schema/rules/latest'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import type { CoreStart } from '@kbn/core/public'; export const getRuleStatesKey = ['get_rules_state_key']; export const useGetCspBenchmarkRulesStatesApi = () => { - const { http } = useKibana().services; + const { http } = useKibana().services; return useQuery(getRuleStatesKey, () => http.get(CSP_GET_BENCHMARK_RULES_STATE_ROUTE_PATH, { version: CSP_GET_BENCHMARK_RULES_STATE_API_CURRENT_VERSION, diff --git a/x-pack/plugins/cloud_security_posture/public/common/utils/show_error_toast.ts b/x-pack/packages/kbn-cloud-security-posture/src/utils/show_error_toast.ts similarity index 90% rename from x-pack/plugins/cloud_security_posture/public/common/utils/show_error_toast.ts rename to x-pack/packages/kbn-cloud-security-posture/src/utils/show_error_toast.ts index 75316d9495b26..060ae8c3b69ee 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/utils/show_error_toast.ts +++ b/x-pack/packages/kbn-cloud-security-posture/src/utils/show_error_toast.ts @@ -4,9 +4,10 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + import type { CoreStart } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; -import { extractErrorMessage } from '../../../common/utils/helpers'; +import { extractErrorMessage } from '@kbn/cloud-security-posture-common'; const SEARCH_FAILED_TEXT = i18n.translate( 'xpack.csp.findings.findingsErrorToast.searchFailedTitle', diff --git a/x-pack/packages/kbn-cloud-security-posture/tsconfig.json b/x-pack/packages/kbn-cloud-security-posture/tsconfig.json index a2652215c4e79..152c3fe8a8b29 100644 --- a/x-pack/packages/kbn-cloud-security-posture/tsconfig.json +++ b/x-pack/packages/kbn-cloud-security-posture/tsconfig.json @@ -33,5 +33,8 @@ "@kbn/es-query", "@kbn/cloud-plugin", "@kbn/spaces-plugin", + "@kbn/kibana-react-plugin", + "@kbn/cloud-security-posture-common", + "@kbn/i18n", ] } diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/models/model_selector/model_selector.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/models/model_selector/model_selector.tsx index 01f4049fb67b3..b23f85519a08b 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/models/model_selector/model_selector.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/models/model_selector/model_selector.tsx @@ -6,7 +6,7 @@ */ import React, { useCallback, useMemo, useState } from 'react'; -import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; +import { EuiComboBox, EuiComboBoxOptionOption, EuiComboBoxProps } from '@elastic/eui'; import * as i18n from './translations'; @@ -49,7 +49,9 @@ export const ModelSelector: React.FC = React.memo( ); // Callback for when user types to create a new model - const onCreateOption = useCallback( + const onCreateOption = useCallback< + NonNullable['onCreateOption']> + >( (searchValue, flattenedOptions = []) => { if (!searchValue || !searchValue.trim().toLowerCase()) { return; @@ -58,8 +60,7 @@ export const ModelSelector: React.FC = React.memo( const normalizedSearchValue = searchValue.trim().toLowerCase(); const optionExists = flattenedOptions.findIndex( - (option: EuiComboBoxOptionOption) => - option.label.trim().toLowerCase() === normalizedSearchValue + (option) => option.label.trim().toLowerCase() === normalizedSearchValue ) !== -1; const newOption = { diff --git a/x-pack/packages/ml/aiops_log_rate_analysis/get_log_rate_analysis_parameters_from_alert.ts b/x-pack/packages/ml/aiops_log_rate_analysis/get_log_rate_analysis_parameters_from_alert.ts index cfd347324a57f..4de3ca83ce702 100644 --- a/x-pack/packages/ml/aiops_log_rate_analysis/get_log_rate_analysis_parameters_from_alert.ts +++ b/x-pack/packages/ml/aiops_log_rate_analysis/get_log_rate_analysis_parameters_from_alert.ts @@ -11,7 +11,7 @@ export interface GetLogRateAnalysisParametersFromAlertArgs { alertStartedAt: string; alertEndedAt?: string; timeSize?: number; - timeUnit?: moment.unitOfTime.DurationConstructor; + timeUnit?: string; } export const getLogRateAnalysisParametersFromAlert = ({ @@ -20,12 +20,7 @@ export const getLogRateAnalysisParametersFromAlert = ({ timeSize, timeUnit, }: GetLogRateAnalysisParametersFromAlertArgs) => { - // Identify `intervalFactor` to adjust time ranges based on alert settings. - // The default time ranges for `initialAnalysisStart` are suitable for a `1m` lookback. - // If an alert would have a `5m` lookback, this would result in a factor of `5`. - const lookbackDuration = - timeSize && timeUnit ? moment.duration(timeSize, timeUnit) : moment.duration(1, 'm'); - const intervalFactor = Math.max(1, lookbackDuration.asSeconds() / 60); + const intervalFactor = getIntervalFactor(timeSize, timeUnit); const alertStart = moment(alertStartedAt); const alertEnd = alertEndedAt ? moment(alertEndedAt) : undefined; @@ -43,6 +38,21 @@ export const getLogRateAnalysisParametersFromAlert = ({ }; }; +// Identify `intervalFactor` to adjust time ranges based on alert settings. +// The default time ranges for `initialAnalysisStart` are suitable for a `1m` lookback. +// If an alert would have a `5m` lookback, this would result in a factor of `5`. +export const getIntervalFactor = (timeSize?: number, timeUnit?: string) => { + const lookbackDuration = + timeSize && timeUnit + ? moment.duration( + timeSize, + // workaround to cast the string based time unit to moment's format. + timeUnit as unknown as moment.unitOfTime.DurationConstructor | undefined + ) + : moment.duration(1, 'm'); + return Math.max(1, lookbackDuration.asSeconds() / 60); +}; + interface GetParameterHelperArgs { alertStart: Moment; intervalFactor: number; diff --git a/x-pack/packages/ml/aiops_log_rate_analysis/queries/fetch_log_rate_analysis_for_alert.ts b/x-pack/packages/ml/aiops_log_rate_analysis/queries/fetch_log_rate_analysis_for_alert.ts new file mode 100644 index 0000000000000..3ba57139901f8 --- /dev/null +++ b/x-pack/packages/ml/aiops_log_rate_analysis/queries/fetch_log_rate_analysis_for_alert.ts @@ -0,0 +1,213 @@ +/* + * 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 moment from 'moment'; +import { queue } from 'async'; +import { chunk } from 'lodash'; + +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +import { withSpan } from '@kbn/apm-utils'; +import type { ElasticsearchClient } from '@kbn/core/server'; +import type { SignificantItem } from '@kbn/ml-agg-utils'; +import { getSampleProbability } from '@kbn/ml-random-sampler-utils'; + +import type { AiopsLogRateAnalysisSchema } from '../api/schema'; +import { getIntervalFactor } from '../get_log_rate_analysis_parameters_from_alert'; +import { getSwappedWindowParameters } from '../get_swapped_window_parameters'; +import { getLogRateChange } from '../get_log_rate_change'; +import { getBaselineAndDeviationRates } from '../get_baseline_and_deviation_rates'; +import { getLogRateAnalysisTypeForCounts } from '../get_log_rate_analysis_type_for_counts'; +import { LOG_RATE_ANALYSIS_TYPE } from '../log_rate_analysis_type'; + +import { fetchIndexInfo } from './fetch_index_info'; +import { fetchSignificantCategories } from './fetch_significant_categories'; +import { fetchSignificantTermPValues } from './fetch_significant_term_p_values'; + +const MAX_CONCURRENT_QUERIES = 5; +const CHUNK_SIZE = 50; + +interface QueueItem { + fn: typeof fetchSignificantCategories | typeof fetchSignificantTermPValues; + fieldNames: string[]; +} + +/** + * Runs log rate analysis data on an index given some alert metadata. + */ +export async function fetchLogRateAnalysisForAlert({ + esClient, + abortSignal, + arguments: args, +}: { + esClient: ElasticsearchClient; + abortSignal?: AbortSignal; + arguments: { + index: string; + alertStartedAt: string; + alertRuleParameterTimeSize?: number; + alertRuleParameterTimeUnit?: string; + timefield?: string; + searchQuery?: estypes.QueryDslQueryContainer; + }; +}) { + const { alertStartedAt, timefield = '@timestamp' } = args; + const alertStart = moment(alertStartedAt); + + const intervalFactor = getIntervalFactor( + args.alertRuleParameterTimeSize, + args.alertRuleParameterTimeUnit + ); + + // The deviation time range is 1 lookback duration before the alert start. + // The baseline time range is 2 lookback durations before the deviation time range. + const windowParameters = { + baselineMin: alertStart + .clone() + .subtract(3 * intervalFactor, 'minutes') + .valueOf(), + baselineMax: alertStart + .clone() + .subtract(1 * intervalFactor, 'minutes') + .valueOf(), + deviationMin: alertStart + .clone() + .subtract(1 * intervalFactor, 'minutes') + .valueOf(), + deviationMax: alertStart.valueOf(), + }; + + const { searchQuery = { match_all: {} } } = args; + + // Step 1: Get field candidates and total doc counts. + const indexInfoParams: AiopsLogRateAnalysisSchema = { + index: args.index, + start: windowParameters.baselineMin, + end: windowParameters.deviationMax, + searchQuery: JSON.stringify(searchQuery), + timeFieldName: timefield, + ...windowParameters, + }; + + const indexInfo = await withSpan( + { name: 'fetch_index_info', type: 'aiops-log-rate-analysis-for-alert' }, + () => + fetchIndexInfo({ + esClient, + abortSignal, + arguments: { + ...indexInfoParams, + textFieldCandidatesOverrides: ['message', 'error.message'], + }, + }) + ); + const { textFieldCandidates, keywordFieldCandidates } = indexInfo; + + const logRateAnalysisType = getLogRateAnalysisTypeForCounts({ + baselineCount: indexInfo.baselineTotalDocCount, + deviationCount: indexInfo.deviationTotalDocCount, + windowParameters, + }); + + // Just in case the log rate analysis type is 'dip', we need to swap + // the window parameters for the analysis. + const analysisWindowParameters = + logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE + ? windowParameters + : getSwappedWindowParameters(windowParameters); + + // Step 2: Identify significant items. + // The following code will fetch significant categories and term p-values + // using an async queue. The field candidates will be passed on as chunks + // of 50 fields with up to 5 concurrent queries. This is to prevent running + // into bucket limit issues if we'd throw possibly hundreds of field candidates + // into a single query. + + const significantItems: SignificantItem[] = []; + + // Set up the queue: A queue item is an object with the function to call and + // the field names to be passed to the function. This is done so we can push + // queries for both keyword fields (using significant_terms/p-values) and + // text fields (using categorize_text + custom code to identify significance) + // into the same queue. + const significantItemsQueue = queue(async function ({ fn, fieldNames }: QueueItem) { + significantItems.push( + ...(await fn({ + esClient, + abortSignal, + arguments: { + ...indexInfoParams, + ...analysisWindowParameters, + fieldNames, + sampleProbability: getSampleProbability( + indexInfo.deviationTotalDocCount + indexInfo.baselineTotalDocCount + ), + }, + })) + ); + }, MAX_CONCURRENT_QUERIES); + + // Push the actual items to the queue. We don't need to chunk the text fields + // since they are just `message` and `error.message`. + significantItemsQueue.push( + [ + { fn: fetchSignificantCategories, fieldNames: textFieldCandidates }, + ...chunk(keywordFieldCandidates, CHUNK_SIZE).map((fieldNames) => ({ + fn: fetchSignificantTermPValues, + fieldNames, + })), + ], + (err) => { + if (err) significantItemsQueue.kill(); + } + ); + + // Wait for the queue to finish. + await withSpan( + { name: 'fetch_significant_items', type: 'aiops-log-rate-analysis-for-alert' }, + () => significantItemsQueue.drain() + ); + + // RETURN DATA + // Adapt the raw significant items data for contextual insights. + return { + logRateAnalysisType, + significantItems: significantItems + .map(({ fieldName, fieldValue, type, doc_count: docCount, bg_count: bgCount }) => { + const { baselineBucketRate, deviationBucketRate } = getBaselineAndDeviationRates( + logRateAnalysisType, + // Normalize the amount of baseline buckets based on treating the + // devation duration as 1 bucket. + (windowParameters.baselineMax - windowParameters.baselineMin) / + (windowParameters.deviationMax - windowParameters.deviationMin), + 1, + docCount, + bgCount + ); + + const fieldType = type === 'keyword' ? 'metadata' : 'log message pattern'; + + const data = { + fieldType, + fieldName, + fieldValue: String(fieldValue).substring(0, 140), + logRateChange: getLogRateChange( + logRateAnalysisType, + baselineBucketRate, + deviationBucketRate + ).message, + }; + + return { + logRateChangeSort: bgCount > 0 ? docCount / bgCount : docCount, + data, + }; + }) + .sort((a, b) => b.logRateChangeSort - a.logRateChangeSort) + .map((d) => d.data), + }; +} diff --git a/x-pack/packages/ml/aiops_log_rate_analysis/tsconfig.json b/x-pack/packages/ml/aiops_log_rate_analysis/tsconfig.json index 711cbfb57a15b..66b978764464e 100644 --- a/x-pack/packages/ml/aiops_log_rate_analysis/tsconfig.json +++ b/x-pack/packages/ml/aiops_log_rate_analysis/tsconfig.json @@ -31,5 +31,6 @@ "@kbn/ml-string-hash", "@kbn/ml-response-stream", "@kbn/i18n", + "@kbn/apm-utils", ] } diff --git a/x-pack/packages/ml/inference_integration_flyout/components/flyout_layout.tsx b/x-pack/packages/ml/inference_integration_flyout/components/flyout_layout.tsx index a859b1d95103f..22c904e63561e 100644 --- a/x-pack/packages/ml/inference_integration_flyout/components/flyout_layout.tsx +++ b/x-pack/packages/ml/inference_integration_flyout/components/flyout_layout.tsx @@ -51,7 +51,7 @@ export const InferenceFlyout: React.FC = ({ }, [inferenceEndpointError]); const onChangingInferenceEndpoint = useCallback( - (value) => { + (value: any) => { setInferenceEndpointId(value); onInferenceEndpointChange(value); }, diff --git a/x-pack/packages/observability/observability_utils/README.md b/x-pack/packages/observability/observability_utils/README.md new file mode 100644 index 0000000000000..bd74c0bdffb47 --- /dev/null +++ b/x-pack/packages/observability/observability_utils/README.md @@ -0,0 +1,5 @@ +# @kbn/observability-utils + +This package contains utilities for Observability plugins. It's a separate package to get out of dependency hell. You can put anything in here that is stateless and has no dependency on other plugins (either directly or via other packages). + +The utility functions should be used via direct imports to minimize impact on bundle size and limit the risk on importing browser code to the server and vice versa. diff --git a/x-pack/packages/observability/observability_utils/es/client/create_observability_es_client.ts b/x-pack/packages/observability/observability_utils/es/client/create_observability_es_client.ts new file mode 100644 index 0000000000000..2e57653365b0b --- /dev/null +++ b/x-pack/packages/observability/observability_utils/es/client/create_observability_es_client.ts @@ -0,0 +1,66 @@ +/* + * 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 { ElasticsearchClient, Logger } from '@kbn/core/server'; +import type { ESSearchRequest, InferSearchResponseOf } from '@kbn/es-types'; +import { withSpan } from '@kbn/apm-utils'; + +type SearchRequest = ESSearchRequest & { + index: string | string[]; + track_total_hits: number | boolean; + size: number | boolean; +}; + +/** + * An Elasticsearch Client with a fully typed `search` method and built-in + * APM instrumentation. + */ +export interface ObservabilityElasticsearchClient { + search( + operationName: string, + parameters: TSearchRequest + ): Promise>; + client: ElasticsearchClient; +} + +export function createObservabilityEsClient({ + client, + logger, + plugin, +}: { + client: ElasticsearchClient; + logger: Logger; + plugin: string; +}): ObservabilityElasticsearchClient { + return { + client, + search( + operationName: string, + parameters: SearchRequest + ) { + logger.trace(() => `Request (${operationName}):\n${JSON.stringify(parameters, null, 2)}`); + // wraps the search operation in a named APM span for better analysis + // (otherwise it would just be a _search span) + return withSpan( + { + name: operationName, + labels: { + plugin, + }, + }, + () => { + return client.search(parameters) as unknown as Promise< + InferSearchResponseOf + >; + } + ).then((response) => { + logger.trace(() => `Response (${operationName}):\n${JSON.stringify(response, null, 2)}`); + return response; + }); + }, + }; +} diff --git a/x-pack/packages/observability/observability_utils/es/queries/kql_query.ts b/x-pack/packages/observability/observability_utils/es/queries/kql_query.ts new file mode 100644 index 0000000000000..2f560157cc8c6 --- /dev/null +++ b/x-pack/packages/observability/observability_utils/es/queries/kql_query.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { estypes } from '@elastic/elasticsearch'; +import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; + +export function kqlQuery(kql?: string): estypes.QueryDslQueryContainer[] { + if (!kql) { + return []; + } + + const ast = fromKueryExpression(kql); + return [toElasticsearchQuery(ast)]; +} diff --git a/x-pack/packages/observability/observability_utils/es/queries/range_query.ts b/x-pack/packages/observability/observability_utils/es/queries/range_query.ts new file mode 100644 index 0000000000000..d73476354c377 --- /dev/null +++ b/x-pack/packages/observability/observability_utils/es/queries/range_query.ts @@ -0,0 +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. + */ +import type { estypes } from '@elastic/elasticsearch'; + +export function rangeQuery( + start?: number, + end?: number, + field = '@timestamp' +): estypes.QueryDslQueryContainer[] { + return [ + { + range: { + [field]: { + gte: start, + lte: end, + format: 'epoch_millis', + }, + }, + }, + ]; +} diff --git a/x-pack/packages/observability/observability_utils/es/queries/term_query.ts b/x-pack/packages/observability/observability_utils/es/queries/term_query.ts new file mode 100644 index 0000000000000..dfaeb737bf8b7 --- /dev/null +++ b/x-pack/packages/observability/observability_utils/es/queries/term_query.ts @@ -0,0 +1,24 @@ +/* + * 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 { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; + +interface TermQueryOpts { + queryEmptyString: boolean; +} + +export function termQuery( + field: T, + value: string | boolean | number | undefined | null, + opts: TermQueryOpts = { queryEmptyString: true } +): QueryDslQueryContainer[] { + if (value === null || value === undefined || (!opts.queryEmptyString && value === '')) { + return []; + } + + return [{ term: { [field]: value } }]; +} diff --git a/x-pack/packages/observability/observability_utils/hooks/use_abort_controller.ts b/x-pack/packages/observability/observability_utils/hooks/use_abort_controller.ts new file mode 100644 index 0000000000000..a383e7b81b4d9 --- /dev/null +++ b/x-pack/packages/observability/observability_utils/hooks/use_abort_controller.ts @@ -0,0 +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. + */ + +import { useEffect, useState } from 'react'; + +export function useAbortController() { + const [controller, setController] = useState(() => new AbortController()); + + useEffect(() => { + return () => { + controller.abort(); + }; + }, [controller]); + + return { + signal: controller.signal, + refresh: () => { + setController(() => new AbortController()); + }, + }; +} diff --git a/x-pack/packages/observability/observability_utils/hooks/use_abortable_async.ts b/x-pack/packages/observability/observability_utils/hooks/use_abortable_async.ts new file mode 100644 index 0000000000000..433ca877b0f62 --- /dev/null +++ b/x-pack/packages/observability/observability_utils/hooks/use_abortable_async.ts @@ -0,0 +1,87 @@ +/* + * 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 { isPromise } from '@kbn/std'; +import { useEffect, useMemo, useRef, useState } from 'react'; + +interface State { + error?: Error; + value?: T; + loading: boolean; +} + +export type AbortableAsyncState = (T extends Promise + ? State + : State) & { refresh: () => void }; + +export function useAbortableAsync( + fn: ({}: { signal: AbortSignal }) => T | Promise, + deps: any[], + options?: { clearValueOnNext?: boolean; defaultValue?: () => T } +): AbortableAsyncState { + const clearValueOnNext = options?.clearValueOnNext; + + const controllerRef = useRef(new AbortController()); + + const [refreshId, setRefreshId] = useState(0); + + const [error, setError] = useState(); + const [loading, setLoading] = useState(false); + const [value, setValue] = useState(options?.defaultValue); + + useEffect(() => { + controllerRef.current.abort(); + + const controller = new AbortController(); + controllerRef.current = controller; + + if (clearValueOnNext) { + setValue(undefined); + setError(undefined); + } + + try { + const response = fn({ signal: controller.signal }); + if (isPromise(response)) { + setLoading(true); + response + .then((nextValue) => { + setError(undefined); + setValue(nextValue); + }) + .catch((err) => { + setValue(undefined); + setError(err); + }) + .finally(() => setLoading(false)); + } else { + setError(undefined); + setValue(response); + setLoading(false); + } + } catch (err) { + setValue(undefined); + setError(err); + setLoading(false); + } + + return () => { + controller.abort(); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, deps.concat(refreshId, clearValueOnNext)); + + return useMemo>(() => { + return { + error, + loading, + value, + refresh: () => { + setRefreshId((id) => id + 1); + }, + } as unknown as AbortableAsyncState; + }, [error, value, loading]); +} diff --git a/x-pack/packages/observability/observability_utils/hooks/use_theme.ts b/x-pack/packages/observability/observability_utils/hooks/use_theme.ts new file mode 100644 index 0000000000000..d0b4ce61edef4 --- /dev/null +++ b/x-pack/packages/observability/observability_utils/hooks/use_theme.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useEuiTheme } from '@elastic/eui'; + +export function useTheme() { + return useEuiTheme().euiTheme; +} diff --git a/x-pack/packages/observability/observability_utils/jest.config.js b/x-pack/packages/observability/observability_utils/jest.config.js new file mode 100644 index 0000000000000..c9dff28ed6cec --- /dev/null +++ b/x-pack/packages/observability/observability_utils/jest.config.js @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/x-pack/packages/observability/observability_utils'], +}; diff --git a/x-pack/packages/observability/observability_utils/kibana.jsonc b/x-pack/packages/observability/observability_utils/kibana.jsonc new file mode 100644 index 0000000000000..096b2565d533f --- /dev/null +++ b/x-pack/packages/observability/observability_utils/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/observability-utils", + "owner": "@elastic/observability-ui" +} diff --git a/x-pack/packages/observability/observability_utils/object/flatten_object.test.ts b/x-pack/packages/observability/observability_utils/object/flatten_object.test.ts new file mode 100644 index 0000000000000..deb7ed998c478 --- /dev/null +++ b/x-pack/packages/observability/observability_utils/object/flatten_object.test.ts @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { flattenObject } from './flatten_object'; + +describe('flattenObject', () => { + it('flattens deeply nested objects', () => { + expect( + flattenObject({ + first: { + second: { + third: 'third', + }, + }, + }) + ).toEqual({ + 'first.second.third': 'third', + }); + }); + + it('does not flatten arrays', () => { + expect( + flattenObject({ + simpleArray: ['0', '1', '2'], + complexArray: [{ one: 'one', two: 'two', three: 'three' }], + nested: { + array: [0, 1, 2], + }, + }) + ).toEqual({ + simpleArray: ['0', '1', '2'], + complexArray: [{ one: 'one', two: 'two', three: 'three' }], + 'nested.array': [0, 1, 2], + }); + }); +}); diff --git a/x-pack/packages/observability/observability_utils/object/flatten_object.ts b/x-pack/packages/observability/observability_utils/object/flatten_object.ts new file mode 100644 index 0000000000000..c83ae8a102d4a --- /dev/null +++ b/x-pack/packages/observability/observability_utils/object/flatten_object.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +type PlainObject = Record; + +/** + * Flattens an object into key-value pairs with dots as separators. + * + * @param obj + * @param prefix + * @param result + * @returns + */ +export function flattenObject( + obj: PlainObject, + prefix: string = '', + result: PlainObject = {} +): PlainObject { + for (const key in obj) { + if (Object.hasOwn(obj, key)) { + const newKey = prefix ? `${prefix}.${key}` : key; + // If the property value is an object and not an array or null, recurse + // (array keys are not flattened because that gets a little weird I think) + if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) { + flattenObject(obj[key], newKey, result); + } else { + // Otherwise, add the value to the result object + result[newKey] = obj[key]; + } + } + } + return result; +} diff --git a/x-pack/packages/observability/observability_utils/object/merge_plain_object.test.ts b/x-pack/packages/observability/observability_utils/object/merge_plain_object.test.ts new file mode 100644 index 0000000000000..02049f1a756c2 --- /dev/null +++ b/x-pack/packages/observability/observability_utils/object/merge_plain_object.test.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { mergePlainObjects } from './merge_plain_objects'; + +describe('mergePlainObjects', () => { + it('recursively merges plain objects', () => { + expect( + mergePlainObjects({}, { foo: { bar: 'baz' } }, { foo: { baz: 'rab', bar: 'baz' } }) + ).toEqual({ + foo: { + bar: 'baz', + baz: 'rab', + }, + }); + }); + + it('overrides arrays', () => { + expect(mergePlainObjects({ myArray: [0, 1, 2, 3] }, { myArray: [4, 5, 6] })).toEqual({ + myArray: [4, 5, 6], + }); + }); + + it('overrides all primitives', () => { + expect( + mergePlainObjects( + { number: 'number', boolean: 'boolean', string: 'string', null: null }, + { number: 'num', boolean: 'bool', string: 'str' } + ) + ).toEqual({ + number: 'num', + boolean: 'bool', + string: 'str', + null: null, + }); + }); +}); diff --git a/x-pack/packages/observability/observability_utils/object/merge_plain_objects.ts b/x-pack/packages/observability/observability_utils/object/merge_plain_objects.ts new file mode 100644 index 0000000000000..e7c1042ac6581 --- /dev/null +++ b/x-pack/packages/observability/observability_utils/object/merge_plain_objects.ts @@ -0,0 +1,84 @@ +/* + * 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 { RequiredKeys } from 'utility-types'; +import { isPlainObject, mergeWith, MergeWithCustomizer } from 'lodash'; + +type DeepOverwrite = U extends Record + ? Omit> & { + [K in keyof U]: K extends keyof T ? DeepOverwrite : U[K]; + } + : U extends undefined + ? T + : U; + +type DeepPartialPlainObjects = T extends Record + ? Partial> & + Partial<{ + [TKey in keyof T]: DeepPartialPlainObjects; + }> + : T; + +type Mergable = Record; + +type MergeRecursively = TMergables extends [ + infer THead, + ...infer TTail +] + ? TTail extends Mergable[] + ? DeepOverwrite> + : THead + : TMergables extends [infer THead] + ? THead + : TMergables extends [] + ? {} + : {}; + +const customMergeFunction: MergeWithCustomizer = (value, sourceValue) => { + if (isPlainObject(sourceValue)) { + return mergeWith(value, sourceValue, customMergeFunction); + } + return sourceValue; +}; + +function mergePlainObjectsOnly(...sources: Mergable[]) { + return mergeWith({}, ...sources.concat(customMergeFunction)); +} + +export function mergePlainObjects | undefined>(t1: T1): T1; + +export function mergePlainObjects>( + t1: T1, + t2: T2 +): MergeRecursively<[T1, T2]>; + +export function mergePlainObjects< + T1 extends Mergable, + T2 extends DeepPartialPlainObjects, + T3 extends DeepPartialPlainObjects +>(t1: T1, t2: T2, t3: T3): MergeRecursively<[T1, T2, T3]>; + +export function mergePlainObjects< + T1 extends Mergable, + T2 extends DeepPartialPlainObjects, + T3 extends DeepPartialPlainObjects, + T4 extends DeepPartialPlainObjects +>(t1: T1, t2: T2, t3: T4): MergeRecursively<[T1, T2, T3, T4]>; +/** + * Merges plain objects. It does two things over merge: + * + * - it expects the objects to be extensions of the type of + * the source object, to provide type autocompletions + * - arrays are not merged but overridden + * + * @param sources + * @returns + */ +export function mergePlainObjects(...sources: Array>) { + const merged = mergePlainObjectsOnly(...sources); + + return merged; +} diff --git a/x-pack/packages/observability/observability_utils/package.json b/x-pack/packages/observability/observability_utils/package.json new file mode 100644 index 0000000000000..06f6e37858927 --- /dev/null +++ b/x-pack/packages/observability/observability_utils/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/observability-utils", + "private": true, + "version": "1.0.0", + "license": "Elastic License 2.0" +} \ No newline at end of file diff --git a/x-pack/packages/observability/observability_utils/tsconfig.json b/x-pack/packages/observability/observability_utils/tsconfig.json new file mode 100644 index 0000000000000..2ed47d10cfad9 --- /dev/null +++ b/x-pack/packages/observability/observability_utils/tsconfig.json @@ -0,0 +1,25 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/std", + "@kbn/core", + "@kbn/es-types", + "@kbn/apm-utils", + "@kbn/es-query", + ] +} diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/constants.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/constants.ts index 26fe2698f077c..25ea07b9d5f27 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/constants.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/constants.ts @@ -8,7 +8,7 @@ import { EcsFlat } from '@elastic/ecs'; import { EuiComboBoxOptionOption } from '@elastic/eui'; -import { EcsFieldMetadata } from './types'; +import { EcsFieldMetadata, PartitionedFieldMetadata, SortConfig } from './types'; import * as i18n from './translations'; export const EcsFlatTyped = EcsFlat as unknown as Record; @@ -42,3 +42,28 @@ export const ilmPhaseOptionsStatic: EuiComboBoxOptionOption[] = [ export const EMPTY_STAT = '--'; export const INTERNAL_API_VERSION = '1'; + +export const defaultSort: SortConfig = { + sort: { + direction: 'desc', + field: 'docsCount', + }, +}; + +export const EMPTY_METADATA: PartitionedFieldMetadata = { + all: [], + ecsCompliant: [], + custom: [], + incompatible: [], + sameFamily: [], +}; + +export const EMPTY_PLACEHOLDER = '--'; + +export const ECS_FIELD_REFERENCE_URL = + 'https://www.elastic.co/guide/en/ecs/current/ecs-field-reference.html'; + +/** The documentation link shown in the `Data Quality` dashboard */ +export const ECS_REFERENCE_URL = 'https://www.elastic.co/guide/en/ecs/current/ecs-reference.html'; +export const MAPPING_URL = + 'https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html'; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/ilm_phases_empty_prompt/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/ilm_phases_empty_prompt/index.tsx index c8a6e7385a122..fe5c4cf59e8a8 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/ilm_phases_empty_prompt/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/ilm_phases_empty_prompt/index.tsx @@ -15,6 +15,11 @@ import { HOT_DESCRIPTION, UNMANAGED_DESCRIPTION, WARM_DESCRIPTION, + HOT, + WARM, + FROZEN, + COLD, + UNMANAGED, } from '../../translations'; import * as i18n from './translations'; @@ -41,17 +46,17 @@ const IlmPhasesEmptyPromptComponent: React.FC = () => {
  • - {i18n.HOT} + {HOT} {': '} {HOT_DESCRIPTION}
  • - {i18n.WARM} + {WARM} {': '} {WARM_DESCRIPTION}
  • - {i18n.UNMANAGED} + {UNMANAGED} {': '} {UNMANAGED_DESCRIPTION}
  • @@ -71,12 +76,12 @@ const IlmPhasesEmptyPromptComponent: React.FC = () => {
    • - {i18n.COLD} + {COLD} {': '} {COLD_DESCRIPTION}
    • - {i18n.FROZEN} + {FROZEN} {': '} {FROZEN_DESCRIPTION}
    • diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/ilm_phases_empty_prompt/translations.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/ilm_phases_empty_prompt/translations.ts index 08a39d5b64d22..1b0e3b1dd10cd 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/ilm_phases_empty_prompt/translations.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/ilm_phases_empty_prompt/translations.ts @@ -15,27 +15,6 @@ export const BODY = i18n.translate( } ); -export const COLD = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptColdLabel', - { - defaultMessage: 'cold', - } -); - -export const FROZEN = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptFrozenLabel', - { - defaultMessage: 'frozen', - } -); - -export const HOT = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptHotLabel', - { - defaultMessage: 'hot', - } -); - export const ILM_PHASES_THAT_CAN_BE_CHECKED = i18n.translate( 'securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptIlmPhasesThatCanBeCheckedSubtitle', { @@ -58,20 +37,6 @@ export const THE_FOLLOWING_ILM_PHASES = i18n.translate( } ); -export const UNMANAGED = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptUnmanagedLabel', - { - defaultMessage: 'unmanaged', - } -); - -export const WARM = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptWarmLabel', - { - defaultMessage: 'warm', - } -); - export const TITLE = i18n.translate( 'securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptTitle', { diff --git a/x-pack/plugins/observability_solution/investigate/public/esql_widget/constants.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/constants.ts similarity index 86% rename from x-pack/plugins/observability_solution/investigate/public/esql_widget/constants.ts rename to x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/constants.ts index 068d4b49fcf80..634f2cd8f59cc 100644 --- a/x-pack/plugins/observability_solution/investigate/public/esql_widget/constants.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/constants.ts @@ -5,4 +5,4 @@ * 2.0. */ -export const ESQL_WIDGET_NAME = 'esql'; +export const MIN_PAGE_SIZE = 10; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/error_empty_prompt/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/error_empty_prompt/index.tsx index 3bac63944838b..da2f51dc6485b 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/error_empty_prompt/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/error_empty_prompt/index.tsx @@ -8,7 +8,7 @@ import { EuiCallOut, EuiCode } from '@elastic/eui'; import React from 'react'; -import * as i18n from '../../../../data_quality_summary/summary_actions/check_status/errors_popover/translations'; +import * as i18n from '../../../../translations'; interface Props { title: string; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/helpers.test.ts deleted file mode 100644 index 56dc6364ba845..0000000000000 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/helpers.test.ts +++ /dev/null @@ -1,1017 +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 { - IlmExplainLifecycleLifecycleExplain, - IlmExplainLifecycleLifecycleExplainManaged, - IlmExplainLifecycleLifecycleExplainUnmanaged, -} from '@elastic/elasticsearch/lib/api/types'; - -import { - defaultSort, - getIlmPhase, - getIndexPropertiesContainerId, - getIlmExplainPhaseCounts, - getIndexIncompatible, - getPageIndex, - getPhaseCount, - getSummaryTableItems, - isManaged, - shouldCreateIndexNames, - shouldCreatePatternRollup, -} from './helpers'; -import { mockIlmExplain } from '../../../mock/ilm_explain/mock_ilm_explain'; -import { mockDataQualityCheckResult } from '../../../mock/data_quality_check_result/mock_index'; -import { auditbeatWithAllResults } from '../../../mock/pattern_rollup/mock_auditbeat_pattern_rollup'; -import { mockStats } from '../../../mock/stats/mock_stats'; -import { DataQualityCheckResult } from '../../../types'; -import { IndexSummaryTableItem } from './types'; -import { getIndexNames, getPatternDocsCount } from './utils/stats'; - -const hot: IlmExplainLifecycleLifecycleExplainManaged = { - index: '.ds-packetbeat-8.6.1-2023.02.04-000001', - managed: true, - policy: 'packetbeat', - index_creation_date_millis: 1675536751379, - time_since_index_creation: '3.98d', - lifecycle_date_millis: 1675536751379, - age: '3.98d', - phase: 'hot', - phase_time_millis: 1675536751809, - action: 'rollover', - action_time_millis: 1675536751809, - step: 'check-rollover-ready', - step_time_millis: 1675536751809, - phase_execution: { - policy: 'packetbeat', - version: 1, - modified_date_in_millis: 1675536751205, - }, -}; -const warm = { - ...hot, - phase: 'warm', -}; -const cold = { - ...hot, - phase: 'cold', -}; -const frozen = { - ...hot, - phase: 'frozen', -}; -const other = { - ...hot, - phase: 'other', // not a valid phase -}; - -const managed: Record = { - hot, - warm, - cold, - frozen, -}; - -const unmanaged: IlmExplainLifecycleLifecycleExplainUnmanaged = { - index: 'michael', - managed: false, -}; - -describe('helpers', () => { - const indexName = '.ds-packetbeat-8.6.1-2023.02.04-000001'; - - describe('isManaged', () => { - test('it returns true when the `ilmExplainRecord` `managed` property is true', () => { - const ilmExplain = mockIlmExplain[indexName]; - - expect(isManaged(ilmExplain)).toBe(true); - }); - - test('it returns false when the `ilmExplainRecord` is undefined', () => { - expect(isManaged(undefined)).toBe(false); - }); - }); - - describe('getPhaseCount', () => { - test('it returns the expected count when an index with the specified `ilmPhase` exists in the `IlmExplainLifecycleLifecycleExplain` record', () => { - expect( - getPhaseCount({ - ilmExplain: mockIlmExplain, - ilmPhase: 'hot', // this phase is in the record - indexName, // valid index name - }) - ).toEqual(1); - }); - - test('it returns zero when `ilmPhase` is null', () => { - expect( - getPhaseCount({ - ilmExplain: null, - ilmPhase: 'hot', - indexName, - }) - ).toEqual(0); - }); - - test('it returns zero when the `indexName` does NOT exist in the `IlmExplainLifecycleLifecycleExplain` record', () => { - expect( - getPhaseCount({ - ilmExplain: mockIlmExplain, - ilmPhase: 'hot', - indexName: 'invalid', // this index does NOT exist - }) - ).toEqual(0); - }); - - test('it returns zero when the specified `ilmPhase` does NOT exist in the `IlmExplainLifecycleLifecycleExplain` record', () => { - expect( - getPhaseCount({ - ilmExplain: mockIlmExplain, - ilmPhase: 'warm', // this phase is NOT in the record - indexName, // valid index name - }) - ).toEqual(0); - }); - - describe('when `ilmPhase` is `unmanaged`', () => { - test('it returns the expected count for an `unmanaged` index', () => { - const index = 'auditbeat-custom-index-1'; - const ilmExplainRecord: IlmExplainLifecycleLifecycleExplain = { - index, - managed: false, - }; - const ilmExplain = { - [index]: ilmExplainRecord, - }; - - expect( - getPhaseCount({ - ilmExplain, - ilmPhase: 'unmanaged', // ilmPhase is unmanaged - indexName: index, // an unmanaged index - }) - ).toEqual(1); - }); - - test('it returns zero for a managed index', () => { - expect( - getPhaseCount({ - ilmExplain: mockIlmExplain, - ilmPhase: 'unmanaged', // ilmPhase is unmanaged - indexName, // a managed (`hot`) index - }) - ).toEqual(0); - }); - }); - }); - - describe('getIlmPhase', () => { - const isILMAvailable = true; - test('it returns undefined when the `ilmExplainRecord` is undefined', () => { - expect(getIlmPhase(undefined, isILMAvailable)).toBeUndefined(); - }); - - describe('when the `ilmExplainRecord` is a `IlmExplainLifecycleLifecycleExplainManaged` record', () => { - Object.keys(managed).forEach((phase) => - test(`it returns the expected phase when 'phase' is '${phase}'`, () => { - expect(getIlmPhase(managed[phase], isILMAvailable)).toEqual(phase); - }) - ); - - test(`it returns undefined when the 'phase' is unknown`, () => { - expect(getIlmPhase(other, isILMAvailable)).toBeUndefined(); - }); - }); - - describe('when the `ilmExplainRecord` is a `IlmExplainLifecycleLifecycleExplainUnmanaged` record', () => { - test('it returns `unmanaged`', () => { - expect(getIlmPhase(unmanaged, isILMAvailable)).toEqual('unmanaged'); - }); - }); - }); - - describe('getIlmExplainPhaseCounts', () => { - test('it returns the expected counts (all zeros) when `ilmExplain` is null', () => { - expect(getIlmExplainPhaseCounts(null)).toEqual({ - cold: 0, - frozen: 0, - hot: 0, - unmanaged: 0, - warm: 0, - }); - }); - - test('it returns the expected counts', () => { - const ilmExplain: Record = { - ...managed, - [unmanaged.index]: unmanaged, - }; - - expect(getIlmExplainPhaseCounts(ilmExplain)).toEqual({ - cold: 1, - frozen: 1, - hot: 1, - unmanaged: 1, - warm: 1, - }); - }); - }); - - describe('getIndexIncompatible', () => { - test('it returns undefined when `results` is undefined', () => { - expect( - getIndexIncompatible({ - indexName, - results: undefined, // <-- - }) - ).toBeUndefined(); - }); - - test('it returns undefined when `indexName` is not in the `results`', () => { - expect( - getIndexIncompatible({ - indexName: 'not_in_the_results', // <-- - results: mockDataQualityCheckResult, - }) - ).toBeUndefined(); - }); - - test('it returns the expected count', () => { - expect( - getIndexIncompatible({ - indexName: 'auditbeat-custom-index-1', - results: mockDataQualityCheckResult, - }) - ).toEqual(3); - }); - }); - - describe('getSummaryTableItems', () => { - const indexNames = [ - '.ds-packetbeat-8.6.1-2023.02.04-000001', - '.ds-packetbeat-8.5.3-2023.02.04-000001', - 'auditbeat-custom-index-1', - ]; - const pattern = 'auditbeat-*'; - const patternDocsCount = 4; - const results: Record = { - 'auditbeat-custom-index-1': { - docsCount: 4, - error: null, - ilmPhase: 'unmanaged', - incompatible: 3, - indexName: 'auditbeat-custom-index-1', - markdownComments: [ - '### auditbeat-custom-index-1\n', - '| Result | Index | Docs | Incompatible fields | ILM Phase |\n|--------|-------|------|---------------------|-----------|\n| ❌ | auditbeat-custom-index-1 | 4 (0.0%) | 3 | `unmanaged` |\n\n', - '### **Incompatible fields** `3` **Custom fields** `4` **ECS compliant fields** `2` **All fields** `9`\n', - "#### 3 incompatible fields, 0 fields with mappings in the same family\n\nFields are incompatible with ECS when index mappings, or the values of the fields in the index, don't conform to the Elastic Common Schema (ECS), version 8.6.1.\n\nIncompatible fields with mappings in the same family have exactly the same search behavior but may have different space usage or performance characteristics.\n\nWhen an incompatible field is not in the same family:\n❌ Detection engine rules referencing these fields may not match them correctly\n❌ Pages may not display some events or fields due to unexpected field mappings or values\n❌ Mappings or field values that don't comply with ECS are not supported\n", - '\n#### Incompatible field mappings - auditbeat-custom-index-1\n\n\n| Field | ECS mapping type (expected) | Index mapping type (actual) | \n|-------|-----------------------------|-----------------------------|\n| host.name | `keyword` | `text` |\n| source.ip | `ip` | `text` |\n\n#### Incompatible field values - auditbeat-custom-index-1\n\n\n| Field | ECS values (expected) | Document values (actual) | \n|-------|-----------------------|--------------------------|\n| event.category | `authentication`, `configuration`, `database`, `driver`, `email`, `file`, `host`, `iam`, `intrusion_detection`, `malware`, `network`, `package`, `process`, `registry`, `session`, `threat`, `vulnerability`, `web` | `an_invalid_category` (2),\n`theory` (1) |\n\n', - ], - pattern: 'auditbeat-*', - sameFamily: 0, - checkedAt: 1706526408000, - }, - }; - const isILMAvailable = true; - - test('it returns the expected summary table items', () => { - expect( - getSummaryTableItems({ - ilmExplain: mockIlmExplain, - indexNames, - isILMAvailable, - pattern, - patternDocsCount, - results, - sortByColumn: defaultSort.sort.field, - sortByDirection: defaultSort.sort.direction, - stats: mockStats, - }) - ).toEqual([ - { - docsCount: 1630289, - ilmPhase: 'hot', - incompatible: undefined, - indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', - pattern: 'auditbeat-*', - patternDocsCount: 4, - sizeInBytes: 733175040, - checkedAt: undefined, - }, - { - docsCount: 1628343, - ilmPhase: 'hot', - incompatible: undefined, - indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', - pattern: 'auditbeat-*', - patternDocsCount: 4, - sizeInBytes: 731583142, - checkedAt: undefined, - }, - { - docsCount: 4, - ilmPhase: 'unmanaged', - incompatible: 3, - indexName: 'auditbeat-custom-index-1', - pattern: 'auditbeat-*', - patternDocsCount: 4, - sizeInBytes: 28413, - checkedAt: 1706526408000, - }, - ]); - }); - - test('it returns the expected summary table items when isILMAvailable is false', () => { - expect( - getSummaryTableItems({ - ilmExplain: mockIlmExplain, - indexNames, - isILMAvailable: false, - pattern, - patternDocsCount, - results, - sortByColumn: defaultSort.sort.field, - sortByDirection: defaultSort.sort.direction, - stats: mockStats, - }) - ).toEqual([ - { - docsCount: 1630289, - ilmPhase: undefined, - incompatible: undefined, - indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', - pattern: 'auditbeat-*', - patternDocsCount: 4, - sizeInBytes: 733175040, - checkedAt: undefined, - }, - { - docsCount: 1628343, - ilmPhase: undefined, - incompatible: undefined, - indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', - pattern: 'auditbeat-*', - patternDocsCount: 4, - sizeInBytes: 731583142, - checkedAt: undefined, - }, - { - docsCount: 4, - ilmPhase: undefined, - incompatible: 3, - indexName: 'auditbeat-custom-index-1', - pattern: 'auditbeat-*', - patternDocsCount: 4, - sizeInBytes: 28413, - checkedAt: 1706526408000, - }, - ]); - }); - - test('it returns the expected summary table items when `sortByDirection` is ascending', () => { - expect( - getSummaryTableItems({ - ilmExplain: mockIlmExplain, - indexNames, - isILMAvailable, - pattern, - patternDocsCount, - results, - sortByColumn: defaultSort.sort.field, - sortByDirection: 'asc', // <-- ascending - stats: mockStats, - }) - ).toEqual([ - { - docsCount: 4, - ilmPhase: 'unmanaged', - incompatible: 3, - indexName: 'auditbeat-custom-index-1', - pattern: 'auditbeat-*', - patternDocsCount: 4, - sizeInBytes: 28413, - checkedAt: 1706526408000, - }, - { - docsCount: 1628343, - ilmPhase: 'hot', - incompatible: undefined, - indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', - pattern: 'auditbeat-*', - patternDocsCount: 4, - sizeInBytes: 731583142, - checkedAt: undefined, - }, - { - docsCount: 1630289, - ilmPhase: 'hot', - incompatible: undefined, - indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', - pattern: 'auditbeat-*', - patternDocsCount: 4, - sizeInBytes: 733175040, - checkedAt: undefined, - }, - ]); - }); - - test('it returns the expected summary table items when data is unavailable', () => { - expect( - getSummaryTableItems({ - ilmExplain: null, // <-- no data - indexNames, - isILMAvailable, - pattern, - patternDocsCount, - results: undefined, // <-- no data - sortByColumn: defaultSort.sort.field, - sortByDirection: defaultSort.sort.direction, - stats: null, // <-- no data - }) - ).toEqual([ - { - docsCount: 0, - ilmPhase: undefined, - incompatible: undefined, - indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', - pattern: 'auditbeat-*', - patternDocsCount: 4, - sizeInBytes: undefined, - checkedAt: undefined, - }, - { - docsCount: 0, - ilmPhase: undefined, - incompatible: undefined, - indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', - pattern: 'auditbeat-*', - patternDocsCount: 4, - sizeInBytes: undefined, - checkedAt: undefined, - }, - { - docsCount: 0, - ilmPhase: undefined, - incompatible: undefined, - indexName: 'auditbeat-custom-index-1', - pattern: 'auditbeat-*', - patternDocsCount: 4, - sizeInBytes: undefined, - checkedAt: undefined, - }, - ]); - }); - }); - - describe('shouldCreateIndexNames', () => { - const indexNames = [ - '.ds-packetbeat-8.6.1-2023.02.04-000001', - '.ds-packetbeat-8.5.3-2023.02.04-000001', - 'auditbeat-custom-index-1', - ]; - const isILMAvailable = true; - - test('returns true when `indexNames` does NOT exist, and the required `stats` and `ilmExplain` are available', () => { - expect( - shouldCreateIndexNames({ - ilmExplain: mockIlmExplain, - indexNames: undefined, - isILMAvailable, - newIndexNames: [], - stats: mockStats, - }) - ).toBe(true); - }); - - test('returns true when `isILMAvailable` is false, and the required `stats` is available, and `ilmExplain` is not available', () => { - expect( - shouldCreateIndexNames({ - ilmExplain: null, - indexNames: undefined, - isILMAvailable: false, - newIndexNames: [], - stats: mockStats, - }) - ).toBe(true); - }); - - test('returns false when `indexNames` exists, and the required `stats` and `ilmExplain` are available', () => { - expect( - shouldCreateIndexNames({ - ilmExplain: mockIlmExplain, - indexNames, - isILMAvailable, - newIndexNames: indexNames, - stats: mockStats, - }) - ).toBe(false); - }); - - test('returns false when `indexNames` does NOT exist, `stats` is NOT available, and `ilmExplain` is available', () => { - expect( - shouldCreateIndexNames({ - ilmExplain: mockIlmExplain, - indexNames: undefined, - isILMAvailable, - newIndexNames: [], - stats: null, - }) - ).toBe(false); - }); - - test('returns false when `indexNames` does NOT exist, `stats` is available, and `ilmExplain` is NOT available', () => { - expect( - shouldCreateIndexNames({ - ilmExplain: null, - indexNames: undefined, - isILMAvailable, - newIndexNames: [], - stats: mockStats, - }) - ).toBe(false); - }); - - test('returns false when `indexNames` does NOT exist, `stats` is NOT available, and `ilmExplain` is NOT available', () => { - expect( - shouldCreateIndexNames({ - ilmExplain: null, - indexNames: undefined, - isILMAvailable, - newIndexNames: [], - stats: null, - }) - ).toBe(false); - }); - - test('returns false when `indexNames` exists, `stats` is NOT available, and `ilmExplain` is NOT available', () => { - expect( - shouldCreateIndexNames({ - ilmExplain: null, - indexNames, - isILMAvailable, - newIndexNames: [], - stats: null, - }) - ).toBe(false); - }); - }); - - describe('shouldCreatePatternRollup', () => { - const isILMAvailable = true; - const newIndexNames = getIndexNames({ - stats: mockStats, - ilmExplain: mockIlmExplain, - ilmPhases: ['hot', 'unmanaged'], - isILMAvailable, - }); - const newDocsCount = getPatternDocsCount({ indexNames: newIndexNames, stats: mockStats }); - test('it returns false when the `patternRollup.docsCount` equals newDocsCount', () => { - expect( - shouldCreatePatternRollup({ - error: null, - ilmExplain: mockIlmExplain, - isILMAvailable, - newDocsCount: auditbeatWithAllResults.docsCount as number, - patternRollup: auditbeatWithAllResults, - stats: mockStats, - }) - ).toBe(false); - }); - - test('it returns true when all data and ILMExplain were loaded', () => { - expect( - shouldCreatePatternRollup({ - error: null, - ilmExplain: mockIlmExplain, - isILMAvailable, - newDocsCount, - patternRollup: undefined, - stats: mockStats, - }) - ).toBe(true); - }); - - test('it returns true when all data was loaded and ILM is not available', () => { - expect( - shouldCreatePatternRollup({ - error: null, - ilmExplain: null, - isILMAvailable: false, - newDocsCount, - patternRollup: undefined, - stats: mockStats, - }) - ).toBe(true); - }); - - test('it returns false when `stats`, but NOT `ilmExplain` was loaded', () => { - expect( - shouldCreatePatternRollup({ - error: null, - ilmExplain: null, - isILMAvailable, - newDocsCount, - patternRollup: undefined, - stats: mockStats, - }) - ).toBe(false); - }); - - test('it returns false when `stats` was NOT loaded, and `ilmExplain` was loaded', () => { - expect( - shouldCreatePatternRollup({ - error: null, - ilmExplain: mockIlmExplain, - isILMAvailable, - newDocsCount, - patternRollup: undefined, - stats: null, - }) - ).toBe(false); - }); - - test('it returns true if an error occurred, and NO data was loaded', () => { - expect( - shouldCreatePatternRollup({ - error: 'whoops', - ilmExplain: null, - isILMAvailable, - newDocsCount, - patternRollup: undefined, - stats: null, - }) - ).toBe(true); - }); - - test('it returns true if an error occurred, and just `stats` was loaded', () => { - expect( - shouldCreatePatternRollup({ - error: 'something went', - ilmExplain: null, - isILMAvailable, - newDocsCount, - patternRollup: undefined, - stats: mockStats, - }) - ).toBe(true); - }); - - test('it returns true if an error occurred, and just `ilmExplain` was loaded', () => { - expect( - shouldCreatePatternRollup({ - error: 'horribly wrong', - ilmExplain: mockIlmExplain, - isILMAvailable, - newDocsCount, - patternRollup: undefined, - stats: null, - }) - ).toBe(true); - }); - - test('it returns true if an error occurred, and all data was loaded', () => { - expect( - shouldCreatePatternRollup({ - error: 'over here', - ilmExplain: mockIlmExplain, - isILMAvailable, - newDocsCount, - patternRollup: undefined, - stats: mockStats, - }) - ).toBe(true); - }); - }); - - describe('getIndexPropertiesContainerId', () => { - const pattern = 'auditbeat-*'; - - test('it returns the expected id', () => { - expect(getIndexPropertiesContainerId({ indexName, pattern })).toEqual( - 'index-properties-container-auditbeat-*.ds-packetbeat-8.6.1-2023.02.04-000001' - ); - }); - }); - - describe('getPageIndex', () => { - const getPageIndexArgs: { - indexName: string; - items: IndexSummaryTableItem[]; - pageSize: number; - } = { - indexName: 'auditbeat-7.17.9-2023.04.09-000001', // <-- on page 2 of 3 (page index 1) - items: [ - { - docsCount: 48077, - incompatible: undefined, - indexName: 'auditbeat-7.14.2-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 43357342, - checkedAt: 1706526408000, - }, - { - docsCount: 48068, - incompatible: undefined, - indexName: 'auditbeat-7.3.2-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 32460397, - checkedAt: 1706526408000, - }, - { - docsCount: 48064, - incompatible: undefined, - indexName: 'auditbeat-7.11.2-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 42782794, - checkedAt: 1706526408000, - }, - { - docsCount: 47868, - incompatible: undefined, - indexName: 'auditbeat-7.6.2-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 31575964, - checkedAt: 1706526408000, - }, - { - docsCount: 47827, - incompatible: 20, - indexName: 'auditbeat-7.15.2-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 44130657, - checkedAt: 1706526408000, - }, - { - docsCount: 47642, - incompatible: undefined, - indexName: '.ds-auditbeat-8.4.3-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 42412521, - checkedAt: 1706526408000, - }, - { - docsCount: 47545, - incompatible: undefined, - indexName: 'auditbeat-7.16.3-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 41423244, - checkedAt: 1706526408000, - }, - { - docsCount: 47531, - incompatible: undefined, - indexName: 'auditbeat-7.5.2-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 32394133, - checkedAt: 1706526408000, - }, - { - docsCount: 47530, - incompatible: undefined, - indexName: 'auditbeat-7.12.1-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 43015519, - checkedAt: 1706526408000, - }, - { - docsCount: 47520, - incompatible: undefined, - indexName: '.ds-auditbeat-8.0.1-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 42230604, - checkedAt: 1706526408000, - }, - { - docsCount: 47496, - incompatible: undefined, - indexName: '.ds-auditbeat-8.2.3-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 41710968, - checkedAt: 1706526408000, - }, - { - docsCount: 47486, - incompatible: undefined, - indexName: '.ds-auditbeat-8.5.3-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 42295944, - checkedAt: 1706526408000, - }, - { - docsCount: 47486, - incompatible: undefined, - indexName: '.ds-auditbeat-8.3.3-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 41761321, - checkedAt: 1706526408000, - }, - { - docsCount: 47460, - incompatible: undefined, - indexName: 'auditbeat-7.2.1-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 30481198, - checkedAt: 1706526408000, - }, - { - docsCount: 47439, - incompatible: undefined, - indexName: 'auditbeat-7.17.9-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 41554041, - checkedAt: 1706526408000, - }, - { - docsCount: 47395, - incompatible: undefined, - indexName: 'auditbeat-7.9.3-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 42815907, - checkedAt: 1706526408000, - }, - { - docsCount: 47394, - incompatible: undefined, - indexName: '.ds-auditbeat-8.7.0-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 41157112, - checkedAt: 1706526408000, - }, - { - docsCount: 47372, - incompatible: undefined, - indexName: 'auditbeat-7.4.2-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 31626792, - checkedAt: 1706526408000, - }, - { - docsCount: 47369, - incompatible: undefined, - indexName: 'auditbeat-7.13.4-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 41828969, - checkedAt: 1706526408000, - }, - { - docsCount: 47348, - incompatible: undefined, - indexName: 'auditbeat-7.7.1-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 40010773, - checkedAt: 1706526408000, - }, - { - docsCount: 47339, - incompatible: undefined, - indexName: 'auditbeat-7.10.2-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 43480570, - checkedAt: 1706526408000, - }, - { - docsCount: 47325, - incompatible: undefined, - indexName: '.ds-auditbeat-8.1.3-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 41822475, - checkedAt: 1706526408000, - }, - { - docsCount: 47294, - incompatible: undefined, - indexName: 'auditbeat-7.8.0-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 43018490, - checkedAt: 1706526408000, - }, - { - docsCount: 24276, - incompatible: undefined, - indexName: '.ds-auditbeat-8.6.1-2023.04.09-000001', - ilmPhase: 'hot', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 23579440, - checkedAt: 1706526408000, - }, - { - docsCount: 4, - incompatible: undefined, - indexName: 'auditbeat-custom-index-1', - ilmPhase: 'unmanaged', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 28409, - checkedAt: 1706526408000, - }, - { - docsCount: 0, - incompatible: undefined, - indexName: 'auditbeat-custom-empty-index-1', - ilmPhase: 'unmanaged', - pattern: 'auditbeat-*', - patternDocsCount: 1118155, - sizeInBytes: 247, - checkedAt: 1706526408000, - }, - ], - pageSize: 10, - }; - - test('it returns the expected page index', () => { - expect(getPageIndex(getPageIndexArgs)).toEqual(1); - }); - - test('it returns the expected page index for the first item', () => { - const firstItemIndexName = 'auditbeat-7.14.2-2023.04.09-000001'; - - expect( - getPageIndex({ - ...getPageIndexArgs, - indexName: firstItemIndexName, - }) - ).toEqual(0); - }); - - test('it returns the expected page index for the last item', () => { - const lastItemIndexName = 'auditbeat-custom-empty-index-1'; - - expect( - getPageIndex({ - ...getPageIndexArgs, - indexName: lastItemIndexName, - }) - ).toEqual(2); - }); - - test('it returns null when the index cannot be found', () => { - expect( - getPageIndex({ - ...getPageIndexArgs, - indexName: 'does_not_exist', // <-- this index is not in the items - }) - ).toBeNull(); - }); - - test('it returns null when `pageSize` is zero', () => { - expect( - getPageIndex({ - ...getPageIndexArgs, - pageSize: 0, // <-- invalid - }) - ).toBeNull(); - }); - }); -}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/helpers.ts deleted file mode 100644 index 5470854fd2ff0..0000000000000 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/helpers.ts +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { IlmExplainLifecycleLifecycleExplain } from '@elastic/elasticsearch/lib/api/types'; -import { isEqual, orderBy } from 'lodash/fp'; - -import type { - IlmPhase, - IlmExplainPhaseCounts, - DataQualityCheckResult, - PatternRollup, - SortConfig, - MeteringStatsIndex, -} from '../../../types'; -import { IndexSummaryTableItem } from './types'; -import { getDocsCount, getSizeInBytes } from '../../../utils/stats'; - -export const isManaged = ( - ilmExplainRecord: IlmExplainLifecycleLifecycleExplain | undefined -): boolean => ilmExplainRecord?.managed === true; - -export const getPhaseCount = ({ - ilmExplain, - ilmPhase, - indexName, -}: { - ilmExplain: Record | null; - ilmPhase: IlmPhase; - indexName: string; -}): number => { - const ilmExplainRecord = ilmExplain != null ? ilmExplain[indexName] : undefined; - - if (ilmPhase === 'unmanaged') { - return isManaged(ilmExplainRecord) ? 0 : 1; - } else if (ilmExplainRecord != null && 'phase' in ilmExplainRecord) { - return ilmExplainRecord.phase === ilmPhase ? 1 : 0; - } - - return 0; -}; - -export const getIlmPhase = ( - ilmExplainRecord: IlmExplainLifecycleLifecycleExplain | undefined, - isILMAvailable: boolean -): IlmPhase | undefined => { - if (ilmExplainRecord == null || !isILMAvailable) { - return undefined; - } - - if ('phase' in ilmExplainRecord) { - const phase = ilmExplainRecord.phase; - - switch (phase) { - case 'hot': - return 'hot'; - case 'warm': - return 'warm'; - case 'cold': - return 'cold'; - case 'frozen': - return 'frozen'; - default: - return undefined; - } - } else { - return 'unmanaged'; - } -}; - -export const getIlmExplainPhaseCounts = ( - ilmExplain: Record | null -): IlmExplainPhaseCounts => { - const indexNames = ilmExplain != null ? Object.keys(ilmExplain) : []; - - return indexNames.reduce( - (acc, indexName) => ({ - hot: - acc.hot + - getPhaseCount({ - ilmExplain, - ilmPhase: 'hot', - indexName, - }), - warm: - acc.warm + - getPhaseCount({ - ilmExplain, - ilmPhase: 'warm', - indexName, - }), - cold: - acc.cold + - getPhaseCount({ - ilmExplain, - ilmPhase: 'cold', - indexName, - }), - frozen: - acc.frozen + - getPhaseCount({ - ilmExplain, - ilmPhase: 'frozen', - indexName, - }), - unmanaged: - acc.unmanaged + - getPhaseCount({ - ilmExplain, - ilmPhase: 'unmanaged', - indexName, - }), - }), - { - hot: 0, - warm: 0, - cold: 0, - frozen: 0, - unmanaged: 0, - } - ); -}; - -export const getIndexIncompatible = ({ - indexName, - results, -}: { - indexName: string; - results: Record | undefined; -}): number | undefined => { - if (results == null || results[indexName] == null) { - return undefined; - } - - return results[indexName].incompatible; -}; - -export const getSummaryTableItems = ({ - ilmExplain, - indexNames, - isILMAvailable, - pattern, - patternDocsCount, - results, - sortByColumn, - sortByDirection, - stats, -}: { - ilmExplain: Record | null; - indexNames: string[]; - isILMAvailable: boolean; - pattern: string; - patternDocsCount: number; - results: Record | undefined; - sortByColumn: string; - sortByDirection: 'desc' | 'asc'; - stats: Record | null; -}): IndexSummaryTableItem[] => { - const summaryTableItems = indexNames.map((indexName) => ({ - docsCount: getDocsCount({ stats, indexName }), - incompatible: getIndexIncompatible({ indexName, results }), - indexName, - ilmPhase: - isILMAvailable && ilmExplain != null - ? getIlmPhase(ilmExplain[indexName], isILMAvailable) - : undefined, - pattern, - patternDocsCount, - sizeInBytes: getSizeInBytes({ stats, indexName }), - checkedAt: results?.[indexName]?.checkedAt, - })); - - return orderBy([sortByColumn], [sortByDirection], summaryTableItems); -}; - -export const shouldCreateIndexNames = ({ - ilmExplain, - indexNames, - isILMAvailable, - newIndexNames, - stats, -}: { - ilmExplain: Record | null; - indexNames: string[] | undefined; - isILMAvailable: boolean; - newIndexNames: string[]; - stats: Record | null; -}): boolean => { - return ( - !isEqual(newIndexNames, indexNames) && - stats != null && - ((isILMAvailable && ilmExplain != null) || !isILMAvailable) - ); -}; - -export const shouldCreatePatternRollup = ({ - error, - ilmExplain, - isILMAvailable, - newDocsCount, - patternRollup, - stats, -}: { - error: string | null; - ilmExplain: Record | null; - isILMAvailable: boolean; - newDocsCount: number; - patternRollup: PatternRollup | undefined; - stats: Record | null; -}): boolean => { - if (patternRollup?.docsCount === newDocsCount) { - return false; - } - - const allDataLoaded: boolean = - stats != null && ((isILMAvailable && ilmExplain != null) || !isILMAvailable); - const errorOccurred: boolean = error != null; - - return allDataLoaded || errorOccurred; -}; - -export const getIndexPropertiesContainerId = ({ - indexName, - pattern, -}: { - indexName: string; - pattern: string; -}): string => `index-properties-container-${pattern}${indexName}`; - -export const defaultSort: SortConfig = { - sort: { - direction: 'desc', - field: 'docsCount', - }, -}; - -export const MIN_PAGE_SIZE = 10; - -export const getPageIndex = ({ - indexName, - items, - pageSize, -}: { - indexName: string; - items: IndexSummaryTableItem[]; - pageSize: number; -}): number | null => { - const index = items.findIndex((x) => x.indexName === indexName); - - if (index !== -1 && pageSize !== 0) { - return Math.floor(index / pageSize); - } else { - return null; - } -}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index.tsx index a59fe7f87d3a5..fc3c698c7a460 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index.tsx @@ -9,22 +9,13 @@ import { EuiSpacer, useGeneratedHtmlId } from '@elastic/eui'; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { ErrorEmptyPrompt } from './error_empty_prompt'; -import { - defaultSort, - getIlmExplainPhaseCounts, - getPageIndex, - getSummaryTableItems, - MIN_PAGE_SIZE, - shouldCreateIndexNames, - shouldCreatePatternRollup, -} from './helpers'; import { getTotalPatternIncompatible, getTotalPatternIndicesChecked } from '../../../utils/stats'; import { getIndexNames, getPatternDocsCount, getPatternSizeInBytes } from './utils/stats'; import { LoadingEmptyPrompt } from './loading_empty_prompt'; import { PatternSummary } from './pattern_summary'; import { RemoteClustersCallout } from './remote_clusters_callout'; import { SummaryTable } from './summary_table'; -import { getSummaryTableColumns } from './summary_table/helpers'; +import { getSummaryTableColumns } from './summary_table/utils/columns'; import * as i18n from './translations'; import type { PatternRollup, SelectedIndex, SortConfig } from '../../../types'; import { useIlmExplain } from './hooks/use_ilm_explain'; @@ -34,6 +25,13 @@ import { PatternAccordion, PatternAccordionChildren } from './styles'; import { IndexCheckFlyout } from './index_check_flyout'; import { useResultsRollupContext } from '../../../contexts/results_rollup_context'; import { useIndicesCheckContext } from '../../../contexts/indices_check_context'; +import { getSummaryTableItems } from '../../../utils/get_summary_table_items'; +import { defaultSort } from '../../../constants'; +import { MIN_PAGE_SIZE } from './constants'; +import { getIlmExplainPhaseCounts } from './utils/ilm_explain'; +import { shouldCreateIndexNames } from './utils/should_create_index_names'; +import { shouldCreatePatternRollup } from './utils/should_create_pattern_rollup'; +import { getPageIndex } from './utils/get_page_index'; const EMPTY_INDEX_NAMES: string[] = []; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index.tsx index 6748fd0651799..0ae749a216856 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index.tsx @@ -21,6 +21,8 @@ import { } from '@elastic/eui'; import React, { useCallback, useEffect } from 'react'; import moment from 'moment'; + +import { getIlmPhase } from '../../../../utils/get_ilm_phase'; import { getDocsCount, getSizeInBytes } from '../../../../utils/stats'; import { useIndicesCheckContext } from '../../../../contexts/indices_check_context'; @@ -28,7 +30,6 @@ import { EMPTY_STAT } from '../../../../constants'; import { MeteringStatsIndex, PatternRollup } from '../../../../types'; import { useDataQualityContext } from '../../../../data_quality_context'; import { IndexProperties } from './index_properties'; -import { getIlmPhase } from '../helpers'; import { IndexResultBadge } from '../index_result_badge'; import { useCurrentWindowWidth } from './hooks/use_current_window_width'; import { CHECK_NOW } from './translations'; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/helpers.test.ts deleted file mode 100644 index 962fa7a825714..0000000000000 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/helpers.test.ts +++ /dev/null @@ -1,249 +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 { getMappingsProperties, getSortedPartitionedFieldMetadata } from './helpers'; -import { mockIndicesGetMappingIndexMappingRecords } from '../../../../../mock/indices_get_mapping_index_mapping_record/mock_indices_get_mapping_index_mapping_record'; -import { mockMappingsProperties } from '../../../../../mock/mappings_properties/mock_mappings_properties'; -import { EcsFlatTyped } from '../../../../../constants'; - -describe('helpers', () => { - describe('getSortedPartitionedFieldMetadata', () => { - test('it returns null when mappings are loading', () => { - expect( - getSortedPartitionedFieldMetadata({ - ecsMetadata: EcsFlatTyped, - loadingMappings: true, // <-- - mappingsProperties: mockMappingsProperties, - unallowedValues: {}, - }) - ).toBeNull(); - }); - - test('it returns null when `unallowedValues` is null', () => { - expect( - getSortedPartitionedFieldMetadata({ - ecsMetadata: EcsFlatTyped, - loadingMappings: false, - mappingsProperties: mockMappingsProperties, - unallowedValues: null, // <-- - }) - ).toBeNull(); - }); - - describe('when `mappingsProperties` is unknown', () => { - const incompatibleFieldMetadata = { - ...EcsFlatTyped['@timestamp'], - hasEcsMetadata: true, - indexFieldName: '@timestamp', - indexFieldType: '-', - indexInvalidValues: [], - isEcsCompliant: false, - isInSameFamily: false, - }; - const expected = { - all: [incompatibleFieldMetadata], - custom: [], - ecsCompliant: [], - incompatible: [incompatibleFieldMetadata], - sameFamily: [], - }; - - test('it returns a `PartitionedFieldMetadata` with an `incompatible` `@timestamp` when `mappingsProperties` is undefined', () => { - expect( - getSortedPartitionedFieldMetadata({ - ecsMetadata: EcsFlatTyped, - loadingMappings: false, - mappingsProperties: undefined, // <-- - unallowedValues: {}, - }) - ).toEqual(expected); - }); - - test('it returns a `PartitionedFieldMetadata` with an `incompatible` `@timestamp` when `mappingsProperties` is null', () => { - expect( - getSortedPartitionedFieldMetadata({ - ecsMetadata: EcsFlatTyped, - loadingMappings: false, - mappingsProperties: null, // <-- - unallowedValues: {}, - }) - ).toEqual(expected); - }); - }); - - test('it returns the expected sorted field metadata', () => { - const unallowedValues = { - 'event.category': [ - { - count: 2, - fieldName: 'an_invalid_category', - }, - { - count: 1, - fieldName: 'theory', - }, - ], - 'event.kind': [], - 'event.outcome': [], - 'event.type': [], - }; - - expect( - getSortedPartitionedFieldMetadata({ - ecsMetadata: EcsFlatTyped, - loadingMappings: false, - mappingsProperties: mockMappingsProperties, - unallowedValues, - }) - ).toMatchObject({ - all: expect.arrayContaining([ - expect.objectContaining({ - name: expect.any(String), - flat_name: expect.any(String), - dashed_name: expect.any(String), - description: expect.any(String), - hasEcsMetadata: true, - isEcsCompliant: expect.any(Boolean), - isInSameFamily: expect.any(Boolean), - }), - ]), - ecsCompliant: expect.arrayContaining([ - expect.objectContaining({ - name: expect.any(String), - flat_name: expect.any(String), - dashed_name: expect.any(String), - description: expect.any(String), - hasEcsMetadata: true, - isEcsCompliant: true, - isInSameFamily: false, - }), - ]), - custom: expect.arrayContaining([ - expect.objectContaining({ - indexFieldName: expect.any(String), - indexFieldType: expect.any(String), - indexInvalidValues: expect.any(Array), - hasEcsMetadata: expect.any(Boolean), - isEcsCompliant: expect.any(Boolean), - isInSameFamily: expect.any(Boolean), - }), - ]), - incompatible: expect.arrayContaining([ - expect.objectContaining({ - name: expect.any(String), - flat_name: expect.any(String), - dashed_name: expect.any(String), - description: expect.any(String), - hasEcsMetadata: expect.any(Boolean), - isEcsCompliant: false, - isInSameFamily: false, - }), - ]), - sameFamily: [], - }); - }); - }); - - describe('getMappingsProperties', () => { - test('it returns the expected mapping properties', () => { - expect( - getMappingsProperties({ - indexes: mockIndicesGetMappingIndexMappingRecords, - indexName: 'auditbeat-custom-index-1', - }) - ).toEqual({ - '@timestamp': { - type: 'date', - }, - event: { - properties: { - category: { - ignore_above: 1024, - type: 'keyword', - }, - }, - }, - host: { - properties: { - name: { - fields: { - keyword: { - ignore_above: 256, - type: 'keyword', - }, - }, - type: 'text', - }, - }, - }, - some: { - properties: { - field: { - fields: { - keyword: { - ignore_above: 256, - type: 'keyword', - }, - }, - type: 'text', - }, - }, - }, - source: { - properties: { - ip: { - fields: { - keyword: { - ignore_above: 256, - type: 'keyword', - }, - }, - type: 'text', - }, - port: { - type: 'long', - }, - }, - }, - }); - }); - - test('it returns null when `indexes` is null', () => { - expect( - getMappingsProperties({ - indexes: null, // <-- - indexName: 'auditbeat-custom-index-1', - }) - ).toBeNull(); - }); - - test('it returns null when `indexName` does not exist in `indexes`', () => { - expect( - getMappingsProperties({ - indexes: mockIndicesGetMappingIndexMappingRecords, - indexName: 'does-not-exist', // <-- - }) - ).toBeNull(); - }); - - test('it returns null when `properties` does not exist in the mappings', () => { - const missingProperties = { - ...mockIndicesGetMappingIndexMappingRecords, - foozle: { - mappings: {}, // <-- does not have a `properties` - }, - }; - - expect( - getMappingsProperties({ - indexes: missingProperties, - indexName: 'foozle', - }) - ).toBeNull(); - }); - }); -}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/helpers.ts deleted file mode 100644 index cf4ae6562b8ed..0000000000000 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/helpers.ts +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { - IndicesGetMappingIndexMappingRecord, - MappingProperty, -} from '@elastic/elasticsearch/lib/api/types'; -import { sortBy } from 'lodash/fp'; - -import { EcsFlatTyped } from '../../../../../constants'; -import type { PartitionedFieldMetadata, UnallowedValueCount } from '../../../../../types'; -import { - getEnrichedFieldMetadata, - getFieldTypes, - getMissingTimestampFieldMetadata, - getPartitionedFieldMetadata, -} from './utils/metadata'; - -export const ALL_TAB_ID = 'allTab'; -export const ECS_COMPLIANT_TAB_ID = 'ecsCompliantTab'; -export const CUSTOM_TAB_ID = 'customTab'; -export const INCOMPATIBLE_TAB_ID = 'incompatibleTab'; -export const SAME_FAMILY_TAB_ID = 'sameFamilyTab'; - -export const EMPTY_METADATA: PartitionedFieldMetadata = { - all: [], - ecsCompliant: [], - custom: [], - incompatible: [], - sameFamily: [], -}; - -export const getSortedPartitionedFieldMetadata = ({ - ecsMetadata, - loadingMappings, - mappingsProperties, - unallowedValues, -}: { - ecsMetadata: EcsFlatTyped; - loadingMappings: boolean; - mappingsProperties: Record | null | undefined; - unallowedValues: Record | null; -}): PartitionedFieldMetadata | null => { - if (loadingMappings || unallowedValues == null) { - return null; - } - - // this covers scenario when we try to check an empty index - // or index without required @timestamp field in the mapping - // - // we create an artifical incompatible timestamp field metadata - // so that we can signal to user that the incompatibility is due to missing timestamp - if (mappingsProperties == null) { - const missingTimestampFieldMetadata = getMissingTimestampFieldMetadata(); - return { - ...EMPTY_METADATA, - all: [missingTimestampFieldMetadata], - incompatible: [missingTimestampFieldMetadata], - }; - } - - const fieldTypes = getFieldTypes(mappingsProperties); - - const enrichedFieldMetadata = sortBy( - 'indexFieldName', - fieldTypes.map((fieldMetadata) => - getEnrichedFieldMetadata({ ecsMetadata, fieldMetadata, unallowedValues }) - ) - ); - - const partitionedFieldMetadata = getPartitionedFieldMetadata(enrichedFieldMetadata); - - return partitionedFieldMetadata; -}; - -export const getMappingsProperties = ({ - indexes, - indexName, -}: { - indexes: Record | null; - indexName: string; -}): Record | null => { - if (indexes != null && indexes[indexName] != null) { - return indexes[indexName].mappings.properties ?? null; - } - - return null; -}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index.tsx index f28d506cda0fa..03d293a02e69a 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index.tsx @@ -10,13 +10,13 @@ import React from 'react'; import { EuiSpacer } from '@elastic/eui'; import { ErrorEmptyPrompt } from '../../error_empty_prompt'; import { LoadingEmptyPrompt } from '../../loading_empty_prompt'; -import { getIndexPropertiesContainerId } from '../../helpers'; import * as i18n from './translations'; import type { IlmPhase, PatternRollup } from '../../../../../types'; import { useIndicesCheckContext } from '../../../../../contexts/indices_check_context'; import { IndexCheckFields } from './index_check_fields'; import { IndexStatsPanel } from './index_stats_panel'; import { useDataQualityContext } from '../../../../../data_quality_context'; +import { getIndexPropertiesContainerId } from './utils/get_index_properties_container_id'; export interface Props { docsCount: number; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/constants.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/constants.ts new file mode 100644 index 0000000000000..889f014a66f1b --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/constants.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const ALL_TAB_ID = 'allTab'; +export const ECS_COMPLIANT_TAB_ID = 'ecsCompliantTab'; +export const CUSTOM_TAB_ID = 'customTab'; +export const INCOMPATIBLE_TAB_ID = 'incompatibleTab'; +export const SAME_FAMILY_TAB_ID = 'sameFamilyTab'; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/index.tsx index db6696e36212a..7e69a906c42ad 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/index.tsx @@ -9,9 +9,10 @@ import React, { useMemo, useState } from 'react'; import { EuiButtonGroup, EuiFlexGroup, EuiSpacer } from '@elastic/eui'; import styled from 'styled-components'; +import { EMPTY_METADATA } from '../../../../../../constants'; import { useDataQualityContext } from '../../../../../../data_quality_context'; import { useIndicesCheckContext } from '../../../../../../contexts/indices_check_context'; -import { EMPTY_METADATA, INCOMPATIBLE_TAB_ID } from '../helpers'; +import { INCOMPATIBLE_TAB_ID } from './constants'; import { IlmPhase, PatternRollup } from '../../../../../../types'; import { getTabs } from './tabs/helpers'; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/get_common_table_columns/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/get_common_table_columns/index.test.tsx index 6a7f522aa803f..5bcd6bb90e0b7 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/get_common_table_columns/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/get_common_table_columns/index.test.tsx @@ -9,7 +9,6 @@ import { render, screen } from '@testing-library/react'; import { omit } from 'lodash/fp'; import React from 'react'; -import { SAME_FAMILY } from '../same_family/translations'; import { eventCategory, someField, @@ -26,6 +25,7 @@ import { } from '../translations'; import { EnrichedFieldMetadata } from '../../../../../../../../../types'; import { EMPTY_PLACEHOLDER, getCommonTableColumns } from '.'; +import { SAME_FAMILY_BADGE_LABEL } from '../../../translate'; describe('getCommonTableColumns', () => { test('it returns the expected column configuration', () => { @@ -128,7 +128,7 @@ describe('getCommonTableColumns', () => { }); test('it renders the same family badge', () => { - expect(screen.getByTestId('sameFamily')).toHaveTextContent(SAME_FAMILY); + expect(screen.getByTestId('sameFamily')).toHaveTextContent(SAME_FAMILY_BADGE_LABEL); }); }); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/get_incompatible_mappings_table_columns/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/get_incompatible_mappings_table_columns/index.test.tsx index 588affcfdbf21..a1d37950da554 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/get_incompatible_mappings_table_columns/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/get_incompatible_mappings_table_columns/index.test.tsx @@ -9,11 +9,11 @@ import { render, screen } from '@testing-library/react'; import { omit } from 'lodash/fp'; import React from 'react'; -import { SAME_FAMILY } from '../same_family/translations'; import { TestExternalProviders } from '../../../../../../../../../mock/test_providers/test_providers'; import { eventCategory } from '../../../../../../../../../mock/enriched_field_metadata/mock_enriched_field_metadata'; import { EcsBasedFieldMetadata } from '../../../../../../../../../types'; import { getIncompatibleMappingsTableColumns } from '.'; +import { SAME_FAMILY_BADGE_LABEL } from '../../../translate'; describe('getIncompatibleMappingsTableColumns', () => { test('it returns the expected column configuration', () => { @@ -97,7 +97,7 @@ describe('getIncompatibleMappingsTableColumns', () => { }); test('it renders the same family badge', () => { - expect(screen.getByTestId('sameFamily')).toHaveTextContent(SAME_FAMILY); + expect(screen.getByTestId('sameFamily')).toHaveTextContent(SAME_FAMILY_BADGE_LABEL); }); }); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/same_family/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/same_family/index.test.tsx index 58889ad1edb2e..210fcc3a2c43b 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/same_family/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/same_family/index.test.tsx @@ -8,9 +8,9 @@ import { render, screen } from '@testing-library/react'; import React from 'react'; -import { SAME_FAMILY } from './translations'; import { TestExternalProviders } from '../../../../../../../../../mock/test_providers/test_providers'; import { SameFamily } from '.'; +import { SAME_FAMILY_BADGE_LABEL } from '../../../translate'; describe('SameFamily', () => { test('it renders a badge with the expected content', () => { @@ -20,6 +20,6 @@ describe('SameFamily', () => { ); - expect(screen.getByTestId('sameFamily')).toHaveTextContent(SAME_FAMILY); + expect(screen.getByTestId('sameFamily')).toHaveTextContent(SAME_FAMILY_BADGE_LABEL); }); }); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/same_family/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/same_family/index.tsx index d3c7cf3c2da61..3ca603944c0d5 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/same_family/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/same_family/index.tsx @@ -8,16 +8,15 @@ import { EuiBadge } from '@elastic/eui'; import React from 'react'; import styled from 'styled-components'; +import { SAME_FAMILY_BADGE_LABEL } from '../../../translate'; const SameFamilyBadge = styled(EuiBadge)` margin: ${({ theme }) => `0 ${theme.eui.euiSizeXS}`}; `; -import * as i18n from './translations'; - const SameFamilyComponent: React.FC = () => ( - {i18n.SAME_FAMILY} + {SAME_FAMILY_BADGE_LABEL} ); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/custom_tab/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/custom_tab/helpers.ts index 4ccebaefaa180..8beb64cfce88e 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/custom_tab/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/custom_tab/helpers.ts @@ -15,7 +15,7 @@ import { getMarkdownTable, getTabCountsMarkdownComment, getSummaryTableMarkdownComment, -} from '../../../markdown/helpers'; +} from '../../utils/markdown'; import * as i18n from '../../../translations'; import type { CustomFieldMetadata, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/helpers.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/helpers.tsx index fa4e63afc6f3b..41b0c49e66ed1 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/helpers.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/helpers.tsx @@ -9,6 +9,7 @@ import { EuiBadge } from '@elastic/eui'; import React from 'react'; import styled from 'styled-components'; +import { INCOMPATIBLE_FIELDS } from '../../../../../../../translations'; import { getSizeInBytes } from '../../../../../../../utils/stats'; import { getIncompatibleStatBadgeColor } from '../../../../../../../utils/get_incompatible_stat_badge_color'; import { AllTab } from './all_tab'; @@ -21,8 +22,7 @@ import { ECS_COMPLIANT_TAB_ID, INCOMPATIBLE_TAB_ID, SAME_FAMILY_TAB_ID, -} from '../../helpers'; -import { getMarkdownComment } from '../../markdown/helpers'; +} from '../constants'; import * as i18n from '../../translations'; import { SameFamilyTab } from './same_family_tab'; import type { @@ -31,6 +31,7 @@ import type { MeteringStatsIndex, PartitionedFieldMetadata, } from '../../../../../../../types'; +import { getMarkdownComment } from '../utils/markdown'; export const getMissingTimestampComment = (): string => getMarkdownComment({ @@ -96,7 +97,7 @@ export const getTabs = ({ /> ), id: INCOMPATIBLE_TAB_ID, - name: i18n.INCOMPATIBLE_FIELDS, + name: INCOMPATIBLE_FIELDS, }, { append: {partitionedFieldMetadata.sameFamily.length}, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/incompatible_tab/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/incompatible_tab/helpers.ts index edd7152c6d492..c7c93f67d80bb 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/incompatible_tab/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/incompatible_tab/helpers.ts @@ -7,16 +7,16 @@ import { EcsVersion } from '@elastic/ecs'; +import { escapeNewlines } from '../../../../../../../../utils/markdown'; import { getSummaryMarkdownComment, getIncompatibleMappingsMarkdownTableRows, getIncompatibleValuesMarkdownTableRows, getMarkdownComment, getMarkdownTable, - getSummaryTableMarkdownComment, getTabCountsMarkdownComment, - escape, -} from '../../../markdown/helpers'; + getSummaryTableMarkdownComment, +} from '../../utils/markdown'; import * as i18n from '../../../translations'; import type { EcsBasedFieldMetadata, @@ -69,7 +69,7 @@ export const getIncompatibleMappingsFields = ( x.type !== x.indexFieldType && !getIsInSameFamily({ ecsExpectedType: x.type, type: x.indexFieldType }) ) { - const field = escape(x.indexFieldName); + const field = escapeNewlines(x.indexFieldName); if (field != null) { return [...acc, field]; } @@ -80,7 +80,7 @@ export const getIncompatibleMappingsFields = ( export const getSameFamilyFields = (ecsBasedFieldMetadata: EcsBasedFieldMetadata[]): string[] => ecsBasedFieldMetadata.reduce((acc, x) => { if (!x.isEcsCompliant && x.type !== x.indexFieldType && x.isInSameFamily) { - const field = escape(x.indexFieldName); + const field = escapeNewlines(x.indexFieldName); if (field != null) { return [...acc, field]; } @@ -98,7 +98,7 @@ export const getIncompatibleValuesFields = ( ): string[] => ecsBasedFieldMetadata.reduce((acc, x) => { if (!x.isEcsCompliant && x.indexInvalidValues.length > 0) { - const field = escape(x.indexFieldName); + const field = escapeNewlines(x.indexFieldName); if (field != null) { return [...acc, field]; } diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/same_family_tab/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/same_family_tab/helpers.ts index 3c90cb81a5906..e96e62704e812 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/same_family_tab/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/same_family_tab/helpers.ts @@ -17,9 +17,9 @@ import { getIncompatibleMappingsMarkdownTableRows, getMarkdownComment, getMarkdownTable, - getSummaryTableMarkdownComment, getTabCountsMarkdownComment, -} from '../../../markdown/helpers'; + getSummaryTableMarkdownComment, +} from '../../utils/markdown'; import * as i18n from '../../../translations'; import { SAME_FAMILY_FIELD_MAPPINGS_TABLE_TITLE } from './translations'; import type { diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/same_family/translations.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/translate.ts similarity index 88% rename from x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/same_family/translations.ts rename to x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/translate.ts index b26a7386e8e4b..1a94c062f0079 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/compare_fields_table/same_family/translations.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/translate.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; -export const SAME_FAMILY = i18n.translate( +export const SAME_FAMILY_BADGE_LABEL = i18n.translate( 'securitySolutionPackages.ecsDataQualityDashboard.sameFamilyBadgeLabel', { defaultMessage: 'same family', diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/utils/markdown.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/utils/markdown.test.ts new file mode 100644 index 0000000000000..ba62b5b0f7874 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/utils/markdown.test.ts @@ -0,0 +1,336 @@ +/* + * 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 numeral from '@elastic/numeral'; + +import { + eventCategory, + mockCustomFields, + mockIncompatibleMappings, + sourceIpWithTextMapping, +} from '../../../../../../../mock/enriched_field_metadata/mock_enriched_field_metadata'; +import { EMPTY_STAT } from '../../../../../../../constants'; +import { mockPartitionedFieldMetadata } from '../../../../../../../mock/partitioned_field_metadata/mock_partitioned_field_metadata'; +import { + escapePreserveNewlines, + getAllowedValues, + getCustomMarkdownTableRows, + getIncompatibleMappingsMarkdownTableRows, + getIncompatibleValuesMarkdownTableRows, + getIndexInvalidValues, + getMarkdownComment, + getMarkdownTable, + getSameFamilyBadge, + getSummaryMarkdownComment, + getSummaryTableMarkdownComment, + getTabCountsMarkdownComment, +} from './markdown'; +import { + ECS_MAPPING_TYPE_EXPECTED, + FIELD, + INDEX_MAPPING_TYPE_ACTUAL, +} from '../tabs/compare_fields_table/translations'; +import { mockAllowedValues } from '../../../../../../../mock/allowed_values/mock_allowed_values'; +import { EcsBasedFieldMetadata, UnallowedValueCount } from '../../../../../../../types'; +import { INCOMPATIBLE_FIELD_MAPPINGS_TABLE_TITLE } from '../tabs/incompatible_tab/translations'; +import { escapeNewlines } from '../../../../../../../utils/markdown'; +import { SAME_FAMILY_BADGE_LABEL } from '../translate'; + +const defaultBytesFormat = '0,0.[0]b'; +const formatBytes = (value: number | undefined) => + value != null ? numeral(value).format(defaultBytesFormat) : EMPTY_STAT; + +const defaultNumberFormat = '0,0.[000]'; +const formatNumber = (value: number | undefined) => + value != null ? numeral(value).format(defaultNumberFormat) : EMPTY_STAT; + +const indexName = 'auditbeat-custom-index-1'; + +describe('getSummaryTableMarkdownComment', () => { + test('it returns the expected comment', () => { + expect( + getSummaryTableMarkdownComment({ + docsCount: 4, + formatBytes, + formatNumber, + ilmPhase: 'unmanaged', + indexName: 'auditbeat-custom-index-1', + isILMAvailable: true, + partitionedFieldMetadata: mockPartitionedFieldMetadata, + patternDocsCount: 57410, + sizeInBytes: 28413, + }) + ).toEqual( + '| Result | Index | Docs | Incompatible fields | ILM Phase | Size |\n|--------|-------|------|---------------------|-----------|------|\n| ❌ | auditbeat-custom-index-1 | 4 (0.0%) | 3 | `unmanaged` | 27.7KB |\n\n' + ); + }); + + test('it returns the expected comment when isILMAvailable is false', () => { + expect( + getSummaryTableMarkdownComment({ + docsCount: 4, + formatBytes, + formatNumber, + ilmPhase: 'unmanaged', + indexName: 'auditbeat-custom-index-1', + isILMAvailable: false, + partitionedFieldMetadata: mockPartitionedFieldMetadata, + patternDocsCount: 57410, + sizeInBytes: undefined, + }) + ).toEqual( + '| Result | Index | Docs | Incompatible fields |\n|--------|-------|------|---------------------|\n| ❌ | auditbeat-custom-index-1 | 4 (0.0%) | 3 |\n\n' + ); + }); + + test('it returns the expected comment when sizeInBytes is undefined', () => { + expect( + getSummaryTableMarkdownComment({ + docsCount: 4, + formatBytes, + formatNumber, + ilmPhase: 'unmanaged', + indexName: 'auditbeat-custom-index-1', + isILMAvailable: false, + partitionedFieldMetadata: mockPartitionedFieldMetadata, + patternDocsCount: 57410, + sizeInBytes: undefined, + }) + ).toEqual( + '| Result | Index | Docs | Incompatible fields |\n|--------|-------|------|---------------------|\n| ❌ | auditbeat-custom-index-1 | 4 (0.0%) | 3 |\n\n' + ); + }); +}); + +describe('escapeNewlines', () => { + test('it returns undefined when `content` is undefined', () => { + expect(escapeNewlines(undefined)).toBeUndefined(); + }); + + test("it returns the content unmodified when there's nothing to escape", () => { + const content = "there's nothing to escape in this content"; + expect(escapeNewlines(content)).toEqual(content); + }); + + test('it replaces all newlines in the content with spaces', () => { + const content = '\nthere were newlines in the beginning, middle,\nand end\n'; + expect(escapeNewlines(content)).toEqual( + ' there were newlines in the beginning, middle, and end ' + ); + }); + + test('it escapes all column separators in the content with spaces', () => { + const content = '|there were column separators in the beginning, middle,|and end|'; + expect(escapeNewlines(content)).toEqual( + '\\|there were column separators in the beginning, middle,\\|and end\\|' + ); + }); + + test('it escapes content containing BOTH newlines and column separators', () => { + const content = + '|\nthere were newlines and column separators in the beginning, middle,\n|and end|\n'; + expect(escapeNewlines(content)).toEqual( + '\\| there were newlines and column separators in the beginning, middle, \\|and end\\| ' + ); + }); +}); + +describe('escapePreserveNewlines', () => { + test('it returns undefined when `content` is undefined', () => { + expect(escapePreserveNewlines(undefined)).toBeUndefined(); + }); + + test("it returns the content unmodified when there's nothing to escape", () => { + const content = "there's (also) nothing to escape in this content"; + expect(escapePreserveNewlines(content)).toEqual(content); + }); + + test('it escapes all column separators in the content with spaces', () => { + const content = '|there were column separators in the beginning, middle,|and end|'; + expect(escapePreserveNewlines(content)).toEqual( + '\\|there were column separators in the beginning, middle,\\|and end\\|' + ); + }); + + test('it does NOT escape newlines in the content', () => { + const content = + '|\nthere were newlines and column separators in the beginning, middle,\n|and end|\n'; + expect(escapePreserveNewlines(content)).toEqual( + '\\|\nthere were newlines and column separators in the beginning, middle,\n\\|and end\\|\n' + ); + }); +}); + +describe('getAllowedValues', () => { + test('it returns the expected placeholder when `allowedValues` is undefined', () => { + expect(getAllowedValues(undefined)).toEqual('`--`'); + }); + + test('it joins the `allowedValues` `name`s as a markdown-code-formatted, comma separated, string', () => { + expect(getAllowedValues(mockAllowedValues)).toEqual( + '`authentication`, `configuration`, `database`, `driver`, `email`, `file`, `host`, `iam`, `intrusion_detection`, `malware`, `network`, `package`, `process`, `registry`, `session`, `threat`, `vulnerability`, `web`' + ); + }); +}); + +describe('getIndexInvalidValues', () => { + test('it returns the expected placeholder when `indexInvalidValues` is empty', () => { + expect(getIndexInvalidValues([])).toEqual('`--`'); + }); + + test('it returns markdown-code-formatted `fieldName`s, and their associated `count`s', () => { + const indexInvalidValues: UnallowedValueCount[] = [ + { + count: 2, + fieldName: 'an_invalid_category', + }, + { + count: 1, + fieldName: 'theory', + }, + ]; + + expect(getIndexInvalidValues(indexInvalidValues)).toEqual( + `\`an_invalid_category\` (2), \`theory\` (1)` + ); + }); +}); + +describe('getCustomMarkdownTableRows', () => { + test('it returns the expected table rows', () => { + expect(getCustomMarkdownTableRows(mockCustomFields)).toEqual( + '| host.name.keyword | `keyword` | `--` |\n| some.field | `text` | `--` |\n| some.field.keyword | `keyword` | `--` |\n| source.ip.keyword | `keyword` | `--` |' + ); + }); +}); + +describe('getSameFamilyBadge', () => { + test('it returns the expected badge text when the field is in the same family', () => { + const inSameFamily = { + ...eventCategory, + isInSameFamily: true, + }; + + expect(getSameFamilyBadge(inSameFamily)).toEqual(`\`${SAME_FAMILY_BADGE_LABEL}\``); + }); + + test('it returns an empty string when the field is NOT the same family', () => { + const notInSameFamily = { + ...eventCategory, + isInSameFamily: false, + }; + + expect(getSameFamilyBadge(notInSameFamily)).toEqual(''); + }); +}); + +describe('getIncompatibleMappingsMarkdownTableRows', () => { + test('it returns the expected table rows when the field is in the same family', () => { + const eventCategoryWithWildcard: EcsBasedFieldMetadata = { + ...eventCategory, // `event.category` is a `keyword` per the ECS spec + indexFieldType: 'wildcard', // this index has a mapping of `wildcard` instead of `keyword` + isInSameFamily: true, // `wildcard` and `keyword` are in the same family + }; + + expect( + getIncompatibleMappingsMarkdownTableRows([eventCategoryWithWildcard, sourceIpWithTextMapping]) + ).toEqual( + '| event.category | `keyword` | `wildcard` `same family` |\n| source.ip | `ip` | `text` |' + ); + }); + + test('it returns the expected table rows when the field is NOT in the same family', () => { + const eventCategoryWithText: EcsBasedFieldMetadata = { + ...eventCategory, // `event.category` is a `keyword` per the ECS spec + indexFieldType: 'text', // this index has a mapping of `text` instead of `keyword` + isInSameFamily: false, // `text` and `keyword` are NOT in the same family + }; + + expect( + getIncompatibleMappingsMarkdownTableRows([eventCategoryWithText, sourceIpWithTextMapping]) + ).toEqual('| event.category | `keyword` | `text` |\n| source.ip | `ip` | `text` |'); + }); +}); + +describe('getIncompatibleValuesMarkdownTableRows', () => { + test('it returns the expected table rows', () => { + expect( + getIncompatibleValuesMarkdownTableRows([ + { + ...eventCategory, + hasEcsMetadata: true, + indexInvalidValues: [ + { + count: 2, + fieldName: 'an_invalid_category', + }, + { + count: 1, + fieldName: 'theory', + }, + ], + isEcsCompliant: false, + }, + ]) + ).toEqual( + '| event.category | `authentication`, `configuration`, `database`, `driver`, `email`, `file`, `host`, `iam`, `intrusion_detection`, `malware`, `network`, `package`, `process`, `registry`, `session`, `threat`, `vulnerability`, `web` | `an_invalid_category` (2), `theory` (1) |' + ); + }); +}); + +describe('getMarkdownComment', () => { + test('it returns the expected markdown comment', () => { + const suggestedAction = + '|\nthere were newlines and column separators in this suggestedAction beginning, middle,\n|and end|\n'; + const title = + '|\nthere were newlines and column separators in this title beginning, middle,\n|and end|\n'; + + expect(getMarkdownComment({ suggestedAction, title })).toEqual( + '#### \\| there were newlines and column separators in this title beginning, middle, \\|and end\\| \n\n\\|\nthere were newlines and column separators in this suggestedAction beginning, middle,\n\\|and end\\|\n' + ); + }); +}); + +describe('getMarkdownTable', () => { + test('it returns the expected table contents', () => { + expect( + getMarkdownTable({ + enrichedFieldMetadata: mockIncompatibleMappings, + getMarkdownTableRows: getIncompatibleMappingsMarkdownTableRows, + headerNames: [FIELD, ECS_MAPPING_TYPE_EXPECTED, INDEX_MAPPING_TYPE_ACTUAL], + title: INCOMPATIBLE_FIELD_MAPPINGS_TABLE_TITLE(indexName), + }) + ).toEqual( + '#### Incompatible field mappings - auditbeat-custom-index-1\n\n\n| Field | ECS mapping type (expected) | Index mapping type (actual) | \n|-------|-----------------------------|-----------------------------|\n| host.name | `keyword` | `text` |\n| source.ip | `ip` | `text` |\n' + ); + }); + + test('it returns an empty string when `enrichedFieldMetadata` is empty', () => { + expect( + getMarkdownTable({ + enrichedFieldMetadata: [], // <-- empty + getMarkdownTableRows: getIncompatibleMappingsMarkdownTableRows, + headerNames: [FIELD, ECS_MAPPING_TYPE_EXPECTED, INDEX_MAPPING_TYPE_ACTUAL], + title: INCOMPATIBLE_FIELD_MAPPINGS_TABLE_TITLE(indexName), + }) + ).toEqual(''); + }); +}); + +describe('getSummaryMarkdownComment', () => { + test('it returns the expected markdown comment', () => { + expect(getSummaryMarkdownComment(indexName)).toEqual('### auditbeat-custom-index-1\n'); + }); +}); + +describe('getTabCountsMarkdownComment', () => { + test('it returns a comment with the expected counts', () => { + expect(getTabCountsMarkdownComment(mockPartitionedFieldMetadata)).toBe( + '### **Incompatible fields** `3` **Same family** `0` **Custom fields** `4` **ECS compliant fields** `2` **All fields** `9`\n' + ); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/utils/markdown.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/utils/markdown.ts new file mode 100644 index 0000000000000..574408cfe600b --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/utils/markdown.ts @@ -0,0 +1,163 @@ +/* + * 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 { INCOMPATIBLE_FIELDS } from '../../../../../../../translations'; +import { + escapeNewlines, + getCodeFormattedValue, + getMarkdownTableHeader, + getSummaryTableMarkdownHeader, + getSummaryTableMarkdownRow, +} from '../../../../../../../utils/markdown'; +import { + AllowedValue, + CustomFieldMetadata, + EcsBasedFieldMetadata, + EnrichedFieldMetadata, + IlmPhase, + PartitionedFieldMetadata, + UnallowedValueCount, +} from '../../../../../../../types'; +import { ALL_FIELDS, CUSTOM_FIELDS, ECS_COMPLIANT_FIELDS, SAME_FAMILY } from '../../translations'; +import { SAME_FAMILY_BADGE_LABEL } from '../translate'; + +export const getSummaryTableMarkdownComment = ({ + docsCount, + formatBytes, + formatNumber, + ilmPhase, + indexName, + isILMAvailable, + partitionedFieldMetadata, + patternDocsCount, + sizeInBytes, +}: { + docsCount: number; + formatBytes: (value: number | undefined) => string; + formatNumber: (value: number | undefined) => string; + ilmPhase: IlmPhase | undefined; + indexName: string; + isILMAvailable: boolean; + partitionedFieldMetadata: PartitionedFieldMetadata; + patternDocsCount: number; + sizeInBytes: number | undefined; +}): string => + `${getSummaryTableMarkdownHeader(isILMAvailable)} +${getSummaryTableMarkdownRow({ + docsCount, + formatBytes, + formatNumber, + ilmPhase, + indexName, + isILMAvailable, + incompatible: partitionedFieldMetadata.incompatible.length, + patternDocsCount, + sizeInBytes, +})} +`; + +export const escapePreserveNewlines = (content: string | undefined): string | undefined => + content != null ? content.replaceAll('|', '\\|') : content; + +export const getAllowedValues = (allowedValues: AllowedValue[] | undefined): string => + allowedValues == null + ? getCodeFormattedValue(undefined) + : allowedValues.map((x) => getCodeFormattedValue(x.name)).join(', '); + +export const getIndexInvalidValues = (indexInvalidValues: UnallowedValueCount[]): string => + indexInvalidValues.length === 0 + ? getCodeFormattedValue(undefined) + : indexInvalidValues + .map( + ({ fieldName, count }) => `${getCodeFormattedValue(escapeNewlines(fieldName))} (${count})` + ) + .join(', '); // newlines are instead joined with spaces + +export const getCustomMarkdownTableRows = (customFieldMetadata: CustomFieldMetadata[]): string => + customFieldMetadata + .map( + (x) => + `| ${escapeNewlines(x.indexFieldName)} | ${getCodeFormattedValue( + x.indexFieldType + )} | ${getAllowedValues(undefined)} |` + ) + .join('\n'); + +export const getSameFamilyBadge = (ecsBasedFieldMetadata: EcsBasedFieldMetadata): string => + ecsBasedFieldMetadata.isInSameFamily ? getCodeFormattedValue(SAME_FAMILY_BADGE_LABEL) : ''; + +export const getIncompatibleMappingsMarkdownTableRows = ( + incompatibleMappings: EcsBasedFieldMetadata[] +): string => + incompatibleMappings + .map( + (x) => + `| ${escapeNewlines(x.indexFieldName)} | ${getCodeFormattedValue( + x.type + )} | ${getCodeFormattedValue(x.indexFieldType)} ${getSameFamilyBadge(x)} |` + ) + .join('\n'); + +export const getIncompatibleValuesMarkdownTableRows = ( + incompatibleValues: EcsBasedFieldMetadata[] +): string => + incompatibleValues + .map( + (x) => + `| ${escapeNewlines(x.indexFieldName)} | ${getAllowedValues( + x.allowed_values + )} | ${getIndexInvalidValues(x.indexInvalidValues)} |` + ) + .join('\n'); + +export const getMarkdownComment = ({ + suggestedAction, + title, +}: { + suggestedAction: string; + title: string; +}): string => + `#### ${escapeNewlines(title)} + +${escapePreserveNewlines(suggestedAction)}`; + +export const getMarkdownTable = ({ + enrichedFieldMetadata, + getMarkdownTableRows, + headerNames, + title, +}: { + enrichedFieldMetadata: T; + getMarkdownTableRows: (enrichedFieldMetadata: T) => string; + headerNames: string[]; + title: string; +}): string => + enrichedFieldMetadata.length > 0 + ? `#### ${escapeNewlines(title)} + +${getMarkdownTableHeader(headerNames)} +${getMarkdownTableRows(enrichedFieldMetadata)} +` + : ''; + +export const getSummaryMarkdownComment = (indexName: string) => + `### ${escapeNewlines(indexName)} +`; + +export const getTabCountsMarkdownComment = ( + partitionedFieldMetadata: PartitionedFieldMetadata +): string => + `### **${INCOMPATIBLE_FIELDS}** ${getCodeFormattedValue( + `${partitionedFieldMetadata.incompatible.length}` + )} **${SAME_FAMILY}** ${getCodeFormattedValue( + `${partitionedFieldMetadata.sameFamily.length}` + )} **${CUSTOM_FIELDS}** ${getCodeFormattedValue( + `${partitionedFieldMetadata.custom.length}` + )} **${ECS_COMPLIANT_FIELDS}** ${getCodeFormattedValue( + `${partitionedFieldMetadata.ecsCompliant.length}` + )} **${ALL_FIELDS}** ${getCodeFormattedValue(`${partitionedFieldMetadata.all.length}`)} +`; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_stats_panel/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_stats_panel/index.tsx index da5ff8efc4242..2df01db28f8a2 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_stats_panel/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_stats_panel/index.tsx @@ -9,9 +9,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSpacer } from '@elastic/eui'; import React from 'react'; import styled from 'styled-components'; -import { DOCS } from '../translations'; -import { ILM_PHASE } from '../../../../../../translations'; -import { SIZE } from '../../../summary_table/translations'; +import { DOCS, ILM_PHASE, SIZE } from '../../../../../../translations'; import { Stat } from '../../../../../../stat'; import { getIlmPhaseDescription } from '../../../../../../utils/get_ilm_phase_description'; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/markdown/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/markdown/helpers.test.ts deleted file mode 100644 index 5fe3dbed0bd25..0000000000000 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/markdown/helpers.test.ts +++ /dev/null @@ -1,727 +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 numeral from '@elastic/numeral'; - -import { - ECS_MAPPING_TYPE_EXPECTED, - FIELD, - INDEX_MAPPING_TYPE_ACTUAL, -} from '../index_check_fields/tabs/compare_fields_table/translations'; -import { ERRORS } from '../../../../../../data_quality_summary/summary_actions/check_status/errors_popover/translations'; -import { - ERROR, - INDEX, - PATTERN, -} from '../../../../../../data_quality_summary/summary_actions/check_status/errors_popover/errors_viewer/translations'; -import { - escape, - escapePreserveNewlines, - getAllowedValues, - getCodeFormattedValue, - getCustomMarkdownTableRows, - getDataQualitySummaryMarkdownComment, - getErrorsMarkdownTable, - getErrorsMarkdownTableRows, - getHeaderSeparator, - getIlmExplainPhaseCountsMarkdownComment, - getIncompatibleMappingsMarkdownTableRows, - getIncompatibleValuesMarkdownTableRows, - getIndexInvalidValues, - getMarkdownComment, - getMarkdownTable, - getMarkdownTableHeader, - getPatternSummaryMarkdownComment, - getResultEmoji, - getSameFamilyBadge, - getStatsRollupMarkdownComment, - getSummaryMarkdownComment, - getSummaryTableMarkdownComment, - getSummaryTableMarkdownHeader, - getSummaryTableMarkdownRow, - getTabCountsMarkdownComment, -} from './helpers'; -import { EMPTY_STAT } from '../../../../../../constants'; -import { mockAllowedValues } from '../../../../../../mock/allowed_values/mock_allowed_values'; -import { - eventCategory, - mockCustomFields, - mockIncompatibleMappings, - sourceIpWithTextMapping, -} from '../../../../../../mock/enriched_field_metadata/mock_enriched_field_metadata'; -import { mockPartitionedFieldMetadata } from '../../../../../../mock/partitioned_field_metadata/mock_partitioned_field_metadata'; -import { - auditbeatNoResults, - auditbeatWithAllResults, -} from '../../../../../../mock/pattern_rollup/mock_auditbeat_pattern_rollup'; -import { SAME_FAMILY } from '../index_check_fields/tabs/compare_fields_table/same_family/translations'; -import { INCOMPATIBLE_FIELD_MAPPINGS_TABLE_TITLE } from '../index_check_fields/tabs/incompatible_tab/translations'; -import { - EcsBasedFieldMetadata, - ErrorSummary, - PatternRollup, - UnallowedValueCount, -} from '../../../../../../types'; - -const errorSummary: ErrorSummary[] = [ - { - pattern: '.alerts-security.alerts-default', - indexName: null, - error: 'Error loading stats: Error: Forbidden', - }, - { - error: - 'Error: Error loading unallowed values for index auditbeat-7.2.1-2023.02.13-000001: Forbidden', - indexName: 'auditbeat-7.2.1-2023.02.13-000001', - pattern: 'auditbeat-*', - }, -]; - -const indexName = 'auditbeat-custom-index-1'; - -const defaultBytesFormat = '0,0.[0]b'; -const formatBytes = (value: number | undefined) => - value != null ? numeral(value).format(defaultBytesFormat) : EMPTY_STAT; - -const defaultNumberFormat = '0,0.[000]'; -const formatNumber = (value: number | undefined) => - value != null ? numeral(value).format(defaultNumberFormat) : EMPTY_STAT; - -describe('helpers', () => { - describe('escape', () => { - test('it returns undefined when `content` is undefined', () => { - expect(escape(undefined)).toBeUndefined(); - }); - - test("it returns the content unmodified when there's nothing to escape", () => { - const content = "there's nothing to escape in this content"; - expect(escape(content)).toEqual(content); - }); - - test('it replaces all newlines in the content with spaces', () => { - const content = '\nthere were newlines in the beginning, middle,\nand end\n'; - expect(escape(content)).toEqual(' there were newlines in the beginning, middle, and end '); - }); - - test('it escapes all column separators in the content with spaces', () => { - const content = '|there were column separators in the beginning, middle,|and end|'; - expect(escape(content)).toEqual( - '\\|there were column separators in the beginning, middle,\\|and end\\|' - ); - }); - - test('it escapes content containing BOTH newlines and column separators', () => { - const content = - '|\nthere were newlines and column separators in the beginning, middle,\n|and end|\n'; - expect(escape(content)).toEqual( - '\\| there were newlines and column separators in the beginning, middle, \\|and end\\| ' - ); - }); - }); - - describe('escapePreserveNewlines', () => { - test('it returns undefined when `content` is undefined', () => { - expect(escapePreserveNewlines(undefined)).toBeUndefined(); - }); - - test("it returns the content unmodified when there's nothing to escape", () => { - const content = "there's (also) nothing to escape in this content"; - expect(escapePreserveNewlines(content)).toEqual(content); - }); - - test('it escapes all column separators in the content with spaces', () => { - const content = '|there were column separators in the beginning, middle,|and end|'; - expect(escapePreserveNewlines(content)).toEqual( - '\\|there were column separators in the beginning, middle,\\|and end\\|' - ); - }); - - test('it does NOT escape newlines in the content', () => { - const content = - '|\nthere were newlines and column separators in the beginning, middle,\n|and end|\n'; - expect(escapePreserveNewlines(content)).toEqual( - '\\|\nthere were newlines and column separators in the beginning, middle,\n\\|and end\\|\n' - ); - }); - }); - - describe('getHeaderSeparator', () => { - test('it returns a sequence of dashes equal to the length of the header, plus two additional dashes to pad each end of the cntent', () => { - const content = '0123456789'; // content.length === 10 - const expected = '------------'; // expected.length === 12 - - expect(getHeaderSeparator(content)).toEqual(expected); - }); - }); - - describe('getMarkdownTableHeader', () => { - const headerNames = [ - '|\nthere were newlines and column separators in the beginning, middle,\n|and end|\n', - 'A second column', - 'A third column', - ]; - - test('it returns the expected table header', () => { - expect(getMarkdownTableHeader(headerNames)).toEqual( - '\n| \\| there were newlines and column separators in the beginning, middle, \\|and end\\| | A second column | A third column | \n|----------------------------------------------------------------------------------|-----------------|----------------|' - ); - }); - }); - - describe('getCodeFormattedValue', () => { - test('it returns the expected placeholder when `value` is undefined', () => { - expect(getCodeFormattedValue(undefined)).toEqual('`--`'); - }); - - test('it returns the content formatted as markdown code', () => { - const value = 'foozle'; - - expect(getCodeFormattedValue(value)).toEqual('`foozle`'); - }); - - test('it escapes content such that `value` may be included in a markdown table cell', () => { - const value = - '|\nthere were newlines and column separators in the beginning, middle,\n|and end|\n'; - - expect(getCodeFormattedValue(value)).toEqual( - '`\\| there were newlines and column separators in the beginning, middle, \\|and end\\| `' - ); - }); - }); - - describe('getAllowedValues', () => { - test('it returns the expected placeholder when `allowedValues` is undefined', () => { - expect(getAllowedValues(undefined)).toEqual('`--`'); - }); - - test('it joins the `allowedValues` `name`s as a markdown-code-formatted, comma separated, string', () => { - expect(getAllowedValues(mockAllowedValues)).toEqual( - '`authentication`, `configuration`, `database`, `driver`, `email`, `file`, `host`, `iam`, `intrusion_detection`, `malware`, `network`, `package`, `process`, `registry`, `session`, `threat`, `vulnerability`, `web`' - ); - }); - }); - - describe('getIndexInvalidValues', () => { - test('it returns the expected placeholder when `indexInvalidValues` is empty', () => { - expect(getIndexInvalidValues([])).toEqual('`--`'); - }); - - test('it returns markdown-code-formatted `fieldName`s, and their associated `count`s', () => { - const indexInvalidValues: UnallowedValueCount[] = [ - { - count: 2, - fieldName: 'an_invalid_category', - }, - { - count: 1, - fieldName: 'theory', - }, - ]; - - expect(getIndexInvalidValues(indexInvalidValues)).toEqual( - `\`an_invalid_category\` (2), \`theory\` (1)` - ); - }); - }); - - describe('getCustomMarkdownTableRows', () => { - test('it returns the expected table rows', () => { - expect(getCustomMarkdownTableRows(mockCustomFields)).toEqual( - '| host.name.keyword | `keyword` | `--` |\n| some.field | `text` | `--` |\n| some.field.keyword | `keyword` | `--` |\n| source.ip.keyword | `keyword` | `--` |' - ); - }); - }); - - describe('getSameFamilyBadge', () => { - test('it returns the expected badge text when the field is in the same family', () => { - const inSameFamily = { - ...eventCategory, - isInSameFamily: true, - }; - - expect(getSameFamilyBadge(inSameFamily)).toEqual(`\`${SAME_FAMILY}\``); - }); - - test('it returns an empty string when the field is NOT the same family', () => { - const notInSameFamily = { - ...eventCategory, - isInSameFamily: false, - }; - - expect(getSameFamilyBadge(notInSameFamily)).toEqual(''); - }); - }); - - describe('getIncompatibleMappingsMarkdownTableRows', () => { - test('it returns the expected table rows when the field is in the same family', () => { - const eventCategoryWithWildcard: EcsBasedFieldMetadata = { - ...eventCategory, // `event.category` is a `keyword` per the ECS spec - indexFieldType: 'wildcard', // this index has a mapping of `wildcard` instead of `keyword` - isInSameFamily: true, // `wildcard` and `keyword` are in the same family - }; - - expect( - getIncompatibleMappingsMarkdownTableRows([ - eventCategoryWithWildcard, - sourceIpWithTextMapping, - ]) - ).toEqual( - '| event.category | `keyword` | `wildcard` `same family` |\n| source.ip | `ip` | `text` |' - ); - }); - - test('it returns the expected table rows when the field is NOT in the same family', () => { - const eventCategoryWithText: EcsBasedFieldMetadata = { - ...eventCategory, // `event.category` is a `keyword` per the ECS spec - indexFieldType: 'text', // this index has a mapping of `text` instead of `keyword` - isInSameFamily: false, // `text` and `keyword` are NOT in the same family - }; - - expect( - getIncompatibleMappingsMarkdownTableRows([eventCategoryWithText, sourceIpWithTextMapping]) - ).toEqual('| event.category | `keyword` | `text` |\n| source.ip | `ip` | `text` |'); - }); - }); - - describe('getIncompatibleValuesMarkdownTableRows', () => { - test('it returns the expected table rows', () => { - expect( - getIncompatibleValuesMarkdownTableRows([ - { - ...eventCategory, - hasEcsMetadata: true, - indexInvalidValues: [ - { - count: 2, - fieldName: 'an_invalid_category', - }, - { - count: 1, - fieldName: 'theory', - }, - ], - isEcsCompliant: false, - }, - ]) - ).toEqual( - '| event.category | `authentication`, `configuration`, `database`, `driver`, `email`, `file`, `host`, `iam`, `intrusion_detection`, `malware`, `network`, `package`, `process`, `registry`, `session`, `threat`, `vulnerability`, `web` | `an_invalid_category` (2), `theory` (1) |' - ); - }); - }); - - describe('getMarkdownComment', () => { - test('it returns the expected markdown comment', () => { - const suggestedAction = - '|\nthere were newlines and column separators in this suggestedAction beginning, middle,\n|and end|\n'; - const title = - '|\nthere were newlines and column separators in this title beginning, middle,\n|and end|\n'; - - expect(getMarkdownComment({ suggestedAction, title })).toEqual( - '#### \\| there were newlines and column separators in this title beginning, middle, \\|and end\\| \n\n\\|\nthere were newlines and column separators in this suggestedAction beginning, middle,\n\\|and end\\|\n' - ); - }); - }); - - describe('getErrorsMarkdownTableRows', () => { - test('it returns the expected markdown table rows', () => { - expect(getErrorsMarkdownTableRows(errorSummary)).toEqual( - '| .alerts-security.alerts-default | -- | `Error loading stats: Error: Forbidden` |\n| auditbeat-* | auditbeat-7.2.1-2023.02.13-000001 | `Error: Error loading unallowed values for index auditbeat-7.2.1-2023.02.13-000001: Forbidden` |' - ); - }); - }); - - describe('getErrorsMarkdownTable', () => { - test('it returns the expected table contents', () => { - expect( - getErrorsMarkdownTable({ - errorSummary, - getMarkdownTableRows: getErrorsMarkdownTableRows, - headerNames: [PATTERN, INDEX, ERROR], - title: ERRORS, - }) - ).toEqual( - `## Errors\n\nSome indices were not checked for Data Quality\n\nErrors may occur when pattern or index metadata is temporarily unavailable, or because you don't have the privileges required for access\n\nThe following privileges are required to check an index:\n- \`monitor\` or \`manage\`\n- \`view_index_metadata\`\n- \`read\`\n\n\n| Pattern | Index | Error | \n|---------|-------|-------|\n| .alerts-security.alerts-default | -- | \`Error loading stats: Error: Forbidden\` |\n| auditbeat-* | auditbeat-7.2.1-2023.02.13-000001 | \`Error: Error loading unallowed values for index auditbeat-7.2.1-2023.02.13-000001: Forbidden\` |\n` - ); - }); - - test('it returns an empty string when the error summary is empty', () => { - expect( - getErrorsMarkdownTable({ - errorSummary: [], // <-- empty - getMarkdownTableRows: getErrorsMarkdownTableRows, - headerNames: [PATTERN, INDEX, ERROR], - title: ERRORS, - }) - ).toEqual(''); - }); - }); - - describe('getMarkdownTable', () => { - test('it returns the expected table contents', () => { - expect( - getMarkdownTable({ - enrichedFieldMetadata: mockIncompatibleMappings, - getMarkdownTableRows: getIncompatibleMappingsMarkdownTableRows, - headerNames: [FIELD, ECS_MAPPING_TYPE_EXPECTED, INDEX_MAPPING_TYPE_ACTUAL], - title: INCOMPATIBLE_FIELD_MAPPINGS_TABLE_TITLE(indexName), - }) - ).toEqual( - '#### Incompatible field mappings - auditbeat-custom-index-1\n\n\n| Field | ECS mapping type (expected) | Index mapping type (actual) | \n|-------|-----------------------------|-----------------------------|\n| host.name | `keyword` | `text` |\n| source.ip | `ip` | `text` |\n' - ); - }); - - test('it returns an empty string when `enrichedFieldMetadata` is empty', () => { - expect( - getMarkdownTable({ - enrichedFieldMetadata: [], // <-- empty - getMarkdownTableRows: getIncompatibleMappingsMarkdownTableRows, - headerNames: [FIELD, ECS_MAPPING_TYPE_EXPECTED, INDEX_MAPPING_TYPE_ACTUAL], - title: INCOMPATIBLE_FIELD_MAPPINGS_TABLE_TITLE(indexName), - }) - ).toEqual(''); - }); - }); - - describe('getSummaryMarkdownComment', () => { - test('it returns the expected markdown comment', () => { - expect(getSummaryMarkdownComment(indexName)).toEqual('### auditbeat-custom-index-1\n'); - }); - }); - - describe('getTabCountsMarkdownComment', () => { - test('it returns a comment with the expected counts', () => { - expect(getTabCountsMarkdownComment(mockPartitionedFieldMetadata)).toBe( - '### **Incompatible fields** `3` **Same family** `0` **Custom fields** `4` **ECS compliant fields** `2` **All fields** `9`\n' - ); - }); - }); - - describe('getResultEmoji', () => { - test('it returns the expected placeholder when `incompatible` is undefined', () => { - expect(getResultEmoji(undefined)).toEqual('--'); - }); - - test('it returns a ✅ when the incompatible count is zero', () => { - expect(getResultEmoji(0)).toEqual('✅'); - }); - - test('it returns a ❌ when the incompatible count is NOT zero', () => { - expect(getResultEmoji(1)).toEqual('❌'); - }); - }); - - describe('getSummaryTableMarkdownHeader', () => { - test('it returns the expected header', () => { - const isILMAvailable = true; - expect(getSummaryTableMarkdownHeader(isILMAvailable)).toEqual( - '| Result | Index | Docs | Incompatible fields | ILM Phase | Size |\n|--------|-------|------|---------------------|-----------|------|' - ); - }); - - test('it returns the expected header when isILMAvailable is false', () => { - const isILMAvailable = false; - expect(getSummaryTableMarkdownHeader(isILMAvailable)).toEqual( - '| Result | Index | Docs | Incompatible fields |\n|--------|-------|------|---------------------|' - ); - }); - - test('it returns the expected header when displayDocSize is false', () => { - const isILMAvailable = false; - expect(getSummaryTableMarkdownHeader(isILMAvailable)).toEqual( - '| Result | Index | Docs | Incompatible fields |\n|--------|-------|------|---------------------|' - ); - }); - }); - - describe('getSummaryTableMarkdownRow', () => { - test('it returns the expected row when all values are provided', () => { - expect( - getSummaryTableMarkdownRow({ - docsCount: 4, - formatBytes, - formatNumber, - incompatible: 3, - ilmPhase: 'unmanaged', - isILMAvailable: true, - indexName: 'auditbeat-custom-index-1', - patternDocsCount: 57410, - sizeInBytes: 28413, - }) - ).toEqual('| ❌ | auditbeat-custom-index-1 | 4 (0.0%) | 3 | `unmanaged` | 27.7KB |\n'); - }); - - test('it returns the expected row when optional values are NOT provided', () => { - expect( - getSummaryTableMarkdownRow({ - docsCount: 4, - formatBytes, - formatNumber, - incompatible: undefined, // <-- - ilmPhase: undefined, // <-- - indexName: 'auditbeat-custom-index-1', - isILMAvailable: true, - patternDocsCount: 57410, - sizeInBytes: 28413, - }) - ).toEqual('| -- | auditbeat-custom-index-1 | 4 (0.0%) | -- | -- | 27.7KB |\n'); - }); - - test('it returns the expected row when isILMAvailable is false', () => { - expect( - getSummaryTableMarkdownRow({ - docsCount: 4, - formatBytes, - formatNumber, - incompatible: undefined, // <-- - ilmPhase: undefined, // <-- - indexName: 'auditbeat-custom-index-1', - isILMAvailable: false, - patternDocsCount: 57410, - sizeInBytes: undefined, - }) - ).toEqual('| -- | auditbeat-custom-index-1 | 4 (0.0%) | -- |\n'); - }); - - test('it returns the expected row when sizeInBytes is undefined', () => { - expect( - getSummaryTableMarkdownRow({ - docsCount: 4, - formatBytes, - formatNumber, - incompatible: undefined, // <-- - ilmPhase: undefined, // <-- - indexName: 'auditbeat-custom-index-1', - isILMAvailable: false, - patternDocsCount: 57410, - sizeInBytes: undefined, - }) - ).toEqual('| -- | auditbeat-custom-index-1 | 4 (0.0%) | -- |\n'); - }); - }); - - describe('getSummaryTableMarkdownComment', () => { - test('it returns the expected comment', () => { - expect( - getSummaryTableMarkdownComment({ - docsCount: 4, - formatBytes, - formatNumber, - ilmPhase: 'unmanaged', - indexName: 'auditbeat-custom-index-1', - isILMAvailable: true, - partitionedFieldMetadata: mockPartitionedFieldMetadata, - patternDocsCount: 57410, - sizeInBytes: 28413, - }) - ).toEqual( - '| Result | Index | Docs | Incompatible fields | ILM Phase | Size |\n|--------|-------|------|---------------------|-----------|------|\n| ❌ | auditbeat-custom-index-1 | 4 (0.0%) | 3 | `unmanaged` | 27.7KB |\n\n' - ); - }); - - test('it returns the expected comment when isILMAvailable is false', () => { - expect( - getSummaryTableMarkdownComment({ - docsCount: 4, - formatBytes, - formatNumber, - ilmPhase: 'unmanaged', - indexName: 'auditbeat-custom-index-1', - isILMAvailable: false, - partitionedFieldMetadata: mockPartitionedFieldMetadata, - patternDocsCount: 57410, - sizeInBytes: undefined, - }) - ).toEqual( - '| Result | Index | Docs | Incompatible fields |\n|--------|-------|------|---------------------|\n| ❌ | auditbeat-custom-index-1 | 4 (0.0%) | 3 |\n\n' - ); - }); - - test('it returns the expected comment when sizeInBytes is undefined', () => { - expect( - getSummaryTableMarkdownComment({ - docsCount: 4, - formatBytes, - formatNumber, - ilmPhase: 'unmanaged', - indexName: 'auditbeat-custom-index-1', - isILMAvailable: false, - partitionedFieldMetadata: mockPartitionedFieldMetadata, - patternDocsCount: 57410, - sizeInBytes: undefined, - }) - ).toEqual( - '| Result | Index | Docs | Incompatible fields |\n|--------|-------|------|---------------------|\n| ❌ | auditbeat-custom-index-1 | 4 (0.0%) | 3 |\n\n' - ); - }); - }); - - describe('getStatsRollupMarkdownComment', () => { - test('it returns the expected comment', () => { - expect( - getStatsRollupMarkdownComment({ - docsCount: 57410, - formatBytes, - formatNumber, - incompatible: 3, - indices: 25, - indicesChecked: 1, - sizeInBytes: 28413, - }) - ).toEqual( - '| Incompatible fields | Indices checked | Indices | Size | Docs |\n|---------------------|-----------------|---------|------|------|\n| 3 | 1 | 25 | 27.7KB | 57,410 |\n' - ); - }); - - test('it returns the expected comment when optional values are undefined', () => { - expect( - getStatsRollupMarkdownComment({ - docsCount: 0, - formatBytes, - formatNumber, - incompatible: undefined, - indices: undefined, - indicesChecked: undefined, - sizeInBytes: undefined, - }) - ).toEqual( - '| Incompatible fields | Indices checked | Indices | Docs |\n|---------------------|-----------------|---------|------|\n| -- | -- | -- | 0 |\n' - ); - }); - }); - - describe('getDataQualitySummaryMarkdownComment', () => { - test('it returns the expected comment', () => { - expect( - getDataQualitySummaryMarkdownComment({ - formatBytes, - formatNumber, - totalDocsCount: 3343719, - totalIncompatible: 4, - totalIndices: 30, - totalIndicesChecked: 2, - sizeInBytes: 4294967296, - }) - ).toEqual( - '# Data quality\n\n| Incompatible fields | Indices checked | Indices | Size | Docs |\n|---------------------|-----------------|---------|------|------|\n| 4 | 2 | 30 | 4GB | 3,343,719 |\n\n' - ); - }); - - test('it returns the expected comment when optional values are undefined', () => { - expect( - getDataQualitySummaryMarkdownComment({ - formatBytes, - formatNumber, - totalDocsCount: undefined, - totalIncompatible: undefined, - totalIndices: undefined, - totalIndicesChecked: undefined, - sizeInBytes: undefined, - }) - ).toEqual( - '# Data quality\n\n| Incompatible fields | Indices checked | Indices | Docs |\n|---------------------|-----------------|---------|------|\n| -- | -- | -- | 0 |\n\n' - ); - }); - }); - - describe('getIlmExplainPhaseCountsMarkdownComment', () => { - test('it returns the expected comment when _all_ of the counts are greater than zero', () => { - expect( - getIlmExplainPhaseCountsMarkdownComment({ - hot: 99, - warm: 8, - unmanaged: 77, - cold: 6, - frozen: 55, - }) - ).toEqual('`hot(99)` `warm(8)` `unmanaged(77)` `cold(6)` `frozen(55)`'); - }); - - test('it returns the expected comment when _some_ of the counts are greater than zero', () => { - expect( - getIlmExplainPhaseCountsMarkdownComment({ - hot: 9, - warm: 0, - unmanaged: 2, - cold: 1, - frozen: 0, - }) - ).toEqual('`hot(9)` `unmanaged(2)` `cold(1)`'); - }); - - test('it returns the expected comment when _none_ of the counts are greater than zero', () => { - expect( - getIlmExplainPhaseCountsMarkdownComment({ - hot: 0, - warm: 0, - unmanaged: 0, - cold: 0, - frozen: 0, - }) - ).toEqual(''); - }); - }); - - describe('getPatternSummaryMarkdownComment', () => { - test('it returns the expected comment when the rollup contains results for all of the indices in the pattern', () => { - expect( - getPatternSummaryMarkdownComment({ - formatBytes, - formatNumber, - patternRollup: auditbeatWithAllResults, - }) - ).toEqual( - '## auditbeat-*\n`hot(1)` `unmanaged(2)`\n\n| Incompatible fields | Indices checked | Indices | Size | Docs |\n|---------------------|-----------------|---------|------|------|\n| 4 | 3 | 3 | 17.9MB | 19,127 |\n\n' - ); - }); - - test('it returns the expected comment when the rollup contains no results', () => { - expect( - getPatternSummaryMarkdownComment({ - formatBytes, - formatNumber, - patternRollup: auditbeatNoResults, - }) - ).toEqual( - '## auditbeat-*\n`hot(1)` `unmanaged(2)`\n\n| Incompatible fields | Indices checked | Indices | Size | Docs |\n|---------------------|-----------------|---------|------|------|\n| -- | 0 | 3 | 17.9MB | 19,127 |\n\n' - ); - }); - - test('it returns the expected comment when the rollup does NOT have `ilmExplainPhaseCounts`', () => { - const noIlmExplainPhaseCounts: PatternRollup = { - ...auditbeatWithAllResults, - ilmExplainPhaseCounts: undefined, // <-- - }; - - expect( - getPatternSummaryMarkdownComment({ - formatBytes, - formatNumber, - patternRollup: noIlmExplainPhaseCounts, - }) - ).toEqual( - '## auditbeat-*\n\n\n| Incompatible fields | Indices checked | Indices | Size | Docs |\n|---------------------|-----------------|---------|------|------|\n| 4 | 3 | 3 | 17.9MB | 19,127 |\n\n' - ); - }); - - test('it returns the expected comment when `docsCount` is undefined', () => { - const noDocsCount: PatternRollup = { - ...auditbeatWithAllResults, - docsCount: undefined, // <-- - }; - - expect( - getPatternSummaryMarkdownComment({ - formatBytes, - formatNumber, - patternRollup: noDocsCount, - }) - ).toEqual( - '## auditbeat-*\n`hot(1)` `unmanaged(2)`\n\n| Incompatible fields | Indices checked | Indices | Size | Docs |\n|---------------------|-----------------|---------|------|------|\n| 4 | 3 | 3 | 17.9MB | 0 |\n\n' - ); - }); - }); -}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/markdown/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/markdown/helpers.ts deleted file mode 100644 index cc32fab713881..0000000000000 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/markdown/helpers.ts +++ /dev/null @@ -1,422 +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 { - getTotalPatternIncompatible, - getTotalPatternIndicesChecked, -} from '../../../../../../utils/stats'; -import { - ERRORS_MAY_OCCUR, - ERRORS_CALLOUT_SUMMARY, - MANAGE, - MONITOR, - OR, - READ, - THE_FOLLOWING_PRIVILEGES_ARE_REQUIRED, - VIEW_INDEX_METADATA, -} from '../../../../../../data_quality_summary/summary_actions/check_status/errors_popover/translations'; -import { EMPTY_STAT } from '../../../../../../constants'; -import { SAME_FAMILY } from '../index_check_fields/tabs/compare_fields_table/same_family/translations'; -import { - HOT, - WARM, - COLD, - FROZEN, - UNMANAGED, -} from '../../../../../ilm_phases_empty_prompt/translations'; -import * as i18n from '../translations'; -import type { - AllowedValue, - CustomFieldMetadata, - EcsBasedFieldMetadata, - EnrichedFieldMetadata, - ErrorSummary, - IlmExplainPhaseCounts, - IlmPhase, - PartitionedFieldMetadata, - PatternRollup, - UnallowedValueCount, -} from '../../../../../../types'; -import { getDocsCountPercent } from '../../../summary_table/helpers'; -import { - DOCS, - ILM_PHASE, - INCOMPATIBLE_FIELDS, - INDEX, - INDICES, - INDICES_CHECKED, - RESULT, - SIZE, -} from '../../../summary_table/translations'; -import { DATA_QUALITY_TITLE } from '../../../../../../translations'; - -export const EMPTY_PLACEHOLDER = '--'; - -export const TRIPLE_BACKTICKS = '```'; - -export const ECS_FIELD_REFERENCE_URL = - 'https://www.elastic.co/guide/en/ecs/current/ecs-field-reference.html'; - -/** The documentation link shown in the `Data Quality` dashboard */ -export const ECS_REFERENCE_URL = 'https://www.elastic.co/guide/en/ecs/current/ecs-reference.html'; -export const MAPPING_URL = - 'https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html'; - -export const escape = (content: string | undefined): string | undefined => - content != null ? content.replaceAll('\n', ' ').replaceAll('|', '\\|') : content; - -export const escapePreserveNewlines = (content: string | undefined): string | undefined => - content != null ? content.replaceAll('|', '\\|') : content; - -export const getHeaderSeparator = (headerText: string): string => '-'.repeat(headerText.length + 2); // 2 extra, for the spaces on both sides of the column name - -export const getMarkdownTableHeader = (headerNames: string[]) => ` -| ${headerNames.map((name) => `${escape(name)} | `).join('')} -|${headerNames.map((name) => `${getHeaderSeparator(name)}|`).join('')}`; - -export const getCodeFormattedValue = (value: string | undefined) => - `\`${escape(value ?? EMPTY_PLACEHOLDER)}\``; - -export const getAllowedValues = (allowedValues: AllowedValue[] | undefined): string => - allowedValues == null - ? getCodeFormattedValue(undefined) - : allowedValues.map((x) => getCodeFormattedValue(x.name)).join(', '); - -export const getIndexInvalidValues = (indexInvalidValues: UnallowedValueCount[]): string => - indexInvalidValues.length === 0 - ? getCodeFormattedValue(undefined) - : indexInvalidValues - .map(({ fieldName, count }) => `${getCodeFormattedValue(escape(fieldName))} (${count})`) - .join(', '); // newlines are instead joined with spaces - -export const getCustomMarkdownTableRows = (customFieldMetadata: CustomFieldMetadata[]): string => - customFieldMetadata - .map( - (x) => - `| ${escape(x.indexFieldName)} | ${getCodeFormattedValue( - x.indexFieldType - )} | ${getAllowedValues(undefined)} |` - ) - .join('\n'); - -export const getSameFamilyBadge = (ecsBasedFieldMetadata: EcsBasedFieldMetadata): string => - ecsBasedFieldMetadata.isInSameFamily ? getCodeFormattedValue(SAME_FAMILY) : ''; - -export const getIncompatibleMappingsMarkdownTableRows = ( - incompatibleMappings: EcsBasedFieldMetadata[] -): string => - incompatibleMappings - .map( - (x) => - `| ${escape(x.indexFieldName)} | ${getCodeFormattedValue(x.type)} | ${getCodeFormattedValue( - x.indexFieldType - )} ${getSameFamilyBadge(x)} |` - ) - .join('\n'); - -export const getIncompatibleValuesMarkdownTableRows = ( - incompatibleValues: EcsBasedFieldMetadata[] -): string => - incompatibleValues - .map( - (x) => - `| ${escape(x.indexFieldName)} | ${getAllowedValues( - x.allowed_values - )} | ${getIndexInvalidValues(x.indexInvalidValues)} |` - ) - .join('\n'); - -export const getMarkdownComment = ({ - suggestedAction, - title, -}: { - suggestedAction: string; - title: string; -}): string => - `#### ${escape(title)} - -${escapePreserveNewlines(suggestedAction)}`; - -export const getErrorsMarkdownTableRows = (errorSummary: ErrorSummary[]): string => - errorSummary - .map( - ({ pattern, indexName, error }) => - `| ${escape(pattern)} | ${escape(indexName ?? EMPTY_PLACEHOLDER)} | ${getCodeFormattedValue( - error - )} |` - ) - .join('\n'); - -export const getErrorsMarkdownTable = ({ - errorSummary, - getMarkdownTableRows, - headerNames, - title, -}: { - errorSummary: ErrorSummary[]; - getMarkdownTableRows: (errorSummary: ErrorSummary[]) => string; - headerNames: string[]; - title: string; -}): string => - errorSummary.length > 0 - ? `## ${escape(title)} - -${ERRORS_CALLOUT_SUMMARY} - -${ERRORS_MAY_OCCUR} - -${THE_FOLLOWING_PRIVILEGES_ARE_REQUIRED} -- \`${MONITOR}\` ${OR} \`${MANAGE}\` -- \`${VIEW_INDEX_METADATA}\` -- \`${READ}\` - -${getMarkdownTableHeader(headerNames)} -${getMarkdownTableRows(errorSummary)} -` - : ''; - -export const getMarkdownTable = ({ - enrichedFieldMetadata, - getMarkdownTableRows, - headerNames, - title, -}: { - enrichedFieldMetadata: T; - getMarkdownTableRows: (enrichedFieldMetadata: T) => string; - headerNames: string[]; - title: string; -}): string => - enrichedFieldMetadata.length > 0 - ? `#### ${escape(title)} - -${getMarkdownTableHeader(headerNames)} -${getMarkdownTableRows(enrichedFieldMetadata)} -` - : ''; - -export const getSummaryMarkdownComment = (indexName: string) => - `### ${escape(indexName)} -`; - -export const getTabCountsMarkdownComment = ( - partitionedFieldMetadata: PartitionedFieldMetadata -): string => - `### **${i18n.INCOMPATIBLE_FIELDS}** ${getCodeFormattedValue( - `${partitionedFieldMetadata.incompatible.length}` - )} **${i18n.SAME_FAMILY}** ${getCodeFormattedValue( - `${partitionedFieldMetadata.sameFamily.length}` - )} **${i18n.CUSTOM_FIELDS}** ${getCodeFormattedValue( - `${partitionedFieldMetadata.custom.length}` - )} **${i18n.ECS_COMPLIANT_FIELDS}** ${getCodeFormattedValue( - `${partitionedFieldMetadata.ecsCompliant.length}` - )} **${i18n.ALL_FIELDS}** ${getCodeFormattedValue(`${partitionedFieldMetadata.all.length}`)} -`; - -export const getResultEmoji = (incompatible: number | undefined): string => { - if (incompatible == null) { - return EMPTY_PLACEHOLDER; - } else { - return incompatible === 0 ? '✅' : '❌'; - } -}; - -export const getSummaryTableMarkdownHeader = (includeDocSize: boolean): string => - includeDocSize - ? `| ${RESULT} | ${INDEX} | ${DOCS} | ${INCOMPATIBLE_FIELDS} | ${ILM_PHASE} | ${SIZE} | -|${getHeaderSeparator(RESULT)}|${getHeaderSeparator(INDEX)}|${getHeaderSeparator( - DOCS - )}|${getHeaderSeparator(INCOMPATIBLE_FIELDS)}|${getHeaderSeparator( - ILM_PHASE - )}|${getHeaderSeparator(SIZE)}|` - : `| ${RESULT} | ${INDEX} | ${DOCS} | ${INCOMPATIBLE_FIELDS} | -|${getHeaderSeparator(RESULT)}|${getHeaderSeparator(INDEX)}|${getHeaderSeparator( - DOCS - )}|${getHeaderSeparator(INCOMPATIBLE_FIELDS)}|`; - -export const getSummaryTableMarkdownRow = ({ - docsCount, - formatBytes, - formatNumber, - ilmPhase, - incompatible, - indexName, - isILMAvailable, - patternDocsCount, - sizeInBytes, -}: { - docsCount: number; - formatBytes: (value: number | undefined) => string; - formatNumber: (value: number | undefined) => string; - ilmPhase: IlmPhase | undefined; - incompatible: number | undefined; - indexName: string; - isILMAvailable: boolean; - patternDocsCount: number; - sizeInBytes: number | undefined; -}): string => - isILMAvailable && Number.isInteger(sizeInBytes) - ? `| ${getResultEmoji(incompatible)} | ${escape(indexName)} | ${formatNumber( - docsCount - )} (${getDocsCountPercent({ - docsCount, - patternDocsCount, - })}) | ${incompatible ?? EMPTY_PLACEHOLDER} | ${ - ilmPhase != null ? getCodeFormattedValue(ilmPhase) : EMPTY_PLACEHOLDER - } | ${formatBytes(sizeInBytes)} | -` - : `| ${getResultEmoji(incompatible)} | ${escape(indexName)} | ${formatNumber( - docsCount - )} (${getDocsCountPercent({ - docsCount, - patternDocsCount, - })}) | ${incompatible ?? EMPTY_PLACEHOLDER} | -`; - -export const getSummaryTableMarkdownComment = ({ - docsCount, - formatBytes, - formatNumber, - ilmPhase, - indexName, - isILMAvailable, - partitionedFieldMetadata, - patternDocsCount, - sizeInBytes, -}: { - docsCount: number; - formatBytes: (value: number | undefined) => string; - formatNumber: (value: number | undefined) => string; - ilmPhase: IlmPhase | undefined; - indexName: string; - isILMAvailable: boolean; - partitionedFieldMetadata: PartitionedFieldMetadata; - patternDocsCount: number; - sizeInBytes: number | undefined; -}): string => - `${getSummaryTableMarkdownHeader(isILMAvailable)} -${getSummaryTableMarkdownRow({ - docsCount, - formatBytes, - formatNumber, - ilmPhase, - indexName, - isILMAvailable, - incompatible: partitionedFieldMetadata.incompatible.length, - patternDocsCount, - sizeInBytes, -})} -`; - -export const getStatsRollupMarkdownComment = ({ - docsCount, - formatBytes, - formatNumber, - incompatible, - indices, - indicesChecked, - sizeInBytes, -}: { - docsCount: number; - formatBytes: (value: number | undefined) => string; - formatNumber: (value: number | undefined) => string; - incompatible: number | undefined; - indices: number | undefined; - indicesChecked: number | undefined; - sizeInBytes: number | undefined; -}): string => - Number.isInteger(sizeInBytes) - ? `| ${INCOMPATIBLE_FIELDS} | ${INDICES_CHECKED} | ${INDICES} | ${SIZE} | ${DOCS} | -|${getHeaderSeparator(INCOMPATIBLE_FIELDS)}|${getHeaderSeparator( - INDICES_CHECKED - )}|${getHeaderSeparator(INDICES)}|${getHeaderSeparator(SIZE)}|${getHeaderSeparator(DOCS)}| -| ${incompatible ?? EMPTY_STAT} | ${indicesChecked ?? EMPTY_STAT} | ${ - indices ?? EMPTY_STAT - } | ${formatBytes(sizeInBytes)} | ${formatNumber(docsCount)} | -` - : `| ${INCOMPATIBLE_FIELDS} | ${INDICES_CHECKED} | ${INDICES} | ${DOCS} | -|${getHeaderSeparator(INCOMPATIBLE_FIELDS)}|${getHeaderSeparator( - INDICES_CHECKED - )}|${getHeaderSeparator(INDICES)}|${getHeaderSeparator(DOCS)}| -| ${incompatible ?? EMPTY_STAT} | ${indicesChecked ?? EMPTY_STAT} | ${ - indices ?? EMPTY_STAT - } | ${formatNumber(docsCount)} | -`; - -export const getDataQualitySummaryMarkdownComment = ({ - formatBytes, - formatNumber, - totalDocsCount, - totalIncompatible, - totalIndices, - totalIndicesChecked, - sizeInBytes, -}: { - formatBytes: (value: number | undefined) => string; - formatNumber: (value: number | undefined) => string; - totalDocsCount: number | undefined; - totalIncompatible: number | undefined; - totalIndices: number | undefined; - totalIndicesChecked: number | undefined; - sizeInBytes: number | undefined; -}): string => - `# ${DATA_QUALITY_TITLE} - -${getStatsRollupMarkdownComment({ - docsCount: totalDocsCount ?? 0, - formatBytes, - formatNumber, - incompatible: totalIncompatible, - indices: totalIndices, - indicesChecked: totalIndicesChecked, - sizeInBytes, -})} -`; - -export const getIlmExplainPhaseCountsMarkdownComment = ({ - hot, - warm, - unmanaged, - cold, - frozen, -}: IlmExplainPhaseCounts): string => - [ - hot > 0 ? getCodeFormattedValue(`${HOT}(${hot})`) : '', - warm > 0 ? getCodeFormattedValue(`${WARM}(${warm})`) : '', - unmanaged > 0 ? getCodeFormattedValue(`${UNMANAGED}(${unmanaged})`) : '', - cold > 0 ? getCodeFormattedValue(`${COLD}(${cold})`) : '', - frozen > 0 ? getCodeFormattedValue(`${FROZEN}(${frozen})`) : '', - ] - .filter((x) => x !== '') // prevents extra whitespace - .join(' '); - -export const getPatternSummaryMarkdownComment = ({ - formatBytes, - formatNumber, - patternRollup, - patternRollup: { docsCount, indices, ilmExplainPhaseCounts, pattern, results }, -}: { - formatBytes: (value: number | undefined) => string; - formatNumber: (value: number | undefined) => string; - patternRollup: PatternRollup; -}): string => - `## ${escape(pattern)} -${ - ilmExplainPhaseCounts != null - ? getIlmExplainPhaseCountsMarkdownComment(ilmExplainPhaseCounts) - : '' -} - -${getStatsRollupMarkdownComment({ - docsCount: docsCount ?? 0, - formatBytes, - formatNumber, - incompatible: getTotalPatternIncompatible(results), - indices, - indicesChecked: getTotalPatternIndicesChecked(patternRollup), - sizeInBytes: patternRollup.sizeInBytes, -})} -`; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/translations.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/translations.ts index 7e18a0941e004..402b58c4915db 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/translations.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/translations.ts @@ -110,13 +110,6 @@ export const CUSTOM_DETECTION_ENGINE_RULES_WORK = i18n.translate( } ); -export const DOCS = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.indexProperties.docsLabel', - { - defaultMessage: 'Docs', - } -); - export const ECS_COMPLIANT_FIELDS = i18n.translate( 'securitySolutionPackages.ecsDataQualityDashboard.indexProperties.ecsCompliantFieldsLabel', { @@ -333,13 +326,6 @@ export const CUSTOM_EMPTY_TITLE = i18n.translate( } ); -export const INCOMPATIBLE_FIELDS = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.indexProperties.incompatibleFieldsTab', - { - defaultMessage: 'Incompatible fields', - } -); - export const INCOMPATIBLE_CALLOUT = (version: string) => i18n.translate( 'securitySolutionPackages.ecsDataQualityDashboard.indexProperties.incompatibleCallout', diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/utils/get_index_properties_container_id.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/utils/get_index_properties_container_id.test.ts new file mode 100644 index 0000000000000..68f4414a624a0 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/utils/get_index_properties_container_id.test.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getIndexPropertiesContainerId } from './get_index_properties_container_id'; + +describe('getIndexPropertiesContainerId', () => { + const pattern = 'auditbeat-*'; + const indexName = '.ds-packetbeat-8.6.1-2023.02.04-000001'; + + test('it returns the expected id', () => { + expect(getIndexPropertiesContainerId({ indexName, pattern })).toEqual( + 'index-properties-container-auditbeat-*.ds-packetbeat-8.6.1-2023.02.04-000001' + ); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/utils/get_index_properties_container_id.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/utils/get_index_properties_container_id.ts new file mode 100644 index 0000000000000..2a7172d58a7b4 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/utils/get_index_properties_container_id.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const getIndexPropertiesContainerId = ({ + indexName, + pattern, +}: { + indexName: string; + pattern: string; +}): string => `index-properties-container-${pattern}${indexName}`; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_result_badge/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_result_badge/index.tsx index 9dcd3ca18e729..5128130971b09 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_result_badge/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_result_badge/index.tsx @@ -9,7 +9,8 @@ import { EuiBadge, EuiToolTip } from '@elastic/eui'; import React from 'react'; import styled from 'styled-components'; -import { getIndexResultBadgeColor, getIndexResultToolTip } from './helpers'; +import { getIndexResultToolTip } from '../utils/get_index_result_tooltip'; +import { getIndexResultBadgeColor } from './utils/get_index_result_badge_color'; import * as i18n from './translations'; const StyledBadge = styled(EuiBadge)` diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_result_badge/utils/get_index_result_badge_color.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_result_badge/utils/get_index_result_badge_color.test.ts new file mode 100644 index 0000000000000..68a5da877da9a --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_result_badge/utils/get_index_result_badge_color.test.ts @@ -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 { getIndexResultBadgeColor } from './get_index_result_badge_color'; + +describe('getIndexResultBadgeColor', () => { + test('it returns `ghost` when `incompatible` is undefined', () => { + expect(getIndexResultBadgeColor(undefined)).toEqual('ghost'); + }); + + test('it returns `success` when `incompatible` is zero', () => { + expect(getIndexResultBadgeColor(0)).toEqual('#6dcbb1'); + }); + + test('it returns `danger` when `incompatible` is NOT zero', () => { + expect(getIndexResultBadgeColor(1)).toEqual('danger'); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_result_badge/utils/get_index_result_badge_color.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_result_badge/utils/get_index_result_badge_color.ts new file mode 100644 index 0000000000000..61f3aaa89a372 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_result_badge/utils/get_index_result_badge_color.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const getIndexResultBadgeColor = (incompatible: number | undefined): string => { + if (incompatible == null) { + return 'ghost'; + } else if (incompatible === 0) { + return '#6dcbb1'; + } else { + return 'danger'; + } +}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/helpers.test.ts deleted file mode 100644 index c00dac59be3c0..0000000000000 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/helpers.test.ts +++ /dev/null @@ -1,97 +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 { getPatternResultTooltip, showResult } from './helpers'; -import { ALL_PASSED, SOME_FAILED, SOME_UNCHECKED } from './translations'; - -describe('helpers', () => { - describe('getPatternResultTooltip', () => { - test('it returns the expected tool tip when `incompatible` is undefined', () => { - expect(getPatternResultTooltip(undefined)).toEqual(SOME_UNCHECKED); - }); - - test('it returns the expected tool tip when `incompatible` is zero', () => { - expect(getPatternResultTooltip(0)).toEqual(ALL_PASSED); - }); - - test('it returns the expected tool tip when `incompatible` is non-zero', () => { - expect(getPatternResultTooltip(1)).toEqual(SOME_FAILED); - }); - }); - - describe('showResult', () => { - test('it returns true when `incompatible` is defined, and `indicesChecked` equals `indices`', () => { - const incompatible = 0; // none of the indices checked had incompatible fields - const indicesChecked = 2; // all indices were checked - const indices = 2; // total indices - - expect( - showResult({ - incompatible, - indices, - indicesChecked, - }) - ).toBe(true); - }); - - test('it returns false when `incompatible` is defined, and `indices` does NOT equal `indicesChecked`', () => { - const incompatible = 0; // the one index checked (so far) didn't have any incompatible fields - const indicesChecked = 1; // only one index has been checked so far - const indices = 2; // total indices - - expect( - showResult({ - incompatible, - indices, - indicesChecked, - }) - ).toBe(false); - }); - - test('it returns false when `incompatible` is undefined', () => { - const incompatible = undefined; // a state of undefined indicates there are no results - const indicesChecked = 1; // all indices were checked - const indices = 1; // total indices - - expect( - showResult({ - incompatible, - indices, - indicesChecked, - }) - ).toBe(false); - }); - - test('it returns false when `indices` is undefined', () => { - const incompatible = 0; // none of the indices checked had incompatible fields - const indicesChecked = 2; // all indices were checked - const indices = undefined; // the total number of indices is unknown - - expect( - showResult({ - incompatible, - indices, - indicesChecked, - }) - ).toBe(false); - }); - - test('it returns false when `indicesChecked` is undefined', () => { - const incompatible = 0; // none of the indices checked had incompatible fields - const indicesChecked = undefined; // no indices were checked - const indices = 2; // total indices - - expect( - showResult({ - incompatible, - indices, - indicesChecked, - }) - ).toBe(false); - }); - }); -}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/ilm_phase_counts/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/ilm_phase_counts/index.test.tsx index f9e04fc707b01..5de02814fd5cd 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/ilm_phase_counts/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/ilm_phase_counts/index.test.tsx @@ -15,7 +15,7 @@ import React from 'react'; import { TestExternalProviders } from '../../../../../../mock/test_providers/test_providers'; import { IlmPhaseCounts } from '.'; -import { getIlmExplainPhaseCounts } from '../../../helpers'; +import { getIlmExplainPhaseCounts } from '../../../utils/ilm_explain'; const hot: IlmExplainLifecycleLifecycleExplainManaged = { index: '.ds-packetbeat-8.6.1-2023.02.04-000001', diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/index.tsx index 03fede1fb7675..f88c9b8f977b0 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/index.tsx @@ -8,11 +8,12 @@ import { EuiTitle, EuiToolTip, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React from 'react'; -import { getPatternResultTooltip, showResult } from './helpers'; -import { IlmPhaseCounts } from './ilm_phase_counts'; -import * as i18n from '../translations'; import type { IlmExplainPhaseCounts } from '../../../../../types'; import { IndexResultBadge } from '../../index_result_badge'; +import * as i18n from '../translations'; +import { IlmPhaseCounts } from './ilm_phase_counts'; +import { getPatternResultTooltip } from './utils/get_pattern_result_tooltip'; +import { showResult } from './utils/show_result'; interface Props { incompatible: number | undefined; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/utils/get_pattern_result_tooltip.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/utils/get_pattern_result_tooltip.test.ts new file mode 100644 index 0000000000000..525eaab098ba6 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/utils/get_pattern_result_tooltip.test.ts @@ -0,0 +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. + */ + +import { getPatternResultTooltip } from './get_pattern_result_tooltip'; +import { ALL_PASSED, SOME_FAILED, SOME_UNCHECKED } from '../translations'; + +describe('helpers', () => { + describe('getPatternResultTooltip', () => { + test('it returns the expected tool tip when `incompatible` is undefined', () => { + expect(getPatternResultTooltip(undefined)).toEqual(SOME_UNCHECKED); + }); + + test('it returns the expected tool tip when `incompatible` is zero', () => { + expect(getPatternResultTooltip(0)).toEqual(ALL_PASSED); + }); + + test('it returns the expected tool tip when `incompatible` is non-zero', () => { + expect(getPatternResultTooltip(1)).toEqual(SOME_FAILED); + }); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/utils/get_pattern_result_tooltip.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/utils/get_pattern_result_tooltip.ts new file mode 100644 index 0000000000000..2bb51c19ced31 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/utils/get_pattern_result_tooltip.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as i18n from '../translations'; + +export const getPatternResultTooltip = (incompatible: number | undefined): string => { + if (incompatible == null) { + return i18n.SOME_UNCHECKED; + } else if (incompatible === 0) { + return i18n.ALL_PASSED; + } else { + return i18n.SOME_FAILED; + } +}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/utils/show_result.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/utils/show_result.test.ts new file mode 100644 index 0000000000000..4957f8c65c2da --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/utils/show_result.test.ts @@ -0,0 +1,80 @@ +/* + * 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 { showResult } from './show_result'; + +describe('showResult', () => { + test('it returns true when `incompatible` is defined, and `indicesChecked` equals `indices`', () => { + const incompatible = 0; // none of the indices checked had incompatible fields + const indicesChecked = 2; // all indices were checked + const indices = 2; // total indices + + expect( + showResult({ + incompatible, + indices, + indicesChecked, + }) + ).toBe(true); + }); + + test('it returns false when `incompatible` is defined, and `indices` does NOT equal `indicesChecked`', () => { + const incompatible = 0; // the one index checked (so far) didn't have any incompatible fields + const indicesChecked = 1; // only one index has been checked so far + const indices = 2; // total indices + + expect( + showResult({ + incompatible, + indices, + indicesChecked, + }) + ).toBe(false); + }); + + test('it returns false when `incompatible` is undefined', () => { + const incompatible = undefined; // a state of undefined indicates there are no results + const indicesChecked = 1; // all indices were checked + const indices = 1; // total indices + + expect( + showResult({ + incompatible, + indices, + indicesChecked, + }) + ).toBe(false); + }); + + test('it returns false when `indices` is undefined', () => { + const incompatible = 0; // none of the indices checked had incompatible fields + const indicesChecked = 2; // all indices were checked + const indices = undefined; // the total number of indices is unknown + + expect( + showResult({ + incompatible, + indices, + indicesChecked, + }) + ).toBe(false); + }); + + test('it returns false when `indicesChecked` is undefined', () => { + const incompatible = 0; // none of the indices checked had incompatible fields + const indicesChecked = undefined; // no indices were checked + const indices = 2; // total indices + + expect( + showResult({ + incompatible, + indices, + indicesChecked, + }) + ).toBe(false); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/utils/show_result.ts similarity index 66% rename from x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/helpers.ts rename to x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/utils/show_result.ts index bce8098e963fc..df7be212f4bc0 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/pattern_summary/pattern_label/utils/show_result.ts @@ -5,17 +5,6 @@ * 2.0. */ -import * as i18n from './translations'; - -export const getPatternResultTooltip = (incompatible: number | undefined): string => { - if (incompatible == null) { - return i18n.SOME_UNCHECKED; - } else if (incompatible === 0) { - return i18n.ALL_PASSED; - } else { - return i18n.SOME_FAILED; - } -}; interface ShowResultProps { incompatible: T; indices: T; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/index.test.tsx index 01d45a3784a5f..223eaf29dd469 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/index.test.tsx @@ -10,7 +10,7 @@ import { render, screen } from '@testing-library/react'; import React from 'react'; import { EMPTY_STAT } from '../../../../constants'; -import { getSummaryTableColumns } from './helpers'; +import { getSummaryTableColumns } from './utils/columns'; import { mockIlmExplain } from '../../../../mock/ilm_explain/mock_ilm_explain'; import { auditbeatWithAllResults } from '../../../../mock/pattern_rollup/mock_auditbeat_pattern_rollup'; import { mockStats } from '../../../../mock/stats/mock_stats'; @@ -18,9 +18,9 @@ import { TestDataQualityProviders, TestExternalProviders, } from '../../../../mock/test_providers/test_providers'; -import { getSummaryTableItems } from '../helpers'; import { SortConfig } from '../../../../types'; import { Props, SummaryTable } from '.'; +import { getSummaryTableItems } from '../../../../utils/get_summary_table_items'; const defaultBytesFormat = '0,0.[0]b'; const formatBytes = (value: number | undefined) => @@ -39,7 +39,7 @@ const indexNames = [ '.ds-packetbeat-8.6.1-2023.02.04-000001', ]; -export const defaultSort: SortConfig = { +const defaultSort: SortConfig = { sort: { direction: 'desc', field: 'docsCount', diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/index.tsx index fad209fb29e54..bc4e572e892fa 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/index.tsx @@ -9,12 +9,12 @@ import type { CriteriaWithPagination, EuiBasicTableColumn, Pagination } from '@e import { EuiInMemoryTable } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; -import { getShowPagination } from './helpers'; -import { defaultSort, MIN_PAGE_SIZE } from '../helpers'; -import { SortConfig } from '../../../../types'; +import { defaultSort } from '../../../../constants'; +import { IndexSummaryTableItem, SortConfig } from '../../../../types'; import { useDataQualityContext } from '../../../../data_quality_context'; -import { IndexSummaryTableItem } from '../types'; import { UseIndicesCheckCheckState } from '../../../../hooks/use_indices_check/types'; +import { MIN_PAGE_SIZE } from '../constants'; +import { getShowPagination } from './utils/get_show_pagination'; export interface Props { getTableColumns: ({ diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/translations.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/translations.ts index 7e005ba659c1d..c3302d7be4b57 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/translations.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/translations.ts @@ -14,13 +14,6 @@ export const COLLAPSE = i18n.translate( } ); -export const DOCS = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.summaryTable.docsColumn', - { - defaultMessage: 'Docs', - } -); - export const VIEW_CHECK_DETAILS = i18n.translate( 'securitySolutionPackages.ecsDataQualityDashboard.summaryTable.viewCheckDetailsLabel', { @@ -35,48 +28,6 @@ export const EXPAND_ROWS = i18n.translate( } ); -export const FAILED = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.summaryTable.failedTooltip', - { - defaultMessage: 'Failed', - } -); - -export const ILM_PHASE = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.summaryTable.ilmPhaseColumn', - { - defaultMessage: 'ILM Phase', - } -); - -export const INCOMPATIBLE_FIELDS = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.summaryTable.incompatibleFieldsColumn', - { - defaultMessage: 'Incompatible fields', - } -); - -export const INDICES = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indicesColumn', - { - defaultMessage: 'Indices', - } -); - -export const INDICES_CHECKED = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indicesCheckedColumn', - { - defaultMessage: 'Indices checked', - } -); - -export const INDEX = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indexColumn', - { - defaultMessage: 'Index', - } -); - export const INDEX_NAME_LABEL = i18n.translate( 'securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indexesNameLabel', { @@ -90,27 +41,6 @@ export const INDEX_TOOL_TIP = (pattern: string) => defaultMessage: 'This index matches the pattern or index name: {pattern}', }); -export const PASSED = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.summaryTable.passedTooltip', - { - defaultMessage: 'Passed', - } -); - -export const RESULT = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.summaryTable.resultColumn', - { - defaultMessage: 'Result', - } -); - -export const SIZE = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.summaryTable.sizeColumn', - { - defaultMessage: 'Size', - } -); - export const LAST_CHECK = i18n.translate( 'securitySolutionPackages.ecsDataQualityDashboard.summaryTable.lastCheckColumn', { @@ -118,13 +48,6 @@ export const LAST_CHECK = i18n.translate( } ); -export const THIS_INDEX_HAS_NOT_BEEN_CHECKED = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.summaryTable.thisIndexHasNotBeenCheckedTooltip', - { - defaultMessage: 'This index has not been checked', - } -); - export const ACTIONS = i18n.translate( 'securitySolutionPackages.ecsDataQualityDashboard.summaryTable.actionsColumn', { diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/helpers.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/utils/columns.test.tsx similarity index 88% rename from x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/helpers.test.tsx rename to x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/utils/columns.test.tsx index 1efaa01d36f9e..930b2a6bfbf96 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/helpers.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/utils/columns.test.tsx @@ -16,20 +16,17 @@ import userEvent from '@testing-library/user-event'; import { omit } from 'lodash/fp'; import React from 'react'; -import { TestExternalProviders } from '../../../../mock/test_providers/test_providers'; -import { EMPTY_STAT } from '../../../../constants'; +import { TestExternalProviders } from '../../../../../mock/test_providers/test_providers'; +import { EMPTY_STAT } from '../../../../../constants'; import { - getDocsCountPercent, getIncompatibleStatColor, - getShowPagination, getSummaryTableColumns, getSummaryTableILMPhaseColumn, getSummaryTableSizeInBytesColumn, - getToggleButtonId, -} from './helpers'; -import { CHECK_INDEX, VIEW_CHECK_DETAILS } from './translations'; -import { IndexSummaryTableItem } from '../types'; -import { getCheckState } from '../../../../stub/get_check_state'; +} from './columns'; +import { CHECK_INDEX, VIEW_CHECK_DETAILS } from '../translations'; +import { IndexSummaryTableItem } from '../../../../../types'; +import { getCheckState } from '../../../../../stub/get_check_state'; const defaultBytesFormat = '0,0.[0]b'; const formatBytes = (value: number | undefined) => @@ -40,59 +37,6 @@ const formatNumber = (value: number | undefined) => value != null ? numeral(value).format(defaultNumberFormat) : EMPTY_STAT; describe('helpers', () => { - describe('getDocsCountPercent', () => { - test('it returns an empty string when `patternDocsCount` is zero', () => { - expect( - getDocsCountPercent({ - docsCount: 0, - patternDocsCount: 0, - }) - ).toEqual(''); - }); - - test('it returns the expected format when when `patternDocsCount` is non-zero, and `locales` is undefined', () => { - expect( - getDocsCountPercent({ - docsCount: 2904, - locales: undefined, - patternDocsCount: 57410, - }) - ).toEqual('5.1%'); - }); - - test('it returns the expected format when when `patternDocsCount` is non-zero, and `locales` is provided', () => { - expect( - getDocsCountPercent({ - docsCount: 2904, - locales: 'en-US', - patternDocsCount: 57410, - }) - ).toEqual('5.1%'); - }); - }); - - describe('getToggleButtonId', () => { - test('it returns the expected id when the button is expanded', () => { - expect( - getToggleButtonId({ - indexName: 'auditbeat-custom-index-1', - isExpanded: true, - pattern: 'auditbeat-*', - }) - ).toEqual('collapseauditbeat-custom-index-1auditbeat-*'); - }); - - test('it returns the expected id when the button is collapsed', () => { - expect( - getToggleButtonId({ - indexName: 'auditbeat-custom-index-1', - isExpanded: false, - pattern: 'auditbeat-*', - }) - ).toEqual('expandauditbeat-custom-index-1auditbeat-*'); - }); - }); - describe('getSummaryTableColumns', () => { const indexName = '.ds-auditbeat-8.6.1-2023.02.07-000001'; const isILMAvailable = true; @@ -638,35 +582,6 @@ describe('helpers', () => { }); }); - describe('getShowPagination', () => { - test('it returns true when `totalItemCount` is greater than `minPageSize`', () => { - expect( - getShowPagination({ - minPageSize: 10, - totalItemCount: 11, - }) - ).toBe(true); - }); - - test('it returns false when `totalItemCount` equals `minPageSize`', () => { - expect( - getShowPagination({ - minPageSize: 10, - totalItemCount: 10, - }) - ).toBe(false); - }); - - test('it returns false when `totalItemCount` is less than `minPageSize`', () => { - expect( - getShowPagination({ - minPageSize: 10, - totalItemCount: 9, - }) - ).toBe(false); - }); - }); - describe('getIncompatibleStatColor', () => { test('it returns the expected color when incompatible is greater than zero', () => { const incompatible = 123; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/helpers.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/utils/columns.tsx similarity index 77% rename from x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/helpers.tsx rename to x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/utils/columns.tsx index 327c5b5e46667..8cdac8e35d1b3 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/helpers.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/utils/columns.tsx @@ -18,48 +18,30 @@ import moment from 'moment'; import styled from 'styled-components'; import { euiThemeVars } from '@kbn/ui-theme'; -import { EMPTY_STAT } from '../../../../constants'; -import { getIlmPhaseDescription } from '../../../../utils/get_ilm_phase_description'; -import { INCOMPATIBLE_INDEX_TOOL_TIP } from '../../../../stat_label/translations'; -import { INDEX_SIZE_TOOLTIP } from '../../../../translations'; -import * as i18n from './translations'; -import { IndexSummaryTableItem } from '../types'; -import { UseIndicesCheckCheckState } from '../../../../hooks/use_indices_check/types'; -import { IndexResultBadge } from '../index_result_badge'; -import { getIndexResultToolTip } from '../index_result_badge/helpers'; -import { Stat } from '../../../../stat'; +import { getDocsCountPercent } from '../../../../../utils/stats'; +import { IndexSummaryTableItem } from '../../../../../types'; +import { EMPTY_STAT } from '../../../../../constants'; +import { getIlmPhaseDescription } from '../../../../../utils/get_ilm_phase_description'; +import { INCOMPATIBLE_INDEX_TOOL_TIP } from '../../../../../stat_label/translations'; +import { + DOCS, + ILM_PHASE_CAPITALIZED, + INCOMPATIBLE_FIELDS, + INDEX, + INDEX_SIZE_TOOLTIP, + RESULT, + SIZE, +} from '../../../../../translations'; +import * as i18n from '../translations'; +import { UseIndicesCheckCheckState } from '../../../../../hooks/use_indices_check/types'; +import { IndexResultBadge } from '../../index_result_badge'; +import { Stat } from '../../../../../stat'; +import { getIndexResultToolTip } from '../../utils/get_index_result_tooltip'; const ProgressContainer = styled.div` width: 150px; `; -export const getDocsCountPercent = ({ - docsCount, - locales, - patternDocsCount, -}: { - docsCount: number; - locales?: string | string[]; - patternDocsCount: number; -}): string => - patternDocsCount !== 0 - ? Number(docsCount / patternDocsCount).toLocaleString(locales, { - style: 'percent', - maximumFractionDigits: 1, - minimumFractionDigits: 1, - }) - : ''; - -export const getToggleButtonId = ({ - indexName, - isExpanded, - pattern, -}: { - indexName: string; - isExpanded: boolean; - pattern: string; -}): string => (isExpanded ? `collapse${indexName}${pattern}` : `expand${indexName}${pattern}`); - export const getSummaryTableILMPhaseColumn = ( isILMAvailable: boolean ): Array> => @@ -67,7 +49,7 @@ export const getSummaryTableILMPhaseColumn = ( ? [ { field: 'ilmPhase', - name: i18n.ILM_PHASE, + name: ILM_PHASE_CAPITALIZED, render: (_, { ilmPhase }) => ilmPhase != null ? ( Number.isInteger(sizeInBytes) ? ( @@ -169,7 +151,7 @@ export const getSummaryTableColumns = ({ }, { field: 'incompatible', - name: i18n.RESULT, + name: RESULT, render: (_, { incompatible }) => incompatible != null ? ( @@ -184,7 +166,7 @@ export const getSummaryTableColumns = ({ }, { field: 'indexName', - name: i18n.INDEX, + name: INDEX, render: (_, { indexName }) => ( @@ -197,7 +179,7 @@ export const getSummaryTableColumns = ({ }, { field: 'docsCount', - name: i18n.DOCS, + name: DOCS, render: (_, { docsCount, patternDocsCount }) => ( ( + name: INCOMPATIBLE_FIELDS, + render: (_, { incompatible }) => ( totalItemCount > minPageSize; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/utils/get_show_pagination.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/utils/get_show_pagination.test.ts new file mode 100644 index 0000000000000..7438431e85535 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/utils/get_show_pagination.test.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getShowPagination } from './get_show_pagination'; + +describe('getShowPagination', () => { + test('it returns true when `totalItemCount` is greater than `minPageSize`', () => { + expect( + getShowPagination({ + minPageSize: 10, + totalItemCount: 11, + }) + ).toBe(true); + }); + + test('it returns false when `totalItemCount` equals `minPageSize`', () => { + expect( + getShowPagination({ + minPageSize: 10, + totalItemCount: 10, + }) + ).toBe(false); + }); + + test('it returns false when `totalItemCount` is less than `minPageSize`', () => { + expect( + getShowPagination({ + minPageSize: 10, + totalItemCount: 9, + }) + ).toBe(false); + }); +}); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/types.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/utils/get_show_pagination.ts similarity index 60% rename from x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/types.ts rename to x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/utils/get_show_pagination.ts index 97d82b862428d..5cf90b3f7a712 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/types.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/summary_table/utils/get_show_pagination.ts @@ -5,9 +5,10 @@ * 2.0. */ -import { FlyoutDataset } from '../../state_machines/dataset_quality_controller'; - -export interface FlyoutProps { - dataset: FlyoutDataset; - closeFlyout: () => void; -} +export const getShowPagination = ({ + minPageSize, + totalItemCount, +}: { + minPageSize: number; + totalItemCount: number; +}): boolean => totalItemCount > minPageSize; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/translations.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/translations.ts index aaf11b1ad405c..8e13a4be4cc30 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/translations.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/translations.ts @@ -22,3 +22,24 @@ export const LOADING_STATS = i18n.translate( defaultMessage: 'Loading stats', } ); + +export const PASSED = i18n.translate( + 'securitySolutionPackages.ecsDataQualityDashboard.passedTooltip', + { + defaultMessage: 'Passed', + } +); + +export const FAILED = i18n.translate( + 'securitySolutionPackages.ecsDataQualityDashboard.failedTooltip', + { + defaultMessage: 'Failed', + } +); + +export const THIS_INDEX_HAS_NOT_BEEN_CHECKED = i18n.translate( + 'securitySolutionPackages.ecsDataQualityDashboard.thisIndexHasNotBeenCheckedTooltip', + { + defaultMessage: 'This index has not been checked', + } +); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_result_badge/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/get_index_result_tooltip.test.ts similarity index 58% rename from x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_result_badge/helpers.test.ts rename to x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/get_index_result_tooltip.test.ts index 2f85a6e0ce692..4869aed07941b 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_result_badge/helpers.test.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/get_index_result_tooltip.test.ts @@ -5,22 +5,8 @@ * 2.0. */ -import { FAILED, PASSED, THIS_INDEX_HAS_NOT_BEEN_CHECKED } from '../summary_table/translations'; -import { getIndexResultBadgeColor, getIndexResultToolTip } from './helpers'; - -describe('getIndexResultBadgeColor', () => { - test('it returns `ghost` when `incompatible` is undefined', () => { - expect(getIndexResultBadgeColor(undefined)).toEqual('ghost'); - }); - - test('it returns `success` when `incompatible` is zero', () => { - expect(getIndexResultBadgeColor(0)).toEqual('#6dcbb1'); - }); - - test('it returns `danger` when `incompatible` is NOT zero', () => { - expect(getIndexResultBadgeColor(1)).toEqual('danger'); - }); -}); +import { FAILED, PASSED, THIS_INDEX_HAS_NOT_BEEN_CHECKED } from '../translations'; +import { getIndexResultToolTip } from './get_index_result_tooltip'; describe('getIndexResultToolTip', () => { test('it returns "this index has not been checked" when `incompatible` is undefined', () => { diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_result_badge/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/get_index_result_tooltip.ts similarity index 67% rename from x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_result_badge/helpers.ts rename to x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/get_index_result_tooltip.ts index f9f1c69733059..7b2bb9fb0507e 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_result_badge/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/get_index_result_tooltip.ts @@ -5,17 +5,7 @@ * 2.0. */ -import { FAILED, PASSED, THIS_INDEX_HAS_NOT_BEEN_CHECKED } from '../summary_table/translations'; - -export const getIndexResultBadgeColor = (incompatible: number | undefined): string => { - if (incompatible == null) { - return 'ghost'; - } else if (incompatible === 0) { - return '#6dcbb1'; - } else { - return 'danger'; - } -}; +import { FAILED, PASSED, THIS_INDEX_HAS_NOT_BEEN_CHECKED } from '../translations'; export const getIndexResultToolTip = (incompatible: number | undefined): string => { if (incompatible == null) { diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/get_page_index.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/get_page_index.test.ts new file mode 100644 index 0000000000000..b2746c830b6de --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/get_page_index.test.ts @@ -0,0 +1,360 @@ +/* + * 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 { mockDataQualityCheckResult } from '../../../../mock/data_quality_check_result/mock_index'; +import { IndexSummaryTableItem } from '../../../../types'; +import { getIndexIncompatible } from '../../../../utils/stats'; +import { getPageIndex } from './get_page_index'; + +describe('helpers', () => { + const indexName = '.ds-packetbeat-8.6.1-2023.02.04-000001'; + describe('getIndexIncompatible', () => { + test('it returns undefined when `results` is undefined', () => { + expect( + getIndexIncompatible({ + indexName, + results: undefined, // <-- + }) + ).toBeUndefined(); + }); + + test('it returns undefined when `indexName` is not in the `results`', () => { + expect( + getIndexIncompatible({ + indexName: 'not_in_the_results', // <-- + results: mockDataQualityCheckResult, + }) + ).toBeUndefined(); + }); + + test('it returns the expected count', () => { + expect( + getIndexIncompatible({ + indexName: 'auditbeat-custom-index-1', + results: mockDataQualityCheckResult, + }) + ).toEqual(3); + }); + }); + + describe('getPageIndex', () => { + const getPageIndexArgs: { + indexName: string; + items: IndexSummaryTableItem[]; + pageSize: number; + } = { + indexName: 'auditbeat-7.17.9-2023.04.09-000001', // <-- on page 2 of 3 (page index 1) + items: [ + { + docsCount: 48077, + incompatible: undefined, + indexName: 'auditbeat-7.14.2-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 43357342, + checkedAt: 1706526408000, + }, + { + docsCount: 48068, + incompatible: undefined, + indexName: 'auditbeat-7.3.2-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 32460397, + checkedAt: 1706526408000, + }, + { + docsCount: 48064, + incompatible: undefined, + indexName: 'auditbeat-7.11.2-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 42782794, + checkedAt: 1706526408000, + }, + { + docsCount: 47868, + incompatible: undefined, + indexName: 'auditbeat-7.6.2-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 31575964, + checkedAt: 1706526408000, + }, + { + docsCount: 47827, + incompatible: 20, + indexName: 'auditbeat-7.15.2-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 44130657, + checkedAt: 1706526408000, + }, + { + docsCount: 47642, + incompatible: undefined, + indexName: '.ds-auditbeat-8.4.3-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 42412521, + checkedAt: 1706526408000, + }, + { + docsCount: 47545, + incompatible: undefined, + indexName: 'auditbeat-7.16.3-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 41423244, + checkedAt: 1706526408000, + }, + { + docsCount: 47531, + incompatible: undefined, + indexName: 'auditbeat-7.5.2-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 32394133, + checkedAt: 1706526408000, + }, + { + docsCount: 47530, + incompatible: undefined, + indexName: 'auditbeat-7.12.1-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 43015519, + checkedAt: 1706526408000, + }, + { + docsCount: 47520, + incompatible: undefined, + indexName: '.ds-auditbeat-8.0.1-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 42230604, + checkedAt: 1706526408000, + }, + { + docsCount: 47496, + incompatible: undefined, + indexName: '.ds-auditbeat-8.2.3-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 41710968, + checkedAt: 1706526408000, + }, + { + docsCount: 47486, + incompatible: undefined, + indexName: '.ds-auditbeat-8.5.3-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 42295944, + checkedAt: 1706526408000, + }, + { + docsCount: 47486, + incompatible: undefined, + indexName: '.ds-auditbeat-8.3.3-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 41761321, + checkedAt: 1706526408000, + }, + { + docsCount: 47460, + incompatible: undefined, + indexName: 'auditbeat-7.2.1-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 30481198, + checkedAt: 1706526408000, + }, + { + docsCount: 47439, + incompatible: undefined, + indexName: 'auditbeat-7.17.9-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 41554041, + checkedAt: 1706526408000, + }, + { + docsCount: 47395, + incompatible: undefined, + indexName: 'auditbeat-7.9.3-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 42815907, + checkedAt: 1706526408000, + }, + { + docsCount: 47394, + incompatible: undefined, + indexName: '.ds-auditbeat-8.7.0-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 41157112, + checkedAt: 1706526408000, + }, + { + docsCount: 47372, + incompatible: undefined, + indexName: 'auditbeat-7.4.2-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 31626792, + checkedAt: 1706526408000, + }, + { + docsCount: 47369, + incompatible: undefined, + indexName: 'auditbeat-7.13.4-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 41828969, + checkedAt: 1706526408000, + }, + { + docsCount: 47348, + incompatible: undefined, + indexName: 'auditbeat-7.7.1-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 40010773, + checkedAt: 1706526408000, + }, + { + docsCount: 47339, + incompatible: undefined, + indexName: 'auditbeat-7.10.2-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 43480570, + checkedAt: 1706526408000, + }, + { + docsCount: 47325, + incompatible: undefined, + indexName: '.ds-auditbeat-8.1.3-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 41822475, + checkedAt: 1706526408000, + }, + { + docsCount: 47294, + incompatible: undefined, + indexName: 'auditbeat-7.8.0-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 43018490, + checkedAt: 1706526408000, + }, + { + docsCount: 24276, + incompatible: undefined, + indexName: '.ds-auditbeat-8.6.1-2023.04.09-000001', + ilmPhase: 'hot', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 23579440, + checkedAt: 1706526408000, + }, + { + docsCount: 4, + incompatible: undefined, + indexName: 'auditbeat-custom-index-1', + ilmPhase: 'unmanaged', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 28409, + checkedAt: 1706526408000, + }, + { + docsCount: 0, + incompatible: undefined, + indexName: 'auditbeat-custom-empty-index-1', + ilmPhase: 'unmanaged', + pattern: 'auditbeat-*', + patternDocsCount: 1118155, + sizeInBytes: 247, + checkedAt: 1706526408000, + }, + ], + pageSize: 10, + }; + + test('it returns the expected page index', () => { + expect(getPageIndex(getPageIndexArgs)).toEqual(1); + }); + + test('it returns the expected page index for the first item', () => { + const firstItemIndexName = 'auditbeat-7.14.2-2023.04.09-000001'; + + expect( + getPageIndex({ + ...getPageIndexArgs, + indexName: firstItemIndexName, + }) + ).toEqual(0); + }); + + test('it returns the expected page index for the last item', () => { + const lastItemIndexName = 'auditbeat-custom-empty-index-1'; + + expect( + getPageIndex({ + ...getPageIndexArgs, + indexName: lastItemIndexName, + }) + ).toEqual(2); + }); + + test('it returns null when the index cannot be found', () => { + expect( + getPageIndex({ + ...getPageIndexArgs, + indexName: 'does_not_exist', // <-- this index is not in the items + }) + ).toBeNull(); + }); + + test('it returns null when `pageSize` is zero', () => { + expect( + getPageIndex({ + ...getPageIndexArgs, + pageSize: 0, // <-- invalid + }) + ).toBeNull(); + }); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/get_page_index.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/get_page_index.ts new file mode 100644 index 0000000000000..3aff52ca9d3f8 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/get_page_index.ts @@ -0,0 +1,26 @@ +/* + * 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 { IndexSummaryTableItem } from '../../../../types'; + +export const getPageIndex = ({ + indexName, + items, + pageSize, +}: { + indexName: string; + items: IndexSummaryTableItem[]; + pageSize: number; +}): number | null => { + const index = items.findIndex((x) => x.indexName === indexName); + + if (index !== -1 && pageSize !== 0) { + return Math.floor(index / pageSize); + } else { + return null; + } +}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/ilm_explain.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/ilm_explain.test.ts new file mode 100644 index 0000000000000..ad588af866c88 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/ilm_explain.test.ts @@ -0,0 +1,173 @@ +/* + * 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 { + IlmExplainLifecycleLifecycleExplain, + IlmExplainLifecycleLifecycleExplainManaged, + IlmExplainLifecycleLifecycleExplainUnmanaged, +} from '@elastic/elasticsearch/lib/api/types'; +import { mockIlmExplain } from '../../../../mock/ilm_explain/mock_ilm_explain'; +import { getIlmExplainPhaseCounts, getPhaseCount, isManaged } from './ilm_explain'; + +const indexName = '.ds-packetbeat-8.6.1-2023.02.04-000001'; + +const hot: IlmExplainLifecycleLifecycleExplainManaged = { + index: '.ds-packetbeat-8.6.1-2023.02.04-000001', + managed: true, + policy: 'packetbeat', + index_creation_date_millis: 1675536751379, + time_since_index_creation: '3.98d', + lifecycle_date_millis: 1675536751379, + age: '3.98d', + phase: 'hot', + phase_time_millis: 1675536751809, + action: 'rollover', + action_time_millis: 1675536751809, + step: 'check-rollover-ready', + step_time_millis: 1675536751809, + phase_execution: { + policy: 'packetbeat', + version: 1, + modified_date_in_millis: 1675536751205, + }, +}; +const warm = { + ...hot, + phase: 'warm', +}; +const cold = { + ...hot, + phase: 'cold', +}; +const frozen = { + ...hot, + phase: 'frozen', +}; + +const managed: Record = { + hot, + warm, + cold, + frozen, +}; + +const unmanaged: IlmExplainLifecycleLifecycleExplainUnmanaged = { + index: 'michael', + managed: false, +}; + +describe('isManaged', () => { + test('it returns true when the `ilmExplainRecord` `managed` property is true', () => { + const ilmExplain = mockIlmExplain[indexName]; + + expect(isManaged(ilmExplain)).toBe(true); + }); + + test('it returns false when the `ilmExplainRecord` is undefined', () => { + expect(isManaged(undefined)).toBe(false); + }); +}); + +describe('getPhaseCount', () => { + test('it returns the expected count when an index with the specified `ilmPhase` exists in the `IlmExplainLifecycleLifecycleExplain` record', () => { + expect( + getPhaseCount({ + ilmExplain: mockIlmExplain, + ilmPhase: 'hot', // this phase is in the record + indexName, // valid index name + }) + ).toEqual(1); + }); + + test('it returns zero when `ilmPhase` is null', () => { + expect( + getPhaseCount({ + ilmExplain: null, + ilmPhase: 'hot', + indexName, + }) + ).toEqual(0); + }); + + test('it returns zero when the `indexName` does NOT exist in the `IlmExplainLifecycleLifecycleExplain` record', () => { + expect( + getPhaseCount({ + ilmExplain: mockIlmExplain, + ilmPhase: 'hot', + indexName: 'invalid', // this index does NOT exist + }) + ).toEqual(0); + }); + + test('it returns zero when the specified `ilmPhase` does NOT exist in the `IlmExplainLifecycleLifecycleExplain` record', () => { + expect( + getPhaseCount({ + ilmExplain: mockIlmExplain, + ilmPhase: 'warm', // this phase is NOT in the record + indexName, // valid index name + }) + ).toEqual(0); + }); + + describe('when `ilmPhase` is `unmanaged`', () => { + test('it returns the expected count for an `unmanaged` index', () => { + const index = 'auditbeat-custom-index-1'; + const ilmExplainRecord: IlmExplainLifecycleLifecycleExplain = { + index, + managed: false, + }; + const ilmExplain = { + [index]: ilmExplainRecord, + }; + + expect( + getPhaseCount({ + ilmExplain, + ilmPhase: 'unmanaged', // ilmPhase is unmanaged + indexName: index, // an unmanaged index + }) + ).toEqual(1); + }); + + test('it returns zero for a managed index', () => { + expect( + getPhaseCount({ + ilmExplain: mockIlmExplain, + ilmPhase: 'unmanaged', // ilmPhase is unmanaged + indexName, // a managed (`hot`) index + }) + ).toEqual(0); + }); + }); +}); + +describe('getIlmExplainPhaseCounts', () => { + test('it returns the expected counts (all zeros) when `ilmExplain` is null', () => { + expect(getIlmExplainPhaseCounts(null)).toEqual({ + cold: 0, + frozen: 0, + hot: 0, + unmanaged: 0, + warm: 0, + }); + }); + + test('it returns the expected counts', () => { + const ilmExplain: Record = { + ...managed, + [unmanaged.index]: unmanaged, + }; + + expect(getIlmExplainPhaseCounts(ilmExplain)).toEqual({ + cold: 1, + frozen: 1, + hot: 1, + unmanaged: 1, + warm: 1, + }); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/ilm_explain.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/ilm_explain.ts new file mode 100644 index 0000000000000..c47353162b003 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/ilm_explain.ts @@ -0,0 +1,87 @@ +/* + * 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 { IlmExplainLifecycleLifecycleExplain } from '@elastic/elasticsearch/lib/api/types'; + +import { IlmExplainPhaseCounts, IlmPhase } from '../../../../types'; + +export const isManaged = ( + ilmExplainRecord: IlmExplainLifecycleLifecycleExplain | undefined +): boolean => ilmExplainRecord?.managed === true; + +export const getPhaseCount = ({ + ilmExplain, + ilmPhase, + indexName, +}: { + ilmExplain: Record | null; + ilmPhase: IlmPhase; + indexName: string; +}): number => { + const ilmExplainRecord = ilmExplain != null ? ilmExplain[indexName] : undefined; + + if (ilmPhase === 'unmanaged') { + return isManaged(ilmExplainRecord) ? 0 : 1; + } else if (ilmExplainRecord != null && 'phase' in ilmExplainRecord) { + return ilmExplainRecord.phase === ilmPhase ? 1 : 0; + } + + return 0; +}; + +export const getIlmExplainPhaseCounts = ( + ilmExplain: Record | null +): IlmExplainPhaseCounts => { + const indexNames = ilmExplain != null ? Object.keys(ilmExplain) : []; + + return indexNames.reduce( + (acc, indexName) => ({ + hot: + acc.hot + + getPhaseCount({ + ilmExplain, + ilmPhase: 'hot', + indexName, + }), + warm: + acc.warm + + getPhaseCount({ + ilmExplain, + ilmPhase: 'warm', + indexName, + }), + cold: + acc.cold + + getPhaseCount({ + ilmExplain, + ilmPhase: 'cold', + indexName, + }), + frozen: + acc.frozen + + getPhaseCount({ + ilmExplain, + ilmPhase: 'frozen', + indexName, + }), + unmanaged: + acc.unmanaged + + getPhaseCount({ + ilmExplain, + ilmPhase: 'unmanaged', + indexName, + }), + }), + { + hot: 0, + warm: 0, + cold: 0, + frozen: 0, + unmanaged: 0, + } + ); +}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/should_create_index_names.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/should_create_index_names.test.ts new file mode 100644 index 0000000000000..7d663b82fc1ff --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/should_create_index_names.test.ts @@ -0,0 +1,103 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { mockIlmExplain } from '../../../../mock/ilm_explain/mock_ilm_explain'; +import { shouldCreateIndexNames } from './should_create_index_names'; +import { mockStats } from '../../../../mock/stats/mock_stats'; + +describe('shouldCreateIndexNames', () => { + const indexNames = [ + '.ds-packetbeat-8.6.1-2023.02.04-000001', + '.ds-packetbeat-8.5.3-2023.02.04-000001', + 'auditbeat-custom-index-1', + ]; + const isILMAvailable = true; + + test('returns true when `indexNames` does NOT exist, and the required `stats` and `ilmExplain` are available', () => { + expect( + shouldCreateIndexNames({ + ilmExplain: mockIlmExplain, + indexNames: undefined, + isILMAvailable, + newIndexNames: [], + stats: mockStats, + }) + ).toBe(true); + }); + + test('returns true when `isILMAvailable` is false, and the required `stats` is available, and `ilmExplain` is not available', () => { + expect( + shouldCreateIndexNames({ + ilmExplain: null, + indexNames: undefined, + isILMAvailable: false, + newIndexNames: [], + stats: mockStats, + }) + ).toBe(true); + }); + + test('returns false when `indexNames` exists, and the required `stats` and `ilmExplain` are available', () => { + expect( + shouldCreateIndexNames({ + ilmExplain: mockIlmExplain, + indexNames, + isILMAvailable, + newIndexNames: indexNames, + stats: mockStats, + }) + ).toBe(false); + }); + + test('returns false when `indexNames` does NOT exist, `stats` is NOT available, and `ilmExplain` is available', () => { + expect( + shouldCreateIndexNames({ + ilmExplain: mockIlmExplain, + indexNames: undefined, + isILMAvailable, + newIndexNames: [], + stats: null, + }) + ).toBe(false); + }); + + test('returns false when `indexNames` does NOT exist, `stats` is available, and `ilmExplain` is NOT available', () => { + expect( + shouldCreateIndexNames({ + ilmExplain: null, + indexNames: undefined, + isILMAvailable, + newIndexNames: [], + stats: mockStats, + }) + ).toBe(false); + }); + + test('returns false when `indexNames` does NOT exist, `stats` is NOT available, and `ilmExplain` is NOT available', () => { + expect( + shouldCreateIndexNames({ + ilmExplain: null, + indexNames: undefined, + isILMAvailable, + newIndexNames: [], + stats: null, + }) + ).toBe(false); + }); + + test('returns false when `indexNames` exists, `stats` is NOT available, and `ilmExplain` is NOT available', () => { + expect( + shouldCreateIndexNames({ + ilmExplain: null, + indexNames, + isILMAvailable, + newIndexNames: [], + stats: null, + }) + ).toBe(false); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/should_create_index_names.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/should_create_index_names.ts new file mode 100644 index 0000000000000..25a6038ae9078 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/should_create_index_names.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { IlmExplainLifecycleLifecycleExplain } from '@elastic/elasticsearch/lib/api/types'; + +import { isEqual } from 'lodash/fp'; +import { MeteringStatsIndex } from '../../../../types'; + +export const shouldCreateIndexNames = ({ + ilmExplain, + indexNames, + isILMAvailable, + newIndexNames, + stats, +}: { + ilmExplain: Record | null; + indexNames: string[] | undefined; + isILMAvailable: boolean; + newIndexNames: string[]; + stats: Record | null; +}): boolean => { + return ( + !isEqual(newIndexNames, indexNames) && + stats != null && + ((isILMAvailable && ilmExplain != null) || !isILMAvailable) + ); +}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/should_create_pattern_rollup.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/should_create_pattern_rollup.test.ts new file mode 100644 index 0000000000000..1adb851d8aafc --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/should_create_pattern_rollup.test.ts @@ -0,0 +1,139 @@ +/* + * 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 { mockStats } from '../../../../mock/stats/mock_stats'; +import { shouldCreatePatternRollup } from './should_create_pattern_rollup'; +import { mockIlmExplain } from '../../../../mock/ilm_explain/mock_ilm_explain'; +import { auditbeatWithAllResults } from '../../../../mock/pattern_rollup/mock_auditbeat_pattern_rollup'; +import { getIndexNames, getPatternDocsCount } from './stats'; + +describe('shouldCreatePatternRollup', () => { + const isILMAvailable = true; + const newIndexNames = getIndexNames({ + stats: mockStats, + ilmExplain: mockIlmExplain, + ilmPhases: ['hot', 'unmanaged'], + isILMAvailable, + }); + const newDocsCount = getPatternDocsCount({ indexNames: newIndexNames, stats: mockStats }); + test('it returns false when the `patternRollup.docsCount` equals newDocsCount', () => { + expect( + shouldCreatePatternRollup({ + error: null, + ilmExplain: mockIlmExplain, + isILMAvailable, + newDocsCount: auditbeatWithAllResults.docsCount as number, + patternRollup: auditbeatWithAllResults, + stats: mockStats, + }) + ).toBe(false); + }); + + test('it returns true when all data and ILMExplain were loaded', () => { + expect( + shouldCreatePatternRollup({ + error: null, + ilmExplain: mockIlmExplain, + isILMAvailable, + newDocsCount, + patternRollup: undefined, + stats: mockStats, + }) + ).toBe(true); + }); + + test('it returns true when all data was loaded and ILM is not available', () => { + expect( + shouldCreatePatternRollup({ + error: null, + ilmExplain: null, + isILMAvailable: false, + newDocsCount, + patternRollup: undefined, + stats: mockStats, + }) + ).toBe(true); + }); + + test('it returns false when `stats`, but NOT `ilmExplain` was loaded', () => { + expect( + shouldCreatePatternRollup({ + error: null, + ilmExplain: null, + isILMAvailable, + newDocsCount, + patternRollup: undefined, + stats: mockStats, + }) + ).toBe(false); + }); + + test('it returns false when `stats` was NOT loaded, and `ilmExplain` was loaded', () => { + expect( + shouldCreatePatternRollup({ + error: null, + ilmExplain: mockIlmExplain, + isILMAvailable, + newDocsCount, + patternRollup: undefined, + stats: null, + }) + ).toBe(false); + }); + + test('it returns true if an error occurred, and NO data was loaded', () => { + expect( + shouldCreatePatternRollup({ + error: 'whoops', + ilmExplain: null, + isILMAvailable, + newDocsCount, + patternRollup: undefined, + stats: null, + }) + ).toBe(true); + }); + + test('it returns true if an error occurred, and just `stats` was loaded', () => { + expect( + shouldCreatePatternRollup({ + error: 'something went', + ilmExplain: null, + isILMAvailable, + newDocsCount, + patternRollup: undefined, + stats: mockStats, + }) + ).toBe(true); + }); + + test('it returns true if an error occurred, and just `ilmExplain` was loaded', () => { + expect( + shouldCreatePatternRollup({ + error: 'horribly wrong', + ilmExplain: mockIlmExplain, + isILMAvailable, + newDocsCount, + patternRollup: undefined, + stats: null, + }) + ).toBe(true); + }); + + test('it returns true if an error occurred, and all data was loaded', () => { + expect( + shouldCreatePatternRollup({ + error: 'over here', + ilmExplain: mockIlmExplain, + isILMAvailable, + newDocsCount, + patternRollup: undefined, + stats: mockStats, + }) + ).toBe(true); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/should_create_pattern_rollup.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/should_create_pattern_rollup.ts new file mode 100644 index 0000000000000..87773ac01de17 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/should_create_pattern_rollup.ts @@ -0,0 +1,36 @@ +/* + * 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 { IlmExplainLifecycleLifecycleExplain } from '@elastic/elasticsearch/lib/api/types'; + +import { MeteringStatsIndex, PatternRollup } from '../../../../types'; + +export const shouldCreatePatternRollup = ({ + error, + ilmExplain, + isILMAvailable, + newDocsCount, + patternRollup, + stats, +}: { + error: string | null; + ilmExplain: Record | null; + isILMAvailable: boolean; + newDocsCount: number; + patternRollup: PatternRollup | undefined; + stats: Record | null; +}): boolean => { + if (patternRollup?.docsCount === newDocsCount) { + return false; + } + + const allDataLoaded: boolean = + stats != null && ((isILMAvailable && ilmExplain != null) || !isILMAvailable); + const errorOccurred: boolean = error != null; + + return allDataLoaded || errorOccurred; +}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/stats.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/stats.ts index 83e2b592dc079..63505211e82a1 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/stats.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/utils/stats.ts @@ -7,9 +7,9 @@ import { IlmExplainLifecycleLifecycleExplain } from '@elastic/elasticsearch/lib/api/types'; +import { getIlmPhase } from '../../../../utils/get_ilm_phase'; import { getDocsCount, getSizeInBytes } from '../../../../utils/stats'; import { MeteringStatsIndex } from '../../../../types'; -import { getIlmPhase } from '../helpers'; export const getPatternDocsCount = ({ indexNames, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/helpers.test.ts deleted file mode 100644 index da46cd2b40f33..0000000000000 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/helpers.test.ts +++ /dev/null @@ -1,516 +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 numeral from '@elastic/numeral'; -import { euiThemeVars } from '@kbn/ui-theme'; - -import { EMPTY_STAT } from '../../constants'; -import { - DEFAULT_INDEX_COLOR, - getFillColor, - getFlattenedBuckets, - getGroupFromPath, - getLayersMultiDimensional, - getLegendItems, - getLegendItemsForPattern, - getPathToFlattenedBucketMap, - getPatternLegendItem, - getPatternSizeInBytes, -} from './helpers'; -import { alertIndexWithAllResults } from '../../mock/pattern_rollup/mock_alerts_pattern_rollup'; -import { auditbeatWithAllResults } from '../../mock/pattern_rollup/mock_auditbeat_pattern_rollup'; -import { packetbeatNoResults } from '../../mock/pattern_rollup/mock_packetbeat_pattern_rollup'; -import { PatternRollup } from '../../types'; - -const defaultBytesFormat = '0,0.[0]b'; -const formatBytes = (value: number | undefined) => - value != null ? numeral(value).format(defaultBytesFormat) : EMPTY_STAT; - -const ilmPhases = ['hot', 'warm', 'unmanaged']; -const patterns = ['.alerts-security.alerts-default', 'auditbeat-*', 'packetbeat-*']; - -const patternRollups: Record = { - '.alerts-security.alerts-default': alertIndexWithAllResults, - 'auditbeat-*': auditbeatWithAllResults, - 'packetbeat-*': packetbeatNoResults, -}; - -/** a valid `PatternRollup` that has an undefined `sizeInBytes` */ -const noSizeInBytes: Record = { - 'valid-*': { - docsCount: 19127, - error: null, - ilmExplain: null, - ilmExplainPhaseCounts: { - hot: 1, - warm: 0, - cold: 0, - frozen: 0, - unmanaged: 2, - }, - indices: 3, - pattern: 'valid-*', - results: undefined, - sizeInBytes: undefined, // <-- - stats: null, - }, -}; - -describe('helpers', () => { - describe('getPatternSizeInBytes', () => { - test('it returns the expected size when the pattern exists in the rollup', () => { - const pattern = 'auditbeat-*'; - - expect(getPatternSizeInBytes({ pattern, patternRollups })).toEqual( - auditbeatWithAllResults.sizeInBytes - ); - }); - - test('it returns undefined when the pattern exists in the rollup, but does not have a sizeInBytes', () => { - const pattern = 'valid-*'; - - expect(getPatternSizeInBytes({ pattern, patternRollups: noSizeInBytes })).toBeUndefined(); - }); - - test('it returns undefined when the pattern does NOT exist in the rollup', () => { - const pattern = 'does-not-exist-*'; - - expect(getPatternSizeInBytes({ pattern, patternRollups })).toBeUndefined(); - }); - }); - - describe('getPatternLegendItem', () => { - test('it returns the expected legend item', () => { - const pattern = 'auditbeat-*'; - - expect(getPatternLegendItem({ pattern, patternRollups })).toEqual({ - color: null, - ilmPhase: null, - index: null, - pattern, - sizeInBytes: auditbeatWithAllResults.sizeInBytes, - docsCount: auditbeatWithAllResults.docsCount, - }); - }); - }); - - describe('getLegendItemsForPattern', () => { - test('it returns the expected legend items', () => { - const pattern = 'auditbeat-*'; - const flattenedBuckets = getFlattenedBuckets({ - ilmPhases, - isILMAvailable: true, - patternRollups, - }); - - expect(getLegendItemsForPattern({ pattern, flattenedBuckets })).toEqual([ - { - color: euiThemeVars.euiColorSuccess, - ilmPhase: 'hot', - index: '.ds-auditbeat-8.6.1-2023.02.07-000001', - pattern: 'auditbeat-*', - sizeInBytes: 18791790, - docsCount: 19123, - }, - { - color: euiThemeVars.euiColorDanger, - ilmPhase: 'unmanaged', - index: 'auditbeat-custom-index-1', - pattern: 'auditbeat-*', - sizeInBytes: 28409, - docsCount: 4, - }, - { - color: euiThemeVars.euiColorDanger, - ilmPhase: 'unmanaged', - index: 'auditbeat-custom-empty-index-1', - pattern: 'auditbeat-*', - sizeInBytes: 247, - docsCount: 0, - }, - ]); - }); - - test('it returns the expected legend items when isILMAvailable is false', () => { - const pattern = 'auditbeat-*'; - const flattenedBuckets = getFlattenedBuckets({ - ilmPhases, - isILMAvailable: false, - patternRollups, - }); - expect(getLegendItemsForPattern({ pattern, flattenedBuckets })).toEqual([ - { - color: euiThemeVars.euiColorSuccess, - ilmPhase: null, - index: '.ds-auditbeat-8.6.1-2023.02.07-000001', - pattern: 'auditbeat-*', - sizeInBytes: 18791790, - docsCount: 19123, - }, - { - color: euiThemeVars.euiColorDanger, - ilmPhase: null, - index: 'auditbeat-custom-index-1', - pattern: 'auditbeat-*', - sizeInBytes: 28409, - docsCount: 4, - }, - { - color: euiThemeVars.euiColorDanger, - ilmPhase: null, - index: 'auditbeat-custom-empty-index-1', - pattern: 'auditbeat-*', - sizeInBytes: 247, - docsCount: 0, - }, - ]); - }); - }); - - describe('getLegendItems', () => { - test('it returns the expected legend items', () => { - const flattenedBuckets = getFlattenedBuckets({ - ilmPhases, - isILMAvailable: true, - patternRollups, - }); - - expect(getLegendItems({ flattenedBuckets, patterns, patternRollups })).toEqual([ - { - color: null, - ilmPhase: null, - index: null, - pattern: '.alerts-security.alerts-default', - sizeInBytes: 29717961631, - docsCount: 26093, - }, - { - color: euiThemeVars.euiColorSuccess, - ilmPhase: 'hot', - index: '.internal.alerts-security.alerts-default-000001', - pattern: '.alerts-security.alerts-default', - sizeInBytes: 0, - docsCount: 26093, - }, - { - color: null, - ilmPhase: null, - index: null, - pattern: 'auditbeat-*', - sizeInBytes: 18820446, - docsCount: 19127, - }, - { - color: euiThemeVars.euiColorSuccess, - ilmPhase: 'hot', - index: '.ds-auditbeat-8.6.1-2023.02.07-000001', - pattern: 'auditbeat-*', - sizeInBytes: 18791790, - docsCount: 19123, - }, - { - color: euiThemeVars.euiColorDanger, - ilmPhase: 'unmanaged', - index: 'auditbeat-custom-index-1', - pattern: 'auditbeat-*', - sizeInBytes: 28409, - docsCount: 4, - }, - { - color: euiThemeVars.euiColorDanger, - ilmPhase: 'unmanaged', - index: 'auditbeat-custom-empty-index-1', - pattern: 'auditbeat-*', - sizeInBytes: 247, - docsCount: 0, - }, - { - color: null, - ilmPhase: null, - index: null, - pattern: 'packetbeat-*', - sizeInBytes: 1096520898, - docsCount: 3258632, - }, - { - color: euiThemeVars.euiColorPrimary, - ilmPhase: 'hot', - index: '.ds-packetbeat-8.5.3-2023.02.04-000001', - pattern: 'packetbeat-*', - sizeInBytes: 584326147, - docsCount: 1630289, - }, - { - color: euiThemeVars.euiColorPrimary, - ilmPhase: 'hot', - index: '.ds-packetbeat-8.6.1-2023.02.04-000001', - pattern: 'packetbeat-*', - sizeInBytes: 512194751, - docsCount: 1628343, - }, - ]); - }); - }); - - describe('getFlattenedBuckets', () => { - test('it returns the expected flattened buckets', () => { - expect( - getFlattenedBuckets({ - ilmPhases, - isILMAvailable: true, - patternRollups, - }) - ).toEqual([ - { - ilmPhase: 'hot', - incompatible: 0, - indexName: '.internal.alerts-security.alerts-default-000001', - pattern: '.alerts-security.alerts-default', - sizeInBytes: 0, - docsCount: 26093, - }, - { - ilmPhase: 'hot', - incompatible: 0, - indexName: '.ds-auditbeat-8.6.1-2023.02.07-000001', - pattern: 'auditbeat-*', - sizeInBytes: 18791790, - docsCount: 19123, - }, - { - ilmPhase: 'unmanaged', - incompatible: 1, - indexName: 'auditbeat-custom-empty-index-1', - pattern: 'auditbeat-*', - sizeInBytes: 247, - docsCount: 0, - }, - { - ilmPhase: 'unmanaged', - incompatible: 3, - indexName: 'auditbeat-custom-index-1', - pattern: 'auditbeat-*', - sizeInBytes: 28409, - docsCount: 4, - }, - { - ilmPhase: 'hot', - indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', - pattern: 'packetbeat-*', - sizeInBytes: 512194751, - docsCount: 1628343, - }, - { - ilmPhase: 'hot', - indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', - pattern: 'packetbeat-*', - sizeInBytes: 584326147, - docsCount: 1630289, - }, - ]); - }); - - test('it returns the expected flattened buckets when isILMAvailable is false', () => { - expect( - getFlattenedBuckets({ - ilmPhases, - isILMAvailable: false, - patternRollups, - }) - ).toEqual([ - { - docsCount: 26093, - ilmPhase: undefined, - incompatible: 0, - indexName: '.internal.alerts-security.alerts-default-000001', - pattern: '.alerts-security.alerts-default', - sizeInBytes: 0, - }, - { - docsCount: 19123, - ilmPhase: undefined, - incompatible: 0, - indexName: '.ds-auditbeat-8.6.1-2023.02.07-000001', - pattern: 'auditbeat-*', - sizeInBytes: 18791790, - }, - { - docsCount: 0, - ilmPhase: undefined, - incompatible: 1, - indexName: 'auditbeat-custom-empty-index-1', - pattern: 'auditbeat-*', - sizeInBytes: 247, - }, - { - docsCount: 4, - ilmPhase: undefined, - incompatible: 3, - indexName: 'auditbeat-custom-index-1', - pattern: 'auditbeat-*', - sizeInBytes: 28409, - }, - { - docsCount: 1628343, - ilmPhase: undefined, - indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', - pattern: 'packetbeat-*', - sizeInBytes: 512194751, - }, - { - docsCount: 1630289, - ilmPhase: undefined, - indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', - pattern: 'packetbeat-*', - sizeInBytes: 584326147, - }, - ]); - }); - }); - - describe('getFillColor', () => { - test('it returns success when `incompatible` is zero', () => { - const incompatible = 0; - - expect(getFillColor(incompatible)).toEqual(euiThemeVars.euiColorSuccess); - }); - - test('it returns danger when `incompatible` is greater than 0', () => { - const incompatible = 1; - - expect(getFillColor(incompatible)).toEqual(euiThemeVars.euiColorDanger); - }); - - test('it returns the default color when `incompatible` is undefined', () => { - const incompatible = undefined; - - expect(getFillColor(incompatible)).toEqual(DEFAULT_INDEX_COLOR); - }); - }); - - describe('getPathToFlattenedBucketMap', () => { - test('it returns the expected map', () => { - const flattenedBuckets = getFlattenedBuckets({ - ilmPhases, - isILMAvailable: true, - patternRollups, - }); - - expect(getPathToFlattenedBucketMap(flattenedBuckets)).toEqual({ - '.alerts-security.alerts-default.internal.alerts-security.alerts-default-000001': { - pattern: '.alerts-security.alerts-default', - indexName: '.internal.alerts-security.alerts-default-000001', - ilmPhase: 'hot', - incompatible: 0, - sizeInBytes: 0, - docsCount: 26093, - }, - 'auditbeat-*.ds-auditbeat-8.6.1-2023.02.07-000001': { - pattern: 'auditbeat-*', - indexName: '.ds-auditbeat-8.6.1-2023.02.07-000001', - ilmPhase: 'hot', - incompatible: 0, - sizeInBytes: 18791790, - docsCount: 19123, - }, - 'auditbeat-*auditbeat-custom-empty-index-1': { - pattern: 'auditbeat-*', - indexName: 'auditbeat-custom-empty-index-1', - ilmPhase: 'unmanaged', - incompatible: 1, - sizeInBytes: 247, - docsCount: 0, - }, - 'auditbeat-*auditbeat-custom-index-1': { - pattern: 'auditbeat-*', - indexName: 'auditbeat-custom-index-1', - ilmPhase: 'unmanaged', - incompatible: 3, - sizeInBytes: 28409, - docsCount: 4, - }, - 'packetbeat-*.ds-packetbeat-8.6.1-2023.02.04-000001': { - pattern: 'packetbeat-*', - indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', - ilmPhase: 'hot', - sizeInBytes: 512194751, - docsCount: 1628343, - }, - 'packetbeat-*.ds-packetbeat-8.5.3-2023.02.04-000001': { - docsCount: 1630289, - pattern: 'packetbeat-*', - indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', - ilmPhase: 'hot', - sizeInBytes: 584326147, - }, - }); - }); - }); - - describe('getGroupFromPath', () => { - it('returns the expected group from the path', () => { - expect( - getGroupFromPath([ - { - index: 0, - value: '__null_small_multiples_key__', - }, - { - index: 0, - value: '__root_key__', - }, - { - index: 0, - value: 'auditbeat-*', - }, - { - index: 1, - value: 'auditbeat-custom-empty-index-1', - }, - ]) - ).toEqual('auditbeat-*'); - }); - - it('returns undefined when path is an empty array', () => { - expect(getGroupFromPath([])).toBeUndefined(); - }); - - it('returns undefined when path is an array with only one value', () => { - expect( - getGroupFromPath([{ index: 0, value: '__null_small_multiples_key__' }]) - ).toBeUndefined(); - }); - }); - - describe('getLayersMultiDimensional', () => { - const layer0FillColor = 'transparent'; - const flattenedBuckets = getFlattenedBuckets({ - ilmPhases, - isILMAvailable: true, - patternRollups, - }); - const pathToFlattenedBucketMap = getPathToFlattenedBucketMap(flattenedBuckets); - - it('returns the expected number of layers', () => { - expect( - getLayersMultiDimensional({ - valueFormatter: formatBytes, - layer0FillColor, - pathToFlattenedBucketMap, - }).length - ).toEqual(2); - }); - - it('returns the expected fillLabel valueFormatter function', () => { - getLayersMultiDimensional({ - valueFormatter: formatBytes, - layer0FillColor, - pathToFlattenedBucketMap, - }).forEach((x) => expect(x.fillLabel.valueFormatter(123)).toEqual('123B')); - }); - }); -}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/helpers.ts deleted file mode 100644 index 283854a62acf2..0000000000000 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/helpers.ts +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { Datum, Key, ArrayNode } from '@elastic/charts'; -import { euiThemeVars } from '@kbn/ui-theme'; -import { orderBy } from 'lodash/fp'; - -import { getIlmPhase } from '../indices_details/pattern/helpers'; -import { PatternRollup } from '../../types'; -import { getDocsCount, getSizeInBytes } from '../../utils/stats'; - -export interface LegendItem { - color: string | null; - ilmPhase: string | null; - index: string | null; - pattern: string; - sizeInBytes: number | undefined; - docsCount: number; -} - -export interface FlattenedBucket { - ilmPhase: string | undefined; - incompatible: number | undefined; - indexName: string | undefined; - pattern: string; - sizeInBytes: number | undefined; - docsCount: number; -} - -export const getPatternSizeInBytes = ({ - pattern, - patternRollups, -}: { - pattern: string; - patternRollups: Record; -}): number | undefined => { - if (patternRollups[pattern] != null) { - return patternRollups[pattern].sizeInBytes; - } else { - return undefined; - } -}; - -export const getPatternDocsCount = ({ - pattern, - patternRollups, -}: { - pattern: string; - patternRollups: Record; -}): number => { - if (patternRollups[pattern] != null) { - return patternRollups[pattern].docsCount ?? 0; - } else { - return 0; - } -}; - -export const getPatternLegendItem = ({ - pattern, - patternRollups, -}: { - pattern: string; - patternRollups: Record; -}): LegendItem => ({ - color: null, - ilmPhase: null, - index: null, - pattern, - sizeInBytes: getPatternSizeInBytes({ pattern, patternRollups }), - docsCount: getPatternDocsCount({ pattern, patternRollups }), -}); - -export const getLegendItemsForPattern = ({ - pattern, - flattenedBuckets, -}: { - pattern: string; - flattenedBuckets: FlattenedBucket[]; -}): LegendItem[] => - orderBy( - ['sizeInBytes'], - ['desc'], - flattenedBuckets - .filter((x) => x.pattern === pattern) - .map((flattenedBucket) => ({ - color: getFillColor(flattenedBucket.incompatible), - ilmPhase: flattenedBucket.ilmPhase ?? null, - index: flattenedBucket.indexName ?? null, - pattern: flattenedBucket.pattern, - sizeInBytes: flattenedBucket.sizeInBytes, - docsCount: flattenedBucket.docsCount, - })) - ); - -export const getLegendItems = ({ - patterns, - flattenedBuckets, - patternRollups, -}: { - patterns: string[]; - flattenedBuckets: FlattenedBucket[]; - patternRollups: Record; -}): LegendItem[] => - patterns.reduce( - (acc, pattern) => [ - ...acc, - getPatternLegendItem({ pattern, patternRollups }), - ...getLegendItemsForPattern({ pattern, flattenedBuckets }), - ], - [] - ); - -export const getFlattenedBuckets = ({ - ilmPhases, - isILMAvailable, - patternRollups, -}: { - ilmPhases: string[]; - isILMAvailable: boolean; - patternRollups: Record; -}): FlattenedBucket[] => - Object.values(patternRollups).reduce((acc, patternRollup) => { - // enables fast lookup of valid phase names: - const ilmPhasesMap = ilmPhases.reduce>( - (phasesMap, phase) => ({ ...phasesMap, [phase]: 0 }), - {} - ); - const { ilmExplain, pattern, results, stats } = patternRollup; - - if (((isILMAvailable && ilmExplain != null) || !isILMAvailable) && stats != null) { - return [ - ...acc, - ...Object.entries(stats).reduce((validStats, [indexName]) => { - const ilmPhase = getIlmPhase(ilmExplain?.[indexName], isILMAvailable); - const isSelectedPhase = - (isILMAvailable && ilmPhase != null && ilmPhasesMap[ilmPhase] != null) || - !isILMAvailable; - - if (isSelectedPhase) { - const incompatible = - results != null && results[indexName] != null - ? results[indexName].incompatible - : undefined; - const sizeInBytes = getSizeInBytes({ indexName, stats }); - const docsCount = getDocsCount({ stats, indexName }); - return [ - ...validStats, - { - ilmPhase, - incompatible, - indexName, - pattern, - sizeInBytes, - docsCount, - }, - ]; - } else { - return validStats; - } - }, []), - ]; - } - - return acc; - }, []); - -const groupByRollup = (d: Datum) => d.pattern; // the treemap is grouped by this field - -export const DEFAULT_INDEX_COLOR = euiThemeVars.euiColorPrimary; - -export const getFillColor = (incompatible: number | undefined): string => { - if (incompatible === 0) { - return euiThemeVars.euiColorSuccess; - } else if (incompatible != null && incompatible > 0) { - return euiThemeVars.euiColorDanger; - } else { - return DEFAULT_INDEX_COLOR; - } -}; - -export const getPathToFlattenedBucketMap = ( - flattenedBuckets: FlattenedBucket[] -): Record => - flattenedBuckets.reduce>( - (acc, { pattern, indexName, ...remaining }) => ({ - ...acc, - [`${pattern}${indexName}`]: { pattern, indexName, ...remaining }, - }), - {} - ); - -/** - * Extracts the first group name from the data representing the second group - */ -export const getGroupFromPath = (path: ArrayNode['path']): string | undefined => { - const OFFSET_FROM_END = 2; // The offset from the end of the path array containing the group - const groupIndex = path.length - OFFSET_FROM_END; - return groupIndex > 0 ? path[groupIndex].value : undefined; -}; - -export const getLayersMultiDimensional = ({ - valueFormatter, - layer0FillColor, - pathToFlattenedBucketMap, -}: { - valueFormatter: (value: number) => string; - layer0FillColor: string; - pathToFlattenedBucketMap: Record; -}) => { - return [ - { - fillLabel: { - valueFormatter, - }, - groupByRollup, - nodeLabel: (ilmPhase: Datum) => ilmPhase, - shape: { - fillColor: layer0FillColor, - }, - }, - { - fillLabel: { - valueFormatter, - }, - groupByRollup: (d: Datum) => d.indexName, - nodeLabel: (indexName: Datum) => indexName, - shape: { - fillColor: (indexName: Key, _sortIndex: number, node: Pick) => { - const pattern = getGroupFromPath(node.path) ?? ''; - const flattenedBucket = pathToFlattenedBucketMap[`${pattern}${indexName}`]; - - return getFillColor(flattenedBucket?.incompatible); - }, - }, - }, - ]; -}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/index.tsx index cfde7c0342585..23a4fc46f6ad4 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/index.tsx @@ -8,12 +8,12 @@ import React, { useCallback, useMemo } from 'react'; import { useResultsRollupContext } from '../../contexts/results_rollup_context'; -import { getFlattenedBuckets } from './helpers'; import { StorageTreemap } from './storage_treemap'; import { DEFAULT_MAX_CHART_HEIGHT } from '../indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/styles'; import { SelectedIndex } from '../../types'; import { useDataQualityContext } from '../../data_quality_context'; import { DOCS_UNIT } from './translations'; +import { getFlattenedBuckets } from './utils/get_flattened_buckets'; export interface Props { onIndexSelected: ({ indexName, pattern }: SelectedIndex) => void; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/constants.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/constants.ts new file mode 100644 index 0000000000000..c67b052fbf2b5 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/constants.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { euiThemeVars } from '@kbn/ui-theme'; + +export const DEFAULT_INDEX_COLOR = euiThemeVars.euiColorPrimary; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/index.test.tsx index a8998a134416f..7e1834e05ed4c 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/index.test.tsx @@ -11,7 +11,6 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; -import { FlattenedBucket, getFlattenedBuckets, getLegendItems } from '../helpers'; import { EMPTY_STAT } from '../../../constants'; import { alertIndexWithAllResults } from '../../../mock/pattern_rollup/mock_alerts_pattern_rollup'; import { auditbeatWithAllResults } from '../../../mock/pattern_rollup/mock_auditbeat_pattern_rollup'; @@ -25,6 +24,9 @@ import { StorageTreemap } from '.'; import { DEFAULT_MAX_CHART_HEIGHT } from '../../indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/styles'; import { NO_DATA_LABEL } from './translations'; import { PatternRollup } from '../../../types'; +import { FlattenedBucket } from '../types'; +import { getFlattenedBuckets } from '../utils/get_flattened_buckets'; +import { getLegendItems } from './utils/get_legend_items'; const defaultBytesFormat = '0,0.[0]b'; const formatBytes = (value: number | undefined) => diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/index.tsx index fbabe4412e493..5a0a7be5bab3d 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/index.tsx @@ -22,12 +22,6 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; -import { - FlattenedBucket, - getLayersMultiDimensional, - getLegendItems, - getPathToFlattenedBucketMap, -} from '../helpers'; import { ChartLegendItem } from './chart_legend_item'; import { NoData } from './no_data'; import { @@ -36,6 +30,10 @@ import { } from '../../indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/styles'; import { PatternRollup, SelectedIndex } from '../../../types'; import { useDataQualityContext } from '../../../data_quality_context'; +import { FlattenedBucket } from '../types'; +import { getPathToFlattenedBucketMap } from './utils/get_path_to_flattened_bucket_map'; +import { getLayersMultiDimensional } from './utils/get_layers_multi_dimensional'; +import { getLegendItems } from './utils/get_legend_items'; export const DEFAULT_MIN_CHART_HEIGHT = 240; // px export const LEGEND_WIDTH = 220; // px diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_fill_color.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_fill_color.test.ts new file mode 100644 index 0000000000000..41ce95e50cfbd --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_fill_color.test.ts @@ -0,0 +1,31 @@ +/* + * 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 { euiThemeVars } from '@kbn/ui-theme'; + +import { getFillColor } from './get_fill_color'; +import { DEFAULT_INDEX_COLOR } from '../constants'; + +describe('getFillColor', () => { + test('it returns success when `incompatible` is zero', () => { + const incompatible = 0; + + expect(getFillColor(incompatible)).toEqual(euiThemeVars.euiColorSuccess); + }); + + test('it returns danger when `incompatible` is greater than 0', () => { + const incompatible = 1; + + expect(getFillColor(incompatible)).toEqual(euiThemeVars.euiColorDanger); + }); + + test('it returns the default color when `incompatible` is undefined', () => { + const incompatible = undefined; + + expect(getFillColor(incompatible)).toEqual(DEFAULT_INDEX_COLOR); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_fill_color.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_fill_color.ts new file mode 100644 index 0000000000000..5c2d43a66ee15 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_fill_color.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { euiThemeVars } from '@kbn/ui-theme'; +import { DEFAULT_INDEX_COLOR } from '../constants'; + +export const getFillColor = (incompatible: number | undefined): string => { + if (incompatible === 0) { + return euiThemeVars.euiColorSuccess; + } else if (incompatible != null && incompatible > 0) { + return euiThemeVars.euiColorDanger; + } else { + return DEFAULT_INDEX_COLOR; + } +}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_layers_multi_dimensional.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_layers_multi_dimensional.test.ts new file mode 100644 index 0000000000000..aa6aee9fafc29 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_layers_multi_dimensional.test.ts @@ -0,0 +1,90 @@ +/* + * 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 numeral from '@elastic/numeral'; + +import { auditbeatWithAllResults } from '../../../../mock/pattern_rollup/mock_auditbeat_pattern_rollup'; +import { getFlattenedBuckets } from '../../utils/get_flattened_buckets'; +import { getGroupFromPath, getLayersMultiDimensional } from './get_layers_multi_dimensional'; +import { getPathToFlattenedBucketMap } from './get_path_to_flattened_bucket_map'; +import { alertIndexWithAllResults } from '../../../../mock/pattern_rollup/mock_alerts_pattern_rollup'; +import { packetbeatNoResults } from '../../../../mock/pattern_rollup/mock_packetbeat_pattern_rollup'; +import { PatternRollup } from '../../../../types'; +import { EMPTY_STAT } from '../../../../constants'; + +const defaultBytesFormat = '0,0.[0]b'; +const formatBytes = (value: number | undefined) => + value != null ? numeral(value).format(defaultBytesFormat) : EMPTY_STAT; + +const ilmPhases = ['hot', 'warm', 'unmanaged']; + +const patternRollups: Record = { + '.alerts-security.alerts-default': alertIndexWithAllResults, + 'auditbeat-*': auditbeatWithAllResults, + 'packetbeat-*': packetbeatNoResults, +}; + +describe('getGroupFromPath', () => { + it('returns the expected group from the path', () => { + expect( + getGroupFromPath([ + { + index: 0, + value: '__null_small_multiples_key__', + }, + { + index: 0, + value: '__root_key__', + }, + { + index: 0, + value: 'auditbeat-*', + }, + { + index: 1, + value: 'auditbeat-custom-empty-index-1', + }, + ]) + ).toEqual('auditbeat-*'); + }); + + it('returns undefined when path is an empty array', () => { + expect(getGroupFromPath([])).toBeUndefined(); + }); + + it('returns undefined when path is an array with only one value', () => { + expect(getGroupFromPath([{ index: 0, value: '__null_small_multiples_key__' }])).toBeUndefined(); + }); +}); + +describe('getLayersMultiDimensional', () => { + const layer0FillColor = 'transparent'; + const flattenedBuckets = getFlattenedBuckets({ + ilmPhases, + isILMAvailable: true, + patternRollups, + }); + const pathToFlattenedBucketMap = getPathToFlattenedBucketMap(flattenedBuckets); + + it('returns the expected number of layers', () => { + expect( + getLayersMultiDimensional({ + valueFormatter: formatBytes, + layer0FillColor, + pathToFlattenedBucketMap, + }).length + ).toEqual(2); + }); + + it('returns the expected fillLabel valueFormatter function', () => { + getLayersMultiDimensional({ + valueFormatter: formatBytes, + layer0FillColor, + pathToFlattenedBucketMap, + }).forEach((x) => expect(x.fillLabel.valueFormatter(123)).toEqual('123B')); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_layers_multi_dimensional.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_layers_multi_dimensional.ts new file mode 100644 index 0000000000000..da5947f742138 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_layers_multi_dimensional.ts @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ArrayNode, Datum, Key } from '@elastic/charts'; + +import { FlattenedBucket } from '../../types'; +import { getFillColor } from './get_fill_color'; + +const groupByRollup = (d: Datum) => d.pattern; // the treemap is grouped by this field + +/** + * Extracts the first group name from the data representing the second group + */ +export const getGroupFromPath = (path: ArrayNode['path']): string | undefined => { + const OFFSET_FROM_END = 2; // The offset from the end of the path array containing the group + const groupIndex = path.length - OFFSET_FROM_END; + return groupIndex > 0 ? path[groupIndex].value : undefined; +}; + +export const getLayersMultiDimensional = ({ + valueFormatter, + layer0FillColor, + pathToFlattenedBucketMap, +}: { + valueFormatter: (value: number) => string; + layer0FillColor: string; + pathToFlattenedBucketMap: Record; +}) => { + return [ + { + fillLabel: { + valueFormatter, + }, + groupByRollup, + nodeLabel: (ilmPhase: Datum) => ilmPhase, + shape: { + fillColor: layer0FillColor, + }, + }, + { + fillLabel: { + valueFormatter, + }, + groupByRollup: (d: Datum) => d.indexName, + nodeLabel: (indexName: Datum) => indexName, + shape: { + fillColor: (indexName: Key, _sortIndex: number, node: Pick) => { + const pattern = getGroupFromPath(node.path) ?? ''; + const flattenedBucket = pathToFlattenedBucketMap[`${pattern}${indexName}`]; + + return getFillColor(flattenedBucket?.incompatible); + }, + }, + }, + ]; +}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_legend_items.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_legend_items.test.ts new file mode 100644 index 0000000000000..eee30b2d974cf --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_legend_items.test.ts @@ -0,0 +1,196 @@ +/* + * 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 { euiThemeVars } from '@kbn/ui-theme'; + +import { getFlattenedBuckets } from '../../utils/get_flattened_buckets'; +import { alertIndexWithAllResults } from '../../../../mock/pattern_rollup/mock_alerts_pattern_rollup'; +import { auditbeatWithAllResults } from '../../../../mock/pattern_rollup/mock_auditbeat_pattern_rollup'; +import { packetbeatNoResults } from '../../../../mock/pattern_rollup/mock_packetbeat_pattern_rollup'; +import { PatternRollup } from '../../../../types'; +import { getLegendItems, getLegendItemsForPattern, getPatternLegendItem } from './get_legend_items'; + +const ilmPhases = ['hot', 'warm', 'unmanaged']; +const patterns = ['.alerts-security.alerts-default', 'auditbeat-*', 'packetbeat-*']; +const patternRollups: Record = { + '.alerts-security.alerts-default': alertIndexWithAllResults, + 'auditbeat-*': auditbeatWithAllResults, + 'packetbeat-*': packetbeatNoResults, +}; + +describe('getPatternLegendItem', () => { + test('it returns the expected legend item', () => { + const pattern = 'auditbeat-*'; + + expect(getPatternLegendItem({ pattern, patternRollups })).toEqual({ + color: null, + ilmPhase: null, + index: null, + pattern, + sizeInBytes: auditbeatWithAllResults.sizeInBytes, + docsCount: auditbeatWithAllResults.docsCount, + }); + }); +}); + +describe('getLegendItemsForPattern', () => { + test('it returns the expected legend items', () => { + const pattern = 'auditbeat-*'; + const flattenedBuckets = getFlattenedBuckets({ + ilmPhases, + isILMAvailable: true, + patternRollups, + }); + + expect(getLegendItemsForPattern({ pattern, flattenedBuckets })).toEqual([ + { + color: euiThemeVars.euiColorSuccess, + ilmPhase: 'hot', + index: '.ds-auditbeat-8.6.1-2023.02.07-000001', + pattern: 'auditbeat-*', + sizeInBytes: 18791790, + docsCount: 19123, + }, + { + color: euiThemeVars.euiColorDanger, + ilmPhase: 'unmanaged', + index: 'auditbeat-custom-index-1', + pattern: 'auditbeat-*', + sizeInBytes: 28409, + docsCount: 4, + }, + { + color: euiThemeVars.euiColorDanger, + ilmPhase: 'unmanaged', + index: 'auditbeat-custom-empty-index-1', + pattern: 'auditbeat-*', + sizeInBytes: 247, + docsCount: 0, + }, + ]); + }); + + test('it returns the expected legend items when isILMAvailable is false', () => { + const pattern = 'auditbeat-*'; + const flattenedBuckets = getFlattenedBuckets({ + ilmPhases, + isILMAvailable: false, + patternRollups, + }); + expect(getLegendItemsForPattern({ pattern, flattenedBuckets })).toEqual([ + { + color: euiThemeVars.euiColorSuccess, + ilmPhase: null, + index: '.ds-auditbeat-8.6.1-2023.02.07-000001', + pattern: 'auditbeat-*', + sizeInBytes: 18791790, + docsCount: 19123, + }, + { + color: euiThemeVars.euiColorDanger, + ilmPhase: null, + index: 'auditbeat-custom-index-1', + pattern: 'auditbeat-*', + sizeInBytes: 28409, + docsCount: 4, + }, + { + color: euiThemeVars.euiColorDanger, + ilmPhase: null, + index: 'auditbeat-custom-empty-index-1', + pattern: 'auditbeat-*', + sizeInBytes: 247, + docsCount: 0, + }, + ]); + }); +}); + +describe('getLegendItems', () => { + test('it returns the expected legend items', () => { + const flattenedBuckets = getFlattenedBuckets({ + ilmPhases, + isILMAvailable: true, + patternRollups, + }); + + expect(getLegendItems({ flattenedBuckets, patterns, patternRollups })).toEqual([ + { + color: null, + ilmPhase: null, + index: null, + pattern: '.alerts-security.alerts-default', + sizeInBytes: 29717961631, + docsCount: 26093, + }, + { + color: euiThemeVars.euiColorSuccess, + ilmPhase: 'hot', + index: '.internal.alerts-security.alerts-default-000001', + pattern: '.alerts-security.alerts-default', + sizeInBytes: 0, + docsCount: 26093, + }, + { + color: null, + ilmPhase: null, + index: null, + pattern: 'auditbeat-*', + sizeInBytes: 18820446, + docsCount: 19127, + }, + { + color: euiThemeVars.euiColorSuccess, + ilmPhase: 'hot', + index: '.ds-auditbeat-8.6.1-2023.02.07-000001', + pattern: 'auditbeat-*', + sizeInBytes: 18791790, + docsCount: 19123, + }, + { + color: euiThemeVars.euiColorDanger, + ilmPhase: 'unmanaged', + index: 'auditbeat-custom-index-1', + pattern: 'auditbeat-*', + sizeInBytes: 28409, + docsCount: 4, + }, + { + color: euiThemeVars.euiColorDanger, + ilmPhase: 'unmanaged', + index: 'auditbeat-custom-empty-index-1', + pattern: 'auditbeat-*', + sizeInBytes: 247, + docsCount: 0, + }, + { + color: null, + ilmPhase: null, + index: null, + pattern: 'packetbeat-*', + sizeInBytes: 1096520898, + docsCount: 3258632, + }, + { + color: euiThemeVars.euiColorPrimary, + ilmPhase: 'hot', + index: '.ds-packetbeat-8.5.3-2023.02.04-000001', + pattern: 'packetbeat-*', + sizeInBytes: 584326147, + docsCount: 1630289, + }, + { + color: euiThemeVars.euiColorPrimary, + ilmPhase: 'hot', + index: '.ds-packetbeat-8.6.1-2023.02.04-000001', + pattern: 'packetbeat-*', + sizeInBytes: 512194751, + docsCount: 1628343, + }, + ]); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_legend_items.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_legend_items.ts new file mode 100644 index 0000000000000..16816dcf2a3c6 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_legend_items.ts @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { orderBy } from 'lodash/fp'; + +import { PatternRollup } from '../../../../types'; +import { FlattenedBucket, LegendItem } from '../../types'; +import { getFillColor } from './get_fill_color'; +import { getPatternDocsCount, getPatternSizeInBytes } from './stats'; + +export const getLegendItemsForPattern = ({ + pattern, + flattenedBuckets, +}: { + pattern: string; + flattenedBuckets: FlattenedBucket[]; +}): LegendItem[] => + orderBy( + ['sizeInBytes'], + ['desc'], + flattenedBuckets + .filter((x) => x.pattern === pattern) + .map((flattenedBucket) => ({ + color: getFillColor(flattenedBucket.incompatible), + ilmPhase: flattenedBucket.ilmPhase ?? null, + index: flattenedBucket.indexName ?? null, + pattern: flattenedBucket.pattern, + sizeInBytes: flattenedBucket.sizeInBytes, + docsCount: flattenedBucket.docsCount, + })) + ); + +export const getPatternLegendItem = ({ + pattern, + patternRollups, +}: { + pattern: string; + patternRollups: Record; +}): LegendItem => ({ + color: null, + ilmPhase: null, + index: null, + pattern, + sizeInBytes: getPatternSizeInBytes({ pattern, patternRollups }), + docsCount: getPatternDocsCount({ pattern, patternRollups }), +}); + +export const getLegendItems = ({ + patterns, + flattenedBuckets, + patternRollups, +}: { + patterns: string[]; + flattenedBuckets: FlattenedBucket[]; + patternRollups: Record; +}): LegendItem[] => + patterns.reduce( + (acc, pattern) => [ + ...acc, + getPatternLegendItem({ pattern, patternRollups }), + ...getLegendItemsForPattern({ pattern, flattenedBuckets }), + ], + [] + ); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_path_to_flattened_bucket_map.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_path_to_flattened_bucket_map.test.ts new file mode 100644 index 0000000000000..f7a3be93fcc85 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_path_to_flattened_bucket_map.test.ts @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { PatternRollup } from '../../../../types'; +import { getFlattenedBuckets } from '../../utils/get_flattened_buckets'; +import { getPathToFlattenedBucketMap } from './get_path_to_flattened_bucket_map'; +import { alertIndexWithAllResults } from '../../../../mock/pattern_rollup/mock_alerts_pattern_rollup'; +import { auditbeatWithAllResults } from '../../../../mock/pattern_rollup/mock_auditbeat_pattern_rollup'; +import { packetbeatNoResults } from '../../../../mock/pattern_rollup/mock_packetbeat_pattern_rollup'; + +const ilmPhases = ['hot', 'warm', 'unmanaged']; + +const patternRollups: Record = { + '.alerts-security.alerts-default': alertIndexWithAllResults, + 'auditbeat-*': auditbeatWithAllResults, + 'packetbeat-*': packetbeatNoResults, +}; + +describe('helpers', () => { + describe('getPathToFlattenedBucketMap', () => { + test('it returns the expected map', () => { + const flattenedBuckets = getFlattenedBuckets({ + ilmPhases, + isILMAvailable: true, + patternRollups, + }); + + expect(getPathToFlattenedBucketMap(flattenedBuckets)).toEqual({ + '.alerts-security.alerts-default.internal.alerts-security.alerts-default-000001': { + pattern: '.alerts-security.alerts-default', + indexName: '.internal.alerts-security.alerts-default-000001', + ilmPhase: 'hot', + incompatible: 0, + sizeInBytes: 0, + docsCount: 26093, + }, + 'auditbeat-*.ds-auditbeat-8.6.1-2023.02.07-000001': { + pattern: 'auditbeat-*', + indexName: '.ds-auditbeat-8.6.1-2023.02.07-000001', + ilmPhase: 'hot', + incompatible: 0, + sizeInBytes: 18791790, + docsCount: 19123, + }, + 'auditbeat-*auditbeat-custom-empty-index-1': { + pattern: 'auditbeat-*', + indexName: 'auditbeat-custom-empty-index-1', + ilmPhase: 'unmanaged', + incompatible: 1, + sizeInBytes: 247, + docsCount: 0, + }, + 'auditbeat-*auditbeat-custom-index-1': { + pattern: 'auditbeat-*', + indexName: 'auditbeat-custom-index-1', + ilmPhase: 'unmanaged', + incompatible: 3, + sizeInBytes: 28409, + docsCount: 4, + }, + 'packetbeat-*.ds-packetbeat-8.6.1-2023.02.04-000001': { + pattern: 'packetbeat-*', + indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + ilmPhase: 'hot', + sizeInBytes: 512194751, + docsCount: 1628343, + }, + 'packetbeat-*.ds-packetbeat-8.5.3-2023.02.04-000001': { + docsCount: 1630289, + pattern: 'packetbeat-*', + indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', + ilmPhase: 'hot', + sizeInBytes: 584326147, + }, + }); + }); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_path_to_flattened_bucket_map.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_path_to_flattened_bucket_map.ts new file mode 100644 index 0000000000000..4afbe4c1b73cd --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/get_path_to_flattened_bucket_map.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FlattenedBucket } from '../../types'; + +export const getPathToFlattenedBucketMap = ( + flattenedBuckets: FlattenedBucket[] +): Record => + flattenedBuckets.reduce>( + (acc, { pattern, indexName, ...remaining }) => ({ + ...acc, + [`${pattern}${indexName}`]: { pattern, indexName, ...remaining }, + }), + {} + ); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/stats.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/stats.test.ts new file mode 100644 index 0000000000000..b2b31eac00ab0 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/stats.test.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { PatternRollup } from '../../../../types'; +import { alertIndexWithAllResults } from '../../../../mock/pattern_rollup/mock_alerts_pattern_rollup'; +import { auditbeatWithAllResults } from '../../../../mock/pattern_rollup/mock_auditbeat_pattern_rollup'; +import { packetbeatNoResults } from '../../../../mock/pattern_rollup/mock_packetbeat_pattern_rollup'; +import { getPatternSizeInBytes } from './stats'; + +const patternRollups: Record = { + '.alerts-security.alerts-default': alertIndexWithAllResults, + 'auditbeat-*': auditbeatWithAllResults, + 'packetbeat-*': packetbeatNoResults, +}; + +/** a valid `PatternRollup` that has an undefined `sizeInBytes` */ +const noSizeInBytes: Record = { + 'valid-*': { + docsCount: 19127, + error: null, + ilmExplain: null, + ilmExplainPhaseCounts: { + hot: 1, + warm: 0, + cold: 0, + frozen: 0, + unmanaged: 2, + }, + indices: 3, + pattern: 'valid-*', + results: undefined, + sizeInBytes: undefined, // <-- + stats: null, + }, +}; + +describe('getPatternSizeInBytes', () => { + test('it returns the expected size when the pattern exists in the rollup', () => { + const pattern = 'auditbeat-*'; + + expect(getPatternSizeInBytes({ pattern, patternRollups })).toEqual( + auditbeatWithAllResults.sizeInBytes + ); + }); + + test('it returns undefined when the pattern exists in the rollup, but does not have a sizeInBytes', () => { + const pattern = 'valid-*'; + + expect(getPatternSizeInBytes({ pattern, patternRollups: noSizeInBytes })).toBeUndefined(); + }); + + test('it returns undefined when the pattern does NOT exist in the rollup', () => { + const pattern = 'does-not-exist-*'; + + expect(getPatternSizeInBytes({ pattern, patternRollups })).toBeUndefined(); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/stats.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/stats.ts new file mode 100644 index 0000000000000..9d999266a40f5 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/storage_treemap/utils/stats.ts @@ -0,0 +1,36 @@ +/* + * 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 { PatternRollup } from '../../../../types'; + +export const getPatternSizeInBytes = ({ + pattern, + patternRollups, +}: { + pattern: string; + patternRollups: Record; +}): number | undefined => { + if (patternRollups[pattern] != null) { + return patternRollups[pattern].sizeInBytes; + } else { + return undefined; + } +}; + +export const getPatternDocsCount = ({ + pattern, + patternRollups, +}: { + pattern: string; + patternRollups: Record; +}): number => { + if (patternRollups[pattern] != null) { + return patternRollups[pattern].docsCount ?? 0; + } else { + return 0; + } +}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/types.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/types.ts similarity index 56% rename from x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/types.ts rename to x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/types.ts index e44300859bffd..a1507d1ad9bcb 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/types.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/types.ts @@ -5,15 +5,20 @@ * 2.0. */ -import { IlmPhase } from '../../../types'; - -export interface IndexSummaryTableItem { +export interface LegendItem { + color: string | null; + ilmPhase: string | null; + index: string | null; + pattern: string; + sizeInBytes: number | undefined; docsCount: number; +} + +export interface FlattenedBucket { + ilmPhase: string | undefined; incompatible: number | undefined; - indexName: string; - ilmPhase: IlmPhase | undefined; + indexName: string | undefined; pattern: string; - patternDocsCount: number; sizeInBytes: number | undefined; - checkedAt: number | undefined; + docsCount: number; } diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/utils/get_flattened_buckets.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/utils/get_flattened_buckets.test.ts new file mode 100644 index 0000000000000..7aaff4888186a --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/utils/get_flattened_buckets.test.ts @@ -0,0 +1,135 @@ +/* + * 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 { alertIndexWithAllResults } from '../../../mock/pattern_rollup/mock_alerts_pattern_rollup'; +import { auditbeatWithAllResults } from '../../../mock/pattern_rollup/mock_auditbeat_pattern_rollup'; +import { packetbeatNoResults } from '../../../mock/pattern_rollup/mock_packetbeat_pattern_rollup'; +import { PatternRollup } from '../../../types'; +import { getFlattenedBuckets } from './get_flattened_buckets'; + +const ilmPhases = ['hot', 'warm', 'unmanaged']; +const patternRollups: Record = { + '.alerts-security.alerts-default': alertIndexWithAllResults, + 'auditbeat-*': auditbeatWithAllResults, + 'packetbeat-*': packetbeatNoResults, +}; + +describe('getFlattenedBuckets', () => { + test('it returns the expected flattened buckets', () => { + expect( + getFlattenedBuckets({ + ilmPhases, + isILMAvailable: true, + patternRollups, + }) + ).toEqual([ + { + ilmPhase: 'hot', + incompatible: 0, + indexName: '.internal.alerts-security.alerts-default-000001', + pattern: '.alerts-security.alerts-default', + sizeInBytes: 0, + docsCount: 26093, + }, + { + ilmPhase: 'hot', + incompatible: 0, + indexName: '.ds-auditbeat-8.6.1-2023.02.07-000001', + pattern: 'auditbeat-*', + sizeInBytes: 18791790, + docsCount: 19123, + }, + { + ilmPhase: 'unmanaged', + incompatible: 1, + indexName: 'auditbeat-custom-empty-index-1', + pattern: 'auditbeat-*', + sizeInBytes: 247, + docsCount: 0, + }, + { + ilmPhase: 'unmanaged', + incompatible: 3, + indexName: 'auditbeat-custom-index-1', + pattern: 'auditbeat-*', + sizeInBytes: 28409, + docsCount: 4, + }, + { + ilmPhase: 'hot', + indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + pattern: 'packetbeat-*', + sizeInBytes: 512194751, + docsCount: 1628343, + }, + { + ilmPhase: 'hot', + indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', + pattern: 'packetbeat-*', + sizeInBytes: 584326147, + docsCount: 1630289, + }, + ]); + }); + + test('it returns the expected flattened buckets when isILMAvailable is false', () => { + expect( + getFlattenedBuckets({ + ilmPhases, + isILMAvailable: false, + patternRollups, + }) + ).toEqual([ + { + docsCount: 26093, + ilmPhase: undefined, + incompatible: 0, + indexName: '.internal.alerts-security.alerts-default-000001', + pattern: '.alerts-security.alerts-default', + sizeInBytes: 0, + }, + { + docsCount: 19123, + ilmPhase: undefined, + incompatible: 0, + indexName: '.ds-auditbeat-8.6.1-2023.02.07-000001', + pattern: 'auditbeat-*', + sizeInBytes: 18791790, + }, + { + docsCount: 0, + ilmPhase: undefined, + incompatible: 1, + indexName: 'auditbeat-custom-empty-index-1', + pattern: 'auditbeat-*', + sizeInBytes: 247, + }, + { + docsCount: 4, + ilmPhase: undefined, + incompatible: 3, + indexName: 'auditbeat-custom-index-1', + pattern: 'auditbeat-*', + sizeInBytes: 28409, + }, + { + docsCount: 1628343, + ilmPhase: undefined, + indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + pattern: 'packetbeat-*', + sizeInBytes: 512194751, + }, + { + docsCount: 1630289, + ilmPhase: undefined, + indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', + pattern: 'packetbeat-*', + sizeInBytes: 584326147, + }, + ]); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/utils/get_flattened_buckets.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/utils/get_flattened_buckets.ts new file mode 100644 index 0000000000000..7363ae1df2c33 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/storage_details/utils/get_flattened_buckets.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { PatternRollup } from '../../../types'; +import { getIlmPhase } from '../../../utils/get_ilm_phase'; +import { getDocsCount, getSizeInBytes } from '../../../utils/stats'; +import { FlattenedBucket } from '../types'; + +export const getFlattenedBuckets = ({ + ilmPhases, + isILMAvailable, + patternRollups, +}: { + ilmPhases: string[]; + isILMAvailable: boolean; + patternRollups: Record; +}): FlattenedBucket[] => + Object.values(patternRollups).reduce((acc, patternRollup) => { + // enables fast lookup of valid phase names: + const ilmPhasesMap = ilmPhases.reduce>( + (phasesMap, phase) => ({ ...phasesMap, [phase]: 0 }), + {} + ); + const { ilmExplain, pattern, results, stats } = patternRollup; + + if (((isILMAvailable && ilmExplain != null) || !isILMAvailable) && stats != null) { + return [ + ...acc, + ...Object.entries(stats).reduce((validStats, [indexName]) => { + const ilmPhase = getIlmPhase(ilmExplain?.[indexName], isILMAvailable); + const isSelectedPhase = + (isILMAvailable && ilmPhase != null && ilmPhasesMap[ilmPhase] != null) || + !isILMAvailable; + + if (isSelectedPhase) { + const incompatible = + results != null && results[indexName] != null + ? results[indexName].incompatible + : undefined; + const sizeInBytes = getSizeInBytes({ indexName, stats }); + const docsCount = getDocsCount({ stats, indexName }); + return [ + ...validStats, + { + ilmPhase, + incompatible, + indexName, + pattern, + sizeInBytes, + docsCount, + }, + ]; + } else { + return validStats; + } + }, []), + ]; + } + + return acc; + }, []); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/helpers.test.ts deleted file mode 100644 index 2b37622baa655..0000000000000 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/helpers.test.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getAllIndicesToCheck, getIndexDocsCountFromRollup, getIndexToCheck } from './helpers'; -import { mockPacketbeatPatternRollup } from '../../../mock/pattern_rollup/mock_packetbeat_pattern_rollup'; - -const patternIndexNames: Record = { - 'packetbeat-*': [ - '.ds-packetbeat-8.6.1-2023.02.04-000001', - '.ds-packetbeat-8.5.3-2023.02.04-000001', - ], - 'auditbeat-*': [ - 'auditbeat-7.17.9-2023.02.13-000001', - 'auditbeat-custom-index-1', - '.ds-auditbeat-8.6.1-2023.02.13-000001', - ], - 'logs-*': [ - '.ds-logs-endpoint.alerts-default-2023.02.24-000001', - '.ds-logs-endpoint.events.process-default-2023.02.24-000001', - ], - 'remote:*': [], - '.alerts-security.alerts-default': ['.internal.alerts-security.alerts-default-000001'], -}; - -describe('helpers', () => { - describe('getIndexToCheck', () => { - test('it returns the expected `IndexToCheck`', () => { - expect( - getIndexToCheck({ - indexName: 'auditbeat-custom-index-1', - pattern: 'auditbeat-*', - }) - ).toEqual({ - indexName: 'auditbeat-custom-index-1', - pattern: 'auditbeat-*', - }); - }); - }); - - describe('getAllIndicesToCheck', () => { - test('it returns the sorted collection of `IndexToCheck`', () => { - expect(getAllIndicesToCheck(patternIndexNames)).toEqual([ - { - indexName: '.internal.alerts-security.alerts-default-000001', - pattern: '.alerts-security.alerts-default', - }, - { - indexName: 'auditbeat-custom-index-1', - pattern: 'auditbeat-*', - }, - { - indexName: 'auditbeat-7.17.9-2023.02.13-000001', - pattern: 'auditbeat-*', - }, - { - indexName: '.ds-auditbeat-8.6.1-2023.02.13-000001', - pattern: 'auditbeat-*', - }, - { - indexName: '.ds-logs-endpoint.events.process-default-2023.02.24-000001', - pattern: 'logs-*', - }, - { - indexName: '.ds-logs-endpoint.alerts-default-2023.02.24-000001', - pattern: 'logs-*', - }, - { - indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', - pattern: 'packetbeat-*', - }, - { - indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', - pattern: 'packetbeat-*', - }, - ]); - }); - }); - - describe('getIndexDocsCountFromRollup', () => { - test('it returns the expected count when the `patternRollup` has `stats`', () => { - expect( - getIndexDocsCountFromRollup({ - indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', - patternRollup: mockPacketbeatPatternRollup, - }) - ).toEqual(1628343); - }); - - test('it returns zero when the `patternRollup` `stats` is null', () => { - const patternRollup = { - ...mockPacketbeatPatternRollup, - stats: null, // <-- - }; - - expect( - getIndexDocsCountFromRollup({ - indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', - patternRollup, - }) - ).toEqual(0); - }); - }); -}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/index.tsx index e2851ee4b3761..9e90b28e71a9e 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/index.tsx @@ -10,7 +10,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import styled from 'styled-components'; import { v4 as uuidv4 } from 'uuid'; -import { getAllIndicesToCheck } from './helpers'; +import { getAllIndicesToCheck } from './utils/get_all_indices_to_check'; import { useResultsRollupContext } from '../../../contexts/results_rollup_context'; import { checkIndex } from '../../../utils/check_index'; import { useDataQualityContext } from '../../../data_quality_context'; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/translations.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/translations.ts deleted file mode 100644 index 219d1039ac290..0000000000000 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/translations.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const AN_ERROR_OCCURRED_CHECKING_INDEX = (indexName: string) => - i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.checkAllErrorCheckingIndexMessage', - { - values: { indexName }, - defaultMessage: 'An error occurred checking index {indexName}', - } - ); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/utils/get_all_indices_to_check.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/utils/get_all_indices_to_check.test.ts new file mode 100644 index 0000000000000..3a3bbf5880455 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/utils/get_all_indices_to_check.test.ts @@ -0,0 +1,79 @@ +/* + * 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 { getAllIndicesToCheck, getIndexToCheck } from './get_all_indices_to_check'; + +const patternIndexNames: Record = { + 'packetbeat-*': [ + '.ds-packetbeat-8.6.1-2023.02.04-000001', + '.ds-packetbeat-8.5.3-2023.02.04-000001', + ], + 'auditbeat-*': [ + 'auditbeat-7.17.9-2023.02.13-000001', + 'auditbeat-custom-index-1', + '.ds-auditbeat-8.6.1-2023.02.13-000001', + ], + 'logs-*': [ + '.ds-logs-endpoint.alerts-default-2023.02.24-000001', + '.ds-logs-endpoint.events.process-default-2023.02.24-000001', + ], + 'remote:*': [], + '.alerts-security.alerts-default': ['.internal.alerts-security.alerts-default-000001'], +}; + +describe('getIndexToCheck', () => { + test('it returns the expected `IndexToCheck`', () => { + expect( + getIndexToCheck({ + indexName: 'auditbeat-custom-index-1', + pattern: 'auditbeat-*', + }) + ).toEqual({ + indexName: 'auditbeat-custom-index-1', + pattern: 'auditbeat-*', + }); + }); +}); + +describe('getAllIndicesToCheck', () => { + test('it returns the sorted collection of `IndexToCheck`', () => { + expect(getAllIndicesToCheck(patternIndexNames)).toEqual([ + { + indexName: '.internal.alerts-security.alerts-default-000001', + pattern: '.alerts-security.alerts-default', + }, + { + indexName: 'auditbeat-custom-index-1', + pattern: 'auditbeat-*', + }, + { + indexName: 'auditbeat-7.17.9-2023.02.13-000001', + pattern: 'auditbeat-*', + }, + { + indexName: '.ds-auditbeat-8.6.1-2023.02.13-000001', + pattern: 'auditbeat-*', + }, + { + indexName: '.ds-logs-endpoint.events.process-default-2023.02.24-000001', + pattern: 'logs-*', + }, + { + indexName: '.ds-logs-endpoint.alerts-default-2023.02.24-000001', + pattern: 'logs-*', + }, + { + indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + pattern: 'packetbeat-*', + }, + { + indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', + pattern: 'packetbeat-*', + }, + ]); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/utils/get_all_indices_to_check.ts similarity index 73% rename from x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/helpers.ts rename to x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/utils/get_all_indices_to_check.ts index dfbc0f69f82aa..dbe1b113bc9aa 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_all/utils/get_all_indices_to_check.ts @@ -7,8 +7,7 @@ import { orderBy } from 'lodash/fp'; -import type { IndexToCheck, MeteringStatsIndex, PatternRollup } from '../../../types'; -import { getDocsCount } from '../../../utils/stats'; +import type { IndexToCheck } from '../../../../types'; export const getIndexToCheck = ({ indexName, @@ -45,18 +44,3 @@ export const getAllIndicesToCheck = ( return [...acc, ...sortedIndicesToCheck]; }, []); }; - -export const getIndexDocsCountFromRollup = ({ - indexName, - patternRollup, -}: { - indexName: string; - patternRollup: PatternRollup; -}): number => { - const stats: Record | null = patternRollup?.stats ?? null; - - return getDocsCount({ - indexName, - stats, - }); -}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/errors_viewer/helpers.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/errors_viewer/helpers.tsx index a72580e464ad4..8644a0a89c02a 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/errors_viewer/helpers.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/errors_viewer/helpers.tsx @@ -9,8 +9,9 @@ import type { EuiTableFieldDataColumnType } from '@elastic/eui'; import { EuiCode } from '@elastic/eui'; import React from 'react'; -import * as i18n from './translations'; import type { ErrorSummary } from '../../../../../types'; +import { INDEX } from '../../../../../translations'; +import { ERROR, PATTERN } from '../../../translations'; export const EMPTY_PLACEHOLDER = '--'; @@ -20,14 +21,14 @@ export const ERRORS_CONTAINER_MIN_WIDTH = 450; // px export const getErrorsViewerTableColumns = (): Array> => [ { field: 'pattern', - name: i18n.PATTERN, + name: PATTERN, sortable: true, truncateText: false, width: '25%', }, { field: 'indexName', - name: i18n.INDEX, + name: INDEX, render: (indexName: string | null) => indexName != null && indexName !== '' ? ( {indexName} @@ -40,7 +41,7 @@ export const getErrorsViewerTableColumns = (): Array {errorText}, sortable: false, truncateText: false, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/errors_viewer/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/errors_viewer/index.test.tsx index 1c605a64d8ab2..aa74e3632b723 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/errors_viewer/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/errors_viewer/index.test.tsx @@ -8,9 +8,10 @@ import { render, screen } from '@testing-library/react'; import React from 'react'; +import { INDEX } from '../../../../../translations'; import { TestExternalProviders } from '../../../../../mock/test_providers/test_providers'; -import { ERROR, INDEX, PATTERN } from './translations'; import { ErrorSummary } from '../../../../../types'; +import { ERROR, PATTERN } from '../../../translations'; import { ErrorsViewer } from '.'; interface ExpectedColumns { diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/index.tsx index a4bb73147e97b..18824bd310ac7 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/index.tsx @@ -16,15 +16,24 @@ import { import React, { useCallback, useMemo, useState } from 'react'; import styled from 'styled-components'; +import { + COPY_TO_CLIPBOARD, + ERRORS_CALLOUT_SUMMARY, + ERRORS_MAY_OCCUR, + INDEX, + MANAGE, + MONITOR, + OR, + READ, + THE_FOLLOWING_PRIVILEGES_ARE_REQUIRED, + VIEW_INDEX_METADATA, +} from '../../../../translations'; import { ErrorsViewer } from './errors_viewer'; import { ERRORS_CONTAINER_MAX_WIDTH } from './errors_viewer/helpers'; -import { - getErrorsMarkdownTable, - getErrorsMarkdownTableRows, -} from '../../../../data_quality_details/indices_details/pattern/index_check_flyout/index_properties/markdown/helpers'; -import * as i18n from './translations'; import type { ErrorSummary } from '../../../../types'; -import { ERROR, INDEX, PATTERN } from './errors_viewer/translations'; +import { getErrorsMarkdownTable, getErrorsMarkdownTableRows } from '../../utils/markdown'; +import { ERROR, ERRORS, PATTERN } from '../../translations'; +import { COPIED_ERRORS_TOAST_TITLE, VIEW_ERRORS } from './translations'; const CallOut = styled(EuiCallOut)` max-width: ${ERRORS_CONTAINER_MAX_WIDTH}px; @@ -45,28 +54,28 @@ const ErrorsPopoverComponent: React.FC = ({ addSuccessToast, errorSummary errorSummary, getMarkdownTableRows: getErrorsMarkdownTableRows, headerNames: [PATTERN, INDEX, ERROR], - title: i18n.ERRORS, + title: ERRORS, }); copyToClipboard(markdown); closePopover(); addSuccessToast({ - title: i18n.COPIED_ERRORS_TOAST_TITLE, + title: COPIED_ERRORS_TOAST_TITLE, }); }, [addSuccessToast, closePopover, errorSummary]); const button = useMemo( () => ( - {i18n.VIEW_ERRORS} + {VIEW_ERRORS} ), [errorSummary.length, onClick] @@ -80,32 +89,32 @@ const ErrorsPopoverComponent: React.FC = ({ addSuccessToast, errorSummary isOpen={isPopoverOpen} panelPaddingSize="s" > - -

      {i18n.ERRORS_CALLOUT_SUMMARY}

      + +

      {ERRORS_CALLOUT_SUMMARY}

      -

      {i18n.ERRORS_MAY_OCCUR}

      +

      {ERRORS_MAY_OCCUR}

      - {i18n.THE_FOLLOWING_PRIVILEGES_ARE_REQUIRED} + {THE_FOLLOWING_PRIVILEGES_ARE_REQUIRED}
      • - {i18n.MONITOR} {i18n.OR} {i18n.MANAGE} + {MONITOR} {OR} {MANAGE}
      • - {i18n.VIEW_INDEX_METADATA} + {VIEW_INDEX_METADATA}
      • - {i18n.READ} + {READ}
      - {i18n.COPY_TO_CLIPBOARD} + {COPY_TO_CLIPBOARD}
      diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/translations.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/translations.ts index 310f69ab5d584..55662b81a0578 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/translations.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/translations.ts @@ -14,74 +14,9 @@ export const COPIED_ERRORS_TOAST_TITLE = i18n.translate( } ); -export const COPY_TO_CLIPBOARD = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.errorsPopover.copyToClipboardButton', - { - defaultMessage: 'Copy to clipboard', - } -); - -export const ERRORS = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.errorsPopover.errorsTitle', - { - defaultMessage: 'Errors', - } -); - -export const ERRORS_CALLOUT_SUMMARY = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.errorsPopover.errorsCalloutSummary', - { - defaultMessage: 'Some indices were not checked for Data Quality', - } -); - -export const ERRORS_MAY_OCCUR = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.errors.errorMayOccurLabel', - { - defaultMessage: - "Errors may occur when pattern or index metadata is temporarily unavailable, or because you don't have the privileges required for access", - } -); - -export const MANAGE = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.errors.manage', - { - defaultMessage: 'manage', - } -); - -export const MONITOR = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.errors.monitor', - { - defaultMessage: 'monitor', - } -); - -export const OR = i18n.translate('securitySolutionPackages.ecsDataQualityDashboard.errors.or', { - defaultMessage: 'or', -}); - -export const READ = i18n.translate('securitySolutionPackages.ecsDataQualityDashboard.errors.read', { - defaultMessage: 'read', -}); - -export const THE_FOLLOWING_PRIVILEGES_ARE_REQUIRED = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.errors.theFollowingPrivilegesLabel', - { - defaultMessage: 'The following privileges are required to check an index:', - } -); - export const VIEW_ERRORS = i18n.translate( 'securitySolutionPackages.ecsDataQualityDashboard.errorsPopover.viewErrorsButton', { defaultMessage: 'View errors', } ); - -export const VIEW_INDEX_METADATA = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.errors.viewIndexMetadata', - { - defaultMessage: 'view_index_metadata', - } -); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/index.tsx index d0037032172c3..88d6e42af97ac 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/index.tsx @@ -12,26 +12,23 @@ import styled from 'styled-components'; import { CheckAll } from './check_all'; import { CheckStatus } from './check_status'; -import { ERROR, INDEX, PATTERN } from './check_status/errors_popover/errors_viewer/translations'; -import { ERRORS } from './check_status/errors_popover/translations'; -import { - getDataQualitySummaryMarkdownComment, - getErrorsMarkdownTable, - getErrorsMarkdownTableRows, - getPatternSummaryMarkdownComment, - getSummaryTableMarkdownHeader, - getSummaryTableMarkdownRow, -} from '../../data_quality_details/indices_details/pattern/index_check_flyout/index_properties/markdown/helpers'; -import { - defaultSort, - getSummaryTableItems, -} from '../../data_quality_details/indices_details/pattern/helpers'; import type { DataQualityCheckResult, IndexToCheck, PatternRollup } from '../../types'; import { useDataQualityContext } from '../../data_quality_context'; import { useResultsRollupContext } from '../../contexts/results_rollup_context'; import { Actions } from '../../actions'; import { getErrorSummaries } from './utils/get_error_summaries'; import { getSizeInBytes } from '../../utils/stats'; +import { getSummaryTableItems } from '../../utils/get_summary_table_items'; +import { defaultSort } from '../../constants'; +import { + getDataQualitySummaryMarkdownComment, + getErrorsMarkdownTable, + getErrorsMarkdownTableRows, + getPatternSummaryMarkdownComment, +} from './utils/markdown'; +import { getSummaryTableMarkdownHeader, getSummaryTableMarkdownRow } from '../../utils/markdown'; +import { ERROR, ERRORS, PATTERN } from './translations'; +import { INDEX } from '../../translations'; const StyledActionsContainerFlexItem = styled(EuiFlexItem)` margin-top: auto; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/errors_viewer/translations.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/translations.ts similarity index 51% rename from x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/errors_viewer/translations.ts rename to x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/translations.ts index a044922748cdf..be47859ccabd1 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/check_status/errors_popover/errors_viewer/translations.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/translations.ts @@ -7,22 +7,29 @@ import { i18n } from '@kbn/i18n'; +export const DATA_QUALITY = i18n.translate( + 'securitySolutionPackages.ecsDataQualityDashboard.dataQuality', + { + defaultMessage: 'Data quality', + } +); + export const ERROR = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.errorsViewerTable.errorColumn', + 'securitySolutionPackages.ecsDataQualityDashboard.errors.error', { defaultMessage: 'Error', } ); -export const INDEX = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.errorsViewerTable.indexColumn', +export const ERRORS = i18n.translate( + 'securitySolutionPackages.ecsDataQualityDashboard.errors.errors', { - defaultMessage: 'Index', + defaultMessage: 'Errors', } ); export const PATTERN = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.errorsViewerTable.patternColumn', + 'securitySolutionPackages.ecsDataQualityDashboard.errors.pattern', { defaultMessage: 'Pattern', } diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/utils/markdown.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/utils/markdown.test.ts new file mode 100644 index 0000000000000..c52a4784f876d --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/utils/markdown.test.ts @@ -0,0 +1,212 @@ +/* + * 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 numeral from '@elastic/numeral'; + +import { EMPTY_STAT } from '../../../constants'; +import { + auditbeatNoResults, + auditbeatWithAllResults, +} from '../../../mock/pattern_rollup/mock_auditbeat_pattern_rollup'; +import { INDEX } from '../../../translations'; +import { ErrorSummary, PatternRollup } from '../../../types'; +import { ERROR, ERRORS, PATTERN } from '../translations'; +import { + getDataQualitySummaryMarkdownComment, + getErrorsMarkdownTable, + getErrorsMarkdownTableRows, + getIlmExplainPhaseCountsMarkdownComment, + getPatternSummaryMarkdownComment, +} from './markdown'; + +const defaultBytesFormat = '0,0.[0]b'; +const formatBytes = (value: number | undefined) => + value != null ? numeral(value).format(defaultBytesFormat) : EMPTY_STAT; + +const defaultNumberFormat = '0,0.[000]'; +const formatNumber = (value: number | undefined) => + value != null ? numeral(value).format(defaultNumberFormat) : EMPTY_STAT; + +describe('getIlmExplainPhaseCountsMarkdownComment', () => { + test('it returns the expected comment when _all_ of the counts are greater than zero', () => { + expect( + getIlmExplainPhaseCountsMarkdownComment({ + hot: 99, + warm: 8, + unmanaged: 77, + cold: 6, + frozen: 55, + }) + ).toEqual('`hot(99)` `warm(8)` `unmanaged(77)` `cold(6)` `frozen(55)`'); + }); + + test('it returns the expected comment when _some_ of the counts are greater than zero', () => { + expect( + getIlmExplainPhaseCountsMarkdownComment({ + hot: 9, + warm: 0, + unmanaged: 2, + cold: 1, + frozen: 0, + }) + ).toEqual('`hot(9)` `unmanaged(2)` `cold(1)`'); + }); + + test('it returns the expected comment when _none_ of the counts are greater than zero', () => { + expect( + getIlmExplainPhaseCountsMarkdownComment({ + hot: 0, + warm: 0, + unmanaged: 0, + cold: 0, + frozen: 0, + }) + ).toEqual(''); + }); +}); + +describe('getPatternSummaryMarkdownComment', () => { + test('it returns the expected comment when the rollup contains results for all of the indices in the pattern', () => { + expect( + getPatternSummaryMarkdownComment({ + formatBytes, + formatNumber, + patternRollup: auditbeatWithAllResults, + }) + ).toEqual( + '## auditbeat-*\n`hot(1)` `unmanaged(2)`\n\n| Incompatible fields | Indices checked | Indices | Size | Docs |\n|---------------------|-----------------|---------|------|------|\n| 4 | 3 | 3 | 17.9MB | 19,127 |\n\n' + ); + }); + + test('it returns the expected comment when the rollup contains no results', () => { + expect( + getPatternSummaryMarkdownComment({ + formatBytes, + formatNumber, + patternRollup: auditbeatNoResults, + }) + ).toEqual( + '## auditbeat-*\n`hot(1)` `unmanaged(2)`\n\n| Incompatible fields | Indices checked | Indices | Size | Docs |\n|---------------------|-----------------|---------|------|------|\n| -- | 0 | 3 | 17.9MB | 19,127 |\n\n' + ); + }); + + test('it returns the expected comment when the rollup does NOT have `ilmExplainPhaseCounts`', () => { + const noIlmExplainPhaseCounts: PatternRollup = { + ...auditbeatWithAllResults, + ilmExplainPhaseCounts: undefined, // <-- + }; + + expect( + getPatternSummaryMarkdownComment({ + formatBytes, + formatNumber, + patternRollup: noIlmExplainPhaseCounts, + }) + ).toEqual( + '## auditbeat-*\n\n\n| Incompatible fields | Indices checked | Indices | Size | Docs |\n|---------------------|-----------------|---------|------|------|\n| 4 | 3 | 3 | 17.9MB | 19,127 |\n\n' + ); + }); + + test('it returns the expected comment when `docsCount` is undefined', () => { + const noDocsCount: PatternRollup = { + ...auditbeatWithAllResults, + docsCount: undefined, // <-- + }; + + expect( + getPatternSummaryMarkdownComment({ + formatBytes, + formatNumber, + patternRollup: noDocsCount, + }) + ).toEqual( + '## auditbeat-*\n`hot(1)` `unmanaged(2)`\n\n| Incompatible fields | Indices checked | Indices | Size | Docs |\n|---------------------|-----------------|---------|------|------|\n| 4 | 3 | 3 | 17.9MB | 0 |\n\n' + ); + }); +}); + +describe('getDataQualitySummaryMarkdownComment', () => { + test('it returns the expected comment', () => { + expect( + getDataQualitySummaryMarkdownComment({ + formatBytes, + formatNumber, + totalDocsCount: 3343719, + totalIncompatible: 4, + totalIndices: 30, + totalIndicesChecked: 2, + sizeInBytes: 4294967296, + }) + ).toEqual( + '# Data quality\n\n| Incompatible fields | Indices checked | Indices | Size | Docs |\n|---------------------|-----------------|---------|------|------|\n| 4 | 2 | 30 | 4GB | 3,343,719 |\n\n' + ); + }); + + test('it returns the expected comment when optional values are undefined', () => { + expect( + getDataQualitySummaryMarkdownComment({ + formatBytes, + formatNumber, + totalDocsCount: undefined, + totalIncompatible: undefined, + totalIndices: undefined, + totalIndicesChecked: undefined, + sizeInBytes: undefined, + }) + ).toEqual( + '# Data quality\n\n| Incompatible fields | Indices checked | Indices | Docs |\n|---------------------|-----------------|---------|------|\n| -- | -- | -- | 0 |\n\n' + ); + }); +}); + +const errorSummary: ErrorSummary[] = [ + { + pattern: '.alerts-security.alerts-default', + indexName: null, + error: 'Error loading stats: Error: Forbidden', + }, + { + error: + 'Error: Error loading unallowed values for index auditbeat-7.2.1-2023.02.13-000001: Forbidden', + indexName: 'auditbeat-7.2.1-2023.02.13-000001', + pattern: 'auditbeat-*', + }, +]; + +describe('getErrorsMarkdownTableRows', () => { + test('it returns the expected markdown table rows', () => { + expect(getErrorsMarkdownTableRows(errorSummary)).toEqual( + '| .alerts-security.alerts-default | -- | `Error loading stats: Error: Forbidden` |\n| auditbeat-* | auditbeat-7.2.1-2023.02.13-000001 | `Error: Error loading unallowed values for index auditbeat-7.2.1-2023.02.13-000001: Forbidden` |' + ); + }); +}); + +describe('getErrorsMarkdownTable', () => { + test('it returns the expected table contents', () => { + expect( + getErrorsMarkdownTable({ + errorSummary, + getMarkdownTableRows: getErrorsMarkdownTableRows, + headerNames: [PATTERN, INDEX, ERROR], + title: ERRORS, + }) + ).toEqual( + `## Errors\n\nSome indices were not checked for Data Quality\n\nErrors may occur when pattern or index metadata is temporarily unavailable, or because you don't have the privileges required for access\n\nThe following privileges are required to check an index:\n- \`monitor\` or \`manage\`\n- \`view_index_metadata\`\n- \`read\`\n\n\n| Pattern | Index | Error | \n|---------|-------|-------|\n| .alerts-security.alerts-default | -- | \`Error loading stats: Error: Forbidden\` |\n| auditbeat-* | auditbeat-7.2.1-2023.02.13-000001 | \`Error: Error loading unallowed values for index auditbeat-7.2.1-2023.02.13-000001: Forbidden\` |\n` + ); + }); + + test('it returns an empty string when the error summary is empty', () => { + expect( + getErrorsMarkdownTable({ + errorSummary: [], // <-- empty + getMarkdownTableRows: getErrorsMarkdownTableRows, + headerNames: [PATTERN, INDEX, ERROR], + title: ERRORS, + }) + ).toEqual(''); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/utils/markdown.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/utils/markdown.ts new file mode 100644 index 0000000000000..2ee2209dbb789 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_summary/summary_actions/utils/markdown.ts @@ -0,0 +1,145 @@ +/* + * 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 { EMPTY_PLACEHOLDER } from '../../../constants'; +import { + COLD, + ERRORS_CALLOUT_SUMMARY, + ERRORS_MAY_OCCUR, + FROZEN, + HOT, + MANAGE, + MONITOR, + OR, + READ, + THE_FOLLOWING_PRIVILEGES_ARE_REQUIRED, + UNMANAGED, + VIEW_INDEX_METADATA, + WARM, +} from '../../../translations'; +import { ErrorSummary, IlmExplainPhaseCounts, PatternRollup } from '../../../types'; +import { + escapeNewlines, + getCodeFormattedValue, + getMarkdownTableHeader, + getStatsRollupMarkdownComment, +} from '../../../utils/markdown'; +import { getTotalPatternIncompatible, getTotalPatternIndicesChecked } from '../../../utils/stats'; +import { DATA_QUALITY } from '../translations'; + +export const getIlmExplainPhaseCountsMarkdownComment = ({ + hot, + warm, + unmanaged, + cold, + frozen, +}: IlmExplainPhaseCounts): string => + [ + hot > 0 ? getCodeFormattedValue(`${HOT}(${hot})`) : '', + warm > 0 ? getCodeFormattedValue(`${WARM}(${warm})`) : '', + unmanaged > 0 ? getCodeFormattedValue(`${UNMANAGED}(${unmanaged})`) : '', + cold > 0 ? getCodeFormattedValue(`${COLD}(${cold})`) : '', + frozen > 0 ? getCodeFormattedValue(`${FROZEN}(${frozen})`) : '', + ] + .filter((x) => x !== '') // prevents extra whitespace + .join(' '); + +export const getPatternSummaryMarkdownComment = ({ + formatBytes, + formatNumber, + patternRollup, + patternRollup: { docsCount, indices, ilmExplainPhaseCounts, pattern, results }, +}: { + formatBytes: (value: number | undefined) => string; + formatNumber: (value: number | undefined) => string; + patternRollup: PatternRollup; +}): string => + `## ${escapeNewlines(pattern)} +${ + ilmExplainPhaseCounts != null + ? getIlmExplainPhaseCountsMarkdownComment(ilmExplainPhaseCounts) + : '' +} + +${getStatsRollupMarkdownComment({ + docsCount: docsCount ?? 0, + formatBytes, + formatNumber, + incompatible: getTotalPatternIncompatible(results), + indices, + indicesChecked: getTotalPatternIndicesChecked(patternRollup), + sizeInBytes: patternRollup.sizeInBytes, +})} +`; + +export const getDataQualitySummaryMarkdownComment = ({ + formatBytes, + formatNumber, + totalDocsCount, + totalIncompatible, + totalIndices, + totalIndicesChecked, + sizeInBytes, +}: { + formatBytes: (value: number | undefined) => string; + formatNumber: (value: number | undefined) => string; + totalDocsCount: number | undefined; + totalIncompatible: number | undefined; + totalIndices: number | undefined; + totalIndicesChecked: number | undefined; + sizeInBytes: number | undefined; +}): string => + `# ${DATA_QUALITY} + +${getStatsRollupMarkdownComment({ + docsCount: totalDocsCount ?? 0, + formatBytes, + formatNumber, + incompatible: totalIncompatible, + indices: totalIndices, + indicesChecked: totalIndicesChecked, + sizeInBytes, +})} +`; + +export const getErrorsMarkdownTable = ({ + errorSummary, + getMarkdownTableRows, + headerNames, + title, +}: { + errorSummary: ErrorSummary[]; + getMarkdownTableRows: (errorSummary: ErrorSummary[]) => string; + headerNames: string[]; + title: string; +}): string => + errorSummary.length > 0 + ? `## ${escapeNewlines(title)} + +${ERRORS_CALLOUT_SUMMARY} + +${ERRORS_MAY_OCCUR} + +${THE_FOLLOWING_PRIVILEGES_ARE_REQUIRED} +- \`${MONITOR}\` ${OR} \`${MANAGE}\` +- \`${VIEW_INDEX_METADATA}\` +- \`${READ}\` + +${getMarkdownTableHeader(headerNames)} +${getMarkdownTableRows(errorSummary)} +` + : ''; + +export const getErrorsMarkdownTableRows = (errorSummary: ErrorSummary[]): string => + errorSummary + .map( + ({ pattern, indexName, error }) => + `| ${escapeNewlines(pattern)} | ${escapeNewlines( + indexName ?? EMPTY_PLACEHOLDER + )} | ${getCodeFormattedValue(error)} |` + ) + .join('\n'); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_results_rollup/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_results_rollup/index.tsx index eb8cd670d70c5..e2571b5d0a75c 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_results_rollup/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_results_rollup/index.tsx @@ -34,10 +34,6 @@ import type { PatternRollup, TelemetryEvents, } from '../../types'; -import { - getIlmPhase, - getIndexIncompatible, -} from '../../data_quality_details/indices_details/pattern/helpers'; import { getIncompatibleMappingsFields, getIncompatibleValuesFields, @@ -45,7 +41,8 @@ import { } from '../../data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/incompatible_tab/helpers'; import { UseResultsRollupReturnValue } from './types'; import { useIsMounted } from '../use_is_mounted'; -import { getDocsCount, getSizeInBytes } from '../../utils/stats'; +import { getDocsCount, getIndexIncompatible, getSizeInBytes } from '../../utils/stats'; +import { getIlmPhase } from '../../utils/get_ilm_phase'; interface Props { ilmPhases: string[]; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_results_rollup/utils/get_pattern_rollups_with_latest_check_result.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_results_rollup/utils/get_pattern_rollups_with_latest_check_result.ts index 22b7eb6db4d8d..e826730df89cc 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_results_rollup/utils/get_pattern_rollups_with_latest_check_result.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_results_rollup/utils/get_pattern_rollups_with_latest_check_result.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { getIndexDocsCountFromRollup } from '../../../data_quality_summary/summary_actions/check_all/helpers'; -import { getIlmPhase } from '../../../data_quality_details/indices_details/pattern/helpers'; import { getAllIncompatibleMarkdownComments } from '../../../data_quality_details/indices_details/pattern/index_check_flyout/index_properties/index_check_fields/tabs/incompatible_tab/helpers'; import { getSizeInBytes } from '../../../utils/stats'; import type { IlmPhase, PartitionedFieldMetadata, PatternRollup } from '../../../types'; +import { getIndexDocsCountFromRollup } from './stats'; +import { getIlmPhase } from '../../../utils/get_ilm_phase'; export const getPatternRollupsWithLatestCheckResult = ({ error, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_results_rollup/utils/stats.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_results_rollup/utils/stats.test.ts index 7f28c6bcd1727..0d48a794670d5 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_results_rollup/utils/stats.test.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_results_rollup/utils/stats.test.ts @@ -15,6 +15,7 @@ import { import { mockStats } from '../../../mock/stats/mock_stats'; import { DataQualityCheckResult, PatternRollup } from '../../../types'; import { + getIndexDocsCountFromRollup, getIndexId, getTotalDocsCount, getTotalIncompatible, @@ -229,3 +230,28 @@ describe('getIndexId', () => { ); }); }); + +describe('getIndexDocsCountFromRollup', () => { + test('it returns the expected count when the `patternRollup` has `stats`', () => { + expect( + getIndexDocsCountFromRollup({ + indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + patternRollup: mockPacketbeatPatternRollup, + }) + ).toEqual(1628343); + }); + + test('it returns zero when the `patternRollup` `stats` is null', () => { + const patternRollup = { + ...mockPacketbeatPatternRollup, + stats: null, // <-- + }; + + expect( + getIndexDocsCountFromRollup({ + indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + patternRollup, + }) + ).toEqual(0); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_results_rollup/utils/stats.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_results_rollup/utils/stats.ts index c3a44f04471ea..80965c706d9f3 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_results_rollup/utils/stats.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_results_rollup/utils/stats.ts @@ -6,7 +6,11 @@ */ import { DataQualityCheckResult, MeteringStatsIndex, PatternRollup } from '../../../types'; -import { getTotalPatternIncompatible, getTotalPatternIndicesChecked } from '../../../utils/stats'; +import { + getDocsCount, + getTotalPatternIncompatible, + getTotalPatternIndicesChecked, +} from '../../../utils/stats'; export const getTotalPatternSameFamily = ( results: Record | undefined @@ -98,3 +102,18 @@ export const getIndexId = ({ indexName: string; stats: Record | null; }): string | null | undefined => stats && stats[indexName]?.uuid; + +export const getIndexDocsCountFromRollup = ({ + indexName, + patternRollup, +}: { + indexName: string; + patternRollup: PatternRollup; +}): number => { + const stats: Record | null = patternRollup?.stats ?? null; + + return getDocsCount({ + indexName, + stats, + }); +}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/stub/get_check_state/index.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/stub/get_check_state/index.ts index 12f45c192aa25..1c56d25367e3a 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/stub/get_check_state/index.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/stub/get_check_state/index.ts @@ -7,10 +7,6 @@ import { IndicesGetMappingIndexMappingRecord } from '@elastic/elasticsearch/lib/api/types'; -import { - getMappingsProperties, - getSortedPartitionedFieldMetadata, -} from '../../data_quality_details/indices_details/pattern/index_check_flyout/index_properties/helpers'; import { mockMappingsResponse } from '../../mock/mappings_response/mock_mappings_response'; import { UseIndicesCheckCheckState } from '../../hooks/use_indices_check/types'; import { getUnallowedValues } from '../../utils/fetch_unallowed_values'; @@ -18,6 +14,7 @@ import { getUnallowedValueRequestItems } from '../../utils/get_unallowed_value_r import { EcsFlatTyped } from '../../constants'; import { mockUnallowedValuesResponse } from '../../mock/unallowed_values/mock_unallowed_values'; import { UnallowedValueSearchResult } from '../../types'; +import { getMappingsProperties, getSortedPartitionedFieldMetadata } from '../../utils/metadata'; export const getCheckState = ( indexName: string, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/translations.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/translations.ts index 3497aa89d97ee..4b0e698d0afb2 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/translations.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/translations.ts @@ -85,13 +85,6 @@ export const DATA_QUALITY_SUGGESTED_USER_PROMPT = i18n.translate( } ); -export const DATA_QUALITY_TITLE = i18n.translate( - 'securitySolutionPackages.ecsDataQualityDashboard.securitySolutionPackages.ecsDataQualityDashboardTitle', - { - defaultMessage: 'Data quality', - } -); - export const DEFAULT_PANEL_TITLE = i18n.translate( 'securitySolutionPackages.ecsDataQualityDashboard.defaultPanelTitle', { @@ -190,6 +183,13 @@ export const ILM_PHASE: string = i18n.translate( } ); +export const ILM_PHASE_CAPITALIZED = i18n.translate( + 'securitySolutionPackages.ecsDataQualityDashboard.ilmPhaseCapitalized', + { + defaultMessage: 'ILM Phase', + } +); + export const LAST_CHECKED = i18n.translate( 'securitySolutionPackages.ecsDataQualityDashboard.lastCheckedLabel', { @@ -296,3 +296,96 @@ export const DATA_QUALITY_DASHBOARD_CONVERSATION_ID = i18n.translate( defaultMessage: 'Data Quality dashboard', } ); + +export const AN_ERROR_OCCURRED_CHECKING_INDEX = (indexName: string) => + i18n.translate( + 'securitySolutionPackages.ecsDataQualityDashboard.checkAllErrorCheckingIndexMessage', + { + values: { indexName }, + defaultMessage: 'An error occurred checking index {indexName}', + } + ); + +export const DOCS = i18n.translate('securitySolutionPackages.ecsDataQualityDashboard.docs', { + defaultMessage: 'Docs', +}); + +export const INCOMPATIBLE_FIELDS = i18n.translate( + 'securitySolutionPackages.ecsDataQualityDashboard.incompatibleFields', + { + defaultMessage: 'Incompatible fields', + } +); + +export const INDICES = i18n.translate('securitySolutionPackages.ecsDataQualityDashboard.indices', { + defaultMessage: 'Indices', +}); + +export const INDICES_CHECKED = i18n.translate( + 'securitySolutionPackages.ecsDataQualityDashboard.indicesChecked', + { + defaultMessage: 'Indices checked', + } +); + +export const INDEX = i18n.translate('securitySolutionPackages.ecsDataQualityDashboard.index', { + defaultMessage: 'Index', +}); + +export const SIZE = i18n.translate('securitySolutionPackages.ecsDataQualityDashboard.size', { + defaultMessage: 'Size', +}); + +export const RESULT = i18n.translate('securitySolutionPackages.ecsDataQualityDashboard.result', { + defaultMessage: 'Result', +}); + +export const ERRORS_CALLOUT_SUMMARY = i18n.translate( + 'securitySolutionPackages.ecsDataQualityDashboard.errors.errorsCalloutSummary', + { + defaultMessage: 'Some indices were not checked for Data Quality', + } +); + +export const ERRORS_MAY_OCCUR = i18n.translate( + 'securitySolutionPackages.ecsDataQualityDashboard.errors.errorMayOccurLabel', + { + defaultMessage: + "Errors may occur when pattern or index metadata is temporarily unavailable, or because you don't have the privileges required for access", + } +); + +export const MANAGE = i18n.translate( + 'securitySolutionPackages.ecsDataQualityDashboard.errors.manage', + { + defaultMessage: 'manage', + } +); + +export const MONITOR = i18n.translate( + 'securitySolutionPackages.ecsDataQualityDashboard.errors.monitor', + { + defaultMessage: 'monitor', + } +); + +export const OR = i18n.translate('securitySolutionPackages.ecsDataQualityDashboard.errors.or', { + defaultMessage: 'or', +}); + +export const READ = i18n.translate('securitySolutionPackages.ecsDataQualityDashboard.errors.read', { + defaultMessage: 'read', +}); + +export const THE_FOLLOWING_PRIVILEGES_ARE_REQUIRED = i18n.translate( + 'securitySolutionPackages.ecsDataQualityDashboard.errors.theFollowingPrivilegesLabel', + { + defaultMessage: 'The following privileges are required to check an index:', + } +); +export const VIEW_INDEX_METADATA = i18n.translate( + 'securitySolutionPackages.ecsDataQualityDashboard.errors.viewIndexMetadata', + { + defaultMessage: 'view_index_metadata', + } +); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/types.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/types.ts index 916d0f377bf85..08c964d423101 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/types.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/types.ts @@ -276,3 +276,14 @@ export interface TelemetryEvents { reportDataQualityIndexChecked?: ReportDataQualityIndexChecked; reportDataQualityCheckAllCompleted?: ReportDataQualityCheckAllCompleted; } + +export interface IndexSummaryTableItem { + docsCount: number; + incompatible: number | undefined; + indexName: string; + ilmPhase: IlmPhase | undefined; + pattern: string; + patternDocsCount: number; + sizeInBytes: number | undefined; + checkedAt: number | undefined; +} diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/check_index.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/check_index.test.ts index 2b90f67966c77..77538a60c65c1 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/check_index.test.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/check_index.test.ts @@ -9,14 +9,11 @@ import { checkIndex, EMPTY_PARTITIONED_FIELD_METADATA } from './check_index'; import { mockMappingsResponse } from '../mock/mappings_response/mock_mappings_response'; import { mockUnallowedValuesResponse } from '../mock/unallowed_values/mock_unallowed_values'; import { UnallowedValueRequestItem, UnallowedValueSearchResult } from '../types'; -import { - getMappingsProperties, - getSortedPartitionedFieldMetadata, -} from '../data_quality_details/indices_details/pattern/index_check_flyout/index_properties/helpers'; import { IndicesGetMappingIndexMappingRecord } from '@elastic/elasticsearch/lib/api/types'; import { getUnallowedValues } from './fetch_unallowed_values'; import { getUnallowedValueRequestItems } from './get_unallowed_value_request_items'; import { EcsFlatTyped, EMPTY_STAT } from '../constants'; +import { getMappingsProperties, getSortedPartitionedFieldMetadata } from './metadata'; let mockFetchMappings = jest.fn( (_: { abortController: AbortController; patternOrIndexName: string }) => diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/check_index.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/check_index.ts index 76094c97f5667..a577ca15d0ad8 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/check_index.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/check_index.ts @@ -13,11 +13,7 @@ import { import { v4 as uuidv4 } from 'uuid'; import { getUnallowedValueRequestItems } from './get_unallowed_value_request_items'; -import { - getMappingsProperties, - getSortedPartitionedFieldMetadata, -} from '../data_quality_details/indices_details/pattern/index_check_flyout/index_properties/helpers'; -import * as i18n from '../data_quality_summary/summary_actions/check_all/translations'; +import * as i18n from '../translations'; import type { OnCheckCompleted, PartitionedFieldMetadata, @@ -27,6 +23,7 @@ import type { import { fetchMappings } from './fetch_mappings'; import { fetchUnallowedValues, getUnallowedValues } from './fetch_unallowed_values'; import { EcsFlatTyped } from '../constants'; +import { getMappingsProperties, getSortedPartitionedFieldMetadata } from './metadata'; export const EMPTY_PARTITIONED_FIELD_METADATA: PartitionedFieldMetadata = { all: [], diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/get_ilm_phase.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/get_ilm_phase.test.ts new file mode 100644 index 0000000000000..dd92e3700c18a --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/get_ilm_phase.test.ts @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + IlmExplainLifecycleLifecycleExplainManaged, + IlmExplainLifecycleLifecycleExplainUnmanaged, +} from '@elastic/elasticsearch/lib/api/types'; + +import { getIlmPhase } from './get_ilm_phase'; + +const hot: IlmExplainLifecycleLifecycleExplainManaged = { + index: '.ds-packetbeat-8.6.1-2023.02.04-000001', + managed: true, + policy: 'packetbeat', + index_creation_date_millis: 1675536751379, + time_since_index_creation: '3.98d', + lifecycle_date_millis: 1675536751379, + age: '3.98d', + phase: 'hot', + phase_time_millis: 1675536751809, + action: 'rollover', + action_time_millis: 1675536751809, + step: 'check-rollover-ready', + step_time_millis: 1675536751809, + phase_execution: { + policy: 'packetbeat', + version: 1, + modified_date_in_millis: 1675536751205, + }, +}; + +const warm = { + ...hot, + phase: 'warm', +}; +const cold = { + ...hot, + phase: 'cold', +}; +const frozen = { + ...hot, + phase: 'frozen', +}; +const other = { + ...hot, + phase: 'other', // not a valid phase +}; + +const managed: Record = { + hot, + warm, + cold, + frozen, +}; + +const unmanaged: IlmExplainLifecycleLifecycleExplainUnmanaged = { + index: 'michael', + managed: false, +}; + +describe('getIlmPhase', () => { + const isILMAvailable = true; + test('it returns undefined when the `ilmExplainRecord` is undefined', () => { + expect(getIlmPhase(undefined, isILMAvailable)).toBeUndefined(); + }); + + describe('when the `ilmExplainRecord` is a `IlmExplainLifecycleLifecycleExplainManaged` record', () => { + Object.keys(managed).forEach((phase) => + test(`it returns the expected phase when 'phase' is '${phase}'`, () => { + expect(getIlmPhase(managed[phase], isILMAvailable)).toEqual(phase); + }) + ); + + test(`it returns undefined when the 'phase' is unknown`, () => { + expect(getIlmPhase(other, isILMAvailable)).toBeUndefined(); + }); + }); + + describe('when the `ilmExplainRecord` is a `IlmExplainLifecycleLifecycleExplainUnmanaged` record', () => { + test('it returns `unmanaged`', () => { + expect(getIlmPhase(unmanaged, isILMAvailable)).toEqual('unmanaged'); + }); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/get_ilm_phase.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/get_ilm_phase.ts new file mode 100644 index 0000000000000..78e9bfb98f2d6 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/get_ilm_phase.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IlmExplainLifecycleLifecycleExplain } from '@elastic/elasticsearch/lib/api/types'; +import { IlmPhase } from '../types'; + +export const getIlmPhase = ( + ilmExplainRecord: IlmExplainLifecycleLifecycleExplain | undefined, + isILMAvailable: boolean +): IlmPhase | undefined => { + if (ilmExplainRecord == null || !isILMAvailable) { + return undefined; + } + + if ('phase' in ilmExplainRecord) { + const phase = ilmExplainRecord.phase; + + switch (phase) { + case 'hot': + return 'hot'; + case 'warm': + return 'warm'; + case 'cold': + return 'cold'; + case 'frozen': + return 'frozen'; + default: + return undefined; + } + } else { + return 'unmanaged'; + } +}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/get_summary_table_items.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/get_summary_table_items.test.ts new file mode 100644 index 0000000000000..7bfde1d8d7844 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/get_summary_table_items.test.ts @@ -0,0 +1,230 @@ +/* + * 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 { defaultSort } from '../constants'; +import { mockIlmExplain } from '../mock/ilm_explain/mock_ilm_explain'; +import { mockStats } from '../mock/stats/mock_stats'; +import { DataQualityCheckResult } from '../types'; +import { getSummaryTableItems } from './get_summary_table_items'; + +describe('getSummaryTableItems', () => { + const indexNames = [ + '.ds-packetbeat-8.6.1-2023.02.04-000001', + '.ds-packetbeat-8.5.3-2023.02.04-000001', + 'auditbeat-custom-index-1', + ]; + const pattern = 'auditbeat-*'; + const patternDocsCount = 4; + const results: Record = { + 'auditbeat-custom-index-1': { + docsCount: 4, + error: null, + ilmPhase: 'unmanaged', + incompatible: 3, + indexName: 'auditbeat-custom-index-1', + markdownComments: [ + '### auditbeat-custom-index-1\n', + '| Result | Index | Docs | Incompatible fields | ILM Phase |\n|--------|-------|------|---------------------|-----------|\n| ❌ | auditbeat-custom-index-1 | 4 (0.0%) | 3 | `unmanaged` |\n\n', + '### **Incompatible fields** `3` **Custom fields** `4` **ECS compliant fields** `2` **All fields** `9`\n', + "#### 3 incompatible fields, 0 fields with mappings in the same family\n\nFields are incompatible with ECS when index mappings, or the values of the fields in the index, don't conform to the Elastic Common Schema (ECS), version 8.6.1.\n\nIncompatible fields with mappings in the same family have exactly the same search behavior but may have different space usage or performance characteristics.\n\nWhen an incompatible field is not in the same family:\n❌ Detection engine rules referencing these fields may not match them correctly\n❌ Pages may not display some events or fields due to unexpected field mappings or values\n❌ Mappings or field values that don't comply with ECS are not supported\n", + '\n#### Incompatible field mappings - auditbeat-custom-index-1\n\n\n| Field | ECS mapping type (expected) | Index mapping type (actual) | \n|-------|-----------------------------|-----------------------------|\n| host.name | `keyword` | `text` |\n| source.ip | `ip` | `text` |\n\n#### Incompatible field values - auditbeat-custom-index-1\n\n\n| Field | ECS values (expected) | Document values (actual) | \n|-------|-----------------------|--------------------------|\n| event.category | `authentication`, `configuration`, `database`, `driver`, `email`, `file`, `host`, `iam`, `intrusion_detection`, `malware`, `network`, `package`, `process`, `registry`, `session`, `threat`, `vulnerability`, `web` | `an_invalid_category` (2),\n`theory` (1) |\n\n', + ], + pattern: 'auditbeat-*', + sameFamily: 0, + checkedAt: 1706526408000, + }, + }; + const isILMAvailable = true; + + test('it returns the expected summary table items', () => { + expect( + getSummaryTableItems({ + ilmExplain: mockIlmExplain, + indexNames, + isILMAvailable, + pattern, + patternDocsCount, + results, + sortByColumn: defaultSort.sort.field, + sortByDirection: defaultSort.sort.direction, + stats: mockStats, + }) + ).toEqual([ + { + docsCount: 1630289, + ilmPhase: 'hot', + incompatible: undefined, + indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', + pattern: 'auditbeat-*', + patternDocsCount: 4, + sizeInBytes: 733175040, + checkedAt: undefined, + }, + { + docsCount: 1628343, + ilmPhase: 'hot', + incompatible: undefined, + indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + pattern: 'auditbeat-*', + patternDocsCount: 4, + sizeInBytes: 731583142, + checkedAt: undefined, + }, + { + docsCount: 4, + ilmPhase: 'unmanaged', + incompatible: 3, + indexName: 'auditbeat-custom-index-1', + pattern: 'auditbeat-*', + patternDocsCount: 4, + sizeInBytes: 28413, + checkedAt: 1706526408000, + }, + ]); + }); + + test('it returns the expected summary table items when isILMAvailable is false', () => { + expect( + getSummaryTableItems({ + ilmExplain: mockIlmExplain, + indexNames, + isILMAvailable: false, + pattern, + patternDocsCount, + results, + sortByColumn: defaultSort.sort.field, + sortByDirection: defaultSort.sort.direction, + stats: mockStats, + }) + ).toEqual([ + { + docsCount: 1630289, + ilmPhase: undefined, + incompatible: undefined, + indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', + pattern: 'auditbeat-*', + patternDocsCount: 4, + sizeInBytes: 733175040, + checkedAt: undefined, + }, + { + docsCount: 1628343, + ilmPhase: undefined, + incompatible: undefined, + indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + pattern: 'auditbeat-*', + patternDocsCount: 4, + sizeInBytes: 731583142, + checkedAt: undefined, + }, + { + docsCount: 4, + ilmPhase: undefined, + incompatible: 3, + indexName: 'auditbeat-custom-index-1', + pattern: 'auditbeat-*', + patternDocsCount: 4, + sizeInBytes: 28413, + checkedAt: 1706526408000, + }, + ]); + }); + + test('it returns the expected summary table items when `sortByDirection` is ascending', () => { + expect( + getSummaryTableItems({ + ilmExplain: mockIlmExplain, + indexNames, + isILMAvailable, + pattern, + patternDocsCount, + results, + sortByColumn: defaultSort.sort.field, + sortByDirection: 'asc', // <-- ascending + stats: mockStats, + }) + ).toEqual([ + { + docsCount: 4, + ilmPhase: 'unmanaged', + incompatible: 3, + indexName: 'auditbeat-custom-index-1', + pattern: 'auditbeat-*', + patternDocsCount: 4, + sizeInBytes: 28413, + checkedAt: 1706526408000, + }, + { + docsCount: 1628343, + ilmPhase: 'hot', + incompatible: undefined, + indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + pattern: 'auditbeat-*', + patternDocsCount: 4, + sizeInBytes: 731583142, + checkedAt: undefined, + }, + { + docsCount: 1630289, + ilmPhase: 'hot', + incompatible: undefined, + indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', + pattern: 'auditbeat-*', + patternDocsCount: 4, + sizeInBytes: 733175040, + checkedAt: undefined, + }, + ]); + }); + + test('it returns the expected summary table items when data is unavailable', () => { + expect( + getSummaryTableItems({ + ilmExplain: null, // <-- no data + indexNames, + isILMAvailable, + pattern, + patternDocsCount, + results: undefined, // <-- no data + sortByColumn: defaultSort.sort.field, + sortByDirection: defaultSort.sort.direction, + stats: null, // <-- no data + }) + ).toEqual([ + { + docsCount: 0, + ilmPhase: undefined, + incompatible: undefined, + indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001', + pattern: 'auditbeat-*', + patternDocsCount: 4, + sizeInBytes: undefined, + checkedAt: undefined, + }, + { + docsCount: 0, + ilmPhase: undefined, + incompatible: undefined, + indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001', + pattern: 'auditbeat-*', + patternDocsCount: 4, + sizeInBytes: undefined, + checkedAt: undefined, + }, + { + docsCount: 0, + ilmPhase: undefined, + incompatible: undefined, + indexName: 'auditbeat-custom-index-1', + pattern: 'auditbeat-*', + patternDocsCount: 4, + sizeInBytes: undefined, + checkedAt: undefined, + }, + ]); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/get_summary_table_items.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/get_summary_table_items.ts new file mode 100644 index 0000000000000..7e518a739b251 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/get_summary_table_items.ts @@ -0,0 +1,51 @@ +/* + * 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 { IlmExplainLifecycleLifecycleExplain } from '@elastic/elasticsearch/lib/api/types'; +import { orderBy } from 'lodash/fp'; + +import { DataQualityCheckResult, IndexSummaryTableItem, MeteringStatsIndex } from '../types'; +import { getIlmPhase } from './get_ilm_phase'; +import { getDocsCount, getIndexIncompatible, getSizeInBytes } from './stats'; + +export const getSummaryTableItems = ({ + ilmExplain, + indexNames, + isILMAvailable, + pattern, + patternDocsCount, + results, + sortByColumn, + sortByDirection, + stats, +}: { + ilmExplain: Record | null; + indexNames: string[]; + isILMAvailable: boolean; + pattern: string; + patternDocsCount: number; + results: Record | undefined; + sortByColumn: string; + sortByDirection: 'desc' | 'asc'; + stats: Record | null; +}): IndexSummaryTableItem[] => { + const summaryTableItems = indexNames.map((indexName) => ({ + docsCount: getDocsCount({ stats, indexName }), + incompatible: getIndexIncompatible({ indexName, results }), + indexName, + ilmPhase: + isILMAvailable && ilmExplain != null + ? getIlmPhase(ilmExplain[indexName], isILMAvailable) + : undefined, + pattern, + patternDocsCount, + sizeInBytes: getSizeInBytes({ stats, indexName }), + checkedAt: results?.[indexName]?.checkedAt, + })); + + return orderBy([sortByColumn], [sortByDirection], summaryTableItems); +}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/markdown.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/markdown.test.ts new file mode 100644 index 0000000000000..a8bbbc0cd5c60 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/markdown.test.ts @@ -0,0 +1,208 @@ +/* + * 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 numeral from '@elastic/numeral'; + +import { EMPTY_STAT } from '../constants'; +import { + getCodeFormattedValue, + getHeaderSeparator, + getMarkdownTableHeader, + getResultEmoji, + getStatsRollupMarkdownComment, + getSummaryTableMarkdownHeader, + getSummaryTableMarkdownRow, +} from './markdown'; + +const defaultBytesFormat = '0,0.[0]b'; +const formatBytes = (value: number | undefined) => + value != null ? numeral(value).format(defaultBytesFormat) : EMPTY_STAT; + +const defaultNumberFormat = '0,0.[000]'; +const formatNumber = (value: number | undefined) => + value != null ? numeral(value).format(defaultNumberFormat) : EMPTY_STAT; + +describe('getHeaderSeparator', () => { + test('it returns a sequence of dashes equal to the length of the header, plus two additional dashes to pad each end of the cntent', () => { + const content = '0123456789'; // content.length === 10 + const expected = '------------'; // expected.length === 12 + + expect(getHeaderSeparator(content)).toEqual(expected); + }); +}); + +describe('getCodeFormattedValue', () => { + test('it returns the expected placeholder when `value` is undefined', () => { + expect(getCodeFormattedValue(undefined)).toEqual('`--`'); + }); + + test('it returns the content formatted as markdown code', () => { + const value = 'foozle'; + + expect(getCodeFormattedValue(value)).toEqual('`foozle`'); + }); + + test('it escapes content such that `value` may be included in a markdown table cell', () => { + const value = + '|\nthere were newlines and column separators in the beginning, middle,\n|and end|\n'; + + expect(getCodeFormattedValue(value)).toEqual( + '`\\| there were newlines and column separators in the beginning, middle, \\|and end\\| `' + ); + }); +}); + +describe('getStatsRollupMarkdownComment', () => { + test('it returns the expected comment', () => { + expect( + getStatsRollupMarkdownComment({ + docsCount: 57410, + formatBytes, + formatNumber, + incompatible: 3, + indices: 25, + indicesChecked: 1, + sizeInBytes: 28413, + }) + ).toEqual( + '| Incompatible fields | Indices checked | Indices | Size | Docs |\n|---------------------|-----------------|---------|------|------|\n| 3 | 1 | 25 | 27.7KB | 57,410 |\n' + ); + }); + + test('it returns the expected comment when optional values are undefined', () => { + expect( + getStatsRollupMarkdownComment({ + docsCount: 0, + formatBytes, + formatNumber, + incompatible: undefined, + indices: undefined, + indicesChecked: undefined, + sizeInBytes: undefined, + }) + ).toEqual( + '| Incompatible fields | Indices checked | Indices | Docs |\n|---------------------|-----------------|---------|------|\n| -- | -- | -- | 0 |\n' + ); + }); +}); + +describe('getSummaryTableMarkdownHeader', () => { + test('it returns the expected header', () => { + const isILMAvailable = true; + expect(getSummaryTableMarkdownHeader(isILMAvailable)).toEqual( + '| Result | Index | Docs | Incompatible fields | ILM Phase | Size |\n|--------|-------|------|---------------------|-----------|------|' + ); + }); + + test('it returns the expected header when isILMAvailable is false', () => { + const isILMAvailable = false; + expect(getSummaryTableMarkdownHeader(isILMAvailable)).toEqual( + '| Result | Index | Docs | Incompatible fields |\n|--------|-------|------|---------------------|' + ); + }); + + test('it returns the expected header when displayDocSize is false', () => { + const isILMAvailable = false; + expect(getSummaryTableMarkdownHeader(isILMAvailable)).toEqual( + '| Result | Index | Docs | Incompatible fields |\n|--------|-------|------|---------------------|' + ); + }); +}); + +describe('getSummaryTableMarkdownRow', () => { + test('it returns the expected row when all values are provided', () => { + expect( + getSummaryTableMarkdownRow({ + docsCount: 4, + formatBytes, + formatNumber, + incompatible: 3, + ilmPhase: 'unmanaged', + isILMAvailable: true, + indexName: 'auditbeat-custom-index-1', + patternDocsCount: 57410, + sizeInBytes: 28413, + }) + ).toEqual('| ❌ | auditbeat-custom-index-1 | 4 (0.0%) | 3 | `unmanaged` | 27.7KB |\n'); + }); + + test('it returns the expected row when optional values are NOT provided', () => { + expect( + getSummaryTableMarkdownRow({ + docsCount: 4, + formatBytes, + formatNumber, + incompatible: undefined, // <-- + ilmPhase: undefined, // <-- + indexName: 'auditbeat-custom-index-1', + isILMAvailable: true, + patternDocsCount: 57410, + sizeInBytes: 28413, + }) + ).toEqual('| -- | auditbeat-custom-index-1 | 4 (0.0%) | -- | -- | 27.7KB |\n'); + }); + + test('it returns the expected row when isILMAvailable is false', () => { + expect( + getSummaryTableMarkdownRow({ + docsCount: 4, + formatBytes, + formatNumber, + incompatible: undefined, // <-- + ilmPhase: undefined, // <-- + indexName: 'auditbeat-custom-index-1', + isILMAvailable: false, + patternDocsCount: 57410, + sizeInBytes: undefined, + }) + ).toEqual('| -- | auditbeat-custom-index-1 | 4 (0.0%) | -- |\n'); + }); + + test('it returns the expected row when sizeInBytes is undefined', () => { + expect( + getSummaryTableMarkdownRow({ + docsCount: 4, + formatBytes, + formatNumber, + incompatible: undefined, // <-- + ilmPhase: undefined, // <-- + indexName: 'auditbeat-custom-index-1', + isILMAvailable: false, + patternDocsCount: 57410, + sizeInBytes: undefined, + }) + ).toEqual('| -- | auditbeat-custom-index-1 | 4 (0.0%) | -- |\n'); + }); +}); + +describe('getResultEmoji', () => { + test('it returns the expected placeholder when `incompatible` is undefined', () => { + expect(getResultEmoji(undefined)).toEqual('--'); + }); + + test('it returns a ✅ when the incompatible count is zero', () => { + expect(getResultEmoji(0)).toEqual('✅'); + }); + + test('it returns a ❌ when the incompatible count is NOT zero', () => { + expect(getResultEmoji(1)).toEqual('❌'); + }); +}); + +describe('getMarkdownTableHeader', () => { + const headerNames = [ + '|\nthere were newlines and column separators in the beginning, middle,\n|and end|\n', + 'A second column', + 'A third column', + ]; + + test('it returns the expected table header', () => { + expect(getMarkdownTableHeader(headerNames)).toEqual( + '\n| \\| there were newlines and column separators in the beginning, middle, \\|and end\\| | A second column | A third column | \n|----------------------------------------------------------------------------------|-----------------|----------------|' + ); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/markdown.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/markdown.ts new file mode 100644 index 0000000000000..e8118df379c82 --- /dev/null +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/markdown.ts @@ -0,0 +1,128 @@ +/* + * 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 { EMPTY_PLACEHOLDER, EMPTY_STAT } from '../constants'; +import { + DOCS, + ILM_PHASE, + ILM_PHASE_CAPITALIZED, + INCOMPATIBLE_FIELDS, + INDEX, + INDICES, + INDICES_CHECKED, + RESULT, + SIZE, +} from '../translations'; +import { IlmPhase } from '../types'; +import { getDocsCountPercent } from './stats'; + +export const escapeNewlines = (content: string | undefined): string | undefined => + content != null ? content.replaceAll('\n', ' ').replaceAll('|', '\\|') : content; + +export const getCodeFormattedValue = (value: string | undefined) => + `\`${escapeNewlines(value ?? EMPTY_PLACEHOLDER)}\``; + +export const getHeaderSeparator = (headerText: string): string => '-'.repeat(headerText.length + 2); // 2 extra, for the spaces on both sides of the column name + +export const getStatsRollupMarkdownComment = ({ + docsCount, + formatBytes, + formatNumber, + incompatible, + indices, + indicesChecked, + sizeInBytes, +}: { + docsCount: number; + formatBytes: (value: number | undefined) => string; + formatNumber: (value: number | undefined) => string; + incompatible: number | undefined; + indices: number | undefined; + indicesChecked: number | undefined; + sizeInBytes: number | undefined; +}): string => + Number.isInteger(sizeInBytes) + ? `| ${INCOMPATIBLE_FIELDS} | ${INDICES_CHECKED} | ${INDICES} | ${SIZE} | ${DOCS} | +|${getHeaderSeparator(INCOMPATIBLE_FIELDS)}|${getHeaderSeparator( + INDICES_CHECKED + )}|${getHeaderSeparator(INDICES)}|${getHeaderSeparator(SIZE)}|${getHeaderSeparator(DOCS)}| +| ${incompatible ?? EMPTY_STAT} | ${indicesChecked ?? EMPTY_STAT} | ${ + indices ?? EMPTY_STAT + } | ${formatBytes(sizeInBytes)} | ${formatNumber(docsCount)} | +` + : `| ${INCOMPATIBLE_FIELDS} | ${INDICES_CHECKED} | ${INDICES} | ${DOCS} | +|${getHeaderSeparator(INCOMPATIBLE_FIELDS)}|${getHeaderSeparator( + INDICES_CHECKED + )}|${getHeaderSeparator(INDICES)}|${getHeaderSeparator(DOCS)}| +| ${incompatible ?? EMPTY_STAT} | ${indicesChecked ?? EMPTY_STAT} | ${ + indices ?? EMPTY_STAT + } | ${formatNumber(docsCount)} | +`; + +export const getSummaryTableMarkdownHeader = (includeDocSize: boolean): string => + includeDocSize + ? `| ${RESULT} | ${INDEX} | ${DOCS} | ${INCOMPATIBLE_FIELDS} | ${ILM_PHASE_CAPITALIZED} | ${SIZE} | +|${getHeaderSeparator(RESULT)}|${getHeaderSeparator(INDEX)}|${getHeaderSeparator( + DOCS + )}|${getHeaderSeparator(INCOMPATIBLE_FIELDS)}|${getHeaderSeparator( + ILM_PHASE + )}|${getHeaderSeparator(SIZE)}|` + : `| ${RESULT} | ${INDEX} | ${DOCS} | ${INCOMPATIBLE_FIELDS} | +|${getHeaderSeparator(RESULT)}|${getHeaderSeparator(INDEX)}|${getHeaderSeparator( + DOCS + )}|${getHeaderSeparator(INCOMPATIBLE_FIELDS)}|`; + +export const getResultEmoji = (incompatible: number | undefined): string => { + if (incompatible == null) { + return EMPTY_PLACEHOLDER; + } else { + return incompatible === 0 ? '✅' : '❌'; + } +}; + +export const getSummaryTableMarkdownRow = ({ + docsCount, + formatBytes, + formatNumber, + ilmPhase, + incompatible, + indexName, + isILMAvailable, + patternDocsCount, + sizeInBytes, +}: { + docsCount: number; + formatBytes: (value: number | undefined) => string; + formatNumber: (value: number | undefined) => string; + ilmPhase: IlmPhase | undefined; + incompatible: number | undefined; + indexName: string; + isILMAvailable: boolean; + patternDocsCount: number; + sizeInBytes: number | undefined; +}): string => + isILMAvailable && Number.isInteger(sizeInBytes) + ? `| ${getResultEmoji(incompatible)} | ${escapeNewlines(indexName)} | ${formatNumber( + docsCount + )} (${getDocsCountPercent({ + docsCount, + patternDocsCount, + })}) | ${incompatible ?? EMPTY_PLACEHOLDER} | ${ + ilmPhase != null ? getCodeFormattedValue(ilmPhase) : EMPTY_PLACEHOLDER + } | ${formatBytes(sizeInBytes)} | +` + : `| ${getResultEmoji(incompatible)} | ${escapeNewlines(indexName)} | ${formatNumber( + docsCount + )} (${getDocsCountPercent({ + docsCount, + patternDocsCount, + })}) | ${incompatible ?? EMPTY_PLACEHOLDER} | +`; + +export const getMarkdownTableHeader = (headerNames: string[]) => ` +| ${headerNames.map((name) => `${escapeNewlines(name)} | `).join('')} +|${headerNames.map((name) => `${getHeaderSeparator(name)}|`).join('')}`; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/utils/metadata.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/metadata.test.ts similarity index 66% rename from x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/utils/metadata.test.ts rename to x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/metadata.test.ts index d59e4821ed1c8..b85f4a7516dbb 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/utils/metadata.test.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/metadata.test.ts @@ -6,21 +6,19 @@ */ import { omit } from 'lodash/fp'; -import { - EnrichedFieldMetadata, - PartitionedFieldMetadata, - UnallowedValueCount, -} from '../../../../../../types'; -import { mockMappingsProperties } from '../../../../../../mock/mappings_properties/mock_mappings_properties'; +import { EnrichedFieldMetadata, PartitionedFieldMetadata, UnallowedValueCount } from '../types'; +import { mockMappingsProperties } from '../mock/mappings_properties/mock_mappings_properties'; import { FieldType, getEnrichedFieldMetadata, getFieldTypes, + getMappingsProperties, getMissingTimestampFieldMetadata, getPartitionedFieldMetadata, + getSortedPartitionedFieldMetadata, isMappingCompatible, } from './metadata'; -import { EcsFlatTyped } from '../../../../../../constants'; +import { EcsFlatTyped } from '../constants'; import { hostNameWithTextMapping, hostNameKeyword, @@ -31,7 +29,8 @@ import { sourcePort, timestamp, eventCategoryWithUnallowedValues, -} from '../../../../../../mock/enriched_field_metadata/mock_enriched_field_metadata'; +} from '../mock/enriched_field_metadata/mock_enriched_field_metadata'; +import { mockIndicesGetMappingIndexMappingRecords } from '../mock/indices_get_mapping_index_mapping_record/mock_indices_get_mapping_index_mapping_record'; describe('getFieldTypes', () => { const expected = [ @@ -400,3 +399,239 @@ describe('getPartitionedFieldMetadata', () => { expect(getPartitionedFieldMetadata(enrichedFieldMetadata)).toEqual(expected); }); }); + +describe('getSortedPartitionedFieldMetadata', () => { + test('it returns null when mappings are loading', () => { + expect( + getSortedPartitionedFieldMetadata({ + ecsMetadata: EcsFlatTyped, + loadingMappings: true, // <-- + mappingsProperties: mockMappingsProperties, + unallowedValues: {}, + }) + ).toBeNull(); + }); + + test('it returns null when `unallowedValues` is null', () => { + expect( + getSortedPartitionedFieldMetadata({ + ecsMetadata: EcsFlatTyped, + loadingMappings: false, + mappingsProperties: mockMappingsProperties, + unallowedValues: null, // <-- + }) + ).toBeNull(); + }); + + describe('when `mappingsProperties` is unknown', () => { + const incompatibleFieldMetadata = { + ...EcsFlatTyped['@timestamp'], + hasEcsMetadata: true, + indexFieldName: '@timestamp', + indexFieldType: '-', + indexInvalidValues: [], + isEcsCompliant: false, + isInSameFamily: false, + }; + const expected = { + all: [incompatibleFieldMetadata], + custom: [], + ecsCompliant: [], + incompatible: [incompatibleFieldMetadata], + sameFamily: [], + }; + + test('it returns a `PartitionedFieldMetadata` with an `incompatible` `@timestamp` when `mappingsProperties` is undefined', () => { + expect( + getSortedPartitionedFieldMetadata({ + ecsMetadata: EcsFlatTyped, + loadingMappings: false, + mappingsProperties: undefined, // <-- + unallowedValues: {}, + }) + ).toEqual(expected); + }); + + test('it returns a `PartitionedFieldMetadata` with an `incompatible` `@timestamp` when `mappingsProperties` is null', () => { + expect( + getSortedPartitionedFieldMetadata({ + ecsMetadata: EcsFlatTyped, + loadingMappings: false, + mappingsProperties: null, // <-- + unallowedValues: {}, + }) + ).toEqual(expected); + }); + }); + + test('it returns the expected sorted field metadata', () => { + const unallowedValues = { + 'event.category': [ + { + count: 2, + fieldName: 'an_invalid_category', + }, + { + count: 1, + fieldName: 'theory', + }, + ], + 'event.kind': [], + 'event.outcome': [], + 'event.type': [], + }; + + expect( + getSortedPartitionedFieldMetadata({ + ecsMetadata: EcsFlatTyped, + loadingMappings: false, + mappingsProperties: mockMappingsProperties, + unallowedValues, + }) + ).toMatchObject({ + all: expect.arrayContaining([ + expect.objectContaining({ + name: expect.any(String), + flat_name: expect.any(String), + dashed_name: expect.any(String), + description: expect.any(String), + hasEcsMetadata: true, + isEcsCompliant: expect.any(Boolean), + isInSameFamily: expect.any(Boolean), + }), + ]), + ecsCompliant: expect.arrayContaining([ + expect.objectContaining({ + name: expect.any(String), + flat_name: expect.any(String), + dashed_name: expect.any(String), + description: expect.any(String), + hasEcsMetadata: true, + isEcsCompliant: true, + isInSameFamily: false, + }), + ]), + custom: expect.arrayContaining([ + expect.objectContaining({ + indexFieldName: expect.any(String), + indexFieldType: expect.any(String), + indexInvalidValues: expect.any(Array), + hasEcsMetadata: expect.any(Boolean), + isEcsCompliant: expect.any(Boolean), + isInSameFamily: expect.any(Boolean), + }), + ]), + incompatible: expect.arrayContaining([ + expect.objectContaining({ + name: expect.any(String), + flat_name: expect.any(String), + dashed_name: expect.any(String), + description: expect.any(String), + hasEcsMetadata: expect.any(Boolean), + isEcsCompliant: false, + isInSameFamily: false, + }), + ]), + sameFamily: [], + }); + }); +}); + +describe('getMappingsProperties', () => { + test('it returns the expected mapping properties', () => { + expect( + getMappingsProperties({ + indexes: mockIndicesGetMappingIndexMappingRecords, + indexName: 'auditbeat-custom-index-1', + }) + ).toEqual({ + '@timestamp': { + type: 'date', + }, + event: { + properties: { + category: { + ignore_above: 1024, + type: 'keyword', + }, + }, + }, + host: { + properties: { + name: { + fields: { + keyword: { + ignore_above: 256, + type: 'keyword', + }, + }, + type: 'text', + }, + }, + }, + some: { + properties: { + field: { + fields: { + keyword: { + ignore_above: 256, + type: 'keyword', + }, + }, + type: 'text', + }, + }, + }, + source: { + properties: { + ip: { + fields: { + keyword: { + ignore_above: 256, + type: 'keyword', + }, + }, + type: 'text', + }, + port: { + type: 'long', + }, + }, + }, + }); + }); + + test('it returns null when `indexes` is null', () => { + expect( + getMappingsProperties({ + indexes: null, // <-- + indexName: 'auditbeat-custom-index-1', + }) + ).toBeNull(); + }); + + test('it returns null when `indexName` does not exist in `indexes`', () => { + expect( + getMappingsProperties({ + indexes: mockIndicesGetMappingIndexMappingRecords, + indexName: 'does-not-exist', // <-- + }) + ).toBeNull(); + }); + + test('it returns null when `properties` does not exist in the mappings', () => { + const missingProperties = { + ...mockIndicesGetMappingIndexMappingRecords, + foozle: { + mappings: {}, // <-- does not have a `properties` + }, + }; + + expect( + getMappingsProperties({ + indexes: missingProperties, + indexName: 'foozle', + }) + ).toBeNull(); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/utils/metadata.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/metadata.ts similarity index 68% rename from x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/utils/metadata.ts rename to x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/metadata.ts index 87adf1e2314e1..c2fb750e4f0a8 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/utils/metadata.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/metadata.ts @@ -5,16 +5,20 @@ * 2.0. */ -import { has } from 'lodash/fp'; +import { + IndicesGetMappingIndexMappingRecord, + MappingProperty, +} from '@elastic/elasticsearch/lib/api/types'; +import { has, sortBy } from 'lodash/fp'; -import { EcsFlatTyped } from '../../../../../../constants'; +import { EMPTY_METADATA, EcsFlatTyped } from '../constants'; import { EcsBasedFieldMetadata, EnrichedFieldMetadata, PartitionedFieldMetadata, UnallowedValueCount, -} from '../../../../../../types'; -import { getIsInSameFamily } from './get_is_in_same_family'; +} from '../types'; +import { getIsInSameFamily } from '../data_quality_details/indices_details/pattern/index_check_flyout/index_properties/utils/get_is_in_same_family'; export const getPartitionedFieldMetadata = ( enrichedFieldMetadata: EnrichedFieldMetadata[] @@ -156,6 +160,49 @@ export const getEnrichedFieldMetadata = ({ } }; +export const getSortedPartitionedFieldMetadata = ({ + ecsMetadata, + loadingMappings, + mappingsProperties, + unallowedValues, +}: { + ecsMetadata: EcsFlatTyped; + loadingMappings: boolean; + mappingsProperties: Record | null | undefined; + unallowedValues: Record | null; +}): PartitionedFieldMetadata | null => { + if (loadingMappings || unallowedValues == null) { + return null; + } + + // this covers scenario when we try to check an empty index + // or index without required @timestamp field in the mapping + // + // we create an artifical incompatible timestamp field metadata + // so that we can signal to user that the incompatibility is due to missing timestamp + if (mappingsProperties == null) { + const missingTimestampFieldMetadata = getMissingTimestampFieldMetadata(); + return { + ...EMPTY_METADATA, + all: [missingTimestampFieldMetadata], + incompatible: [missingTimestampFieldMetadata], + }; + } + + const fieldTypes = getFieldTypes(mappingsProperties); + + const enrichedFieldMetadata = sortBy( + 'indexFieldName', + fieldTypes.map((fieldMetadata) => + getEnrichedFieldMetadata({ ecsMetadata, fieldMetadata, unallowedValues }) + ) + ); + + const partitionedFieldMetadata = getPartitionedFieldMetadata(enrichedFieldMetadata); + + return partitionedFieldMetadata; +}; + export const getMissingTimestampFieldMetadata = (): EcsBasedFieldMetadata => ({ ...EcsFlatTyped['@timestamp'], hasEcsMetadata: true, @@ -165,3 +212,17 @@ export const getMissingTimestampFieldMetadata = (): EcsBasedFieldMetadata => ({ isEcsCompliant: false, isInSameFamily: false, // `date` is not a member of any families }); + +export const getMappingsProperties = ({ + indexes, + indexName, +}: { + indexes: Record | null; + indexName: string; +}): Record | null => { + if (indexes != null && indexes[indexName] != null) { + return indexes[indexName].mappings.properties ?? null; + } + + return null; +}; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/stats.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/stats.test.ts index ad91466634ea7..fd48ba39073fe 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/stats.test.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/stats.test.ts @@ -15,6 +15,7 @@ import { mockStatsAuditbeatIndex } from '../mock/stats/mock_stats_packetbeat_ind import { DataQualityCheckResult } from '../types'; import { getDocsCount, + getDocsCountPercent, getSizeInBytes, getTotalPatternIncompatible, getTotalPatternIndicesChecked, @@ -250,3 +251,34 @@ describe('getTotalPatternIncompatible', () => { expect(getTotalPatternIncompatible(undefined)).toBeUndefined(); }); }); + +describe('getDocsCountPercent', () => { + test('it returns an empty string when `patternDocsCount` is zero', () => { + expect( + getDocsCountPercent({ + docsCount: 0, + patternDocsCount: 0, + }) + ).toEqual(''); + }); + + test('it returns the expected format when when `patternDocsCount` is non-zero, and `locales` is undefined', () => { + expect( + getDocsCountPercent({ + docsCount: 2904, + locales: undefined, + patternDocsCount: 57410, + }) + ).toEqual('5.1%'); + }); + + test('it returns the expected format when when `patternDocsCount` is non-zero, and `locales` is provided', () => { + expect( + getDocsCountPercent({ + docsCount: 2904, + locales: 'en-US', + patternDocsCount: 57410, + }) + ).toEqual('5.1%'); + }); +}); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/stats.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/stats.ts index b8f60be24a87c..a59a43faa18db 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/stats.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/utils/stats.ts @@ -7,6 +7,20 @@ import { DataQualityCheckResult, MeteringStatsIndex, PatternRollup } from '../types'; +export const getIndexIncompatible = ({ + indexName, + results, +}: { + indexName: string; + results: Record | undefined; +}): number | undefined => { + if (results == null || results[indexName] == null) { + return undefined; + } + + return results[indexName].incompatible; +}; + export const getSizeInBytes = ({ indexName, stats, @@ -45,3 +59,20 @@ export const getTotalPatternIncompatible = ( return allResults.reduce((acc, { incompatible }) => acc + (incompatible ?? 0), 0); }; + +export const getDocsCountPercent = ({ + docsCount, + locales, + patternDocsCount, +}: { + docsCount: number; + locales?: string | string[]; + patternDocsCount: number; +}): string => + patternDocsCount !== 0 + ? Number(docsCount / patternDocsCount).toLocaleString(locales, { + style: 'percent', + maximumFractionDigits: 1, + minimumFractionDigits: 1, + }) + : ''; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/index.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/index.ts index 96288f2bfec6c..245fdbf7a75d4 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/index.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/index.ts @@ -20,4 +20,8 @@ export { DATA_QUALITY_DASHBOARD_CONVERSATION_ID, } from './impl/data_quality_panel/translations'; -export { ECS_REFERENCE_URL } from './impl/data_quality_panel/data_quality_details/indices_details/pattern/index_check_flyout/index_properties/markdown/helpers'; +export { + ECS_REFERENCE_URL, + ECS_FIELD_REFERENCE_URL, + MAPPING_URL, +} from './impl/data_quality_panel/constants'; diff --git a/x-pack/packages/security-solution/features/src/security/kibana_sub_features.ts b/x-pack/packages/security-solution/features/src/security/kibana_sub_features.ts index 24c8d0a57e772..fe0354b34a558 100644 --- a/x-pack/packages/security-solution/features/src/security/kibana_sub_features.ts +++ b/x-pack/packages/security-solution/features/src/security/kibana_sub_features.ts @@ -673,11 +673,13 @@ export const getSecuritySubFeaturesMap = ({ [SecuritySubFeatureId.processOperations, processOperationsSubFeature], [SecuritySubFeatureId.fileOperations, fileOperationsSubFeature], [SecuritySubFeatureId.executeAction, executeActionSubFeature], + [SecuritySubFeatureId.scanAction, scanActionSubFeature], ]; - if (experimentalFeatures.responseActionScanEnabled) { - securitySubFeaturesList.push([SecuritySubFeatureId.scanAction, scanActionSubFeature]); - } + // Use the following code to add feature based on feature flag + // if (experimentalFeatures.featureFlagName) { + // securitySubFeaturesList.push([SecuritySubFeatureId.featureId, featureSubFeature]); + // } const securitySubFeaturesMap = new Map( securitySubFeaturesList diff --git a/x-pack/packages/security/plugin_types_public/index.ts b/x-pack/packages/security/plugin_types_public/index.ts index 0b326ce2ee664..a2a6f4ea6a3ee 100644 --- a/x-pack/packages/security/plugin_types_public/index.ts +++ b/x-pack/packages/security/plugin_types_public/index.ts @@ -17,3 +17,5 @@ export type { UserProfileAPIClient, } from './src/user_profile'; export type { RolePutPayload, RolesAPIClient } from './src/roles'; +export { PrivilegesAPIClientPublicContract } from './src/privileges'; +export type { PrivilegesAPIClientGetAllArgs } from './src/privileges'; diff --git a/x-pack/packages/security/plugin_types_public/src/authorization/authorization_service.ts b/x-pack/packages/security/plugin_types_public/src/authorization/authorization_service.ts index 5ad462f8c2aa1..f04acf8020b24 100644 --- a/x-pack/packages/security/plugin_types_public/src/authorization/authorization_service.ts +++ b/x-pack/packages/security/plugin_types_public/src/authorization/authorization_service.ts @@ -6,6 +6,7 @@ */ import type { RolesAPIClient } from '../roles'; +import type { PrivilegesAPIClientPublicContract } from '../privileges'; export interface AuthorizationServiceSetup { /** @@ -17,6 +18,11 @@ export interface AuthorizationServiceSetup { * A set of methods to work with Kibana user roles. */ roles: RolesAPIClient; + + /** + * A set of methods to work with Kibana role privileges + */ + privileges: PrivilegesAPIClientPublicContract; } /** diff --git a/x-pack/packages/security/plugin_types_public/src/privileges/index.ts b/x-pack/packages/security/plugin_types_public/src/privileges/index.ts new file mode 100644 index 0000000000000..b8d111a0c79fe --- /dev/null +++ b/x-pack/packages/security/plugin_types_public/src/privileges/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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { PrivilegesAPIClientPublicContract } from './privileges_api_client'; +export type { PrivilegesAPIClientGetAllArgs } from './privileges_api_client'; diff --git a/x-pack/packages/security/plugin_types_public/src/privileges/privileges_api_client.ts b/x-pack/packages/security/plugin_types_public/src/privileges/privileges_api_client.ts new file mode 100644 index 0000000000000..e3a97398db7a3 --- /dev/null +++ b/x-pack/packages/security/plugin_types_public/src/privileges/privileges_api_client.ts @@ -0,0 +1,21 @@ +/* + * 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 { RawKibanaPrivileges } from '@kbn/security-authorization-core'; + +export interface PrivilegesAPIClientGetAllArgs { + includeActions: boolean; + /* + * respectLicenseLevel is an internal optional parameter solely for getting all sub-feature + * privileges to use in the UI. It is not meant for any other use. + */ + respectLicenseLevel: boolean; +} +// TODO: Eyo include the proper return types for contract +export abstract class PrivilegesAPIClientPublicContract { + abstract getAll(args: PrivilegesAPIClientGetAllArgs): Promise; +} diff --git a/x-pack/packages/security/plugin_types_public/tsconfig.json b/x-pack/packages/security/plugin_types_public/tsconfig.json index 6779851e86367..5c97e25656ecf 100644 --- a/x-pack/packages/security/plugin_types_public/tsconfig.json +++ b/x-pack/packages/security/plugin_types_public/tsconfig.json @@ -14,5 +14,6 @@ "@kbn/core-user-profile-common", "@kbn/security-plugin-types-common", "@kbn/core-security-common", + "@kbn/security-authorization-core" ] } diff --git a/x-pack/packages/security/ui_components/README.md b/x-pack/packages/security/ui_components/README.md new file mode 100644 index 0000000000000..dd5ee7d160285 --- /dev/null +++ b/x-pack/packages/security/ui_components/README.md @@ -0,0 +1,3 @@ +# @kbn/security-ui-components + +Contains stateless components for RBAC administration within Kibana. diff --git a/x-pack/packages/security/ui_components/index.ts b/x-pack/packages/security/ui_components/index.ts new file mode 100644 index 0000000000000..3730109d9c0f8 --- /dev/null +++ b/x-pack/packages/security/ui_components/index.ts @@ -0,0 +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. + */ + +export { + FeatureTable as KibanaPrivilegeTable, + FeatureTableCell, +} from './src/kibana_privilege_table'; +export { PrivilegeFormCalculator } from './src/privilege_form_calculator'; +export * as constants from './src/constants'; diff --git a/x-pack/packages/security/ui_components/jest.config.js b/x-pack/packages/security/ui_components/jest.config.js new file mode 100644 index 0000000000000..12c8dfc44691b --- /dev/null +++ b/x-pack/packages/security/ui_components/jest.config.js @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +module.exports = { + coverageDirectory: '/target/kibana-coverage/jest/x-pack/packages/security/ui_components', + coverageReporters: ['text', 'html'], + collectCoverageFrom: ['/x-pack/packages/security/ui_components/**/*.{ts,tsx}'], + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/x-pack/packages/security/ui_components'], +}; diff --git a/x-pack/packages/security/ui_components/kibana.jsonc b/x-pack/packages/security/ui_components/kibana.jsonc new file mode 100644 index 0000000000000..1aad2d80ed7f7 --- /dev/null +++ b/x-pack/packages/security/ui_components/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/security-ui-components", + "owner": "@elastic/kibana-security" +} diff --git a/x-pack/packages/security/ui_components/package.json b/x-pack/packages/security/ui_components/package.json new file mode 100644 index 0000000000000..59bf7383b958e --- /dev/null +++ b/x-pack/packages/security/ui_components/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/security-ui-components", + "private": true, + "version": "1.0.0", + "license": "Elastic License 2.0" +} diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/constants.ts b/x-pack/packages/security/ui_components/src/constants.ts similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/constants.ts rename to x-pack/packages/security/ui_components/src/constants.ts diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/__fixtures__/index.ts b/x-pack/packages/security/ui_components/src/kibana_privilege_table/__fixtures__/index.ts similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/__fixtures__/index.ts rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/__fixtures__/index.ts diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/change_all_privileges.scss b/x-pack/packages/security/ui_components/src/kibana_privilege_table/change_all_privileges.scss similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/change_all_privileges.scss rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/change_all_privileges.scss diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/change_all_privileges.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/change_all_privileges.tsx similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/change_all_privileges.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/change_all_privileges.tsx diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell/feature_table_cell.scss b/x-pack/packages/security/ui_components/src/kibana_privilege_table/components/feature_table_cell.scss similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell/feature_table_cell.scss rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/components/feature_table_cell.scss diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell/feature_table_cell.test.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/components/feature_table_cell.test.tsx similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell/feature_table_cell.test.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/components/feature_table_cell.test.tsx diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell/feature_table_cell.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/components/feature_table_cell.tsx similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell/feature_table_cell.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/components/feature_table_cell.tsx diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell/index.ts b/x-pack/packages/security/ui_components/src/kibana_privilege_table/components/index.ts similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table_cell/index.ts rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/components/index.ts diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.scss b/x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.scss similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.scss rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.scss diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.test.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.test.tsx similarity index 99% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.test.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.test.tsx index 5a43e7931d474..83a0da2e26815 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.test.tsx +++ b/x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.test.tsx @@ -18,7 +18,7 @@ import { findTestSubject, mountWithIntl } from '@kbn/test-jest-helpers'; import { getDisplayedFeaturePrivileges } from './__fixtures__'; import { FeatureTable } from './feature_table'; -import type { Role } from '../../../../../../../common'; +import type { Role } from '@kbn/security-plugin-types-common'; import { PrivilegeFormCalculator } from '../privilege_form_calculator'; const createRole = (kibana: Role['kibana'] = []): Role => { diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.tsx similarity index 99% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.tsx index 6b4e7af240eb5..4b0d520dee661 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.tsx +++ b/x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table.tsx @@ -35,7 +35,7 @@ import type { KibanaPrivileges, SecuredFeature } from '@kbn/security-role-manage import { ChangeAllPrivilegesControl } from './change_all_privileges'; import { FeatureTableExpandedRow } from './feature_table_expanded_row'; import { NO_PRIVILEGE_VALUE } from '../constants'; -import { FeatureTableCell } from '../feature_table_cell'; +import { FeatureTableCell } from './components/feature_table_cell'; import type { PrivilegeFormCalculator } from '../privilege_form_calculator'; interface Props { diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.test.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table_expanded_row.test.tsx similarity index 99% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.test.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table_expanded_row.test.tsx index 92a33136c7678..3b787f01cdf92 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.test.tsx +++ b/x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table_expanded_row.test.tsx @@ -15,7 +15,7 @@ import { import { findTestSubject, mountWithIntl } from '@kbn/test-jest-helpers'; import { FeatureTableExpandedRow } from './feature_table_expanded_row'; -import type { Role } from '../../../../../../../common'; +import type { Role } from '@kbn/security-plugin-types-common'; import { PrivilegeFormCalculator } from '../privilege_form_calculator'; const createRole = (kibana: Role['kibana'] = []): Role => { diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table_expanded_row.tsx similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/feature_table_expanded_row.tsx diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/index.ts b/x-pack/packages/security/ui_components/src/kibana_privilege_table/index.ts similarity index 86% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/index.ts rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/index.ts index 75d8daef05a3e..ad439d6aad3fa 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/index.ts +++ b/x-pack/packages/security/ui_components/src/kibana_privilege_table/index.ts @@ -6,3 +6,4 @@ */ export { FeatureTable } from './feature_table'; +export { FeatureTableCell } from './components'; diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/sub_feature_form.test.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/sub_feature_form.test.tsx similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/sub_feature_form.test.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/sub_feature_form.test.tsx diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/sub_feature_form.tsx b/x-pack/packages/security/ui_components/src/kibana_privilege_table/sub_feature_form.tsx similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/sub_feature_form.tsx rename to x-pack/packages/security/ui_components/src/kibana_privilege_table/sub_feature_form.tsx diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/index.ts b/x-pack/packages/security/ui_components/src/privilege_form_calculator/index.ts similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/index.ts rename to x-pack/packages/security/ui_components/src/privilege_form_calculator/index.ts diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/privilege_form_calculator.test.ts b/x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.test.ts similarity index 99% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/privilege_form_calculator.test.ts rename to x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.test.ts index b47501e08f376..0281605f00f34 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/privilege_form_calculator.test.ts +++ b/x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.test.ts @@ -11,7 +11,7 @@ import { } from '@kbn/security-role-management-model/src/__fixtures__'; import { PrivilegeFormCalculator } from './privilege_form_calculator'; -import type { Role } from '../../../../../../../common'; +import type { Role } from '@kbn/security-plugin-types-common'; const createRole = (kibana: Role['kibana'] = []): Role => { return { diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/privilege_form_calculator.ts b/x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts similarity index 100% rename from x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/privilege_form_calculator.ts rename to x-pack/packages/security/ui_components/src/privilege_form_calculator/privilege_form_calculator.ts diff --git a/x-pack/packages/security/ui_components/tsconfig.json b/x-pack/packages/security/ui_components/tsconfig.json new file mode 100644 index 0000000000000..736612a488852 --- /dev/null +++ b/x-pack/packages/security/ui_components/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": ["jest", "node", "react"] + }, + "include": ["**/*.ts", "**/*.tsx"], + "exclude": ["target/**/*"], + "kbn_references": [ + "@kbn/core", + "@kbn/i18n", + "@kbn/i18n-react", + "@kbn/security-plugin-types-common", + "@kbn/test-jest-helpers", + "@kbn/security-role-management-model", + "@kbn/features-plugin", + ] +} diff --git a/x-pack/plugins/actions/server/integration_tests/__snapshots__/connector_types.test.ts.snap b/x-pack/plugins/actions/server/integration_tests/__snapshots__/connector_types.test.ts.snap index d534170f74d0f..ae1289b2a9e2e 100644 --- a/x-pack/plugins/actions/server/integration_tests/__snapshots__/connector_types.test.ts.snap +++ b/x-pack/plugins/actions/server/integration_tests/__snapshots__/connector_types.test.ts.snap @@ -4318,6 +4318,27 @@ Object { ], "type": "array", }, + "systemInstruction": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, "temperature": Object { "flags": Object { "default": [Function], @@ -4344,6 +4365,95 @@ Object { ], "type": "number", }, + "toolConfig": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "keys": Object { + "allowedFunctionNames": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "items": Array [ + Object { + "flags": Object { + "error": [Function], + "presence": "optional", + }, + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + ], + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "array", + }, + "mode": Object { + "flags": Object { + "error": [Function], + }, + "matches": Array [ + Object { + "schema": Object { + "allow": Array [ + "AUTO", + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + Object { + "schema": Object { + "allow": Array [ + "ANY", + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + Object { + "schema": Object { + "allow": Array [ + "NONE", + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + ], + "type": "alternatives", + }, + }, + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "object", + }, "tools": Object { "flags": Object { "default": [Function], @@ -4464,6 +4574,27 @@ Object { ], "type": "array", }, + "systemInstruction": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, "temperature": Object { "flags": Object { "default": [Function], @@ -4610,6 +4741,27 @@ Object { ], "type": "array", }, + "systemInstruction": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, "temperature": Object { "flags": Object { "default": [Function], @@ -4636,6 +4788,95 @@ Object { ], "type": "number", }, + "toolConfig": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "keys": Object { + "allowedFunctionNames": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "items": Array [ + Object { + "flags": Object { + "error": [Function], + "presence": "optional", + }, + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + ], + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "array", + }, + "mode": Object { + "flags": Object { + "error": [Function], + }, + "matches": Array [ + Object { + "schema": Object { + "allow": Array [ + "AUTO", + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + Object { + "schema": Object { + "allow": Array [ + "ANY", + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + Object { + "schema": Object { + "allow": Array [ + "NONE", + ], + "flags": Object { + "error": [Function], + "only": true, + }, + "type": "any", + }, + }, + ], + "type": "alternatives", + }, + }, + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "object", + }, "tools": Object { "flags": Object { "default": [Function], diff --git a/x-pack/plugins/actions/server/lib/action_executor.test.ts b/x-pack/plugins/actions/server/lib/action_executor.test.ts index b2e6badae3c59..560d5dc3ecea5 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.test.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.test.ts @@ -4,7 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import { KibanaRequest } from '@kbn/core/server'; import { schema } from '@kbn/config-schema'; import { ActionExecutor } from './action_executor'; @@ -18,7 +17,7 @@ import { } from '@kbn/core/server/mocks'; import { eventLoggerMock } from '@kbn/event-log-plugin/server/mocks'; import { spacesServiceMock } from '@kbn/spaces-plugin/server/spaces_service/spaces_service.mock'; -import { ActionType as ConnectorType } from '../types'; +import { ActionType as ConnectorType, ConnectorUsageCollector } from '../types'; import { actionsAuthorizationMock, actionsMock } from '../mocks'; import { asBackgroundTaskExecutionSource, @@ -150,6 +149,10 @@ const connectorSavedObject = { references: [], }; +interface ActionUsage { + request_body_bytes: number; +} + const getBaseExecuteStartEventLogDoc = (unsecured: boolean) => { return { event: { @@ -163,6 +166,7 @@ const getBaseExecuteStartEventLogDoc = (unsecured: boolean) => { }, id: CONNECTOR_ID, name: '1', + type_id: 'test', }, ...(unsecured ? {} @@ -190,10 +194,23 @@ const getBaseExecuteStartEventLogDoc = (unsecured: boolean) => { }; }; -const getBaseExecuteEventLogDoc = (unsecured: boolean) => { +const getBaseExecuteEventLogDoc = ( + unsecured: boolean, + actionUsage: ActionUsage = { request_body_bytes: 0 } +) => { const base = getBaseExecuteStartEventLogDoc(unsecured); return { ...base, + kibana: { + ...base.kibana, + action: { + ...base.kibana.action, + execution: { + ...base.kibana.action.execution, + usage: actionUsage, + }, + }, + }, event: { ...base.event, action: 'execute', @@ -211,9 +228,12 @@ const getBaseExecuteEventLogDoc = (unsecured: boolean) => { }; }; +const mockGetRequestBodyByte = jest.spyOn(ConnectorUsageCollector.prototype, 'getRequestBodyByte'); + beforeEach(() => { jest.resetAllMocks(); jest.clearAllMocks(); + mockGetRequestBodyByte.mockReturnValue(0); spacesMock.getSpaceId.mockReturnValue('some-namespace'); loggerMock.get.mockImplementation(() => loggerMock); const mockRealm = { name: 'default_native', type: 'native' }; @@ -237,6 +257,7 @@ describe('Action Executor', () => { const label = executeUnsecure ? 'executes unsecured' : 'executes'; test(`successfully ${label}`, async () => { + mockGetRequestBodyByte.mockReturnValue(300); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce( connectorSavedObject ); @@ -280,13 +301,15 @@ describe('Action Executor', () => { }, params: { foo: true }, logger: loggerMock, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(loggerMock.debug).toBeCalledWith('executing action test:1: 1'); expect(eventLogger.logEvent).toHaveBeenCalledTimes(2); const execStartDoc = getBaseExecuteStartEventLogDoc(executeUnsecure); - const execDoc = getBaseExecuteEventLogDoc(executeUnsecure); + const execDoc = getBaseExecuteEventLogDoc(executeUnsecure, { request_body_bytes: 300 }); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(1, execStartDoc); expect(eventLogger.logEvent).toHaveBeenNthCalledWith(2, execDoc); }); @@ -353,6 +376,7 @@ describe('Action Executor', () => { params: { foo: true }, logger: loggerMock, source: executionSource.source, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(loggerMock.debug).toBeCalledWith('executing action test:1: 1'); @@ -360,6 +384,7 @@ describe('Action Executor', () => { const execStartDoc = getBaseExecuteStartEventLogDoc(executeUnsecure); const execDoc = getBaseExecuteEventLogDoc(executeUnsecure); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(1, { ...execStartDoc, kibana: { @@ -431,6 +456,7 @@ describe('Action Executor', () => { }, params: { foo: true }, logger: loggerMock, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(loggerMock.debug).toBeCalledWith('executing action test:preconfigured: Preconfigured'); @@ -438,6 +464,7 @@ describe('Action Executor', () => { const execStartDoc = getBaseExecuteStartEventLogDoc(executeUnsecure); const execDoc = getBaseExecuteEventLogDoc(executeUnsecure); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(1, { ...execStartDoc, kibana: { @@ -513,6 +540,7 @@ describe('Action Executor', () => { params: { foo: true }, logger: loggerMock, request: {}, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); } @@ -532,6 +560,7 @@ describe('Action Executor', () => { const execStartDoc = getBaseExecuteStartEventLogDoc(executeUnsecure); const execDoc = getBaseExecuteEventLogDoc(executeUnsecure); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(1, { ...execStartDoc, kibana: { @@ -540,6 +569,7 @@ describe('Action Executor', () => { ...execStartDoc.kibana.action, id: 'system-connector-.cases', name: 'System action: .cases', + type_id: '.cases', }, saved_objects: [ { @@ -569,6 +599,7 @@ describe('Action Executor', () => { ...execDoc.kibana.action, id: 'system-connector-.cases', name: 'System action: .cases', + type_id: '.cases', }, saved_objects: [ { @@ -890,6 +921,7 @@ describe('Action Executor', () => { }, params: { foo: true }, logger: loggerMock, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }); @@ -921,6 +953,7 @@ describe('Action Executor', () => { params: { foo: true }, logger: loggerMock, request: {}, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }); @@ -989,6 +1022,7 @@ describe('Action Executor', () => { }, params: { foo: true }, logger: loggerMock, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(loggerMock.debug).toBeCalledWith('executing action test:preconfigured: Preconfigured'); @@ -996,6 +1030,7 @@ describe('Action Executor', () => { const execStartDoc = getBaseExecuteStartEventLogDoc(executeUnsecure); const execDoc = getBaseExecuteEventLogDoc(executeUnsecure); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(1, { ...execStartDoc, kibana: { @@ -1026,6 +1061,12 @@ describe('Action Executor', () => { ...execDoc.kibana.action, id: 'preconfigured', name: 'Preconfigured', + execution: { + ...execStartDoc.kibana.action.execution, + usage: { + request_body_bytes: 0, + }, + }, }, saved_objects: [ { @@ -1074,6 +1115,7 @@ describe('Action Executor', () => { params: { foo: true }, logger: loggerMock, request: {}, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(loggerMock.debug).toBeCalledWith( @@ -1083,6 +1125,7 @@ describe('Action Executor', () => { const execStartDoc = getBaseExecuteStartEventLogDoc(executeUnsecure); const execDoc = getBaseExecuteEventLogDoc(executeUnsecure); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(1, { ...execStartDoc, kibana: { @@ -1091,6 +1134,7 @@ describe('Action Executor', () => { ...execStartDoc.kibana.action, id: 'system-connector-.cases', name: 'System action: .cases', + type_id: '.cases', }, saved_objects: [ { @@ -1120,6 +1164,7 @@ describe('Action Executor', () => { ...execDoc.kibana.action, id: 'system-connector-.cases', name: 'System action: .cases', + type_id: '.cases', }, saved_objects: [ { @@ -1290,6 +1335,7 @@ describe('Action Executor', () => { }, params: { foo: true }, logger: loggerMock, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); } }); @@ -1385,6 +1431,7 @@ describe('Event log', () => { }, name: undefined, id: 'action1', + type_id: 'test', }, alert: { rule: { @@ -1430,6 +1477,7 @@ describe('Event log', () => { }, name: 'action-1', id: '1', + type_id: 'test', }, alert: { rule: { @@ -1483,6 +1531,7 @@ describe('Event log', () => { }, name: 'action-1', id: '1', + type_id: 'test', }, alert: { rule: { @@ -1559,9 +1608,13 @@ describe('Event log', () => { gen_ai: { usage: mockGenAi.usage, }, + usage: { + request_body_bytes: 0, + }, }, name: 'action-1', id: '1', + type_id: '.gen-ai', }, alert: { rule: { @@ -1655,9 +1708,13 @@ describe('Event log', () => { total_tokens: 35, }, }, + usage: { + request_body_bytes: 0, + }, }, name: 'action-1', id: '1', + type_id: '.gen-ai', }, alert: { rule: { diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts index 685e18c585ae0..c302b0da3e886 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -23,6 +23,7 @@ import { IEventLogger, SAVED_OBJECT_REL_PRIMARY } from '@kbn/event-log-plugin/se import { createTaskRunError, TaskErrorSource } from '@kbn/task-manager-plugin/server'; import { getErrorSource } from '@kbn/task-manager-plugin/server/task_running'; import { GEN_AI_TOKEN_COUNT_EVENT } from './event_based_telemetry'; +import { ConnectorUsageCollector } from '../usage/connector_usage_collector'; import { getGenAiTokenTracking, shouldTrackGenAiToken } from './gen_ai_token_tracking'; import { validateConfig, @@ -293,6 +294,7 @@ export class ActionExecutor { actionExecutionId, isInMemory: this.actionInfo.isInMemory, ...(source ? { source } : {}), + actionTypeId: this.actionInfo.actionTypeId, }); eventLogger.logEvent(event); @@ -394,6 +396,14 @@ export class ActionExecutor { const { actionTypeId, name, config, secrets } = actionInfo; + const loggerId = actionTypeId.startsWith('.') ? actionTypeId.substring(1) : actionTypeId; + const logger = this.actionExecutorContext!.logger.get(loggerId); + + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: actionId, + }); + if (!this.actionInfo || this.actionInfo.actionId !== actionId) { this.actionInfo = actionInfo; } @@ -434,9 +444,6 @@ export class ActionExecutor { return err.result; } - const loggerId = actionTypeId.startsWith('.') ? actionTypeId.substring(1) : actionTypeId; - const logger = this.actionExecutorContext!.logger.get(loggerId); - if (span) { span.name = `${executeLabel} ${actionTypeId}`; span.addLabels({ @@ -477,6 +484,7 @@ export class ActionExecutor { actionExecutionId, isInMemory: this.actionInfo.isInMemory, ...(source ? { source } : {}), + actionTypeId, }); eventLogger.startTiming(event); @@ -510,6 +518,7 @@ export class ActionExecutor { logger, source, ...(actionType.isSystemActionType ? { request } : {}), + connectorUsageCollector, }); if (rawResult && rawResult.status === 'error') { @@ -548,6 +557,11 @@ export class ActionExecutor { event.user = event.user || {}; event.user.name = currentUser?.username; event.user.id = currentUser?.profile_uid; + set( + event, + 'kibana.action.execution.usage.request_body_bytes', + connectorUsageCollector.getRequestBodyByte() + ); if (result.status === 'ok') { span?.setOutcome('success'); diff --git a/x-pack/plugins/actions/server/lib/axios_utils.test.ts b/x-pack/plugins/actions/server/lib/axios_utils.test.ts index c5e23f6cd3db3..bee09a90ed27b 100644 --- a/x-pack/plugins/actions/server/lib/axios_utils.test.ts +++ b/x-pack/plugins/actions/server/lib/axios_utils.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import axios, { AxiosInstance } from 'axios'; +import axios, { AxiosError, AxiosInstance } from 'axios'; import { Agent as HttpsAgent } from 'https'; import HttpProxyAgent from 'http-proxy-agent'; import { HttpsProxyAgent } from 'https-proxy-agent'; @@ -21,6 +21,7 @@ import { import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '../actions_config.mock'; import { getCustomAgents } from './get_custom_agents'; +import { ConnectorUsageCollector } from '../usage/connector_usage_collector'; const TestUrl = 'https://elastic.co/foo/bar/baz'; @@ -79,6 +80,80 @@ describe('request', () => { }); }); + test('adds request body bytes from request header on a successful request when connectorUsageCollector is provided', async () => { + const contentLength = 12; + axiosMock.mockImplementation(() => ({ + status: 200, + headers: { 'content-type': 'application/json' }, + data: { incidentId: '123' }, + request: { + headers: { 'Content-Length': contentLength }, + getHeader: () => contentLength, + }, + })); + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); + await request({ + axios, + url: '/test', + logger, + data: { test: 12345 }, + configurationUtilities, + connectorUsageCollector, + }); + + expect(connectorUsageCollector.getRequestBodyByte()).toBe(contentLength); + }); + + test('adds request body bytes from request header on a failed', async () => { + const contentLength = 12; + axiosMock.mockImplementation( + () => + new AxiosError('failed', '500', undefined, { + headers: { 'Content-Length': contentLength }, + }) + ); + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); + + try { + await request({ + axios, + url: '/test', + logger, + configurationUtilities, + connectorUsageCollector, + }); + } catch (e) { + expect(connectorUsageCollector.getRequestBodyByte()).toBe(contentLength); + } + }); + + test('adds request body bytes from data when request header does not exist', async () => { + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); + const data = { test: 12345 }; + + await request({ + axios, + url: '/test', + logger, + data, + configurationUtilities, + connectorUsageCollector, + }); + + expect(connectorUsageCollector.getRequestBodyByte()).toBe( + Buffer.byteLength(JSON.stringify(data), 'utf8') + ); + }); + test('it have been called with proper proxy agent for a valid url', async () => { configurationUtilities.getProxySettings.mockReturnValue({ proxySSLSettings: { diff --git a/x-pack/plugins/actions/server/lib/axios_utils.ts b/x-pack/plugins/actions/server/lib/axios_utils.ts index 3852f2a33755b..254ad1a36f6e2 100644 --- a/x-pack/plugins/actions/server/lib/axios_utils.ts +++ b/x-pack/plugins/actions/server/lib/axios_utils.ts @@ -17,7 +17,7 @@ import { import { Logger } from '@kbn/core/server'; import { getCustomAgents } from './get_custom_agents'; import { ActionsConfigurationUtilities } from '../actions_config'; -import { SSLSettings } from '../types'; +import { ConnectorUsageCollector, SSLSettings } from '../types'; import { combineHeadersWithBasicAuthHeader } from './get_basic_auth_header'; export const request = async ({ @@ -30,6 +30,7 @@ export const request = async ({ headers, sslOverrides, timeout, + connectorUsageCollector, ...config }: { axios: AxiosInstance; @@ -41,6 +42,7 @@ export const request = async ({ headers?: Record; timeout?: number; sslOverrides?: SSLSettings; + connectorUsageCollector?: ConnectorUsageCollector; } & AxiosRequestConfig): Promise => { if (!isEmpty(axios?.defaults?.baseURL ?? '')) { throw new Error( @@ -64,18 +66,31 @@ export const request = async ({ headers, }); - return await axios(url, { - ...restConfig, - method, - headers: headersWithBasicAuth, - ...(data ? { data } : {}), - // use httpAgent and httpsAgent and set axios proxy: false, to be able to handle fail on invalid certs - httpAgent, - httpsAgent, - proxy: false, - maxContentLength, - timeout: Math.max(settingsTimeout, timeout ?? 0), - }); + try { + const result = await axios(url, { + ...restConfig, + method, + headers: headersWithBasicAuth, + ...(data ? { data } : {}), + // use httpAgent and httpsAgent and set axios proxy: false, to be able to handle fail on invalid certs + httpAgent, + httpsAgent, + proxy: false, + maxContentLength, + timeout: Math.max(settingsTimeout, timeout ?? 0), + }); + + if (connectorUsageCollector) { + connectorUsageCollector.addRequestBodyBytes(result, data); + } + + return result; + } catch (error) { + if (connectorUsageCollector) { + connectorUsageCollector.addRequestBodyBytes(error, data); + } + throw error; + } }; export const patch = async ({ @@ -84,12 +99,14 @@ export const patch = async ({ data, logger, configurationUtilities, + connectorUsageCollector, }: { axios: AxiosInstance; url: string; data: T; logger: Logger; configurationUtilities: ActionsConfigurationUtilities; + connectorUsageCollector?: ConnectorUsageCollector; }): Promise => { return request({ axios, @@ -98,6 +115,7 @@ export const patch = async ({ method: 'patch', data, configurationUtilities, + connectorUsageCollector, }); }; diff --git a/x-pack/plugins/actions/server/lib/create_action_event_log_record_object.test.ts b/x-pack/plugins/actions/server/lib/create_action_event_log_record_object.test.ts index cb6390a4b3335..46f13ae1182ac 100644 --- a/x-pack/plugins/actions/server/lib/create_action_event_log_record_object.test.ts +++ b/x-pack/plugins/actions/server/lib/create_action_event_log_record_object.test.ts @@ -33,6 +33,7 @@ describe('createActionEventLogRecordObject', () => { spaceId: 'default', name: 'test name', actionExecutionId: '123abc', + actionTypeId: '.slack', }) ).toStrictEqual({ '@timestamp': '1970-01-01T00:00:00.000Z', @@ -64,6 +65,7 @@ describe('createActionEventLogRecordObject', () => { }, action: { name: 'test name', + type_id: '.slack', id: '1', execution: { uuid: '123abc', @@ -92,6 +94,7 @@ describe('createActionEventLogRecordObject', () => { }, ], actionExecutionId: '123abc', + actionTypeId: '.slack', }) ).toStrictEqual({ event: { @@ -118,6 +121,7 @@ describe('createActionEventLogRecordObject', () => { ], action: { name: 'test name', + type_id: '.slack', id: '1', execution: { uuid: '123abc', @@ -145,6 +149,7 @@ describe('createActionEventLogRecordObject', () => { }, ], actionExecutionId: '123abc', + actionTypeId: '.slack', }) ).toStrictEqual({ event: { @@ -163,6 +168,7 @@ describe('createActionEventLogRecordObject', () => { ], action: { name: 'test name', + type_id: '.slack', id: '1', execution: { uuid: '123abc', @@ -192,6 +198,7 @@ describe('createActionEventLogRecordObject', () => { ], name: 'test name', actionExecutionId: '123abc', + actionTypeId: '.slack', }) ).toStrictEqual({ event: { @@ -220,6 +227,7 @@ describe('createActionEventLogRecordObject', () => { }, action: { name: 'test name', + type_id: '.slack', id: '1', execution: { uuid: '123abc', @@ -255,6 +263,7 @@ describe('createActionEventLogRecordObject', () => { }, ], actionExecutionId: '123abc', + actionTypeId: '.slack', }) ).toStrictEqual({ event: { @@ -289,6 +298,7 @@ describe('createActionEventLogRecordObject', () => { ], action: { name: 'test name', + type_id: '.slack', id: '1', execution: { uuid: '123abc', @@ -319,6 +329,7 @@ describe('createActionEventLogRecordObject', () => { ], actionExecutionId: '123abc', source: asHttpRequestExecutionSource(httpServerMock.createKibanaRequest()), + actionTypeId: '.slack', }) ).toStrictEqual({ event: { @@ -345,6 +356,7 @@ describe('createActionEventLogRecordObject', () => { ], action: { name: 'test name', + type_id: '.slack', id: '1', execution: { source: 'http_request', @@ -376,6 +388,7 @@ describe('createActionEventLogRecordObject', () => { ], actionExecutionId: '123abc', source: asHttpRequestExecutionSource(httpServerMock.createKibanaRequest()), + actionTypeId: '.slack', }) ).toStrictEqual({ event: { @@ -402,6 +415,7 @@ describe('createActionEventLogRecordObject', () => { ], action: { name: 'test name', + type_id: '.slack', id: '1', execution: { source: 'http_request', @@ -433,6 +447,7 @@ describe('createActionEventLogRecordObject', () => { ], actionExecutionId: '123abc', isInMemory: true, + actionTypeId: '.slack', }) ).toStrictEqual({ event: { @@ -460,6 +475,7 @@ describe('createActionEventLogRecordObject', () => { ], action: { name: 'test name', + type_id: '.slack', id: '1', execution: { uuid: '123abc', diff --git a/x-pack/plugins/actions/server/lib/create_action_event_log_record_object.ts b/x-pack/plugins/actions/server/lib/create_action_event_log_record_object.ts index 4f8bf08966c59..c3b7a3b35f512 100644 --- a/x-pack/plugins/actions/server/lib/create_action_event_log_record_object.ts +++ b/x-pack/plugins/actions/server/lib/create_action_event_log_record_object.ts @@ -37,6 +37,7 @@ interface CreateActionEventLogRecordParams { relatedSavedObjects?: RelatedSavedObjects; isInMemory?: boolean; source?: ActionExecutionSource; + actionTypeId: string; } export function createActionEventLogRecordObject(params: CreateActionEventLogRecordParams): Event { @@ -54,6 +55,7 @@ export function createActionEventLogRecordObject(params: CreateActionEventLogRec isInMemory, actionId, source, + actionTypeId, } = params; const kibanaAlertRule = { @@ -89,6 +91,7 @@ export function createActionEventLogRecordObject(params: CreateActionEventLogRec action: { ...(name ? { name } : {}), id: actionId, + type_id: actionTypeId, execution: { uuid: actionExecutionId, }, diff --git a/x-pack/plugins/actions/server/sub_action_framework/case.test.ts b/x-pack/plugins/actions/server/sub_action_framework/case.test.ts index 91e2df1972de8..aa32dd8853dba 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/case.test.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/case.test.ts @@ -12,12 +12,14 @@ import { actionsConfigMock } from '../actions_config.mock'; import { actionsMock } from '../mocks'; import { TestCaseConnector } from './mocks'; import { ActionsConfigurationUtilities } from '../actions_config'; +import { ConnectorUsageCollector } from '../usage'; describe('CaseConnector', () => { let logger: MockedLogger; let services: ReturnType; let mockedActionsConfig: jest.Mocked; let service: TestCaseConnector; + let connectorUsageCollector: ConnectorUsageCollector; const pushToServiceIncidentParamsSchema = { name: schema.string(), category: schema.nullable(schema.string()), @@ -57,6 +59,11 @@ describe('CaseConnector', () => { }, pushToServiceIncidentParamsSchema ); + + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); describe('Sub actions', () => { @@ -191,7 +198,7 @@ describe('CaseConnector', () => { describe('pushToService', () => { it('should create an incident if externalId is null', async () => { - const res = await service.pushToService(pushToServiceParams); + const res = await service.pushToService(pushToServiceParams, connectorUsageCollector); expect(res).toEqual({ id: 'create-incident', title: 'Test incident', @@ -201,10 +208,13 @@ describe('CaseConnector', () => { }); it('should update an incident if externalId is not null', async () => { - const res = await service.pushToService({ - incident: { ...pushToServiceParams.incident, externalId: 'test-id' }, - comments: [], - }); + const res = await service.pushToService( + { + incident: { ...pushToServiceParams.incident, externalId: 'test-id' }, + comments: [], + }, + connectorUsageCollector + ); expect(res).toEqual({ id: 'update-incident', @@ -215,13 +225,16 @@ describe('CaseConnector', () => { }); it('should add comments', async () => { - const res = await service.pushToService({ - ...pushToServiceParams, - comments: [ - { comment: 'comment-1', commentId: 'comment-id-1' }, - { comment: 'comment-2', commentId: 'comment-id-2' }, - ], - }); + const res = await service.pushToService( + { + ...pushToServiceParams, + comments: [ + { comment: 'comment-1', commentId: 'comment-id-1' }, + { comment: 'comment-2', commentId: 'comment-id-2' }, + ], + }, + connectorUsageCollector + ); expect(res).toEqual({ id: 'create-incident', @@ -242,11 +255,14 @@ describe('CaseConnector', () => { }); it.each([[undefined], [null]])('should throw if externalId is %p', async (comments) => { - const res = await service.pushToService({ - ...pushToServiceParams, - // @ts-expect-error - comments, - }); + const res = await service.pushToService( + { + ...pushToServiceParams, + // @ts-expect-error + comments, + }, + connectorUsageCollector + ); expect(res).toEqual({ id: 'create-incident', @@ -257,10 +273,13 @@ describe('CaseConnector', () => { }); it('should not add comments if comments are an empty array', async () => { - const res = await service.pushToService({ - ...pushToServiceParams, - comments: [], - }); + const res = await service.pushToService( + { + ...pushToServiceParams, + comments: [], + }, + connectorUsageCollector + ); expect(res).toEqual({ id: 'create-incident', diff --git a/x-pack/plugins/actions/server/sub_action_framework/case.ts b/x-pack/plugins/actions/server/sub_action_framework/case.ts index 24a0512378912..1d942b210dbf9 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/case.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/case.ts @@ -9,22 +9,38 @@ import { schema, Type } from '@kbn/config-schema'; import { ExternalServiceIncidentResponse, PushToServiceResponse } from './types'; import { SubActionConnector } from './sub_action_connector'; import { ServiceParams } from './types'; +import { ConnectorUsageCollector } from '../usage'; export interface CaseConnectorInterface { - addComment: ({ incidentId, comment }: { incidentId: string; comment: string }) => Promise; - createIncident: (incident: Incident) => Promise; - updateIncident: ({ - incidentId, - incident, - }: { - incidentId: string; - incident: Incident; - }) => Promise; - getIncident: ({ id }: { id: string }) => Promise; - pushToService: (params: { - incident: { externalId: string | null } & Incident; - comments: Array<{ commentId: string; comment: string }>; - }) => Promise; + addComment: ( + { incidentId, comment }: { incidentId: string; comment: string }, + connectorUsageCollector: ConnectorUsageCollector + ) => Promise; + createIncident: ( + incident: Incident, + connectorUsageCollector: ConnectorUsageCollector + ) => Promise; + updateIncident: ( + { + incidentId, + incident, + }: { + incidentId: string; + incident: Incident; + }, + connectorUsageCollector: ConnectorUsageCollector + ) => Promise; + getIncident: ( + { id }: { id: string }, + connectorUsageCollector: ConnectorUsageCollector + ) => Promise; + pushToService: ( + params: { + incident: { externalId: string | null } & Incident; + comments: Array<{ commentId: string; comment: string }>; + }, + connectorUsageCollector: ConnectorUsageCollector + ) => Promise; } export abstract class CaseConnector @@ -56,50 +72,71 @@ export abstract class CaseConnector; + public abstract addComment( + { + incidentId, + comment, + }: { + incidentId: string; + comment: string; + }, + connectorUsageCollector: ConnectorUsageCollector + ): Promise; - public abstract createIncident(incident: Incident): Promise; - public abstract updateIncident({ - incidentId, - incident, - }: { - incidentId: string; - incident: Incident; - }): Promise; - public abstract getIncident({ id }: { id: string }): Promise; + public abstract createIncident( + incident: Incident, + connectorUsageCollector: ConnectorUsageCollector + ): Promise; + public abstract updateIncident( + { + incidentId, + incident, + }: { + incidentId: string; + incident: Incident; + }, + connectorUsageCollector: ConnectorUsageCollector + ): Promise; + public abstract getIncident( + { id }: { id: string }, + connectorUsageCollector: ConnectorUsageCollector + ): Promise; - public async pushToService(params: { - incident: { externalId: string | null } & Incident; - comments: Array<{ commentId: string; comment: string }>; - }) { + public async pushToService( + params: { + incident: { externalId: string | null } & Incident; + comments: Array<{ commentId: string; comment: string }>; + }, + connectorUsageCollector: ConnectorUsageCollector + ) { const { incident, comments } = params; const { externalId, ...rest } = incident; let res: PushToServiceResponse; if (externalId != null) { - res = await this.updateIncident({ - incidentId: externalId, - incident: rest as Incident, - }); + res = await this.updateIncident( + { + incidentId: externalId, + incident: rest as Incident, + }, + connectorUsageCollector + ); } else { - res = await this.createIncident(rest as Incident); + res = await this.createIncident(rest as Incident, connectorUsageCollector); } if (comments && Array.isArray(comments) && comments.length > 0) { res.comments = []; for (const currentComment of comments) { - await this.addComment({ - incidentId: res.id, - comment: currentComment.comment, - }); + await this.addComment( + { + incidentId: res.id, + comment: currentComment.comment, + }, + connectorUsageCollector + ); res.comments = [ ...(res.comments ?? []), diff --git a/x-pack/plugins/actions/server/sub_action_framework/executor.test.ts b/x-pack/plugins/actions/server/sub_action_framework/executor.test.ts index 35b1fa43c6ce3..1b8bdf0adcaee 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/executor.test.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/executor.test.ts @@ -21,6 +21,7 @@ import { } from './mocks'; import { IService, ServiceParams } from './types'; import { getErrorSource, TaskErrorSource } from '@kbn/task-manager-plugin/server/task_running'; +import { ConnectorUsageCollector } from '../usage'; describe('Executor', () => { const actionId = 'test-action-id'; @@ -30,6 +31,7 @@ describe('Executor', () => { let logger: MockedLogger; let services: ReturnType; let mockedActionsConfig: jest.Mocked; + let connectorUsageCollector: ConnectorUsageCollector; const createExecutor = (Service: IService) => { const connector = { @@ -55,6 +57,10 @@ describe('Executor', () => { logger = loggingSystemMock.createLogger(); services = actionsMock.createServices(); mockedActionsConfig = actionsConfigMock.create(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); it('should execute correctly', async () => { @@ -68,6 +74,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }); expect(res).toEqual({ @@ -90,6 +97,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }); expect(res).toEqual({ @@ -112,6 +120,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }); expect(res).toEqual({ @@ -132,6 +141,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }); expect(res).toEqual({ @@ -153,6 +163,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }) ).rejects.toThrowError('You should register at least one subAction for your connector type'); }); @@ -169,6 +180,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }) ).rejects.toThrowError( 'Sub action "not-exist" is not registered. Connector id: test-action-id. Connector name: Test. Connector type: .test' @@ -187,6 +199,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }); } catch (e) { expect(getErrorSource(e)).toBe(TaskErrorSource.USER); @@ -208,6 +221,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }) ).rejects.toThrowError( 'Method "not-exist" does not exists in service. Sub action: "testUrl". Connector id: test-action-id. Connector name: Test. Connector type: .test' @@ -226,6 +240,7 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }) ).rejects.toThrowError( 'Method "notAFunction" must be a function. Connector id: test-action-id. Connector name: Test. Connector type: .test' @@ -244,9 +259,50 @@ describe('Executor', () => { services, configurationUtilities: mockedActionsConfig, logger, + connectorUsageCollector, }) ).rejects.toThrowError( 'Request validation failed (Error: [id]: expected value of type [string] but got [undefined])' ); }); + + it('Passes connectorUsageCollector to the subAction method as a second param', async () => { + let echoSpy; + + const subActionParams = { id: 'test-id' }; + const connector = { + id: '.test', + name: 'Test', + minimumLicenseRequired: 'basic' as const, + supportedFeatureIds: ['alerting'], + schema: { + config: TestConfigSchema, + secrets: TestSecretsSchema, + }, + getService: (serviceParams: ServiceParams) => { + const service = new TestExecutor(serviceParams); + echoSpy = jest.spyOn(service, 'echo').mockResolvedValue(subActionParams); + return service; + }, + }; + + const executor = buildExecutor({ + configurationUtilities: mockedActionsConfig, + logger, + connector, + }); + + await executor({ + actionId, + params: { subAction: 'echo', subActionParams }, + config, + secrets, + services, + configurationUtilities: mockedActionsConfig, + logger, + connectorUsageCollector, + }); + + expect(echoSpy).toHaveBeenCalledWith(subActionParams, connectorUsageCollector); + }); }); diff --git a/x-pack/plugins/actions/server/sub_action_framework/executor.ts b/x-pack/plugins/actions/server/sub_action_framework/executor.ts index d9f2f693c175d..a8fbcb6e05984 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/executor.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/executor.ts @@ -30,7 +30,15 @@ export const buildExecutor = < logger: Logger; configurationUtilities: ActionsConfigurationUtilities; }): ExecutorType => { - return async ({ actionId, params, config, secrets, services, request }) => { + return async ({ + actionId, + params, + config, + secrets, + services, + request, + connectorUsageCollector, + }) => { const subAction = params.subAction; const subActionParams = params.subActionParams; @@ -88,7 +96,7 @@ export const buildExecutor = < } } - const data = await func.call(service, subActionParams); + const data = await func.call(service, subActionParams, connectorUsageCollector); return { status: 'ok', data: data ?? {}, actionId }; }; }; diff --git a/x-pack/plugins/actions/server/sub_action_framework/mocks.ts b/x-pack/plugins/actions/server/sub_action_framework/mocks.ts index f6c8e86dd5af3..28e4a2abc224e 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/mocks.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/mocks.ts @@ -8,6 +8,7 @@ import { schema, Type, TypeOf } from '@kbn/config-schema'; import { AxiosError } from 'axios'; +import { ConnectorUsageCollector } from '../usage'; import { SubActionConnector } from './sub_action_connector'; import { CaseConnector } from './case'; import { ExternalServiceIncidentResponse, ServiceParams } from './types'; @@ -57,36 +58,54 @@ export class TestSubActionConnector extends SubActionConnector | null }) { - const res = await this.request({ - url, - data, - headers: { 'X-Test-Header': 'test' }, - responseSchema: schema.object({ status: schema.string() }), - }); + public async testUrl( + { url, data = {} }: { url: string; data?: Record | null }, + connectorUsageCollector: ConnectorUsageCollector + ) { + const res = await this.request( + { + url, + data, + headers: { 'X-Test-Header': 'test' }, + responseSchema: schema.object({ status: schema.string() }), + }, + connectorUsageCollector + ); return res; } - public async testData({ data }: { data: Record }) { - const res = await this.request({ - url: 'https://example.com', - data: this.removeNullOrUndefinedFields(data), - headers: { 'X-Test-Header': 'test' }, - responseSchema: schema.object({ status: schema.string() }), - }); + public async testData( + { data }: { data: Record }, + connectorUsageCollector: ConnectorUsageCollector + ) { + const res = await this.request( + { + url: 'https://example.com', + data: this.removeNullOrUndefinedFields(data), + headers: { 'X-Test-Header': 'test' }, + responseSchema: schema.object({ status: schema.string() }), + }, + connectorUsageCollector + ); return res; } - public async testAuth({ headers }: { headers?: Record } = {}) { - const res = await this.request({ - url: 'https://example.com', - data: {}, - auth: { username: 'username', password: 'password' }, - headers: { 'X-Test-Header': 'test', ...headers }, - responseSchema: schema.object({ status: schema.string() }), - }); + public async testAuth( + { headers }: { headers?: Record } = {}, + connectorUsageCollector: ConnectorUsageCollector + ) { + const res = await this.request( + { + url: 'https://example.com', + data: {}, + auth: { username: 'username', password: 'password' }, + headers: { 'X-Test-Header': 'test', ...headers }, + responseSchema: schema.object({ status: schema.string() }), + }, + connectorUsageCollector + ); return res; } diff --git a/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.test.ts b/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.test.ts index 1358684d86093..ed599c3f30f71 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.test.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.test.ts @@ -13,6 +13,7 @@ import { actionsMock } from '../mocks'; import { TestSubActionConnector } from './mocks'; import { ActionsConfigurationUtilities } from '../actions_config'; import * as utils from '../lib/axios_utils'; +import { ConnectorUsageCollector } from '../usage'; jest.mock('axios'); @@ -43,6 +44,7 @@ describe('SubActionConnector', () => { let services: ReturnType; let mockedActionsConfig: jest.Mocked; let service: TestSubActionConnector; + let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { jest.resetAllMocks(); @@ -70,6 +72,11 @@ describe('SubActionConnector', () => { secrets: { username: 'elastic', password: 'changeme' }, services, }); + + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); describe('Sub actions', () => { @@ -85,34 +92,37 @@ describe('SubActionConnector', () => { describe('URL validation', () => { it('removes double slashes correctly', async () => { - await service.testUrl({ url: 'https://example.com//api///test-endpoint' }); + await service.testUrl( + { url: 'https://example.com//api///test-endpoint' }, + connectorUsageCollector + ); expect(requestMock.mock.calls[0][0].url).toBe('https://example.com/api/test-endpoint'); }); it('removes the ending slash correctly', async () => { - await service.testUrl({ url: 'https://example.com/' }); + await service.testUrl({ url: 'https://example.com/' }, connectorUsageCollector); expect(requestMock.mock.calls[0][0].url).toBe('https://example.com'); }); it('throws an error if the url is invalid', async () => { expect.assertions(1); - await expect(async () => service.testUrl({ url: 'invalid-url' })).rejects.toThrow( - 'URL Error: Invalid URL: invalid-url' - ); + await expect(async () => + service.testUrl({ url: 'invalid-url' }, connectorUsageCollector) + ).rejects.toThrow('URL Error: Invalid URL: invalid-url'); }); it('throws an error if the url starts with backslashes', async () => { expect.assertions(1); - await expect(async () => service.testUrl({ url: '//example.com/foo' })).rejects.toThrow( - 'URL Error: Invalid URL: //example.com/foo' - ); + await expect(async () => + service.testUrl({ url: '//example.com/foo' }, connectorUsageCollector) + ).rejects.toThrow('URL Error: Invalid URL: //example.com/foo'); }); it('throws an error if the protocol is not supported', async () => { expect.assertions(1); - await expect(async () => service.testUrl({ url: 'ftp://example.com' })).rejects.toThrow( - 'URL Error: Invalid protocol' - ); + await expect(async () => + service.testUrl({ url: 'ftp://example.com' }, connectorUsageCollector) + ).rejects.toThrow('URL Error: Invalid protocol'); }); it('throws if the host is the URI is not allowed', async () => { @@ -122,15 +132,15 @@ describe('SubActionConnector', () => { throw new Error('URI is not allowed'); }); - await expect(async () => service.testUrl({ url: 'https://example.com' })).rejects.toThrow( - 'error configuring connector action: URI is not allowed' - ); + await expect(async () => + service.testUrl({ url: 'https://example.com' }, connectorUsageCollector) + ).rejects.toThrow('error configuring connector action: URI is not allowed'); }); }); describe('Data', () => { it('sets data to an empty object if the data are null', async () => { - await service.testUrl({ url: 'https://example.com', data: null }); + await service.testUrl({ url: 'https://example.com', data: null }, connectorUsageCollector); expect(requestMock).toHaveBeenCalledTimes(1); const { data } = requestMock.mock.calls[0][0]; @@ -138,7 +148,10 @@ describe('SubActionConnector', () => { }); it('pass data to axios correctly if not null', async () => { - await service.testUrl({ url: 'https://example.com', data: { foo: 'foo' } }); + await service.testUrl( + { url: 'https://example.com', data: { foo: 'foo' } }, + connectorUsageCollector + ); expect(requestMock).toHaveBeenCalledTimes(1); const { data } = requestMock.mock.calls[0][0]; @@ -146,7 +159,10 @@ describe('SubActionConnector', () => { }); it('removeNullOrUndefinedFields: removes null values and undefined values correctly', async () => { - await service.testData({ data: { foo: 'foo', bar: null, baz: undefined } }); + await service.testData( + { data: { foo: 'foo', bar: null, baz: undefined } }, + connectorUsageCollector + ); expect(requestMock).toHaveBeenCalledTimes(1); const { data } = requestMock.mock.calls[0][0]; @@ -167,7 +183,7 @@ describe('SubActionConnector', () => { describe('Fetching', () => { it('fetch correctly', async () => { - const res = await service.testUrl({ url: 'https://example.com' }); + const res = await service.testUrl({ url: 'https://example.com' }, connectorUsageCollector); expect(requestMock).toHaveBeenCalledTimes(1); expect(requestMock).toBeCalledWith({ @@ -181,6 +197,7 @@ describe('SubActionConnector', () => { 'X-Test-Header': 'test', }, url: 'https://example.com', + connectorUsageCollector, }); expect(logger.debug).toBeCalledWith( @@ -192,7 +209,9 @@ describe('SubActionConnector', () => { it('validates the response correctly', async () => { requestMock.mockReturnValue({ data: { invalidField: 'test' } }); - await expect(async () => service.testUrl({ url: 'https://example.com' })).rejects.toThrow( + await expect(async () => + service.testUrl({ url: 'https://example.com' }, connectorUsageCollector) + ).rejects.toThrow( 'Response validation failed (Error: [status]: expected value of type [string] but got [undefined])' ); }); @@ -202,9 +221,9 @@ describe('SubActionConnector', () => { throw createAxiosError(); }); - await expect(async () => service.testUrl({ url: 'https://example.com' })).rejects.toThrow( - 'Message: An error occurred. Code: 500' - ); + await expect(async () => + service.testUrl({ url: 'https://example.com' }, connectorUsageCollector) + ).rejects.toThrow('Message: An error occurred. Code: 500'); expect(logger.debug).toHaveBeenLastCalledWith( 'Request to external service failed. Connector Id: test-id. Connector type: .test. Method: get. URL: https://example.com' @@ -212,7 +231,7 @@ describe('SubActionConnector', () => { }); it('converts auth axios property to a basic auth header if provided', async () => { - await service.testAuth(); + await service.testAuth(undefined, connectorUsageCollector); expect(requestMock).toHaveBeenCalledTimes(1); expect(requestMock).toBeCalledWith({ @@ -227,11 +246,15 @@ describe('SubActionConnector', () => { Authorization: `Basic ${Buffer.from('username:password').toString('base64')}`, }, url: 'https://example.com', + connectorUsageCollector, }); }); it('does not override an authorization header if provided', async () => { - await service.testAuth({ headers: { Authorization: 'Bearer my_token' } }); + await service.testAuth( + { headers: { Authorization: 'Bearer my_token' } }, + connectorUsageCollector + ); expect(requestMock).toHaveBeenCalledTimes(1); expect(requestMock).toBeCalledWith({ @@ -246,6 +269,7 @@ describe('SubActionConnector', () => { Authorization: 'Bearer my_token', }, url: 'https://example.com', + connectorUsageCollector, }); }); }); diff --git a/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts b/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts index d5ad5391628bc..fe59feab4376b 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts @@ -24,6 +24,7 @@ import { IncomingMessage } from 'http'; import { PassThrough } from 'stream'; import { KibanaRequest } from '@kbn/core-http-server'; import { inspect } from 'util'; +import { ConnectorUsageCollector } from '../usage'; import { assertURL } from './helpers/validators'; import { ActionsConfigurationUtilities } from '../actions_config'; import { SubAction, SubActionRequestParams } from './types'; @@ -130,15 +131,18 @@ export abstract class SubActionConnector { protected abstract getResponseErrorMessage(error: AxiosError): string; - protected async request({ - url, - data, - method = 'get', - responseSchema, - headers, - timeout, - ...config - }: SubActionRequestParams): Promise> { + protected async request( + { + url, + data, + method = 'get', + responseSchema, + headers, + timeout, + ...config + }: SubActionRequestParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise> { try { this.assertURL(url); this.ensureUriAllowed(url); @@ -160,6 +164,7 @@ export abstract class SubActionConnector { configurationUtilities: this.configurationUtilities, headers: this.getHeaders(auth, headers as AxiosHeaders), timeout, + connectorUsageCollector, }); this.validateResponse(responseSchema, res.data); diff --git a/x-pack/plugins/actions/server/types.ts b/x-pack/plugins/actions/server/types.ts index aa6c7b26cf0ae..487e7630d40f9 100644 --- a/x-pack/plugins/actions/server/types.ts +++ b/x-pack/plugins/actions/server/types.ts @@ -39,11 +39,11 @@ export type ActionTypeSecrets = Record; export type ActionTypeParams = Record; export type ConnectorTokenClientContract = PublicMethodsOf; -import type { ActionExecutionSource } from './lib'; import { Connector, ConnectorWithExtraFindData } from './application/connector/types'; -export type { ActionExecutionSource } from './lib'; - +import type { ActionExecutionSource } from './lib'; export { ActionExecutionSourceType } from './lib'; +import { ConnectorUsageCollector } from './usage'; +export { ConnectorUsageCollector } from './usage'; export interface Services { savedObjectsClient: SavedObjectsClientContract; @@ -88,6 +88,7 @@ export interface ActionTypeExecutorOptions< configurationUtilities: ActionsConfigurationUtilities; source?: ActionExecutionSource; request?: KibanaRequest; + connectorUsageCollector: ConnectorUsageCollector; } export type ActionResult = Connector; diff --git a/x-pack/plugins/actions/server/unsecured_actions_client/unsecured_actions_client.ts b/x-pack/plugins/actions/server/unsecured_actions_client/unsecured_actions_client.ts index 8331f6890486c..066c477947e2c 100644 --- a/x-pack/plugins/actions/server/unsecured_actions_client/unsecured_actions_client.ts +++ b/x-pack/plugins/actions/server/unsecured_actions_client/unsecured_actions_client.ts @@ -12,11 +12,8 @@ import { ExecuteOptions, ExecutionResponse, } from '../create_unsecured_execute_function'; -import { - ActionExecutorContract, - asNotificationExecutionSource, - type RelatedSavedObjects, -} from '../lib'; +import { ActionExecutorContract, asNotificationExecutionSource } from '../lib'; +import type { RelatedSavedObjects } from '../lib'; import { ActionTypeExecutorResult, InMemoryConnector } from '../types'; import { asBackgroundTaskExecutionSource } from '../lib/action_execution_source'; import { ConnectorWithExtraFindData } from '../application/connector/types'; diff --git a/x-pack/plugins/actions/server/usage/connector_usage_collector.test.ts b/x-pack/plugins/actions/server/usage/connector_usage_collector.test.ts new file mode 100644 index 0000000000000..dcf071685f24f --- /dev/null +++ b/x-pack/plugins/actions/server/usage/connector_usage_collector.test.ts @@ -0,0 +1,102 @@ +/* + * 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 { ConnectorUsageCollector } from '../types'; +import { AxiosHeaders, AxiosResponse } from 'axios'; +import { loggingSystemMock } from '@kbn/core/server/mocks'; + +describe('ConnectorUsageCollector', () => { + const logger = loggingSystemMock.createLogger(); + + test('it collects requestBodyBytes from response.request.headers', async () => { + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); + const data = { test: 'foo' }; + const contentLength = Buffer.byteLength(JSON.stringify(data), 'utf8'); + + const axiosResponse: AxiosResponse = { + data, + status: 200, + statusText: 'OK', + headers: {}, + config: { headers: new AxiosHeaders() }, + request: { + headers: { 'Content-Length': contentLength }, + getHeader: () => contentLength, + }, + }; + + connectorUsageCollector.addRequestBodyBytes(axiosResponse, data); + + expect(connectorUsageCollector.getRequestBodyByte()).toBe(contentLength); + + connectorUsageCollector.addRequestBodyBytes(axiosResponse, data); + + expect(connectorUsageCollector.getRequestBodyByte()).toBe(contentLength + contentLength); + }); + test('it collects requestBodyBytes from data when header is is missing', async () => { + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); + const data = { test: 'foo' }; + const contentLength = Buffer.byteLength(JSON.stringify(data), 'utf8'); + + const axiosResponse: AxiosResponse = { + data, + status: 200, + statusText: 'OK', + headers: {}, + config: { headers: new AxiosHeaders() }, + request: { + getHeader: () => undefined, + }, + }; + + connectorUsageCollector.addRequestBodyBytes(axiosResponse, data); + + expect(connectorUsageCollector.getRequestBodyByte()).toBe(contentLength); + + connectorUsageCollector.addRequestBodyBytes(axiosResponse, data); + + expect(connectorUsageCollector.getRequestBodyByte()).toBe(contentLength + contentLength); + }); + + test('it logs an error when the body cannot be stringified ', async () => { + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); + + const data = { + name: 'arun', + }; + + // @ts-ignore + data.foo = data; // this is to force JSON.stringify to throw + + const axiosResponse: AxiosResponse = { + data, + status: 200, + statusText: 'OK', + headers: {}, + config: { headers: new AxiosHeaders() }, + request: { + getHeader: () => undefined, + }, + }; + + connectorUsageCollector.addRequestBodyBytes(axiosResponse, data); + + expect(logger.error).toHaveBeenCalledTimes(1); + expect(logger.error).toHaveBeenCalledWith( + expect.stringContaining("Request body bytes couldn't be calculated, Error: ") + ); + }); +}); diff --git a/x-pack/plugins/actions/server/usage/connector_usage_collector.ts b/x-pack/plugins/actions/server/usage/connector_usage_collector.ts new file mode 100644 index 0000000000000..542be0ebf7c70 --- /dev/null +++ b/x-pack/plugins/actions/server/usage/connector_usage_collector.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { AxiosError, AxiosResponse } from 'axios'; +import { Logger } from '@kbn/core/server'; +import { isUndefined } from 'lodash'; + +interface ConnectorUsage { + requestBodyBytes: number; +} + +export class ConnectorUsageCollector { + private connectorId: string; + private usage: ConnectorUsage = { + requestBodyBytes: 0, + }; + + private logger: Logger; + + constructor({ logger, connectorId }: { logger: Logger; connectorId: string }) { + this.logger = logger; + this.connectorId = connectorId; + } + + public addRequestBodyBytes(result?: AxiosError | AxiosResponse, body: string | object = '') { + const contentLength = result?.request?.getHeader('content-length'); + let bytes = 0; + + if (!isUndefined(contentLength)) { + bytes = parseInt(contentLength, 10); + } else { + try { + const sBody = typeof body === 'string' ? body : JSON.stringify(body); + bytes = Buffer.byteLength(sBody, 'utf8'); + } catch (e) { + this.logger.error( + `Request body bytes couldn't be calculated, Error: ${e.message}, connectorId:${this.connectorId}` + ); + } + } + + this.usage.requestBodyBytes = this.usage.requestBodyBytes + bytes; + } + + public getRequestBodyByte() { + return this.usage.requestBodyBytes; + } +} diff --git a/x-pack/plugins/actions/server/usage/index.ts b/x-pack/plugins/actions/server/usage/index.ts index 722ad76014f07..d4faf364b7295 100644 --- a/x-pack/plugins/actions/server/usage/index.ts +++ b/x-pack/plugins/actions/server/usage/index.ts @@ -6,3 +6,4 @@ */ export { registerActionsUsageCollector } from './actions_usage_collector'; +export { ConnectorUsageCollector } from './connector_usage_collector'; diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table.tsx index 38cf611b4bdd1..f6f3ea0f4d9db 100644 --- a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table.tsx +++ b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table.tsx @@ -104,7 +104,7 @@ export const LogRateAnalysisResultsTable: FC = groupFilter !== undefined ); - const onChange = useCallback((tableSettings) => { + const onChange = useCallback((tableSettings: any) => { if (tableSettings.page) { const { index, size } = tableSettings.page; setPageIndex(index); diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table_groups.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table_groups.tsx index 905ac53b149ca..d69a0fec7200f 100644 --- a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table_groups.tsx +++ b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table_groups.tsx @@ -247,7 +247,7 @@ export const LogRateAnalysisResultsGroupsTable: FC { + const onChange = useCallback((tableSettings: any) => { if (tableSettings.page) { const { index, size } = tableSettings.page; setPageIndex(index); diff --git a/x-pack/plugins/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.tsx b/x-pack/plugins/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.tsx index cd69f972c675a..e74f3117d55f9 100644 --- a/x-pack/plugins/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.tsx +++ b/x-pack/plugins/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.tsx @@ -9,6 +9,7 @@ import moment from 'moment'; import { FIELD_TYPES, Form, + FormSubmitHandler, getUseField, useForm, useFormData, @@ -136,7 +137,7 @@ export const CreateMaintenanceWindowForm = React.memo>( async (formData, isValid) => { if (!isValid || scopedQueryErrors.length !== 0) { return; diff --git a/x-pack/plugins/alerting/public/pages/maintenance_windows/components/maintenance_windows_list.tsx b/x-pack/plugins/alerting/public/pages/maintenance_windows/components/maintenance_windows_list.tsx index dd396057e3724..7e474859981ef 100644 --- a/x-pack/plugins/alerting/public/pages/maintenance_windows/components/maintenance_windows_list.tsx +++ b/x-pack/plugins/alerting/public/pages/maintenance_windows/components/maintenance_windows_list.tsx @@ -29,7 +29,7 @@ import { MaintenanceWindow, } from '../../../../common'; import { StatusFilter } from './status_filter'; -import { TableActionsPopover } from './table_actions_popover'; +import { TableActionsPopover, TableActionsPopoverProps } from './table_actions_popover'; import { useFinishMaintenanceWindow } from '../../../hooks/use_finish_maintenance_window'; import { useArchiveMaintenanceWindow } from '../../../hooks/use_archive_maintenance_window'; import { useFinishAndArchiveMaintenanceWindow } from '../../../hooks/use_finish_and_archive_maintenance_window'; @@ -115,13 +115,13 @@ export const MaintenanceWindowsList = React.memo( }; const { euiTheme } = useEuiTheme(); const { navigateToEditMaintenanceWindows } = useEditMaintenanceWindowsNavigation(); - const onEdit = useCallback( + const onEdit = useCallback( (id) => navigateToEditMaintenanceWindows(id), [navigateToEditMaintenanceWindows] ); const { mutate: finishMaintenanceWindow, isLoading: isLoadingFinish } = useFinishMaintenanceWindow(); - const onCancel = useCallback( + const onCancel = useCallback( (id) => finishMaintenanceWindow(id, { onSuccess: () => refreshData() }), [finishMaintenanceWindow, refreshData] ); diff --git a/x-pack/plugins/alerting/public/pages/maintenance_windows/components/table_actions_popover.tsx b/x-pack/plugins/alerting/public/pages/maintenance_windows/components/table_actions_popover.tsx index ffe0509c1fd32..c91f518f6976f 100644 --- a/x-pack/plugins/alerting/public/pages/maintenance_windows/components/table_actions_popover.tsx +++ b/x-pack/plugins/alerting/public/pages/maintenance_windows/components/table_actions_popover.tsx @@ -18,7 +18,7 @@ import { import * as i18n from '../translations'; import { MaintenanceWindowStatus } from '../../../../common'; -interface TableActionsPopoverProps { +export interface TableActionsPopoverProps { id: string; status: MaintenanceWindowStatus; onEdit: (id: string) => void; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.test.ts b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.test.ts index f43ffc6096dcf..c7c795359aaee 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.test.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.test.ts @@ -3214,7 +3214,8 @@ describe('bulkEdit()', () => { value: ['test-1'], }, ], - paramsModifier: async (params) => { + paramsModifier: async (rule) => { + const params = rule.params; params.index = ['test-index-*']; return { modifiedParams: params, isParamsUpdateSkipped: false, skipReasons: [] }; @@ -3431,7 +3432,8 @@ describe('bulkEdit()', () => { value: ['test-1'], }, ], - paramsModifier: async (params) => { + paramsModifier: async (rule) => { + const params = rule.params; params.index = ['test-index-*']; return { modifiedParams: params, isParamsUpdateSkipped: false, skipReasons: [] }; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts index 8bd10fe722c1d..81dd189116949 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.ts @@ -16,7 +16,7 @@ import { SavedObjectsUpdateResponse, } from '@kbn/core/server'; import { validateAndAuthorizeSystemActions } from '../../../../lib/validate_authorize_system_actions'; -import { RuleAction, RuleSystemAction } from '../../../../../common'; +import { Rule, RuleAction, RuleSystemAction } from '../../../../../common'; import { RULE_SAVED_OBJECT_TYPE } from '../../../../saved_objects'; import { BulkActionSkipResult } from '../../../../../common/bulk_edit'; import { RuleTypeRegistry } from '../../../../types'; @@ -505,7 +505,8 @@ async function updateRuleAttributesAndParamsInMemory( validateScheduleInterval(context, updatedRule.schedule.interval, ruleType.id, rule.id); const { modifiedParams: ruleParams, isParamsUpdateSkipped } = paramsModifier - ? await paramsModifier(updatedRule.params) + ? // TODO (http-versioning): Remove the cast when all rule types are fixed + await paramsModifier(updatedRule as Rule) : { modifiedParams: updatedRule.params, isParamsUpdateSkipped: true, diff --git a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/types/bulk_edit_rules_options.ts b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/types/bulk_edit_rules_options.ts index c099cde044363..7c30f6583865e 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/types/bulk_edit_rules_options.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/types/bulk_edit_rules_options.ts @@ -12,14 +12,15 @@ import { bulkEditOperationsSchema, bulkEditOperationSchema, } from '../schemas'; -import { RuleParams, RuleDomain, Rule } from '../../../types'; +import { RuleParams, RuleDomain } from '../../../types'; +import { Rule } from '../../../../../../common'; export type BulkEditRuleSnoozeSchedule = TypeOf; export type BulkEditOperation = TypeOf; export type BulkEditOperations = TypeOf; export type ParamsModifier = ( - params: Params + rule: Rule ) => Promise>; interface ParamsModifierResult { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/vis_dimension.tsx b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/vis_dimension.tsx index 89c3cf35a7c36..488abfcc80e0a 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/vis_dimension.tsx +++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/vis_dimension.tsx @@ -6,7 +6,7 @@ */ import React, { useState, useEffect, useCallback } from 'react'; -import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSelect } from '@elastic/eui'; +import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSelect, EuiSelectProps } from '@elastic/eui'; import { DatatableColumn, ExpressionAstExpression } from '@kbn/expressions-plugin/common'; import { templateFromReactComponent } from '../../../public/lib/template_from_react_component'; import { ArgumentStrings } from '../../../i18n'; @@ -15,7 +15,7 @@ import { ResolvedArgProps, ResolvedColumns } from '../../../public/expression_ty const { VisDimension: strings } = ArgumentStrings; type VisDimensionArgInputProps = { - onValueChange: (value: ExpressionAstExpression) => void; + onValueChange: (value: ExpressionAstExpression | string) => void; argValue: ExpressionAstExpression; typeInstance: { options?: { @@ -30,14 +30,14 @@ const VisDimensionArgInput: React.FC = ({ onValueChange, resolved: { columns }, }) => { - const [value, setValue] = useState(argValue); + const [value, setValue] = useState(argValue); const confirm = typeInstance?.options?.confirm; useEffect(() => { setValue(argValue); }, [argValue]); - const onChange = useCallback( + const onChange = useCallback>( (ev) => { const onChangeFn = confirm ? setValue : onValueChange; const astObj: ExpressionAstExpression = { diff --git a/x-pack/plugins/canvas/kibana.jsonc b/x-pack/plugins/canvas/kibana.jsonc index 1f6a3bf5554b4..f752f37443fef 100644 --- a/x-pack/plugins/canvas/kibana.jsonc +++ b/x-pack/plugins/canvas/kibana.jsonc @@ -12,7 +12,6 @@ "canvas" ], "requiredPlugins": [ - "bfetch", "charts", "data", "dataViews", diff --git a/x-pack/plugins/canvas/public/components/arg_form/arg_template_form.tsx b/x-pack/plugins/canvas/public/components/arg_form/arg_template_form.tsx index 053cda9dd03f3..f2abceff1f67f 100644 --- a/x-pack/plugins/canvas/public/components/arg_form/arg_template_form.tsx +++ b/x-pack/plugins/canvas/public/components/arg_form/arg_template_form.tsx @@ -59,14 +59,18 @@ const ArgTemplateFormComponent: React.FunctionComponent = mountedArgumentRef.current = undefined; }); - const onMount = useCallback((ref) => { - if (!mountedArgumentRef.current && ref) { - mountedArgumentRef.current = ref; - } - }, []); + const onMount = useCallback( + (ref: UpdatePropsRef | null) => { + if (!mountedArgumentRef.current && ref) { + mountedArgumentRef.current = ref; + } + }, + [] + ); const renderTemplate = useCallback( - (domNode) => template && template(domNode, argumentProps, updatedHandlers, onMount), + (domNode: HTMLElement) => + template && template(domNode, argumentProps, updatedHandlers, onMount), [argumentProps, onMount, template, updatedHandlers] ); diff --git a/x-pack/plugins/canvas/public/components/var_config/var_value_field.tsx b/x-pack/plugins/canvas/public/components/var_config/var_value_field.tsx index 24b9a82e32e5c..6b91497fa0f64 100644 --- a/x-pack/plugins/canvas/public/components/var_config/var_value_field.tsx +++ b/x-pack/plugins/canvas/public/components/var_config/var_value_field.tsx @@ -48,7 +48,7 @@ export const VarValueField: FC = ({ type, value, onChange }) => { ]; const onNumberChange = useCallback( - (e) => { + (e: React.ChangeEvent) => { const floatVal = parseFloat(e.target.value); const varValue = isNaN(floatVal) ? '' : floatVal; onChange(varValue); diff --git a/x-pack/plugins/canvas/public/components/workpad/workpad.tsx b/x-pack/plugins/canvas/public/components/workpad/workpad.tsx index 7cc077203c737..1e604a6deb850 100644 --- a/x-pack/plugins/canvas/public/components/workpad/workpad.tsx +++ b/x-pack/plugins/canvas/public/components/workpad/workpad.tsx @@ -74,7 +74,7 @@ export const Workpad: FC = (props) => { ); const getAnimation = useCallback( - (pageNumber) => { + (pageNumber: number) => { if (!transition || !transition.name) { return null; } @@ -94,7 +94,7 @@ export const Workpad: FC = (props) => { const onTransitionEnd = useCallback(() => setTransition(null), [setTransition]); const setFullscreenWithEffect = useCallback( - (fullscreen) => { + (fullscreen: boolean) => { setFullscreen(fullscreen); if (fullscreen === true) { trackCanvasUiMetric( diff --git a/x-pack/plugins/canvas/public/components/workpad_color_picker/workpad_color_picker.component.tsx b/x-pack/plugins/canvas/public/components/workpad_color_picker/workpad_color_picker.component.tsx index c14e54d8e8549..64e0c259cd048 100644 --- a/x-pack/plugins/canvas/public/components/workpad_color_picker/workpad_color_picker.component.tsx +++ b/x-pack/plugins/canvas/public/components/workpad_color_picker/workpad_color_picker.component.tsx @@ -21,8 +21,11 @@ const strings = { export const WorkpadColorPicker = (props: Props) => { const dispatch = useDispatch(); - const onAddColor = useCallback((payload) => dispatch(addColor(payload)), [dispatch]); - const onRemoveColor = useCallback((payload) => dispatch(removeColor(payload)), [dispatch]); + const onAddColor = useCallback((payload: string) => dispatch(addColor(payload)), [dispatch]); + const onRemoveColor = useCallback( + (payload: string) => dispatch(removeColor(payload)), + [dispatch] + ); const colors = useSelector(getWorkpadColors); return ( diff --git a/x-pack/plugins/canvas/public/expression_types/datasource.tsx b/x-pack/plugins/canvas/public/expression_types/datasource.tsx index a7d5cd4e7a2b4..f7bd89200cfda 100644 --- a/x-pack/plugins/canvas/public/expression_types/datasource.tsx +++ b/x-pack/plugins/canvas/public/expression_types/datasource.tsx @@ -61,12 +61,12 @@ const DatasourceWrapperComponent: React.FunctionComponent { + const onMount = useCallback((ref: UpdatePropsRef | null) => { datasourceRef.current = ref ?? undefined; }, []); const callRenderFn = useCallback( - (domNode) => { + (domNode: HTMLDivElement) => { const { template } = spec; if (!template) { return null; diff --git a/x-pack/plugins/canvas/public/plugin.tsx b/x-pack/plugins/canvas/public/plugin.tsx index 495dea5873f95..5f385ce5f079b 100644 --- a/x-pack/plugins/canvas/public/plugin.tsx +++ b/x-pack/plugins/canvas/public/plugin.tsx @@ -27,7 +27,6 @@ import { UiActionsSetup, UiActionsStart } from '@kbn/ui-actions-plugin/public'; import { EmbeddableStart } from '@kbn/embeddable-plugin/public'; import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; import { Start as InspectorStart } from '@kbn/inspector-plugin/public'; -import { BfetchPublicSetup } from '@kbn/bfetch-plugin/public'; import { PresentationUtilPluginStart } from '@kbn/presentation-util-plugin/public'; import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public'; @@ -53,7 +52,6 @@ export interface CanvasSetupDeps { expressions: ExpressionsSetup; home?: HomePublicPluginSetup; usageCollection?: UsageCollectionSetup; - bfetch: BfetchPublicSetup; charts: ChartsPluginSetup; uiActions: UiActionsSetup; } diff --git a/x-pack/plugins/canvas/public/setup_expressions.ts b/x-pack/plugins/canvas/public/setup_expressions.ts index 655daef80f856..848fb9a12b0cd 100644 --- a/x-pack/plugins/canvas/public/setup_expressions.ts +++ b/x-pack/plugins/canvas/public/setup_expressions.ts @@ -21,7 +21,7 @@ export const setupExpressions = async ({ coreSetup: CoreSetup; setupPlugins: CanvasSetupDeps; }) => { - const { expressions, bfetch } = setupPlugins; + const { expressions } = setupPlugins; const loadServerFunctionWrappers = async () => { if (!cached) { @@ -29,7 +29,6 @@ export const setupExpressions = async ({ const serverFunctionList = await coreSetup.http.get(API_ROUTE_FUNCTIONS, { version: '1', }); - const batchedFunction = bfetch.batchedFunction({ url: API_ROUTE_FUNCTIONS }); const { serialize } = serializeProvider(expressions.getTypes()); // For every sever-side function, register a client-side @@ -43,7 +42,10 @@ export const setupExpressions = async ({ const fn = () => ({ ...serverFunctionList[functionName], fn: (input: any, args: any) => { - return batchedFunction({ functionName, args, context: serialize(input) }); + return coreSetup.http.post(API_ROUTE_FUNCTIONS, { + body: JSON.stringify({ functionName, args, context: serialize(input) }), + version: '1', + }); }, }); diff --git a/x-pack/plugins/canvas/server/plugin.ts b/x-pack/plugins/canvas/server/plugin.ts index 36a6fbbd0e3e2..074d29ec977f9 100644 --- a/x-pack/plugins/canvas/server/plugin.ts +++ b/x-pack/plugins/canvas/server/plugin.ts @@ -11,7 +11,6 @@ import { PluginStart as DataPluginStart, } from '@kbn/data-plugin/server'; import { ExpressionsServerSetup } from '@kbn/expressions-plugin/server'; -import { BfetchServerSetup } from '@kbn/bfetch-plugin/server'; import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import { HomeServerPluginSetup } from '@kbn/home-plugin/server'; import { EmbeddableSetup } from '@kbn/embeddable-plugin/server'; @@ -33,7 +32,6 @@ interface PluginsSetup { embeddable: EmbeddableSetup; features: FeaturesPluginSetup; home: HomeServerPluginSetup; - bfetch: BfetchServerSetup; data: DataPluginSetup; reporting?: ReportingServerPluginSetup; usageCollection?: UsageCollectionSetup; @@ -81,7 +79,6 @@ export class CanvasPlugin implements Plugin { initRoutes({ router: canvasRouter, expressions: expressionsSetup, - bfetch: plugins.bfetch, logger: this.logger, }); diff --git a/x-pack/plugins/canvas/server/routes/functions/functions.ts b/x-pack/plugins/canvas/server/routes/functions/functions.ts index 73036b35af05b..3a8ff207fa000 100644 --- a/x-pack/plugins/canvas/server/routes/functions/functions.ts +++ b/x-pack/plugins/canvas/server/routes/functions/functions.ts @@ -6,6 +6,7 @@ */ import { serializeProvider } from '@kbn/expressions-plugin/common'; +import { schema } from '@kbn/config-schema'; import { RouteInitializerDeps } from '..'; import { API_ROUTE_FUNCTIONS } from '../../../common/lib/constants'; @@ -32,7 +33,43 @@ export function initializeGetFunctionsRoute(deps: RouteInitializerDeps) { } export function initializeBatchFunctionsRoute(deps: RouteInitializerDeps) { - const { bfetch, expressions } = deps; + const { router, expressions } = deps; + router.versioned + .post({ + path: API_ROUTE_FUNCTIONS, + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: { + request: { + body: schema.object({ + functionName: schema.string(), + args: schema.object({}, { unknowns: 'allow' }), + context: schema.object({}, { unknowns: 'allow' }), + }), + }, + }, + }, + async (context, request, response) => { + const handlers = { + environment: 'server', + }; + const fnCall: FunctionCall = { + functionName: request.body.functionName, + args: request.body.args, + context: request.body.context, + }; + const result = await runFunction(handlers, fnCall); + if (typeof result === 'undefined') { + throw new Error(`Function ${fnCall.functionName} did not return anything.`); + } + return response.ok({ + body: result, + }); + } + ); async function runFunction(handlers: { environment: string }, fnCall: FunctionCall) { const { functionName, args, context } = fnCall; @@ -46,23 +83,4 @@ export function initializeBatchFunctionsRoute(deps: RouteInitializerDeps) { return result; } - - /** - * Register an endpoint that executes a batch of functions, and streams the - * results back using ND-JSON. - */ - bfetch.addBatchProcessingRoute(API_ROUTE_FUNCTIONS, (request) => { - return { - onBatchItem: async (fnCall: FunctionCall) => { - const handlers = { - environment: 'server', - }; - const result = await runFunction(handlers, fnCall); - if (typeof result === 'undefined') { - throw new Error(`Function ${fnCall.functionName} did not return anything.`); - } - return result; - }, - }; - }); } diff --git a/x-pack/plugins/canvas/server/routes/index.ts b/x-pack/plugins/canvas/server/routes/index.ts index 9b2d712b17c5f..80dc1b56e3dba 100644 --- a/x-pack/plugins/canvas/server/routes/index.ts +++ b/x-pack/plugins/canvas/server/routes/index.ts @@ -7,7 +7,6 @@ import { IRouter, Logger } from '@kbn/core/server'; import { ExpressionsServerSetup } from '@kbn/expressions-plugin/server'; -import { BfetchServerSetup } from '@kbn/bfetch-plugin/server'; import { initCustomElementsRoutes } from './custom_elements'; import { initShareablesRoutes } from './shareables'; import { initWorkpadRoutes } from './workpad'; @@ -19,7 +18,6 @@ export interface RouteInitializerDeps { router: IRouter; logger: Logger; expressions: ExpressionsServerSetup; - bfetch: BfetchServerSetup; } export function initRoutes(deps: RouteInitializerDeps) { diff --git a/x-pack/plugins/canvas/server/routes/test_helpers.ts b/x-pack/plugins/canvas/server/routes/test_helpers.ts index 30d63576ed6f2..ded9076909cb9 100644 --- a/x-pack/plugins/canvas/server/routes/test_helpers.ts +++ b/x-pack/plugins/canvas/server/routes/test_helpers.ts @@ -10,13 +10,11 @@ import { loggingSystemMock, elasticsearchServiceMock, } from '@kbn/core/server/mocks'; -import { bfetchPluginMock } from '@kbn/bfetch-plugin/server/mocks'; import { expressionsPluginMock } from '@kbn/expressions-plugin/server/mocks'; export function getMockedRouterDeps() { const httpService = httpServiceMock.createSetupContract(); const elasticsearch = elasticsearchServiceMock.createSetup(); - const bfetch = bfetchPluginMock.createSetupContract(); const expressions = expressionsPluginMock.createSetupContract(); const router = httpService.createRouter(); @@ -24,7 +22,6 @@ export function getMockedRouterDeps() { router, expressions, elasticsearch, - bfetch, logger: loggingSystemMock.create().get(), }; } diff --git a/x-pack/plugins/canvas/tsconfig.json b/x-pack/plugins/canvas/tsconfig.json index 124d2c660e9fe..85121b72c868c 100644 --- a/x-pack/plugins/canvas/tsconfig.json +++ b/x-pack/plugins/canvas/tsconfig.json @@ -27,7 +27,6 @@ "kbn_references": [ { "path": "../../../src/setup_node_env/tsconfig.json" }, "@kbn/core", - "@kbn/bfetch-plugin", "@kbn/charts-plugin", "@kbn/data-plugin", "@kbn/share-plugin", diff --git a/x-pack/plugins/cases/public/components/actions/assignees/edit_assignees_selectable.tsx b/x-pack/plugins/cases/public/components/actions/assignees/edit_assignees_selectable.tsx index d3a4d9cbb06e1..0d4bd261647d1 100644 --- a/x-pack/plugins/cases/public/components/actions/assignees/edit_assignees_selectable.tsx +++ b/x-pack/plugins/cases/public/components/actions/assignees/edit_assignees_selectable.tsx @@ -198,7 +198,7 @@ const EditAssigneesSelectableComponent: React.FC = ({ ); const onSearchChange = useCallback( - (value) => { + (value: string) => { setSearchValue(value); onContentChange(value); }, diff --git a/x-pack/plugins/cases/public/components/actions/tags/edit_tags_selectable.tsx b/x-pack/plugins/cases/public/components/actions/tags/edit_tags_selectable.tsx index 17cf9939f8145..947228ce9b136 100644 --- a/x-pack/plugins/cases/public/components/actions/tags/edit_tags_selectable.tsx +++ b/x-pack/plugins/cases/public/components/actions/tags/edit_tags_selectable.tsx @@ -120,10 +120,6 @@ const EditTagsSelectableComponent: React.FC = ({ [options, searchValue, state.items] ); - const onSearchChange = useCallback((value) => { - setSearchValue(value); - }, []); - return ( = ({ placeholder: i18n.SEARCH_PLACEHOLDER, isLoading, isClearable: !isLoading, - onChange: onSearchChange, + onChange: setSearchValue, value: searchValue, 'data-test-subj': 'cases-actions-tags-edit-selectable-search-input', }} diff --git a/x-pack/plugins/cases/public/components/add_comment/index.tsx b/x-pack/plugins/cases/public/components/add_comment/index.tsx index 009594df200f7..c84f799b1c899 100644 --- a/x-pack/plugins/cases/public/components/add_comment/index.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/index.tsx @@ -26,7 +26,7 @@ import { import { AttachmentType } from '../../../common/types/domain'; import { useCreateAttachments } from '../../containers/use_create_attachments'; import type { CaseUI } from '../../containers/types'; -import type { EuiMarkdownEditorRef } from '../markdown_editor'; +import type { MarkdownEditorRef } from '../markdown_editor'; import { MarkdownEditorForm } from '../markdown_editor'; import { getMarkdownEditorStorageKey } from '../markdown_editor/utils'; import { removeItemFromSessionStorage } from '../utils'; @@ -45,7 +45,7 @@ const initialCommentValue: AddCommentFormSchema = { export interface AddCommentRefObject { addQuote: (quote: string) => void; setComment: (newComment: string) => void; - editor: EuiMarkdownEditorRef | null; + editor: MarkdownEditorRef | null; } /* eslint-disable react/no-unused-prop-types */ @@ -65,7 +65,7 @@ export const AddComment = React.memo( { id, caseId, onCommentPosted, onCommentSaving, showLoading = true, statusActionButton }, ref ) => { - const editorRef = useRef(null); + const editorRef = useRef(null); const [focusOnContext, setFocusOnContext] = useState(false); const { permissions, owner } = useCasesContext(); const { isLoading, mutate: createAttachments } = useCreateAttachments(); @@ -85,7 +85,7 @@ export const AddComment = React.memo( const { setFieldValue, reset, submit } = form; const [{ comment }] = useFormData<{ comment: string }>({ form, watch: [fieldName] }); - const addQuote = useCallback( + const addQuote = useCallback( (quote) => { const addCarrots = quote.replace(new RegExp('\r?\n', 'g'), '\n> '); const val = `> ${addCarrots} \n\n`; @@ -95,7 +95,7 @@ export const AddComment = React.memo( [comment, setFieldValue] ); - const setComment = useCallback( + const setComment = useCallback( (newComment) => { setFieldValue(fieldName, newComment); }, diff --git a/x-pack/plugins/cases/public/components/all_cases/nav_buttons.tsx b/x-pack/plugins/cases/public/components/all_cases/nav_buttons.tsx index 29b0607ec62af..310340f0366eb 100644 --- a/x-pack/plugins/cases/public/components/all_cases/nav_buttons.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/nav_buttons.tsx @@ -27,7 +27,7 @@ export const NavButtons: FunctionComponent = ({ actionsErrors }) => { const { getCreateCaseUrl, navigateToCreateCase } = useCreateCaseNavigation(); const { euiTheme } = useEuiTheme(); const navigateToCreateCaseClick = useCallback( - (e) => { + (e: React.SyntheticEvent) => { e.preventDefault(); navigateToCreateCase(); }, diff --git a/x-pack/plugins/cases/public/components/all_cases/search.tsx b/x-pack/plugins/cases/public/components/all_cases/search.tsx index 265c42470cdbd..542ebf9e0c51d 100644 --- a/x-pack/plugins/cases/public/components/all_cases/search.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/search.tsx @@ -22,7 +22,7 @@ const TableSearchComponent: React.FC = ({ const [search, setSearch] = useState(filterOptionsSearch); const onSearch = useCallback( - (newSearch) => { + (newSearch: string) => { const trimSearch = newSearch.trim(); setSearch(trimSearch); onFilterOptionsChange({ search: trimSearch }); diff --git a/x-pack/plugins/cases/public/components/all_cases/table.tsx b/x-pack/plugins/cases/public/components/all_cases/table.tsx index c2b429f4789eb..c95059660b3e4 100644 --- a/x-pack/plugins/cases/public/components/all_cases/table.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/table.tsx @@ -59,7 +59,7 @@ export const CasesTable: FunctionComponent = ({ const { getCreateCaseUrl, navigateToCreateCase } = useCreateCaseNavigation(); const { euiTheme } = useEuiTheme(); const navigateToCreateCaseClick = useCallback( - (ev) => { + (ev: React.SyntheticEvent) => { ev.preventDefault(); if (goToCreateCase != null) { goToCreateCase(); diff --git a/x-pack/plugins/cases/public/components/app/routes.tsx b/x-pack/plugins/cases/public/components/app/routes.tsx index 501cd665ff24b..ee2c82777dbf6 100644 --- a/x-pack/plugins/cases/public/components/app/routes.tsx +++ b/x-pack/plugins/cases/public/components/app/routes.tsx @@ -28,6 +28,7 @@ import { NoPrivilegesPage } from '../no_privileges'; import * as i18n from './translations'; import { useReadonlyHeader } from './use_readonly_header'; import type { CaseViewProps } from '../case_view/types'; +import type { CreateCaseFormProps } from '../create/form'; const CaseViewLazy: React.FC = lazy(() => import('../case_view')); @@ -45,7 +46,7 @@ const CasesRoutesComponent: React.FC = ({ const { navigateToCaseView } = useCaseViewNavigation(); useReadonlyHeader(); - const onCreateCaseSuccess = useCallback( + const onCreateCaseSuccess: CreateCaseFormProps['onSuccess'] = useCallback( async ({ id }) => navigateToCaseView({ detailName: id }), [navigateToCaseView] ); diff --git a/x-pack/plugins/cases/public/components/case_view/case_view_page.tsx b/x-pack/plugins/cases/public/components/case_view/case_view_page.tsx index adc2b41f6ce6a..add85202d0e55 100644 --- a/x-pack/plugins/cases/public/components/case_view/case_view_page.tsx +++ b/x-pack/plugins/cases/public/components/case_view/case_view_page.tsx @@ -73,7 +73,7 @@ export const CaseViewPage = React.memo( }, [isLoading, refreshRef, refreshCaseViewPage]); const onSubmitTitle = useCallback( - (newTitle) => + (newTitle: string) => onUpdateField({ key: 'title', value: newTitle, diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx index d0e5cefa458a4..6e945ef836272 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx @@ -25,6 +25,7 @@ import { useGetSupportedActionConnectors } from '../../../containers/configure/u import type { CaseSeverity, CaseStatuses } from '../../../../common/types/domain'; import type { CaseUICustomField, UseFetchAlertData } from '../../../../common/ui/types'; import type { CaseUI } from '../../../../common'; +import type { EditConnectorProps } from '../../edit_connector'; import { EditConnector } from '../../edit_connector'; import type { CasesNavigation } from '../../links'; import { StatusActionButton } from '../../status/button'; @@ -115,12 +116,12 @@ export const CaseViewActivity = ({ ); const onSubmitTags = useCallback( - (newTags) => onUpdateField({ key: 'tags', value: newTags }), + (newTags: string[]) => onUpdateField({ key: 'tags', value: newTags }), [onUpdateField] ); const onSubmitCategory = useCallback( - (newCategory) => onUpdateField({ key: 'category', value: newCategory }), + (newCategory: string | null) => onUpdateField({ key: 'category', value: newCategory }), [onUpdateField] ); @@ -142,7 +143,7 @@ export const CaseViewActivity = ({ const { isLoading: isLoadingAllAvailableConnectors, data: supportedActionConnectors } = useGetSupportedActionConnectors(); - const onSubmitConnector = useCallback( + const onSubmitConnector = useCallback( (connector) => { onUpdateField({ key: 'connector', diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_files.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_files.tsx index 85cd4685a41fb..25f6929fbb81b 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_files.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_files.tsx @@ -57,7 +57,7 @@ export const CaseViewFiles = ({ caseData }: CaseViewFilesProps) => { ); const onSearchChange = useCallback( - (newSearch) => { + (newSearch: string) => { const trimSearch = newSearch.trim(); if (!isEqual(trimSearch, filteringOptions.searchTerm)) { setFilteringOptions({ diff --git a/x-pack/plugins/cases/public/components/case_view/components/custom_fields.tsx b/x-pack/plugins/cases/public/components/case_view/components/custom_fields.tsx index 32d03bac8dc8e..c30e2b1767eed 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/custom_fields.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/custom_fields.tsx @@ -33,7 +33,7 @@ const CustomFieldsComponent: React.FC = ({ ); const onSubmitCustomField = useCallback( - (customFieldToAdd) => { + (customFieldToAdd: CaseUICustomField) => { onSubmit(customFieldToAdd); }, [onSubmit] diff --git a/x-pack/plugins/cases/public/components/case_view/components/edit_category.tsx b/x-pack/plugins/cases/public/components/case_view/components/edit_category.tsx index f4992f96d9856..460fa364bc4d7 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/edit_category.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/edit_category.tsx @@ -28,7 +28,7 @@ import { RemovableItem } from '../../removable_item/removable_item'; export interface EditCategoryProps { isLoading: boolean; - onSubmit: (category?: string | null) => void; + onSubmit: (category: string | null) => void; category?: string | null; } diff --git a/x-pack/plugins/cases/public/components/description/index.tsx b/x-pack/plugins/cases/public/components/description/index.tsx index 78440cf9b7f1e..6599bc3ef43cb 100644 --- a/x-pack/plugins/cases/public/components/description/index.tsx +++ b/x-pack/plugins/cases/public/components/description/index.tsx @@ -21,7 +21,7 @@ import { getMarkdownEditorStorageKey } from '../markdown_editor/utils'; import * as i18n from '../user_actions/translations'; import { useCasesContext } from '../cases_context/use_cases_context'; import { useLensDraftComment } from '../markdown_editor/plugins/lens/use_lens_draft_comment'; -import type { EditableMarkdownRefObject, EuiMarkdownEditorRef } from '../markdown_editor'; +import type { EditableMarkdownRefObject, MarkdownEditorRef } from '../markdown_editor'; import { EditableMarkdown, ScrollableMarkdown } from '../markdown_editor'; import type { CaseUI } from '../../containers/types'; import type { OnUpdateFields } from '../case_view/types'; @@ -30,7 +30,7 @@ import { schema } from './schema'; const DESCRIPTION_ID = 'description'; export interface DescriptionMarkdownRefObject extends EditableMarkdownRefObject { - editor: EuiMarkdownEditorRef | null; + editor: MarkdownEditorRef | null; } export interface DescriptionProps { caseData: CaseUI; diff --git a/x-pack/plugins/cases/public/components/files/add_file.tsx b/x-pack/plugins/cases/public/components/files/add_file.tsx index 449e9bf269923..7b91879834a78 100644 --- a/x-pack/plugins/cases/public/components/files/add_file.tsx +++ b/x-pack/plugins/cases/public/components/files/add_file.tsx @@ -31,6 +31,7 @@ import { useCasesContext } from '../cases_context/use_cases_context'; import * as i18n from './translations'; import { useRefreshCaseViewPage } from '../case_view/use_on_refresh_case_view_page'; import { deleteFileAttachments } from '../../containers/api'; +import type { ServerError } from '../../types'; interface AddFileProps { caseId: string; @@ -47,7 +48,7 @@ const AddFileComponent: React.FC = ({ caseId }) => { const showModal = () => setIsModalVisible(true); const onError = useCallback( - (error) => { + (error: Error | ServerError) => { showErrorToast(error, { title: i18n.FAILED_UPLOAD, }); diff --git a/x-pack/plugins/cases/public/components/filter_popover/index.tsx b/x-pack/plugins/cases/public/components/filter_popover/index.tsx index 60b7964761499..142a8aac8833a 100644 --- a/x-pack/plugins/cases/public/components/filter_popover/index.tsx +++ b/x-pack/plugins/cases/public/components/filter_popover/index.tsx @@ -62,7 +62,7 @@ export const FilterPopoverComponent = ({ const setIsPopoverOpenCb = useCallback(() => setIsPopoverOpen(!isPopoverOpen), [isPopoverOpen]); const toggleSelectedGroupCb = useCallback( - (option) => onSelectedOptionsChanged(toggleSelectedGroup(option, selectedOptions)), + (option: string) => onSelectedOptionsChanged(toggleSelectedGroup(option, selectedOptions)), [selectedOptions, onSelectedOptionsChanged] ); diff --git a/x-pack/plugins/cases/public/components/header_page/index.tsx b/x-pack/plugins/cases/public/components/header_page/index.tsx index 60aa4a9160cf8..1901700fe428d 100644 --- a/x-pack/plugins/cases/public/components/header_page/index.tsx +++ b/x-pack/plugins/cases/public/components/header_page/index.tsx @@ -56,7 +56,7 @@ const HeaderPageComponent: React.FC = ({ const xsFontSize = useEuiFontSize('xs').fontSize; const navigateToAllCasesClick = useCallback( - (e) => { + (e: React.SyntheticEvent) => { if (e) { e.preventDefault(); } diff --git a/x-pack/plugins/cases/public/components/links/index.tsx b/x-pack/plugins/cases/public/components/links/index.tsx index f09a9f852a28f..cc6e29da8008c 100644 --- a/x-pack/plugins/cases/public/components/links/index.tsx +++ b/x-pack/plugins/cases/public/components/links/index.tsx @@ -44,7 +44,7 @@ const CaseDetailsLinkComponent: React.FC = ({ }) => { const { getCaseViewUrl, navigateToCaseView } = useCaseViewNavigation(); const navigateToCaseViewClick = useCallback( - (ev) => { + (ev: React.SyntheticEvent) => { ev.preventDefault(); navigateToCaseView({ detailName }); }, @@ -83,7 +83,7 @@ const ConfigureCaseButtonComponent: React.FC = ({ const { getConfigureCasesUrl, navigateToConfigureCases } = useConfigureCasesNavigation(); const navigateToConfigureCasesClick = useCallback( - (e) => { + (e: React.SyntheticEvent) => { e.preventDefault(); navigateToConfigureCases(); }, diff --git a/x-pack/plugins/cases/public/components/markdown_editor/editable_markdown_renderer.tsx b/x-pack/plugins/cases/public/components/markdown_editor/editable_markdown_renderer.tsx index bd91d219ee877..0353c7491d00c 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/editable_markdown_renderer.tsx +++ b/x-pack/plugins/cases/public/components/markdown_editor/editable_markdown_renderer.tsx @@ -50,7 +50,7 @@ const EditableMarkDownRenderer = forwardRef< const { submit, setFieldValue, isValid: isFormValid } = form; const setComment = useCallback( - (newComment) => { + (newComment: string) => { setFieldValue(fieldName, newComment); }, [setFieldValue, fieldName] diff --git a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/use_lens_draft_comment.ts b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/use_lens_draft_comment.ts index 95e558ca1f79f..23c4a66fa4e58 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/use_lens_draft_comment.ts +++ b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/use_lens_draft_comment.ts @@ -11,6 +11,7 @@ import { first } from 'rxjs'; import { useKibana } from '../../../../common/lib/kibana'; import { DRAFT_COMMENT_STORAGE_ID } from './constants'; import { VISUALIZATION } from './translations'; +import type { MarkdownEditorRef } from '../../editor'; interface DraftComment { commentId: string; @@ -51,9 +52,11 @@ export const useLensDraftComment = () => { fetchDraftComment(); }, [currentAppId$, embeddable, storage]); - const openLensModal = useCallback(({ editorRef }) => { + const openLensModal = useCallback(({ editorRef }: { editorRef: MarkdownEditorRef }) => { if (editorRef && editorRef.textarea && editorRef.toolbar) { - const lensPluginButton = editorRef.toolbar?.querySelector(`[aria-label="${VISUALIZATION}"]`); + const lensPluginButton = editorRef.toolbar?.querySelector( + `[aria-label="${VISUALIZATION}"]` + ); if (lensPluginButton) { lensPluginButton.click(); } diff --git a/x-pack/plugins/cases/public/components/recent_cases/filters/index.tsx b/x-pack/plugins/cases/public/components/recent_cases/filters/index.tsx index 5478f5b918822..1d7c22eccb68f 100644 --- a/x-pack/plugins/cases/public/components/recent_cases/filters/index.tsx +++ b/x-pack/plugins/cases/public/components/recent_cases/filters/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import type { EuiSelectOption } from '@elastic/eui'; +import type { EuiSelectOption, EuiSelectProps } from '@elastic/eui'; import { EuiSelect } from '@elastic/eui'; import React, { useCallback } from 'react'; @@ -50,7 +50,7 @@ export const RecentCasesFilters = React.memo<{ }; }); - const onChange = useCallback( + const onChange = useCallback>( (e) => { setFilterBy(e.target.value as FilterMode); }, diff --git a/x-pack/plugins/cases/public/components/recent_cases/index.tsx b/x-pack/plugins/cases/public/components/recent_cases/index.tsx index 28c632f843d76..55df7a6c9ac43 100644 --- a/x-pack/plugins/cases/public/components/recent_cases/index.tsx +++ b/x-pack/plugins/cases/public/components/recent_cases/index.tsx @@ -48,7 +48,7 @@ const RecentCasesComponent = React.memo(({ maxCasesToShow }: RecentCasesProps) = useState('recentlyCreated'); const navigateToAllCasesClick = useCallback( - (e) => { + (e: React.SyntheticEvent) => { e.preventDefault(); navigateToAllCases(); }, diff --git a/x-pack/plugins/cases/public/components/recent_cases/no_cases/index.tsx b/x-pack/plugins/cases/public/components/recent_cases/no_cases/index.tsx index d284c99af76d0..5fc24e8655eef 100644 --- a/x-pack/plugins/cases/public/components/recent_cases/no_cases/index.tsx +++ b/x-pack/plugins/cases/public/components/recent_cases/no_cases/index.tsx @@ -23,7 +23,7 @@ const NoCasesComponent = ({ recentCasesFilterBy }: NoCasesComp) => { const { getCreateCaseUrl, navigateToCreateCase } = useCreateCaseNavigation(); const navigateToCreateCaseClick = useCallback( - (e) => { + (e: React.SyntheticEvent) => { e.preventDefault(); navigateToCreateCase(); }, diff --git a/x-pack/plugins/cases/public/components/use_create_case_modal/index.tsx b/x-pack/plugins/cases/public/components/use_create_case_modal/index.tsx index 92a24b615e383..a83fa98836716 100644 --- a/x-pack/plugins/cases/public/components/use_create_case_modal/index.tsx +++ b/x-pack/plugins/cases/public/components/use_create_case_modal/index.tsx @@ -24,7 +24,7 @@ export const useCreateCaseModal = ({ onCaseCreated }: UseCreateCaseModalProps) = const closeModal = useCallback(() => setIsModalOpen(false), []); const openModal = useCallback(() => setIsModalOpen(true), []); const onSuccess = useCallback( - async (theCase) => { + async (theCase: CaseUI) => { onCaseCreated(theCase); closeModal(); }, diff --git a/x-pack/plugins/cases/public/components/use_push_to_service/callout/callout.tsx b/x-pack/plugins/cases/public/components/use_push_to_service/callout/callout.tsx index c94fbb826df48..a3326b3cb90f4 100644 --- a/x-pack/plugins/cases/public/components/use_push_to_service/callout/callout.tsx +++ b/x-pack/plugins/cases/public/components/use_push_to_service/callout/callout.tsx @@ -36,7 +36,7 @@ const CallOutComponent = ({ const { permissions } = useCasesContext(); const handleCallOut = useCallback( - (e) => handleButtonClick(e, id, type), + (e: React.MouseEvent) => handleButtonClick(e, id, type), [handleButtonClick, id, type] ); diff --git a/x-pack/plugins/cases/public/components/use_push_to_service/callout/index.tsx b/x-pack/plugins/cases/public/components/use_push_to_service/callout/index.tsx index 07f4ab2768c0b..f311044e835a2 100644 --- a/x-pack/plugins/cases/public/components/use_push_to_service/callout/index.tsx +++ b/x-pack/plugins/cases/public/components/use_push_to_service/callout/index.tsx @@ -36,7 +36,7 @@ const CaseCallOutComponent = ({ }: CaseCallOutProps) => { const { navigateToConfigureCases } = useConfigureCasesNavigation(); const handleCallOut = useCallback( - (e) => { + (e: React.SyntheticEvent) => { e.preventDefault(); // if theres connectors open dropdown editor // if no connectors, redirect to create case page diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/alert_event.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/alert_event.tsx index 94f9d290e3757..42e5e6b9d4427 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/alert_event.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/alert_event.tsx @@ -29,7 +29,7 @@ interface MultipleAlertsProps extends SingleAlertProps { const RuleLink: React.FC = memo( ({ onRuleDetailsClick, getRuleDetailsHref, ruleId, ruleName, loadingAlertData, actionId }) => { const onLinkClick = useCallback( - (ev) => { + (ev: React.MouseEvent) => { ev.preventDefault(); if (onRuleDetailsClick) onRuleDetailsClick(ruleId, ev); }, diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/host_isolation_event.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/host_isolation_event.tsx index a638c1a69b30e..66e7c65f8695b 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/host_isolation_event.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/host_isolation_event.tsx @@ -31,7 +31,7 @@ const HostIsolationCommentEventComponent: React.FC = ({ const endpointDetailsHref = href ? href(endpoints[0].endpointId) : ''; const onLinkClick = useCallback( - (ev) => { + (ev: React.MouseEvent) => { ev.preventDefault(); if (onClick) onClick(endpoints[0].endpointId, ev); }, diff --git a/x-pack/plugins/cloud_defend/public/components/control_general_view_response/index.tsx b/x-pack/plugins/cloud_defend/public/components/control_general_view_response/index.tsx index af2d7c0fd1cdf..1c782973dd0ed 100644 --- a/x-pack/plugins/cloud_defend/public/components/control_general_view_response/index.tsx +++ b/x-pack/plugins/cloud_defend/public/components/control_general_view_response/index.tsx @@ -139,7 +139,7 @@ export const ControlGeneralViewResponse = ({ }, [closePopover, onDuplicate, response]); const onChangeMatches = useCallback( - (options) => { + (options: any) => { response.match = options.map((option: EuiComboBoxOptionOption) => option.value); onResponseChange(response, index); @@ -148,7 +148,7 @@ export const ControlGeneralViewResponse = ({ ); const onChangeExcludes = useCallback( - (options) => { + (options: any) => { response.exclude = options.map((option: EuiComboBoxOptionOption) => option.value); if (response.exclude?.length === 0) { diff --git a/x-pack/plugins/cloud_defend/public/components/control_general_view_selector/index.tsx b/x-pack/plugins/cloud_defend/public/components/control_general_view_selector/index.tsx index 4511aa71f056c..05820541fd02c 100644 --- a/x-pack/plugins/cloud_defend/public/components/control_general_view_selector/index.tsx +++ b/x-pack/plugins/cloud_defend/public/components/control_general_view_selector/index.tsx @@ -24,6 +24,7 @@ import { EuiFlexItem, EuiText, EuiCheckbox, + EuiCheckboxProps, } from '@elastic/eui'; import { useStyles } from './styles'; import { @@ -69,7 +70,7 @@ const BooleanCondition = ({ onRemoveCondition, }: BooleanConditionProps) => { const value = selector[prop as keyof Selector] as boolean; - const onChange = useCallback( + const onChange = useCallback( (e) => { onChangeBooleanCondition(prop, e.target.checked); }, diff --git a/x-pack/plugins/cloud_defend/public/components/control_yaml_view/index.tsx b/x-pack/plugins/cloud_defend/public/components/control_yaml_view/index.tsx index 4dc47b8b5263f..6d1262afa135b 100644 --- a/x-pack/plugins/cloud_defend/public/components/control_yaml_view/index.tsx +++ b/x-pack/plugins/cloud_defend/public/components/control_yaml_view/index.tsx @@ -43,7 +43,7 @@ export const ControlYamlView = ({ policy, onChange, show }: ViewDeps) => { const currentModel = useConfigModel(configuration); // not all validations can be done via json-schema - const validateAdditional = useCallback((value) => { + const validateAdditional = useCallback((value: any) => { const errors: string[] = []; const { selectors, responses } = getSelectorsAndResponsesFromYaml(value); @@ -125,7 +125,7 @@ export const ControlYamlView = ({ policy, onChange, show }: ViewDeps) => { ]); const onYamlChange = useCallback( - (value) => { + (value: any) => { if (show && input?.vars) { input.vars.configuration.value = value; diff --git a/x-pack/plugins/cloud_defend/public/components/policy_settings/index.tsx b/x-pack/plugins/cloud_defend/public/components/policy_settings/index.tsx index 0c74551183942..b842453382b68 100644 --- a/x-pack/plugins/cloud_defend/public/components/policy_settings/index.tsx +++ b/x-pack/plugins/cloud_defend/public/components/policy_settings/index.tsx @@ -16,6 +16,7 @@ import { EuiFormRow, EuiFieldText, EuiHorizontalRule, + EuiSwitchProps, } from '@elastic/eui'; import { INPUT_CONTROL } from '../../../common/constants'; import { getInputFromPolicy } from '../../../common/utils/helpers'; @@ -27,7 +28,7 @@ export const PolicySettings = ({ policy, onChange }: SettingsDeps) => { const [policyHasErrors, setPolicyHasErrors] = useState(false); const controlInput = getInputFromPolicy(policy, INPUT_CONTROL); const controlEnabled = !!controlInput?.enabled; - const onToggleEnabled = useCallback( + const onToggleEnabled = useCallback( (e) => { if (controlInput) { controlInput.enabled = e.target.checked; diff --git a/x-pack/plugins/cloud_integrations/cloud_full_story/public/plugin.test.ts b/x-pack/plugins/cloud_integrations/cloud_full_story/public/plugin.test.ts index b0abbbe568d21..8409a8275ef19 100644 --- a/x-pack/plugins/cloud_integrations/cloud_full_story/public/plugin.test.ts +++ b/x-pack/plugins/cloud_integrations/cloud_full_story/public/plugin.test.ts @@ -52,6 +52,7 @@ describe('Cloud Plugin', () => { fullStoryOrgId: 'foo', scriptUrl: '/internal/cloud/100/fullstory.js', namespace: 'FSKibana', + captureOnStartup: false, }); }); @@ -66,6 +67,7 @@ describe('Cloud Plugin', () => { pageVarsDebounceTimeMs: 500, scriptUrl: '/internal/cloud/100/fullstory.js', namespace: 'FSKibana', + captureOnStartup: false, }); }); diff --git a/x-pack/plugins/cloud_integrations/cloud_full_story/public/plugin.ts b/x-pack/plugins/cloud_integrations/cloud_full_story/public/plugin.ts index 420346c19b3ce..05a635d782c0e 100755 --- a/x-pack/plugins/cloud_integrations/cloud_full_story/public/plugin.ts +++ b/x-pack/plugins/cloud_integrations/cloud_full_story/public/plugin.ts @@ -85,6 +85,8 @@ export class CloudFullStoryPlugin implements Plugin { `/internal/cloud/${this.initializerContext.env.packageInfo.buildNum}/fullstory.js` ), namespace: 'FSKibana', + // Tell FullStory to not capture from the start, and wait for the opt-in confirmation + captureOnStartup: false, }); } } diff --git a/x-pack/plugins/cloud_security_posture/common/types/benchmarks/v2.ts b/x-pack/plugins/cloud_security_posture/common/types/benchmarks/v2.ts index efcdd38f4e9b3..d0619d4a72dde 100644 --- a/x-pack/plugins/cloud_security_posture/common/types/benchmarks/v2.ts +++ b/x-pack/plugins/cloud_security_posture/common/types/benchmarks/v2.ts @@ -7,12 +7,11 @@ // Optionally, re-export the entire set of types. Interfaces and types declared after this will override v1 declarations. import { schema } from '@kbn/config-schema'; +import type { BenchmarksCisId } from '@kbn/cloud-security-posture-common'; import type { BenchmarkScore } from './v1'; export type { BenchmarkScore } from './v1'; -export type BenchmarksCisId = 'cis_k8s' | 'cis_azure' | 'cis_aws' | 'cis_eks' | 'cis_gcp'; - export interface Benchmark { id: BenchmarksCisId; name: string; diff --git a/x-pack/plugins/cloud_security_posture/common/types/index.ts b/x-pack/plugins/cloud_security_posture/common/types/index.ts index c59071d114251..144a2d2e9afda 100644 --- a/x-pack/plugins/cloud_security_posture/common/types/index.ts +++ b/x-pack/plugins/cloud_security_posture/common/types/index.ts @@ -5,22 +5,8 @@ * 2.0. */ -export * as rulesV1 from './rules/v1'; -export * as rulesV2 from './rules/v2'; -export * as rulesV3 from './rules/v3'; -export * as rulesV4 from './rules/v4'; -export * as rulesV5 from './rules/v5'; - export * as benchmarkV1 from './benchmarks/v1'; export * as benchmarkV2 from './benchmarks/v2'; // Explicit export of everything from latest -export type { - CspBenchmarkRule, - FindCspBenchmarkRuleRequest, - FindCspBenchmarkRuleResponse, - BenchmarkScore, - Benchmark, - GetBenchmarkResponse, - BenchmarkRuleSelectParams, -} from './latest'; +export type { BenchmarkScore, Benchmark, GetBenchmarkResponse } from './latest'; diff --git a/x-pack/plugins/cloud_security_posture/common/types/latest.ts b/x-pack/plugins/cloud_security_posture/common/types/latest.ts index 32006fe5b5aef..7844ef6e36f18 100644 --- a/x-pack/plugins/cloud_security_posture/common/types/latest.ts +++ b/x-pack/plugins/cloud_security_posture/common/types/latest.ts @@ -5,5 +5,4 @@ * 2.0. */ -export * from './rules/v5'; export * from './benchmarks/v2'; diff --git a/x-pack/plugins/cloud_security_posture/common/types_old.ts b/x-pack/plugins/cloud_security_posture/common/types_old.ts index b5e399e4e639c..c6531605bc328 100644 --- a/x-pack/plugins/cloud_security_posture/common/types_old.ts +++ b/x-pack/plugins/cloud_security_posture/common/types_old.ts @@ -5,7 +5,7 @@ * 2.0. */ import { type TypeOf } from '@kbn/config-schema'; -import type { CspBenchmarkRuleMetadata } from '@kbn/cloud-security-posture-common'; +import type { CspBenchmarkRuleMetadata } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import type { CspFinding } from '@kbn/cloud-security-posture-common'; import { SUPPORTED_CLOUDBEAT_INPUTS, SUPPORTED_POLICY_TEMPLATES } from './constants'; diff --git a/x-pack/plugins/cloud_security_posture/common/utils/detection_rules.test.ts b/x-pack/plugins/cloud_security_posture/common/utils/detection_rules.test.ts index fa514fe0fc2a5..2e859ae314cb1 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/detection_rules.test.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/detection_rules.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { CspBenchmarkRuleMetadata } from '@kbn/cloud-security-posture-common'; +import type { CspBenchmarkRuleMetadata } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { convertRuleTagsToMatchAllKQL, convertRuleTagsToMatchAnyKQL, diff --git a/x-pack/plugins/cloud_security_posture/common/utils/detection_rules.ts b/x-pack/plugins/cloud_security_posture/common/utils/detection_rules.ts index 4ae8385290955..ae888cde81c28 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/detection_rules.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/detection_rules.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { CspBenchmarkRuleMetadata } from '@kbn/cloud-security-posture-common'; +import type { CspBenchmarkRuleMetadata } from '@kbn/cloud-security-posture-common/schema/rules/latest'; const CSP_RULE_TAG = 'Cloud Security'; const CSP_RULE_TAG_USE_CASE = 'Use Case: Configuration Audit'; diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts index 950803c2c65c9..90e11734d72c6 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts @@ -6,7 +6,7 @@ */ import { Truthy } from 'lodash'; -import type { BaseCspSetupStatus } from '@kbn/cloud-security-posture-common'; +import type { BaseCspSetupStatus, BenchmarksCisId } from '@kbn/cloud-security-posture-common'; import { NewPackagePolicy, NewPackagePolicyInput, @@ -15,6 +15,8 @@ import { PackagePolicyInput, UpdatePackagePolicy, } from '@kbn/fleet-plugin/common'; +import type { BenchmarkRuleSelectParams } from '@kbn/cloud-security-posture-common/schema/rules/latest'; +import type { BenchmarkRuleSelectParams as BenchmarkRuleSelectParamsV4 } from '@kbn/cloud-security-posture-common/schema/rules/v4'; import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME, CLOUDBEAT_VANILLA, @@ -31,8 +33,6 @@ import type { AzureCredentialsType, RuleSection, } from '../types_old'; -import type { BenchmarkRuleSelectParams, BenchmarksCisId } from '../types/latest'; -import type { BenchmarkRuleSelectParams as BenchmarkRuleSelectParamsV1 } from '../types/rules/v4'; /** * @example @@ -44,13 +44,6 @@ export const isNonNullable = (v: T): v is NonNullable => export const truthy = (value: T): value is Truthy => !!value; -export const extractErrorMessage = (e: unknown, defaultMessage = 'Unknown Error'): string => { - if (e instanceof Error) return e.message; - if (typeof e === 'string') return e; - - return defaultMessage; // TODO: i18n -}; - export const getBenchmarkFilter = (type: BenchmarkId, section?: RuleSection): string => `${CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE}.attributes.metadata.benchmark.id: "${type}"${ section @@ -236,7 +229,7 @@ export const getCloudProviderNameFromAbbreviation = (cloudProvider: string) => { export const getBenchmarkFilterQuery = ( benchmarkId: BenchmarkId, benchmarkVersion?: string, - selectParams?: BenchmarkRuleSelectParamsV1 + selectParams?: BenchmarkRuleSelectParamsV4 ): string => { const baseQuery = `${CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE}.attributes.metadata.benchmark.id:${benchmarkId} AND ${CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE}.attributes.metadata.benchmark.version:"v${benchmarkVersion}"`; const sectionQuery = selectParams?.section diff --git a/x-pack/plugins/cloud_security_posture/common/utils/rules_states.ts b/x-pack/plugins/cloud_security_posture/common/utils/rules_states.ts index 9a142729e410b..e2351d3ddcaa9 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/rules_states.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/rules_states.ts @@ -4,31 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { QueryDslQueryContainer } from '@kbn/data-views-plugin/common/types'; -import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common'; - -export const buildMutedRulesFilter = ( - rulesStates: CspBenchmarkRulesStates -): QueryDslQueryContainer[] => { - const mutedRules = Object.fromEntries( - Object.entries(rulesStates).filter(([key, value]) => value.muted === true) - ); - - const mutedRulesFilterQuery = Object.keys(mutedRules).map((key) => { - const rule = mutedRules[key]; - return { - bool: { - must: [ - { term: { 'rule.benchmark.id': rule.benchmark_id } }, - { term: { 'rule.benchmark.version': rule.benchmark_version } }, - { term: { 'rule.benchmark.rule_number': rule.rule_number } }, - ], - }, - }; - }); - - return mutedRulesFilterQuery; -}; export const buildRuleKey = (benchmarkId: string, benchmarkVersion: string, ruleNumber: string) => { return `${benchmarkId};${benchmarkVersion};${ruleNumber}`; diff --git a/x-pack/plugins/cloud_security_posture/public/common/hooks/use_benchmark_dynamic_values.test.ts b/x-pack/plugins/cloud_security_posture/public/common/hooks/use_benchmark_dynamic_values.test.ts index 6207885b60ab0..af488c4bb81b3 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/hooks/use_benchmark_dynamic_values.test.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/hooks/use_benchmark_dynamic_values.test.ts @@ -7,8 +7,8 @@ import { useBenchmarkDynamicValues } from './use_benchmark_dynamic_values'; import { renderHook } from '@testing-library/react-hooks/dom'; +import type { BenchmarksCisId } from '@kbn/cloud-security-posture-common'; import { useCspIntegrationLink } from '../navigation/use_csp_integration_link'; -import { BenchmarksCisId } from '../../../common/types/benchmarks/v2'; jest.mock('../navigation/use_csp_integration_link'); diff --git a/x-pack/plugins/cloud_security_posture/public/common/hooks/use_benchmark_dynamic_values.ts b/x-pack/plugins/cloud_security_posture/public/common/hooks/use_benchmark_dynamic_values.ts index 7f9a2b5fd35f6..7540b96797a18 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/hooks/use_benchmark_dynamic_values.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/hooks/use_benchmark_dynamic_values.ts @@ -7,8 +7,8 @@ import { i18n } from '@kbn/i18n'; import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; +import type { BenchmarksCisId } from '@kbn/cloud-security-posture-common'; import { useCspIntegrationLink } from '../navigation/use_csp_integration_link'; -import { BenchmarksCisId } from '../../../common/types/benchmarks/v2'; type BenchmarkDynamicNames = | { diff --git a/x-pack/plugins/cloud_security_posture/public/common/hooks/use_cloud_posture_data_table/use_cloud_posture_data_table.ts b/x-pack/plugins/cloud_security_posture/public/common/hooks/use_cloud_posture_data_table/use_cloud_posture_data_table.ts index ae8ddb48488c1..acd63279bdccf 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/hooks/use_cloud_posture_data_table/use_cloud_posture_data_table.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/hooks/use_cloud_posture_data_table/use_cloud_posture_data_table.ts @@ -59,7 +59,7 @@ export const useCloudPostureDataTable = ({ const { pageSize, setPageSize } = usePageSize(paginationLocalStorageKey); const onChangeItemsPerPage = useCallback( - (newPageSize) => { + (newPageSize: any) => { setPageSize(newPageSize); setUrlQuery({ pageIndex: 0, @@ -81,7 +81,7 @@ export const useCloudPostureDataTable = ({ }, [setUrlQuery]); const onChangePage = useCallback( - (newPageIndex) => { + (newPageIndex: any) => { setUrlQuery({ pageIndex: newPageIndex, }); @@ -90,7 +90,7 @@ export const useCloudPostureDataTable = ({ ); const onSort = useCallback( - (sort) => { + (sort: any) => { setUrlQuery({ sort, }); @@ -99,7 +99,7 @@ export const useCloudPostureDataTable = ({ ); const setTableOptions = useCallback( - ({ page, sort }) => { + ({ page, sort }: any) => { setPageSize(page.size); setUrlQuery({ sort, @@ -119,7 +119,7 @@ export const useCloudPostureDataTable = ({ }); const handleUpdateQuery = useCallback( - (query) => { + (query: any) => { setUrlQuery({ ...query, pageIndex: 0 }); }, [setUrlQuery] diff --git a/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.test.tsx b/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.test.tsx index 22fc6b4ae65f8..9e2275c62e31c 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.test.tsx @@ -24,7 +24,7 @@ import { NoDataPage } from '@kbn/kibana-react-plugin/public'; const chance = new Chance(); -jest.mock('../common/api/use_setup_status_api'); +jest.mock('@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'); jest.mock('../common/api/use_license_management_locator_api'); jest.mock('../common/hooks/use_is_subscription_status_valid'); jest.mock('../common/navigation/use_csp_integration_link'); diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx index 7590e998cd0c2..d62f86651f93f 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx @@ -39,7 +39,7 @@ import { } from '../../../common/constants'; import { useParams } from 'react-router-dom'; import { createReactQueryResponse } from '../../test/fixtures/react_query'; -import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; +import { useCspSetupStatusApi } from '@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'; import { usePackagePolicyList } from '../../common/api/use_package_policy_list'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; import { @@ -67,7 +67,7 @@ jest.mock('react-router-dom', () => ({ integration: undefined, }), })); -jest.mock('../../common/api/use_setup_status_api'); +jest.mock('@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'); jest.mock('../../common/api/use_package_policy_list'); jest.mock('../../common/hooks/use_is_subscription_status_valid'); jest.mock('../../common/api/use_license_management_locator_api'); diff --git a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.tsx b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.tsx index 096c6f0e8aae5..9c8f2da45f8e8 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.tsx @@ -22,6 +22,7 @@ import { i18n } from '@kbn/i18n'; import { css } from '@emotion/react'; import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; import type { IndexDetails, CspStatusCode } from '@kbn/cloud-security-posture-common'; +import { useCspSetupStatusApi } from '@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'; import { FullSizeCenteredPage } from '../full_size_centered_page'; import { useCISIntegrationPoliciesLink } from '../../common/navigation/use_navigate_to_cis_integration_policies'; import { @@ -30,7 +31,6 @@ import { NO_FINDINGS_STATUS_TEST_SUBJ, } from '../test_subjects'; import { CloudPosturePage, PACKAGE_NOT_INSTALLED_TEST_SUBJECT } from '../cloud_posture_page'; -import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; import type { PostureTypes } from '../../../common/types_old'; import noDataIllustration from '../../assets/illustrations/no_data_illustration.svg'; import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link'; diff --git a/x-pack/plugins/cloud_security_posture/public/components/no_vulnerabilities_states.tsx b/x-pack/plugins/cloud_security_posture/public/components/no_vulnerabilities_states.tsx index a15cf0aacd6fa..074e75915a5b7 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/no_vulnerabilities_states.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/no_vulnerabilities_states.tsx @@ -22,10 +22,10 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { css } from '@emotion/react'; import type { IndexDetails } from '@kbn/cloud-security-posture-common'; +import { useCspSetupStatusApi } from '@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'; import { VULN_MGMT_POLICY_TEMPLATE } from '../../common/constants'; import { FullSizeCenteredPage } from './full_size_centered_page'; import { CloudPosturePage } from './cloud_posture_page'; -import { useCspSetupStatusApi } from '../common/api/use_setup_status_api'; import { NO_VULNERABILITIES_STATUS_TEST_SUBJ, CNVM_NOT_INSTALLED_ACTION_SUBJ, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.test.tsx index f625470fb08c5..e11095bb622f0 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.test.tsx @@ -14,13 +14,13 @@ import { TestProvider } from '../../test/test_provider'; import { Benchmarks } from './benchmarks'; import * as TEST_SUBJ from './test_subjects'; import { useCspBenchmarkIntegrationsV2 } from './use_csp_benchmark_integrations'; -import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; +import { useCspSetupStatusApi } from '@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'; import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link'; import { ERROR_STATE_TEST_SUBJECT } from './benchmarks_table'; import { useLicenseManagementLocatorApi } from '../../common/api/use_license_management_locator_api'; jest.mock('./use_csp_benchmark_integrations'); -jest.mock('../../common/api/use_setup_status_api'); +jest.mock('@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'); jest.mock('../../common/api/use_license_management_locator_api'); jest.mock('../../common/hooks/use_is_subscription_status_valid'); jest.mock('../../common/navigation/use_csp_integration_link'); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.tsx b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.tsx index 13b4750317810..dd6b8ce45318b 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.tsx @@ -21,6 +21,8 @@ import { FormattedMessage } from '@kbn/i18n-react'; import useDebounce from 'react-use/lib/useDebounce'; import { i18n } from '@kbn/i18n'; import { pagePathGetters } from '@kbn/fleet-plugin/public'; +import { extractErrorMessage } from '@kbn/cloud-security-posture-common'; +import { useCspSetupStatusApi } from '@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'; import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME } from '../../../common/constants'; import { CloudPosturePageTitle } from '../../components/cloud_posture_page_title'; import { CloudPosturePage } from '../../components/cloud_posture_page'; @@ -29,7 +31,7 @@ import { useCspBenchmarkIntegrationsV2, UseCspBenchmarkIntegrationsProps, } from './use_csp_benchmark_integrations'; -import { extractErrorMessage, getBenchmarkCisName } from '../../../common/utils/helpers'; +import { getBenchmarkCisName } from '../../../common/utils/helpers'; import * as TEST_SUBJ from './test_subjects'; import { LOCAL_STORAGE_PAGE_SIZE_BENCHMARK_KEY, @@ -37,7 +39,6 @@ import { } from '../../common/constants'; import { usePageSize } from '../../common/hooks/use_page_size'; import { useKibana } from '../../common/hooks/use_kibana'; -import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; import { NoFindingsStates } from '../../components/no_findings_states'; const SEARCH_DEBOUNCE_MS = 300; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx index 2da4cc06ddd5d..ea08ce0398146 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx @@ -21,9 +21,10 @@ import React, { useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { generatePath } from 'react-router-dom'; +import type { BenchmarksCisId } from '@kbn/cloud-security-posture-common'; import { FINDINGS_GROUPING_OPTIONS } from '../../common/constants'; import { useNavigateFindings } from '../../common/hooks/use_navigate_findings'; -import type { BenchmarkScore, Benchmark, BenchmarksCisId } from '../../../common/types/latest'; +import type { BenchmarkScore, Benchmark } from '../../../common/types/latest'; import * as TEST_SUBJ from './test_subjects'; import { isCommonError } from '../../components/cloud_posture_page'; import { FullSizeCenteredPage } from '../../components/full_size_centered_page'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx index 46b0e59612083..11d7a71118eae 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx @@ -12,7 +12,7 @@ import type { BaseCspSetupStatus, CspStatusCode } from '@kbn/cloud-security-post import { render, screen } from '@testing-library/react'; import { TestProvider } from '../../test/test_provider'; import { ComplianceDashboard, getDefaultTab } from '.'; -import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; +import { useCspSetupStatusApi } from '@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'; import { useLicenseManagementLocatorApi } from '../../common/api/use_license_management_locator_api'; import { useKspmStatsApi, useCspmStatsApi } from '../../common/api/use_stats_api'; import { @@ -36,7 +36,7 @@ import { ComplianceDashboardDataV2 } from '../../../common/types_old'; import { cloudPosturePages } from '../../common/navigation/constants'; import { MemoryRouter } from 'react-router-dom'; -jest.mock('../../common/api/use_setup_status_api'); +jest.mock('@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'); jest.mock('../../common/api/use_stats_api'); jest.mock('../../common/api/use_license_management_locator_api'); jest.mock('../../common/hooks/use_is_subscription_status_valid'); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx index 1629a000d5e64..16037fa204766 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx @@ -15,6 +15,7 @@ import { Route, Routes } from '@kbn/shared-ux-router'; import { Redirect, useHistory, useLocation } from 'react-router-dom'; import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; import type { BaseCspSetupStatus } from '@kbn/cloud-security-posture-common'; +import { useCspSetupStatusApi } from '@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'; import { NO_FINDINGS_STATUS_TEST_SUBJ } from '../../components/test_subjects'; import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link'; import type { PosturePolicyTemplate, ComplianceDashboardDataV2 } from '../../../common/types_old'; @@ -35,7 +36,6 @@ import { CLOUD_POSTURE_DASHBOARD_PAGE_HEADER, } from './test_subjects'; import { useCspmStatsApi, useKspmStatsApi } from '../../common/api/use_stats_api'; -import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; import { NoFindingsStates } from '../../components/no_findings_states'; import { SummarySection } from './dashboard_sections/summary_section'; import { BenchmarksSection } from './dashboard_sections/benchmarks_section'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.tsx index f17a8039db885..3f088e799239b 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.tsx @@ -8,8 +8,8 @@ import React from 'react'; import { Redirect, useLocation } from 'react-router-dom'; import { Routes, Route } from '@kbn/shared-ux-router'; import { TrackApplicationView } from '@kbn/usage-collection-plugin/public'; +import { useCspSetupStatusApi } from '@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'; import { CDR_MISCONFIGURATIONS_DATA_VIEW_ID_PREFIX } from '../../../common/constants'; -import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; import { NoFindingsStates } from '../../components/no_findings_states'; import { CloudPosturePage, defaultLoadingRenderer } from '../../components/cloud_posture_page'; import { useDataView } from '../../common/api/use_data_view'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_grouped_findings.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_grouped_findings.tsx index 532998f0f712f..75234c0495f51 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_grouped_findings.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_grouped_findings.tsx @@ -11,8 +11,8 @@ import { GenericBuckets, GroupingQuery, RootAggregation } from '@kbn/grouping/sr import { useQuery } from '@tanstack/react-query'; import { lastValueFrom } from 'rxjs'; import { CDR_MISCONFIGURATIONS_INDEX_PATTERN } from '@kbn/cloud-security-posture-common'; +import { showErrorToast } from '@kbn/cloud-security-posture'; import { useKibana } from '../../../common/hooks/use_kibana'; -import { showErrorToast } from '../../../common/utils/show_error_toast'; // Elasticsearch returns `null` when a sub-aggregation cannot be computed type NumberOrNull = number | null; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings.ts b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings.ts index 5a77337ba171c..f8cd0238ef0bb 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings.ts @@ -11,18 +11,18 @@ import type { IKibanaSearchResponse, IKibanaSearchRequest } from '@kbn/search-ty import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { buildDataTableRecord } from '@kbn/discover-utils'; import { EsHitRecord } from '@kbn/discover-utils/types'; -import { MAX_FINDINGS_TO_LOAD } from '@kbn/cloud-security-posture-common'; +import { showErrorToast } from '@kbn/cloud-security-posture'; +import { MAX_FINDINGS_TO_LOAD, buildMutedRulesFilter } from '@kbn/cloud-security-posture-common'; import { CDR_MISCONFIGURATIONS_INDEX_PATTERN, LATEST_FINDINGS_RETENTION_POLICY, } from '@kbn/cloud-security-posture-common'; -import type { CspBenchmarkRulesStates, CspFinding } from '@kbn/cloud-security-posture-common'; +import type { CspFinding } from '@kbn/cloud-security-posture-common'; +import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import type { FindingsBaseEsQuery } from '@kbn/cloud-security-posture'; +import { useGetCspBenchmarkRulesStatesApi } from '@kbn/cloud-security-posture/src/hooks/use_get_benchmark_rules_state_api'; import { useKibana } from '../../../common/hooks/use_kibana'; import { getAggregationCount, getFindingsCountAggQuery } from '../utils/utils'; -import { showErrorToast } from '../../../common/utils/show_error_toast'; -import { useGetCspBenchmarkRulesStatesApi } from './use_get_benchmark_rules_state_api'; -import { buildMutedRulesFilter } from '../../../../common/utils/rules_states'; interface UseFindingsOptions extends FindingsBaseEsQuery { sort: string[][]; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx index d94f063933b0e..cc409fb95024d 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx @@ -15,7 +15,11 @@ import { } from '@kbn/grouping/src'; import { useMemo } from 'react'; import { buildEsQuery, Filter } from '@kbn/es-query'; -import { LATEST_FINDINGS_RETENTION_POLICY } from '@kbn/cloud-security-posture-common'; +import { + LATEST_FINDINGS_RETENTION_POLICY, + buildMutedRulesFilter, +} from '@kbn/cloud-security-posture-common'; +import { useGetCspBenchmarkRulesStatesApi } from '@kbn/cloud-security-posture/src/hooks/use_get_benchmark_rules_state_api'; import { FINDINGS_GROUPING_OPTIONS, LOCAL_STORAGE_FINDINGS_GROUPING_KEY, @@ -36,8 +40,6 @@ import { } from './constants'; import { useCloudSecurityGrouping } from '../../../components/cloud_security_grouping'; import { getFilters } from '../utils/get_filters'; -import { useGetCspBenchmarkRulesStatesApi } from './use_get_benchmark_rules_state_api'; -import { buildMutedRulesFilter } from '../../../../common/utils/rules_states'; const getTermAggregation = (key: keyof FindingsGroupingAggregation, field: string) => ({ [key]: { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/utils/create_detection_rule_from_benchmark.ts b/x-pack/plugins/cloud_security_posture/public/pages/configurations/utils/create_detection_rule_from_benchmark.ts index 289c6c2cb153f..0ce1b7d09e897 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/utils/create_detection_rule_from_benchmark.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/utils/create_detection_rule_from_benchmark.ts @@ -7,7 +7,7 @@ import { HttpSetup } from '@kbn/core/public'; import { LATEST_FINDINGS_RETENTION_POLICY } from '@kbn/cloud-security-posture-common'; -import { CspBenchmarkRule } from '../../../../common/types/latest'; +import type { CspBenchmarkRule } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { FINDINGS_INDEX_PATTERN } from '../../../../common/constants'; import { createDetectionRule } from '../../../common/api/create_detection_rule'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.tsx index f8d91d5250234..b3995e405ba73 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.tsx @@ -10,11 +10,11 @@ import { EuiSpacer, EuiTab, EuiTabs, EuiTitle } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { Redirect, useHistory, useLocation, matchPath } from 'react-router-dom'; import { Routes, Route } from '@kbn/shared-ux-router'; +import { useCspSetupStatusApi } from '@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'; import { Configurations } from '../configurations'; import { cloudPosturePages, findingsNavigation } from '../../common/navigation/constants'; import { LOCAL_STORAGE_FINDINGS_LAST_SELECTED_TAB_KEY } from '../../common/constants'; import { VULNERABILITIES_INDEX_NAME, FINDINGS_INDEX_NAME } from '../../../common/constants'; -import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; import { getStatusForIndexName } from '../../../common/utils/helpers'; import { Vulnerabilities } from '../vulnerabilities'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx index 365af617b7f28..f404b6a82d215 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx @@ -10,6 +10,7 @@ import { generatePath, Link, type RouteComponentProps } from 'react-router-dom'; import { EuiButtonEmpty, EuiFlexGroup, EuiPageHeader, EuiSpacer, EuiFlexItem } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; +import type { PageUrlParams } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { CloudPosturePageTitle } from '../../components/cloud_posture_page_title'; import { RulesContainer } from './rules_container'; import { cloudPosturePages } from '../../common/navigation/constants'; @@ -18,7 +19,6 @@ import { useSecuritySolutionContext } from '../../application/security_solution_ import { useCspBenchmarkIntegrationsV2 } from '../benchmarks/use_csp_benchmark_integrations'; import { CISBenchmarkIcon } from '../../components/cis_benchmark_icon'; import { getBenchmarkCisName } from '../../../common/utils/helpers'; -import { PageUrlParams } from '../../../common/types/latest'; export const Rules = ({ match: { params } }: RouteComponentProps) => { const benchmarksInfo = useCspBenchmarkIntegrationsV2(); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx index 642aff1ef267d..ff427e7809454 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx @@ -12,16 +12,16 @@ import { render, screen } from '@testing-library/react'; import { QueryClient } from '@tanstack/react-query'; import { TestProvider } from '../../test/test_provider'; import { type RouteComponentProps } from 'react-router-dom'; -import { PageUrlParams } from '../../../common/types/latest'; +import type { PageUrlParams } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { createReactQueryResponse } from '../../test/fixtures/react_query'; import { coreMock } from '@kbn/core/public/mocks'; -import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; +import { useCspSetupStatusApi } from '@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'; import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link'; import { useLicenseManagementLocatorApi } from '../../common/api/use_license_management_locator_api'; import { useCspBenchmarkIntegrationsV2 } from '../benchmarks/use_csp_benchmark_integrations'; import * as TEST_SUBJECTS from './test_subjects'; -jest.mock('../../common/api/use_setup_status_api'); +jest.mock('@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'); jest.mock('../../common/api/use_license_management_locator_api'); jest.mock('../../common/hooks/use_is_subscription_status_valid'); jest.mock('../../common/navigation/use_csp_integration_link'); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx index d81b834f9c933..4718dbae911ae 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx @@ -13,7 +13,7 @@ import { useFindCspBenchmarkRule } from './use_csp_benchmark_rules'; import * as TEST_SUBJECTS from './test_subjects'; import { Chance } from 'chance'; import { TestProvider } from '../../test/test_provider'; -import type { CspBenchmarkRule } from '../../../common/types/latest'; +import type { CspBenchmarkRule } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { useParams } from 'react-router-dom'; import { coreMock } from '@kbn/core/public/mocks'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx index c134e405f8a3c..1b1af9aab4292 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx @@ -8,9 +8,14 @@ import React, { useState, useMemo, useEffect } from 'react'; import compareVersions from 'compare-versions'; import { EuiSpacer } from '@elastic/eui'; import { useParams, useHistory, generatePath } from 'react-router-dom'; +import type { + CspBenchmarkRule, + PageUrlParams, + RuleStateAttributes, +} from '@kbn/cloud-security-posture-common/schema/rules/latest'; +import { extractErrorMessage } from '@kbn/cloud-security-posture-common'; import { benchmarksNavigation } from '../../common/navigation/constants'; import { buildRuleKey } from '../../../common/utils/rules_states'; -import { extractErrorMessage } from '../../../common/utils/helpers'; import { RulesTable } from './rules_table'; import { RulesTableHeader } from './rules_table_header'; import { useFindCspBenchmarkRule, type RulesQuery } from './use_csp_benchmark_rules'; @@ -18,11 +23,6 @@ import * as TEST_SUBJECTS from './test_subjects'; import { RuleFlyout } from './rules_flyout'; import { LOCAL_STORAGE_PAGE_SIZE_RULES_KEY } from '../../common/constants'; import { usePageSize } from '../../common/hooks/use_page_size'; -import type { - CspBenchmarkRule, - PageUrlParams, - RuleStateAttributes, -} from '../../../common/types/latest'; import { useCspGetRulesStates } from './use_csp_rules_state'; import { RulesCounters } from './rules_counters'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_detection_rule_counter.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_detection_rule_counter.tsx index b47b55149743c..70d1d951b50b5 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_detection_rule_counter.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_detection_rule_counter.tsx @@ -7,7 +7,7 @@ import type { HttpSetup } from '@kbn/core/public'; import React from 'react'; -import { CspBenchmarkRule } from '../../../common/types/latest'; +import type { CspBenchmarkRule } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { getFindingsDetectionRuleSearchTags } from '../../../common/utils/detection_rules'; import { DetectionRuleCounter } from '../../components/detection_rule_counter'; import { createDetectionRuleFromBenchmarkRule } from '../configurations/utils/create_detection_rule_from_benchmark'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_flyout.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_flyout.tsx index 0bafc004a5e11..7447d82d251ee 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_flyout.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_flyout.tsx @@ -23,7 +23,7 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { HttpSetup } from '@kbn/core/public'; -import type { CspBenchmarkRuleMetadata } from '@kbn/cloud-security-posture-common'; +import type { CspBenchmarkRuleMetadata } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { getRuleList } from '../configurations/findings_flyout/rule_tab'; import { getRemediationList } from '../configurations/findings_flyout/overview_tab'; import * as TEST_SUBJECTS from './test_subjects'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_change_csp_rule_state.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_change_csp_rule_state.test.tsx index cd205bb7f6b7b..6c28df502e5fc 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_change_csp_rule_state.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_change_csp_rule_state.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { act, renderHook } from '@testing-library/react-hooks'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useKibana } from '@kbn/kibana-react-plugin/public'; +import type { RuleStateAttributes } from '@kbn/cloud-security-posture-common/schema/rules/v4'; import { useChangeCspRuleState, createRulesWithUpdatedState, @@ -17,7 +18,6 @@ import { CSP_RULES_STATES_QUERY_KEY } from './use_csp_rules_state'; import { BENCHMARK_INTEGRATION_QUERY_KEY_V2 } from '../benchmarks/use_csp_benchmark_integrations'; import { CSPM_STATS_QUERY_KEY, KSPM_STATS_QUERY_KEY } from '../../common/api'; import { CSP_BENCHMARK_RULES_BULK_ACTION_ROUTE_PATH } from '../../../common/constants'; -import { RuleStateAttributes } from '../../../common/types/rules/v4'; const initialRules = { rule_1: { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_change_csp_rule_state.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_change_csp_rule_state.tsx index 9b616062b0050..e570603636942 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_change_csp_rule_state.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_change_csp_rule_state.tsx @@ -10,13 +10,13 @@ import { toMountPoint } from '@kbn/react-kibana-mount'; import { EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n as kbnI18n } from '@kbn/i18n'; +import type { + CspBenchmarkRulesBulkActionResponse, + RuleStateAttributes, +} from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { CSP_RULES_STATES_QUERY_KEY } from './use_csp_rules_state'; import { CSPM_STATS_QUERY_KEY, KSPM_STATS_QUERY_KEY } from '../../common/api'; import { BENCHMARK_INTEGRATION_QUERY_KEY_V2 } from '../benchmarks/use_csp_benchmark_integrations'; -import { - CspBenchmarkRulesBulkActionResponse, - RuleStateAttributes, -} from '../../../common/types/latest'; import { CSP_BENCHMARK_RULES_BULK_ACTION_ROUTE_PATH } from '../../../common/constants'; import { CloudSecurityPostureStartServices } from '../../types'; import { useKibana } from '../../common/hooks/use_kibana'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_benchmark_rules.ts b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_benchmark_rules.ts index fd8c5bf794935..8c62485bf4a8c 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_benchmark_rules.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_benchmark_rules.ts @@ -8,7 +8,7 @@ import { useQuery } from '@tanstack/react-query'; import { FindCspBenchmarkRuleRequest, FindCspBenchmarkRuleResponse, -} from '../../../common/types/latest'; +} from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { useKibana } from '../../common/hooks/use_kibana'; import { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules_state.ts b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules_state.ts index 640dc92274481..e6535d90006e4 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules_state.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules_state.ts @@ -7,7 +7,7 @@ import { useQuery } from '@tanstack/react-query'; import { CSP_GET_BENCHMARK_RULES_STATE_ROUTE_PATH } from '@kbn/cloud-security-posture-common'; -import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common'; +import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { useKibana } from '../../common/hooks/use_kibana'; export const CSP_RULES_STATES_QUERY_KEY = ['csp_rules_states_v1']; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_grouped_vulnerabilities.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_grouped_vulnerabilities.tsx index 79cb2aad7e60e..50e712612302b 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_grouped_vulnerabilities.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_grouped_vulnerabilities.tsx @@ -10,9 +10,9 @@ import type { IKibanaSearchResponse } from '@kbn/search-types'; import { GenericBuckets, GroupingQuery, RootAggregation } from '@kbn/grouping/src'; import { useQuery } from '@tanstack/react-query'; import { lastValueFrom } from 'rxjs'; +import { showErrorToast } from '@kbn/cloud-security-posture'; import { LATEST_VULNERABILITIES_INDEX_PATTERN } from '../../../../common/constants'; import { useKibana } from '../../../common/hooks/use_kibana'; -import { showErrorToast } from '../../../common/utils/show_error_toast'; // Elasticsearch returns `null` when a sub-aggregation cannot be computed type NumberOrNull = number | null; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities.tsx index 3b1d3a156f305..aa1603fc9e985 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities.tsx @@ -17,7 +17,7 @@ import { import { buildDataTableRecord } from '@kbn/discover-utils'; import { EsHitRecord } from '@kbn/discover-utils/types'; import { MAX_FINDINGS_TO_LOAD } from '@kbn/cloud-security-posture-common'; -import { FindingsBaseEsQuery } from '@kbn/cloud-security-posture'; +import { FindingsBaseEsQuery, showErrorToast } from '@kbn/cloud-security-posture'; import { VULNERABILITY_FIELDS } from '../../../common/constants'; import { CspVulnerabilityFinding } from '../../../../common/schemas'; import { @@ -25,7 +25,6 @@ import { LATEST_VULNERABILITIES_RETENTION_POLICY, } from '../../../../common/constants'; import { useKibana } from '../../../common/hooks/use_kibana'; -import { showErrorToast } from '../../../common/utils/show_error_toast'; import { getCaseInsensitiveSortScript } from '../utils/custom_sort_script'; type LatestFindingsRequest = IKibanaSearchRequest; type LatestFindingsResponse = IKibanaSearchResponse< diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities.tsx index 5940b022a0b90..6d3b2e5cf1b77 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities.tsx @@ -6,9 +6,9 @@ */ import React from 'react'; import { Routes, Route } from '@kbn/shared-ux-router'; +import { useCspSetupStatusApi } from '@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'; import { CDR_VULNERABILITIES_DATA_VIEW_ID_PREFIX } from '../../../common/constants'; import { NoVulnerabilitiesStates } from '../../components/no_vulnerabilities_states'; -import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; import { CloudPosturePage } from '../../components/cloud_posture_page'; import { findingsNavigation } from '../../common/navigation/constants'; import { useDataView } from '../../common/api/use_data_view'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilties.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilties.test.tsx index c9e13c15613a5..59fa1cfa0ef92 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilties.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilties.test.tsx @@ -12,7 +12,7 @@ import { LATEST_VULNERABILITIES_INDEX_DEFAULT_NS, VULN_MGMT_POLICY_TEMPLATE, } from '../../../common/constants'; -import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; +import { useCspSetupStatusApi } from '@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'; import { useDataView } from '../../common/api/use_data_view'; import { createReactQueryResponse } from '../../test/fixtures/react_query'; import { useCISIntegrationPoliciesLink } from '../../common/navigation/use_navigate_to_cis_integration_policies'; @@ -28,7 +28,7 @@ import { useLicenseManagementLocatorApi } from '../../common/api/use_license_man import { createStubDataView } from '@kbn/data-views-plugin/common/stubs'; jest.mock('../../common/api/use_data_view'); -jest.mock('../../common/api/use_setup_status_api'); +jest.mock('@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'); jest.mock('../../common/api/use_license_management_locator_api'); jest.mock('../../common/hooks/use_is_subscription_status_valid'); jest.mock('../../common/navigation/use_navigate_to_cis_integration_policies'); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_dashboard.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_dashboard.test.tsx index 6203adbb11d28..0d477ef77d831 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_dashboard.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_dashboard.test.tsx @@ -14,7 +14,7 @@ import { } from '../../../common/constants'; import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import { discoverPluginMock } from '@kbn/discover-plugin/public/mocks'; -import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; +import { useCspSetupStatusApi } from '@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'; import { createReactQueryResponse } from '../../test/fixtures/react_query'; import { useCISIntegrationPoliciesLink } from '../../common/navigation/use_navigate_to_cis_integration_policies'; import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link'; @@ -32,7 +32,7 @@ import { useVulnerabilityDashboardApi } from '../../common/api/use_vulnerability import { mockCnvmDashboardData } from './_mocks_/vulnerability_dashboard.mock'; jest.mock('../../common/api/use_data_view'); -jest.mock('../../common/api/use_setup_status_api'); +jest.mock('@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'); jest.mock('../../common/api/use_license_management_locator_api'); jest.mock('../../common/hooks/use_is_subscription_status_valid'); jest.mock('../../common/navigation/use_navigate_to_cis_integration_policies'); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_dashboard.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_dashboard.tsx index 33c1a5fdad4d7..9ca46a8e3640b 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_dashboard.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_dashboard.tsx @@ -7,9 +7,9 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiPageHeader, EuiSpacer } from '@elastic/eui'; +import { useCspSetupStatusApi } from '@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api'; import { useVulnerabilityDashboardApi } from '../../common/api/use_vulnerability_dashboard_api'; import { VulnerabilityTrendGraph } from './vulnerability_trend_graph'; -import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; import { NoVulnerabilitiesStates } from '../../components/no_vulnerabilities_states'; import { VULNERABILITY_DASHBOARD_CONTAINER, diff --git a/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/muted_rules_stats_collector.ts b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/muted_rules_stats_collector.ts index 63fc68caff47b..e5acf7b992e22 100644 --- a/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/muted_rules_stats_collector.ts +++ b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/muted_rules_stats_collector.ts @@ -10,8 +10,8 @@ import { SavedObjectsClientContract, } from '@kbn/core-saved-objects-api-server'; import type { Logger } from '@kbn/core/server'; +import type { CspBenchmarkRule } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '../../../../common/constants'; -import { CspBenchmarkRule } from '../../../../common/types/latest'; import { getCspBenchmarkRulesStatesHandler } from '../../../routes/benchmark_rules/get_states/v1'; import { MutedRulesStats } from './types'; diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.ts b/x-pack/plugins/cloud_security_posture/server/plugin.ts index f3a0192149142..b373b6d80c5ee 100755 --- a/x-pack/plugins/cloud_security_posture/server/plugin.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.ts @@ -24,6 +24,10 @@ import type { TaskManagerSetupContract, TaskManagerStartContract, } from '@kbn/task-manager-plugin/server'; +import type { + CspBenchmarkRule, + CspSettings, +} from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { isCspPackage } from '../common/utils/helpers'; import { isSubscriptionAllowed } from '../common/utils/subscription'; import { cleanupCredentials } from '../common/utils/helpers'; @@ -47,7 +51,6 @@ import { } from './tasks/findings_stats_task'; import { registerCspmUsageCollector } from './lib/telemetry/collectors/register'; import { CloudSecurityPostureConfig } from './config'; -import { CspBenchmarkRule, CspSettings } from '../common/types/latest'; export class CspPlugin implements diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/bulk_action.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/bulk_action.ts index 63a9201b1f265..5ac233f5be0f5 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/bulk_action.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/bulk_action.ts @@ -9,8 +9,8 @@ import { transformError } from '@kbn/securitysolution-es-utils'; import { CspBenchmarkRulesBulkActionRequestSchema, cspBenchmarkRulesBulkActionRequestSchema, - CspBenchmarkRulesBulkActionResponse, -} from '../../../../common/types/rules/v4'; +} from '@kbn/cloud-security-posture-common/schema/rules/v4'; +import type { CspBenchmarkRulesBulkActionResponse } from '@kbn/cloud-security-posture-common/schema/rules/v4'; import { CspRouter } from '../../../types'; import { CSP_BENCHMARK_RULES_BULK_ACTION_ROUTE_PATH } from '../../../../common/constants'; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/utils.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/utils.ts index e733f6cc96003..ce70dfb7bfc47 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/utils.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/utils.ts @@ -6,14 +6,14 @@ */ import type { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; -import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common'; +import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import type { FindResult, RulesClient } from '@kbn/alerting-plugin/server'; import type { RuleParams } from '@kbn/alerting-plugin/server/application/rule/types'; import type { CspBenchmarkRule, RulesToUpdate, CspSettings, -} from '../../../../common/types/rules/v4'; +} from '@kbn/cloud-security-posture-common/schema/rules/v4'; import { convertRuleTagsToMatchAllKQL, generateBenchmarkRuleTags, diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/v1.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/v1.ts index ce68e094c0ba1..24aa7106e1705 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/v1.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/bulk_action/v1.ts @@ -7,6 +7,10 @@ import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; import { Logger } from '@kbn/core/server'; import type { RulesClient } from '@kbn/alerting-plugin/server'; +import type { + BulkActionBenchmarkRulesResponse, + RulesToUpdate, +} from '@kbn/cloud-security-posture-common/schema/rules/v4'; import { buildRuleKey } from '../../../../common/utils/rules_states'; import { getBenchmarkRules, @@ -14,10 +18,6 @@ import { setRulesStates, updateBenchmarkRulesStates, } from './utils'; -import type { - BulkActionBenchmarkRulesResponse, - RulesToUpdate, -} from '../../../../common/types/rules/v4'; const muteStatesMap = { mute: true, diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/find.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/find.test.ts index a2814e4b48ff0..0ce455ae35cec 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/find.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/find.test.ts @@ -5,8 +5,8 @@ * 2.0. */ +import type { CspBenchmarkRule } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { getSortedCspBenchmarkRulesTemplates } from './utils'; -import { CspBenchmarkRule } from '../../../../common/types/latest'; describe('getSortedCspBenchmarkRules', () => { it('sorts by metadata.benchmark.rule_number, invalid semantic version still should still get sorted and empty values should be sorted last', () => { diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/find.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/find.ts index c1b481b01f2cd..3e4373ad8fedb 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/find.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/find.ts @@ -9,15 +9,11 @@ import { FindCspBenchmarkRuleRequest, FindCspBenchmarkRuleResponse, findCspBenchmarkRuleRequestSchema, -} from '../../../../common/types/latest'; -import { - FindCspBenchmarkRuleRequest as FindCspBenchmarkRuleRequestV1, - findCspBenchmarkRuleRequestSchema as findCspBenchmarkRuleRequestSchemaV1, -} from '../../../../common/types/rules/v3'; -import { - FindCspBenchmarkRuleRequest as FindCspBenchmarkRuleRequestV2, - findCspBenchmarkRuleRequestSchema as findCspBenchmarkRuleRequestSchemaV2, -} from '../../../../common/types/rules/v4'; +} from '@kbn/cloud-security-posture-common/schema/rules/latest'; +import { findCspBenchmarkRuleRequestSchema as findCspBenchmarkRuleRequestSchemaV1 } from '@kbn/cloud-security-posture-common/schema/rules/v3'; +import type { FindCspBenchmarkRuleRequest as FindCspBenchmarkRuleRequestV1 } from '@kbn/cloud-security-posture-common/schema/rules/v3'; +import { findCspBenchmarkRuleRequestSchema as findCspBenchmarkRuleRequestSchemaV2 } from '@kbn/cloud-security-posture-common/schema/rules/v4'; +import type { FindCspBenchmarkRuleRequest as FindCspBenchmarkRuleRequestV2 } from '@kbn/cloud-security-posture-common/schema/rules/v4'; import { FIND_CSP_BENCHMARK_RULE_ROUTE_PATH } from '../../../../common/constants'; import { CspRouter } from '../../../types'; import { findBenchmarkRuleHandler as findRuleHandlerV1 } from './v1'; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/utils.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/utils.ts index f118ed0e8c56d..17e4f44fd10e5 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/utils.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/utils.ts @@ -8,11 +8,10 @@ import semverValid from 'semver/functions/valid'; import semverCompare from 'semver/functions/compare'; import { NewPackagePolicy } from '@kbn/fleet-plugin/common'; import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; +import type { CspBenchmarkRule } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../../benchmarks/benchmarks'; import { getBenchmarkFromPackagePolicy } from '../../../../common/utils/helpers'; -import type { CspBenchmarkRule } from '../../../../common/types/latest'; - export const getSortedCspBenchmarkRulesTemplates = ( cspBenchmarkRules: CspBenchmarkRule[], sortDirection: 'asc' | 'desc' diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/v1.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/v1.ts index a1d5668ba8c22..c8db792e6a9bd 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/v1.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/v1.ts @@ -5,14 +5,14 @@ * 2.0. */ import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; -import { getBenchmarkFilter } from '../../../../common/utils/helpers'; -import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '../../../../common/constants'; -import { getBenchmarkIdFromPackagePolicyId, getSortedCspBenchmarkRulesTemplates } from './utils'; -import type { CspBenchmarkRule } from '../../../../common/types/latest'; +import type { CspBenchmarkRule } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import type { FindCspBenchmarkRuleRequest, FindCspBenchmarkRuleResponse, -} from '../../../../common/types/rules/v3'; +} from '@kbn/cloud-security-posture-common/schema/rules/v3'; +import { getBenchmarkFilter } from '../../../../common/utils/helpers'; +import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '../../../../common/constants'; +import { getBenchmarkIdFromPackagePolicyId, getSortedCspBenchmarkRulesTemplates } from './utils'; export const findBenchmarkRuleHandler = async ( soClient: SavedObjectsClientContract, diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/v2.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/v2.ts index e7db9544b7dd3..858463e94fa5f 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/v2.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/v2.ts @@ -6,14 +6,14 @@ */ import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; -import { getBenchmarkFilterQuery } from '../../../../common/utils/helpers'; -import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '../../../../common/constants'; - import type { CspBenchmarkRule, FindCspBenchmarkRuleRequest, FindCspBenchmarkRuleResponse, -} from '../../../../common/types/rules/v4'; +} from '@kbn/cloud-security-posture-common/schema/rules/v4'; +import { getBenchmarkFilterQuery } from '../../../../common/utils/helpers'; +import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '../../../../common/constants'; + import { getSortedCspBenchmarkRulesTemplates } from './utils'; export const findBenchmarkRuleHandler = async ( diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/v3.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/v3.ts index c3b77a1a38ac3..f1797c0673755 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/v3.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/v3.ts @@ -6,14 +6,14 @@ */ import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; -import { getBenchmarkFilterQueryV2 } from '../../../../common/utils/helpers'; -import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '../../../../common/constants'; - import type { CspBenchmarkRule, FindCspBenchmarkRuleRequest, FindCspBenchmarkRuleResponse, -} from '../../../../common/types/latest'; +} from '@kbn/cloud-security-posture-common/schema/rules/latest'; +import { getBenchmarkFilterQueryV2 } from '../../../../common/utils/helpers'; +import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '../../../../common/constants'; + import { getSortedCspBenchmarkRulesTemplates } from './utils'; export const findBenchmarkRuleHandler = async ( diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/get_states/get_states.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/get_states/get_states.ts index 44dd77cc67059..6099921efdc61 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/get_states/get_states.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/get_states/get_states.ts @@ -7,7 +7,7 @@ import { transformError } from '@kbn/securitysolution-es-utils'; import { CSP_GET_BENCHMARK_RULES_STATE_ROUTE_PATH } from '@kbn/cloud-security-posture-common'; -import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common'; +import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { CspRouter } from '../../../types'; import { getCspBenchmarkRulesStatesHandler } from './v1'; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/get_states/v1.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/get_states/v1.ts index 1c7ddccf91bba..e6c2e90cd9886 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/get_states/v1.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/get_states/v1.ts @@ -10,13 +10,13 @@ import { } from '@kbn/core-saved-objects-api-server'; import { transformError } from '@kbn/securitysolution-es-utils'; import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common'; -import { CspSettings } from '../../../../common/types/rules/v4'; +import { buildMutedRulesFilter } from '@kbn/cloud-security-posture-common'; +import type { CspBenchmarkRulesStates } from '@kbn/cloud-security-posture-common/schema/rules/latest'; +import type { CspSettings } from '@kbn/cloud-security-posture-common/schema/rules/v4'; import { INTERNAL_CSP_SETTINGS_SAVED_OBJECT_ID, INTERNAL_CSP_SETTINGS_SAVED_OBJECT_TYPE, } from '../../../../common/constants'; -import { buildMutedRulesFilter } from '../../../../common/utils/rules_states'; export const createCspSettingObject = async (soClient: SavedObjectsClientContract) => { return soClient.create( diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/utilities.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/utilities.ts index d7ce82da9d98c..166349d863fb2 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/utilities.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/utilities.ts @@ -7,9 +7,9 @@ import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; +import { CspBenchmarkRule } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '../../../common/constants'; -import { CspBenchmarkRule } from '../../../common/types/latest'; import { BenchmarkId } from '../../../common/types_old'; import { getBenchmarkFilter } from '../../../common/utils/helpers'; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/v2.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/v2.ts index 55e32fdb45a8f..327a2da76f336 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/v2.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/v2.ts @@ -9,12 +9,13 @@ import { QueryDslQueryContainer } from '@kbn/data-views-plugin/common/types'; import { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient, Logger } from '@kbn/core/server'; import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; +import type { CspBenchmarkRule } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE, LATEST_FINDINGS_INDEX_DEFAULT_NS, } from '../../../common/constants'; -import { CspBenchmarkRule, Benchmark } from '../../../common/types/latest'; +import { Benchmark } from '../../../common/types/latest'; import { getClusters } from '../compliance_dashboard/get_clusters'; import { getStats } from '../compliance_dashboard/get_stats'; import { getSafePostureTypeRuntimeMapping } from '../../../common/runtime_mappings/get_safe_posture_type_runtime_mapping'; diff --git a/x-pack/plugins/cloud_security_posture/server/saved_objects/csp_benchmark_rule.ts b/x-pack/plugins/cloud_security_posture/server/saved_objects/csp_benchmark_rule.ts index ebf90aa500097..dc8c93ae4bc93 100644 --- a/x-pack/plugins/cloud_security_posture/server/saved_objects/csp_benchmark_rule.ts +++ b/x-pack/plugins/cloud_security_posture/server/saved_objects/csp_benchmark_rule.ts @@ -7,7 +7,7 @@ import { SECURITY_SOLUTION_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; import { SavedObjectsType } from '@kbn/core/server'; -import { rulesV1, rulesV2, rulesV3 } from '../../common/types'; +import { rulesV1, rulesV2, rulesV3 } from '@kbn/cloud-security-posture-common/schema/rules'; import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '../../common/constants'; import { cspBenchmarkRuleMigrations } from './migrations'; import { cspBenchmarkRuleSavedObjectMapping } from './mappings'; diff --git a/x-pack/plugins/cloud_security_posture/server/saved_objects/csp_settings.ts b/x-pack/plugins/cloud_security_posture/server/saved_objects/csp_settings.ts index f1c61df75b4fc..676828367f638 100644 --- a/x-pack/plugins/cloud_security_posture/server/saved_objects/csp_settings.ts +++ b/x-pack/plugins/cloud_security_posture/server/saved_objects/csp_settings.ts @@ -7,7 +7,7 @@ import { SavedObjectsType } from '@kbn/core/server'; import { SECURITY_SOLUTION_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; -import { cspSettingsSchema } from '../../common/types/rules/v4'; +import { cspSettingsSchema } from '@kbn/cloud-security-posture-common/schema/rules/v4'; import { cspSettingsSavedObjectMapping } from './mappings'; import { INTERNAL_CSP_SETTINGS_SAVED_OBJECT_TYPE } from '../../common/constants'; diff --git a/x-pack/plugins/cloud_security_posture/server/saved_objects/migrations/csp_benchmark_rule.ts b/x-pack/plugins/cloud_security_posture/server/saved_objects/migrations/csp_benchmark_rule.ts index e440342d2083d..942f2a2fc648a 100644 --- a/x-pack/plugins/cloud_security_posture/server/saved_objects/migrations/csp_benchmark_rule.ts +++ b/x-pack/plugins/cloud_security_posture/server/saved_objects/migrations/csp_benchmark_rule.ts @@ -10,7 +10,7 @@ import { SavedObjectUnsanitizedDoc, SavedObjectMigrationContext, } from '@kbn/core/server'; -import { rulesV1, rulesV2, rulesV3 } from '../../../common/types'; +import { rulesV1, rulesV2, rulesV3 } from '@kbn/cloud-security-posture-common/schema/rules'; function migrateCspBenchmarkRuleToV840( doc: SavedObjectUnsanitizedDoc, diff --git a/x-pack/plugins/data_quality/common/index.ts b/x-pack/plugins/data_quality/common/index.ts index 1b174a9efe524..a1869cd9ac356 100644 --- a/x-pack/plugins/data_quality/common/index.ts +++ b/x-pack/plugins/data_quality/common/index.ts @@ -12,4 +12,8 @@ export const PLUGIN_NAME = i18n.translate('xpack.dataQuality.name', { defaultMessage: 'Data Set Quality', }); -export { DATA_QUALITY_URL_STATE_KEY, datasetQualityUrlSchemaV1 } from './url_schema'; +export { + DATA_QUALITY_URL_STATE_KEY, + datasetQualityUrlSchemaV1, + datasetQualityDetailsUrlSchemaV1, +} from './url_schema'; diff --git a/x-pack/plugins/data_quality/common/locators/construct_dataset_quality_details_locator_path.ts b/x-pack/plugins/data_quality/common/locators/construct_dataset_quality_details_locator_path.ts new file mode 100644 index 0000000000000..31ae8591bb5b8 --- /dev/null +++ b/x-pack/plugins/data_quality/common/locators/construct_dataset_quality_details_locator_path.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/common'; +import { ManagementAppLocatorParams } from '@kbn/management-plugin/common/locator'; +import { LocatorPublic } from '@kbn/share-plugin/common'; +import { DataQualityDetailsLocatorParams } from '@kbn/deeplinks-observability'; +import { datasetQualityDetailsUrlSchemaV1, DATA_QUALITY_URL_STATE_KEY } from '../url_schema'; +import { deepCompactObject } from '../utils/deep_compact_object'; + +interface LocatorPathConstructionParams { + locatorParams: DataQualityDetailsLocatorParams; + useHash: boolean; + managementLocator: LocatorPublic; +} + +export const constructDatasetQualityDetailsLocatorPath = async ( + params: LocatorPathConstructionParams +) => { + const { locatorParams, useHash, managementLocator } = params; + + const pageState = datasetQualityDetailsUrlSchemaV1.urlSchemaRT.encode( + deepCompactObject({ + v: 1, + ...locatorParams, + }) + ); + + const managementPath = await managementLocator.getLocation({ + sectionId: 'data', + appId: 'data_quality/details', + }); + + const path = setStateToKbnUrl( + DATA_QUALITY_URL_STATE_KEY, + pageState, + { useHash, storeInHashQuery: false }, + `${managementPath.app}${managementPath.path}` + ); + + return { + app: '', + path, + state: {}, + }; +}; diff --git a/x-pack/plugins/data_quality/common/locators/construct_dataset_quality_locator_path.ts b/x-pack/plugins/data_quality/common/locators/construct_dataset_quality_locator_path.ts index f5b5b0bf7ce59..4fc97618d33e1 100644 --- a/x-pack/plugins/data_quality/common/locators/construct_dataset_quality_locator_path.ts +++ b/x-pack/plugins/data_quality/common/locators/construct_dataset_quality_locator_path.ts @@ -20,7 +20,7 @@ interface LocatorPathConstructionParams { export const constructDatasetQualityLocatorPath = async (params: LocatorPathConstructionParams) => { const { - locatorParams: { filters, flyout }, + locatorParams: { filters }, useHash, managementLocator, } = params; @@ -29,7 +29,6 @@ export const constructDatasetQualityLocatorPath = async (params: LocatorPathCons deepCompactObject({ v: 1, filters, - flyout, }) ); diff --git a/x-pack/plugins/data_quality/common/locators/dataset_quality_details_locator.ts b/x-pack/plugins/data_quality/common/locators/dataset_quality_details_locator.ts new file mode 100644 index 0000000000000..a25e065b1efb4 --- /dev/null +++ b/x-pack/plugins/data_quality/common/locators/dataset_quality_details_locator.ts @@ -0,0 +1,31 @@ +/* + * 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 { LocatorDefinition } from '@kbn/share-plugin/public'; +import { + DataQualityDetailsLocatorParams, + DATA_QUALITY_DETAILS_LOCATOR_ID, +} from '@kbn/deeplinks-observability'; +import { DataQualityLocatorDependencies } from './types'; +import { constructDatasetQualityDetailsLocatorPath } from './construct_dataset_quality_details_locator_path'; + +export class DatasetQualityDetailsLocatorDefinition + implements LocatorDefinition +{ + public readonly id = DATA_QUALITY_DETAILS_LOCATOR_ID; + + constructor(protected readonly deps: DataQualityLocatorDependencies) {} + + public readonly getLocation = async (params: DataQualityDetailsLocatorParams) => { + const { useHash, managementLocator } = this.deps; + return await constructDatasetQualityDetailsLocatorPath({ + useHash, + managementLocator, + locatorParams: params, + }); + }; +} diff --git a/x-pack/plugins/data_quality/common/locators/dataset_quality_locator.ts b/x-pack/plugins/data_quality/common/locators/dataset_quality_locator.ts index 4bf804955b6bc..5db4980e4f661 100644 --- a/x-pack/plugins/data_quality/common/locators/dataset_quality_locator.ts +++ b/x-pack/plugins/data_quality/common/locators/dataset_quality_locator.ts @@ -5,13 +5,11 @@ * 2.0. */ -import type { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/public'; +import type { LocatorDefinition } from '@kbn/share-plugin/public'; import { DataQualityLocatorParams, DATA_QUALITY_LOCATOR_ID } from '@kbn/deeplinks-observability'; import { DataQualityLocatorDependencies } from './types'; import { constructDatasetQualityLocatorPath } from './construct_dataset_quality_locator_path'; -export type DatasetQualityLocator = LocatorPublic; - export class DatasetQualityLocatorDefinition implements LocatorDefinition { diff --git a/x-pack/plugins/data_quality/common/locators/index.ts b/x-pack/plugins/data_quality/common/locators/index.ts index 97df9e70698d7..02d91cadb5fdb 100644 --- a/x-pack/plugins/data_quality/common/locators/index.ts +++ b/x-pack/plugins/data_quality/common/locators/index.ts @@ -5,11 +5,6 @@ * 2.0. */ -import { DatasetQualityLocator } from './dataset_quality_locator'; - export * from './dataset_quality_locator'; +export * from './dataset_quality_details_locator'; export * from './types'; - -export interface DataQualityLocators { - datasetQualityLocator: DatasetQualityLocator; -} diff --git a/x-pack/plugins/data_quality/common/url_schema/dataset_quality_detils_url_schema_v1.ts b/x-pack/plugins/data_quality/common/url_schema/dataset_quality_details_url_schema_v1.ts similarity index 100% rename from x-pack/plugins/data_quality/common/url_schema/dataset_quality_detils_url_schema_v1.ts rename to x-pack/plugins/data_quality/common/url_schema/dataset_quality_details_url_schema_v1.ts diff --git a/x-pack/plugins/data_quality/common/url_schema/dataset_quality_url_schema_v1.ts b/x-pack/plugins/data_quality/common/url_schema/dataset_quality_url_schema_v1.ts index 78c4faeca8cd8..5121f1b7f64d7 100644 --- a/x-pack/plugins/data_quality/common/url_schema/dataset_quality_url_schema_v1.ts +++ b/x-pack/plugins/data_quality/common/url_schema/dataset_quality_url_schema_v1.ts @@ -6,43 +6,14 @@ */ import * as rt from 'io-ts'; -import { degradedFieldRT, tableRT, timeRangeRT } from './common'; - -const integrationRT = rt.strict({ - name: rt.string, - title: rt.string, - version: rt.string, -}); - -const datasetRT = rt.intersection([ - rt.strict({ - rawName: rt.string, - type: rt.string, - name: rt.string, - namespace: rt.string, - }), - rt.exact( - rt.partial({ - integration: integrationRT, - title: rt.string, - }) - ), -]); - -export const flyoutRT = rt.exact( - rt.partial({ - dataset: datasetRT, - insightsTimeRange: timeRangeRT, - breakdownField: rt.string, - degradedFields: degradedFieldRT, - }) -); +import { tableRT, timeRangeRT } from './common'; export const filtersRT = rt.exact( rt.partial({ inactive: rt.boolean, fullNames: rt.boolean, timeRange: timeRangeRT, + types: rt.array(rt.string), integrations: rt.array(rt.string), namespaces: rt.array(rt.string), qualities: rt.array(rt.union([rt.literal('poor'), rt.literal('degraded'), rt.literal('good')])), @@ -54,7 +25,6 @@ export const urlSchemaRT = rt.exact( rt.partial({ v: rt.literal(1), table: tableRT, - flyout: flyoutRT, filters: filtersRT, }) ); diff --git a/x-pack/plugins/data_quality/common/url_schema/index.ts b/x-pack/plugins/data_quality/common/url_schema/index.ts index 0af03b6d503f5..bf984fa73f129 100644 --- a/x-pack/plugins/data_quality/common/url_schema/index.ts +++ b/x-pack/plugins/data_quality/common/url_schema/index.ts @@ -7,4 +7,4 @@ export { DATA_QUALITY_URL_STATE_KEY } from './common'; export * as datasetQualityUrlSchemaV1 from './dataset_quality_url_schema_v1'; -export * as datasetQualityDetailsUrlSchemaV1 from './dataset_quality_detils_url_schema_v1'; +export * as datasetQualityDetailsUrlSchemaV1 from './dataset_quality_details_url_schema_v1'; diff --git a/x-pack/plugins/data_quality/public/plugin.ts b/x-pack/plugins/data_quality/public/plugin.ts index cb217abf86fec..025268848a9a8 100644 --- a/x-pack/plugins/data_quality/public/plugin.ts +++ b/x-pack/plugins/data_quality/public/plugin.ts @@ -16,7 +16,10 @@ import { AppPluginSetupDependencies, } from './types'; import { PLUGIN_ID, PLUGIN_NAME } from '../common'; -import { DatasetQualityLocatorDefinition } from '../common/locators'; +import { + DatasetQualityLocatorDefinition, + DatasetQualityDetailsLocatorDefinition, +} from '../common/locators'; export class DataQualityPlugin implements @@ -67,6 +70,12 @@ export class DataQualityPlugin managementLocator, }) ); + share.url.locators.create( + new DatasetQualityDetailsLocatorDefinition({ + useHash, + managementLocator, + }) + ); } return {}; diff --git a/x-pack/plugins/data_quality/public/routes/dataset_quality/context.tsx b/x-pack/plugins/data_quality/public/routes/dataset_quality/context.tsx index ddd3227fa1a2b..0614ab02db677 100644 --- a/x-pack/plugins/data_quality/public/routes/dataset_quality/context.tsx +++ b/x-pack/plugins/data_quality/public/routes/dataset_quality/context.tsx @@ -44,13 +44,6 @@ export function DatasetQualityContextProvider({ }); datasetQualityController.service.start(); - if (initialState?.flyout?.dataset) { - datasetQualityController.service.send({ - type: 'OPEN_FLYOUT', - dataset: initialState.flyout.dataset, - }); - } - setController(datasetQualityController); const datasetQualityStateSubscription = datasetQualityController.state$.subscribe((state) => { diff --git a/x-pack/plugins/data_quality/public/routes/dataset_quality/url_schema_v1.ts b/x-pack/plugins/data_quality/public/routes/dataset_quality/url_schema_v1.ts index ee7fd8904a593..072acf88aa460 100644 --- a/x-pack/plugins/data_quality/public/routes/dataset_quality/url_schema_v1.ts +++ b/x-pack/plugins/data_quality/public/routes/dataset_quality/url_schema_v1.ts @@ -5,10 +5,7 @@ * 2.0. */ -import { - DatasetQualityFlyoutOptions, - DatasetQualityPublicStateUpdate, -} from '@kbn/dataset-quality-plugin/public/controller/dataset_quality'; +import { DatasetQualityPublicStateUpdate } from '@kbn/dataset-quality-plugin/public/controller/dataset_quality'; import * as rt from 'io-ts'; import { deepCompactObject } from '../../../common/utils/deep_compact_object'; import { datasetQualityUrlSchemaV1 } from '../../../common/url_schema'; @@ -18,7 +15,6 @@ export const getStateFromUrlValue = ( ): DatasetQualityPublicStateUpdate => deepCompactObject({ table: urlValue.table, - flyout: getFlyoutFromUrlValue(urlValue.flyout), filters: urlValue.filters, }); @@ -27,7 +23,6 @@ export const getUrlValueFromState = ( ): datasetQualityUrlSchemaV1.UrlSchema => deepCompactObject({ table: state.table, - flyout: state.flyout, filters: state.filters, v: 1, }); @@ -45,25 +40,3 @@ const stateFromUrlSchemaRT = new rt.Type< export const stateFromUntrustedUrlRT = datasetQualityUrlSchemaV1.urlSchemaRT.pipe(stateFromUrlSchemaRT); - -const getFlyoutFromUrlValue = ( - flyout?: datasetQualityUrlSchemaV1.UrlSchema['flyout'] -): DatasetQualityFlyoutOptions => - deepCompactObject({ - ...(flyout - ? { - ...flyout, - dataset: flyout.dataset - ? { - ...flyout.dataset, - integration: flyout.dataset.integration - ? { - ...flyout.dataset.integration, - datasets: {}, - } - : undefined, - } - : undefined, - } - : {}), - }); diff --git a/x-pack/plugins/data_quality/public/routes/dataset_quality_details/url_schema_v1.ts b/x-pack/plugins/data_quality/public/routes/dataset_quality_details/url_schema_v1.ts index b97d1bb9100eb..551ae51892adf 100644 --- a/x-pack/plugins/data_quality/public/routes/dataset_quality_details/url_schema_v1.ts +++ b/x-pack/plugins/data_quality/public/routes/dataset_quality_details/url_schema_v1.ts @@ -17,6 +17,7 @@ export const getStateFromUrlValue = ( dataStream: urlValue.dataStream, timeRange: urlValue.timeRange, degradedFields: urlValue.degradedFields, + breakdownField: urlValue.breakdownField, }); export const getUrlValueFromState = ( @@ -26,6 +27,7 @@ export const getUrlValueFromState = ( dataStream: state.dataStream, timeRange: state.timeRange, degradedFields: state.degradedFields, + breakdownField: state.breakdownField, v: 1, }); diff --git a/x-pack/plugins/data_quality/server/plugin.ts b/x-pack/plugins/data_quality/server/plugin.ts index 4977e6f09a5c1..088905b8975d4 100644 --- a/x-pack/plugins/data_quality/server/plugin.ts +++ b/x-pack/plugins/data_quality/server/plugin.ts @@ -25,6 +25,20 @@ export class DataQualityPlugin implements Plugin { ['logs-*-*']: ['read'], }, }, + { + ui: [], + requiredClusterPrivileges: [], + requiredIndexPrivileges: { + ['traces-*-*']: ['read'], + }, + }, + { + ui: [], + requiredClusterPrivileges: [], + requiredIndexPrivileges: { + ['metrics-*-*']: ['read'], + }, + }, ], }); } diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.test.tsx index 58b5065e7dbda..17739a7791b56 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.test.tsx @@ -5,6 +5,8 @@ * 2.0. */ +import { setMockValues } from '../../../__mocks__/kea_logic'; + import React from 'react'; import { shallow } from 'enzyme'; @@ -16,7 +18,13 @@ import { WorkplaceSearchHeaderActions } from '.'; describe('WorkplaceSearchHeaderActions', () => { const ENT_SEARCH_URL = 'http://localhost:3002'; + beforeEach(() => { + jest.clearAllMocks(); + setMockValues({ dataLoading: false, organization: { kibanaUIsEnabled: true } }); + }); + it('does not render without an Enterprise Search URL set', () => { + setMockValues({ dataLoading: false, organization: {} }); const wrapper = shallow(); expect(wrapper.isEmptyRender()).toBe(true); @@ -39,4 +47,21 @@ describe('WorkplaceSearchHeaderActions', () => { 'http://localhost:3002/ws/search' ); }); + + it('renders the dashboard and search button when not gated', () => { + externalUrl.enterpriseSearchUrl = ENT_SEARCH_URL; + const wrapper = shallow(); + + expect(wrapper.find('[data-test-subj="PersonalDashboardButton"]').exists()).toBe(true); + expect(wrapper.find('[data-test-subj="HeaderSearchButton"]').exists()).toBe(true); + }); + + it('does not render the dashboard and search button on the gated form', () => { + externalUrl.enterpriseSearchUrl = ENT_SEARCH_URL; + setMockValues({ dataLoading: false, organization: { kibanaUIsEnabled: false } }); + const wrapper = shallow(); + + expect(wrapper.find('[data-test-subj="PersonalDashboardButton"]').exists()).toBe(false); + expect(wrapper.find('[data-test-subj="HeaderSearchButton"]').exists()).toBe(false); + }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.tsx index d1eb78b184223..d113df570f445 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.tsx @@ -7,17 +7,34 @@ import React from 'react'; +import { useValues } from 'kea'; + import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { externalUrl, getWorkplaceSearchUrl } from '../../../shared/enterprise_search_url'; import { EndpointsHeaderAction } from '../../../shared/layout/endpoints_header_action'; import { EuiButtonEmptyTo } from '../../../shared/react_router_helpers'; +import { AppLogic } from '../../app_logic'; import { NAV } from '../../constants'; import { PRIVATE_SOURCES_PATH } from '../../routes'; export const WorkplaceSearchHeaderActions: React.FC = () => { + const { + organization: { kibanaUIsEnabled }, + } = useValues(AppLogic); + if (!externalUrl.enterpriseSearchUrl) return null; + if (!kibanaUIsEnabled) { + // we can't just return a null here as it will not render + // the Endpoints and Keys flyout button + return ( + + <> + + ); + } + return ( diff --git a/x-pack/plugins/event_log/generated/mappings.json b/x-pack/plugins/event_log/generated/mappings.json index 98908f516fc96..5fc8128baa7ae 100644 --- a/x-pack/plugins/event_log/generated/mappings.json +++ b/x-pack/plugins/event_log/generated/mappings.json @@ -482,6 +482,10 @@ "type": "keyword", "ignore_above": 1024 }, + "type_id": { + "type": "keyword", + "ignore_above": 1024 + }, "execution": { "properties": { "source": { @@ -508,6 +512,13 @@ } } } + }, + "usage": { + "properties": { + "request_body_bytes": { + "type": "long" + } + } } } } diff --git a/x-pack/plugins/event_log/generated/schemas.ts b/x-pack/plugins/event_log/generated/schemas.ts index f8db21105539e..7542d6db5213a 100644 --- a/x-pack/plugins/event_log/generated/schemas.ts +++ b/x-pack/plugins/event_log/generated/schemas.ts @@ -212,6 +212,7 @@ export const EventSchema = schema.maybe( schema.object({ name: ecsString(), id: ecsString(), + type_id: ecsString(), execution: schema.maybe( schema.object({ source: ecsString(), @@ -227,6 +228,11 @@ export const EventSchema = schema.maybe( ), }) ), + usage: schema.maybe( + schema.object({ + request_body_bytes: ecsStringOrNumber(), + }) + ), }) ), }) diff --git a/x-pack/plugins/event_log/scripts/mappings.js b/x-pack/plugins/event_log/scripts/mappings.js index aa91f7fc5c2d6..770f9e6d45f9a 100644 --- a/x-pack/plugins/event_log/scripts/mappings.js +++ b/x-pack/plugins/event_log/scripts/mappings.js @@ -257,6 +257,10 @@ exports.EcsCustomPropertyMappings = { type: 'keyword', ignore_above: 1024, }, + type_id: { + type: 'keyword', + ignore_above: 1024, + }, execution: { properties: { source: { @@ -284,6 +288,13 @@ exports.EcsCustomPropertyMappings = { }, }, }, + usage: { + properties: { + request_body_bytes: { + type: 'long', + }, + }, + }, }, }, }, diff --git a/x-pack/plugins/fleet/common/openapi/bundled.json b/x-pack/plugins/fleet/common/openapi/bundled.json index 989955b748ed5..fc9e292bdeff7 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.json +++ b/x-pack/plugins/fleet/common/openapi/bundled.json @@ -4112,6 +4112,17 @@ "tags": [ "Fleet enrollment API keys" ], + "parameters": [ + { + "$ref": "#/components/parameters/page_size" + }, + { + "$ref": "#/components/parameters/page_index" + }, + { + "$ref": "#/components/parameters/kuery" + } + ], "responses": { "200": { "description": "OK", @@ -4157,8 +4168,7 @@ "$ref": "#/components/responses/error" } }, - "operationId": "get-enrollment-api-keys", - "parameters": [] + "operationId": "get-enrollment-api-keys" }, "post": { "summary": "Create enrollment API key", @@ -4191,6 +4201,28 @@ "$ref": "#/components/responses/error" } }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the enrollment API key. Must be unique." + }, + "policy_id": { + "type": "string", + "description": "The ID of the agent policy the Elastic Agent will be enrolled in." + } + }, + "required": [ + "policy_id" + ] + } + } + } + }, "operationId": "create-enrollment-api-keys", "parameters": [ { @@ -4241,7 +4273,7 @@ "operationId": "get-enrollment-api-key" }, "delete": { - "summary": "Delete enrollment API key by ID", + "summary": "Revoke enrollment API key by ID by marking it as inactive", "tags": [ "Fleet enrollment API keys" ], @@ -8199,19 +8231,24 @@ "type": "string" }, "api_key_id": { - "type": "string" + "type": "string", + "description": "The ID of the API key in the Security API." }, "api_key": { - "type": "string" + "type": "string", + "description": "The enrollment API key (token) used for enrolling Elastic Agents." }, "name": { - "type": "string" + "type": "string", + "description": "The name of the enrollment API key." }, "active": { - "type": "boolean" + "type": "boolean", + "description": "When false, the enrollment API key is revoked and cannot be used for enrolling Elastic Agents." }, "policy_id": { - "type": "string" + "type": "string", + "description": "The ID of the agent policy the Elastic Agent will be enrolled in." }, "created_at": { "type": "string" diff --git a/x-pack/plugins/fleet/common/openapi/bundled.yaml b/x-pack/plugins/fleet/common/openapi/bundled.yaml index fe1c2fc68c58a..2a1a18326fc31 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.yaml +++ b/x-pack/plugins/fleet/common/openapi/bundled.yaml @@ -2561,6 +2561,10 @@ paths: summary: List enrollment API keys tags: - Fleet enrollment API keys + parameters: + - $ref: '#/components/parameters/page_size' + - $ref: '#/components/parameters/page_index' + - $ref: '#/components/parameters/kuery' responses: '200': description: OK @@ -2592,7 +2596,6 @@ paths: '400': $ref: '#/components/responses/error' operationId: get-enrollment-api-keys - parameters: [] post: summary: Create enrollment API key tags: @@ -2613,6 +2616,22 @@ paths: - created '400': $ref: '#/components/responses/error' + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: The name of the enrollment API key. Must be unique. + policy_id: + type: string + description: >- + The ID of the agent policy the Elastic Agent will be + enrolled in. + required: + - policy_id operationId: create-enrollment-api-keys parameters: - $ref: '#/components/parameters/kbn_xsrf' @@ -2643,7 +2662,7 @@ paths: $ref: '#/components/responses/error' operationId: get-enrollment-api-key delete: - summary: Delete enrollment API key by ID + summary: Revoke enrollment API key by ID by marking it as inactive tags: - Fleet enrollment API keys responses: @@ -5279,14 +5298,21 @@ components: type: string api_key_id: type: string + description: The ID of the API key in the Security API. api_key: type: string + description: The enrollment API key (token) used for enrolling Elastic Agents. name: type: string + description: The name of the enrollment API key. active: type: boolean + description: >- + When false, the enrollment API key is revoked and cannot be used for + enrolling Elastic Agents. policy_id: type: string + description: The ID of the agent policy the Elastic Agent will be enrolled in. created_at: type: string required: diff --git a/x-pack/plugins/fleet/common/openapi/components/schemas/enrollment_api_key.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/enrollment_api_key.yaml index 7be406cf5b831..e1ce2243dc29f 100644 --- a/x-pack/plugins/fleet/common/openapi/components/schemas/enrollment_api_key.yaml +++ b/x-pack/plugins/fleet/common/openapi/components/schemas/enrollment_api_key.yaml @@ -5,14 +5,19 @@ properties: type: string api_key_id: type: string + description: The ID of the API key in the Security API. api_key: type: string + description: The enrollment API key (token) used for enrolling Elastic Agents. name: type: string + description: The name of the enrollment API key. active: type: boolean + description: When false, the enrollment API key is revoked and cannot be used for enrolling Elastic Agents. policy_id: type: string + description: The ID of the agent policy the Elastic Agent will be enrolled in. created_at: type: string required: diff --git a/x-pack/plugins/fleet/common/openapi/components/schemas/new_package_policy.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/new_package_policy.yaml index 956f51a8016f5..ef22c197c5b40 100644 --- a/x-pack/plugins/fleet/common/openapi/components/schemas/new_package_policy.yaml +++ b/x-pack/plugins/fleet/common/openapi/components/schemas/new_package_policy.yaml @@ -47,6 +47,7 @@ properties: - enabled policy_id: type: string + nullable: true deprecated: true policy_ids: type: array diff --git a/x-pack/plugins/fleet/common/openapi/components/schemas/package_policy_request.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/package_policy_request.yaml index 7e820c75bf4c3..871bc8b6d1ae8 100644 --- a/x-pack/plugins/fleet/common/openapi/components/schemas/package_policy_request.yaml +++ b/x-pack/plugins/fleet/common/openapi/components/schemas/package_policy_request.yaml @@ -16,11 +16,17 @@ properties: type: string description: The package policy namespace. Leave blank to inherit the agent policy's namespace. example: 'customnamespace' + output_id: + type: string + description: Output ID to send package data to + example: 'output-id' + nullable: true policy_id: type: string description: Agent policy ID where that package policy will be added example: 'agent-policy-id' deprecated: true + nullable: true policy_ids: type: array items: diff --git a/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys.yaml b/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys.yaml index 625ad82e3f3f2..7da2e9374353b 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys.yaml @@ -2,6 +2,10 @@ get: summary: List enrollment API keys tags: - Fleet enrollment API keys + parameters: + - $ref: ../components/parameters/page_size.yaml + - $ref: ../components/parameters/page_index.yaml + - $ref: ../components/parameters/kuery.yaml responses: '200': description: OK @@ -33,7 +37,6 @@ get: '400': $ref: ../components/responses/error.yaml operationId: get-enrollment-api-keys - parameters: [] post: summary: Create enrollment API key tags: @@ -54,6 +57,20 @@ post: - created '400': $ref: ../components/responses/error.yaml + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: The name of the enrollment API key. Must be unique. + policy_id: + type: string + description: The ID of the agent policy the Elastic Agent will be enrolled in. + required: + - policy_id operationId: create-enrollment-api-keys parameters: - $ref: ../components/headers/kbn_xsrf.yaml diff --git a/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys@{key_id}.yaml b/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys@{key_id}.yaml index f3bdc459d6ccf..f0f8be73d8666 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys@{key_id}.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys@{key_id}.yaml @@ -24,7 +24,7 @@ get: $ref: ../components/responses/error.yaml operationId: get-enrollment-api-key delete: - summary: Delete enrollment API key by ID + summary: Revoke enrollment API key by ID by marking it as inactive tags: - Fleet enrollment API keys responses: diff --git a/x-pack/plugins/fleet/common/services/simplified_package_policy_helper.ts b/x-pack/plugins/fleet/common/services/simplified_package_policy_helper.ts index 8d616bf4cae11..14c7b3888f775 100644 --- a/x-pack/plugins/fleet/common/services/simplified_package_policy_helper.ts +++ b/x-pack/plugins/fleet/common/services/simplified_package_policy_helper.ts @@ -41,7 +41,7 @@ export type SimplifiedInputs = Record< export interface SimplifiedPackagePolicy { id?: string; - policy_id?: string; + policy_id?: string | null; policy_ids: string[]; output_id?: string; namespace: string; diff --git a/x-pack/plugins/fleet/common/types/models/package_policy.ts b/x-pack/plugins/fleet/common/types/models/package_policy.ts index a6db753d1a1ce..1e456f3e4d21d 100644 --- a/x-pack/plugins/fleet/common/types/models/package_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/package_policy.ts @@ -78,8 +78,8 @@ export interface NewPackagePolicy { namespace?: string; enabled: boolean; is_managed?: boolean; - /** @deprecated */ - policy_id?: string; + /** @deprecated Nullable to allow user to clear existing policy id */ + policy_id?: string | null; policy_ids: string[]; // Nullable to allow user to reset to default outputs output_id?: string | null; diff --git a/x-pack/plugins/fleet/common/types/models/uninstall_token.ts b/x-pack/plugins/fleet/common/types/models/uninstall_token.ts index 2d8a87c6fddcc..52ddd47143f7f 100644 --- a/x-pack/plugins/fleet/common/types/models/uninstall_token.ts +++ b/x-pack/plugins/fleet/common/types/models/uninstall_token.ts @@ -11,6 +11,7 @@ export interface UninstallToken { policy_name: string | null; token: string; created_at: string; + namespaces?: string[]; } export type UninstallTokenMetadata = Omit; diff --git a/x-pack/plugins/fleet/common/types/rest_spec/agent_policy.ts b/x-pack/plugins/fleet/common/types/rest_spec/agent_policy.ts index 3b35e986a5d55..4e6a85ccdc270 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/agent_policy.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/agent_policy.ts @@ -89,4 +89,6 @@ export type FetchAllAgentPoliciesOptions = Pick< 'perPage' | 'kuery' | 'sortField' | 'sortOrder' > & { fields?: string[] }; -export type FetchAllAgentPolicyIdsOptions = Pick; +export type FetchAllAgentPolicyIdsOptions = Pick & { + spaceId?: string; +}; diff --git a/x-pack/plugins/fleet/common/types/rest_spec/package_policy.ts b/x-pack/plugins/fleet/common/types/rest_spec/package_policy.ts index 8b74a3142fa97..4aa2e367e04ec 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/package_policy.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/package_policy.ts @@ -61,7 +61,7 @@ export type PostDeletePackagePoliciesResponse = Array<{ name?: string; success: boolean; package?: PackagePolicyPackage; - policy_id?: string; + policy_id?: string | null; policy_ids?: string[]; output_id?: string; // Support generic errors diff --git a/x-pack/plugins/fleet/cypress/tasks/integrations.ts b/x-pack/plugins/fleet/cypress/tasks/integrations.ts index ab640d8f26a0e..002aaadefa859 100644 --- a/x-pack/plugins/fleet/cypress/tasks/integrations.ts +++ b/x-pack/plugins/fleet/cypress/tasks/integrations.ts @@ -18,22 +18,18 @@ import { CONFIRM_MODAL } from '../screens/navigation'; import { request } from './common'; export const addIntegration = ({ useExistingPolicy } = { useExistingPolicy: false }) => { + cy.intercept('/api/fleet/agent_status?*').as('agentStatus'); + cy.getBySel(ADD_INTEGRATION_POLICY_BTN).click(); if (useExistingPolicy) { cy.getBySel(EXISTING_HOSTS_TAB).click(); + cy.wait('@agentStatus'); } else { - // speeding up creating with unchecking system and agent integration + // speeding up creating with unchecking system integration cy.getBySel(AGENT_POLICY_SYSTEM_MONITORING_CHECKBOX).uncheck({ force: true }); - cy.get('.euiAccordion__button').click(); - - cy.get('*[id^="logs_"]').uncheck({ - force: true, - }); - cy.get('*[id^="metrics_"]').uncheck({ - force: true, - }); } - cy.getBySel(CREATE_PACKAGE_POLICY_SAVE_BTN).click(); + cy.getBySel(CREATE_PACKAGE_POLICY_SAVE_BTN).should('be.enabled').click(); + // sometimes agent is assigned to default policy, sometimes not cy.getBySel(CONFIRM_MODAL.CONFIRM_BUTTON).click(); diff --git a/x-pack/plugins/fleet/dev_docs/secrets.md b/x-pack/plugins/fleet/dev_docs/secrets.md index 77c5f8521a4c5..a486f4d3b65ce 100644 --- a/x-pack/plugins/fleet/dev_docs/secrets.md +++ b/x-pack/plugins/fleet/dev_docs/secrets.md @@ -99,6 +99,6 @@ Integration secrets are only supported by Fleet server 8.10.0 or greater, output For integration secrets, when performing CRUD on a package policy, we first check the global settings saved object to see if secrets are enabled, if so then secret storage is used. -If secret storage s not enabled, we check all flee tserver versions, if they meet the minimum spec, then we enable secret storage on the global settings saved object and the check is never performed again. +If secret storage is not enabled, we check all fleet server versions, if they meet the minimum spec, then we enable secret storage on the global settings saved object and the check is never performed again. For output secrets, we do not perform this check as outputs offer a plain text alternative for all secret fields. Instead we warn the user about the version requirements and let them decide. diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_integration.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_integration.tsx index 6ab901cb5e27c..a08c6bfe22496 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_integration.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_integration.tsx @@ -6,29 +6,15 @@ */ import React from 'react'; -import { - EuiAccordion, - EuiDescribedFormGroup, - EuiForm, - EuiHorizontalRule, - EuiSpacer, -} from '@elastic/eui'; +import { EuiDescribedFormGroup, EuiForm } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import styled from 'styled-components'; import type { NewAgentPolicy, AgentPolicy } from '../../../types'; -import { AgentPolicyAdvancedOptionsContent } from './agent_policy_advanced_fields'; import { AgentPolicyGeneralFields } from './agent_policy_general_fields'; import { AgentPolicyFormSystemMonitoringCheckbox } from './agent_policy_system_monitoring_field'; import type { ValidationResults } from './agent_policy_validation'; -const StyledEuiAccordion = styled(EuiAccordion)` - .ingest-active-button { - color: ${(props) => props.theme.eui.euiColorPrimary}; - } -`; - interface Props { agentPolicy: Partial; updateAgentPolicy: (u: Partial) => void; @@ -80,27 +66,6 @@ export const AgentPolicyIntegrationForm: React.FunctionComponent = ({ updateSysMonitoring={updateSysMonitoring} /> - <> - - - - } - buttonClassName="ingest-active-button" - > - - - - ); }; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_validation.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_validation.tsx index bb4e39b265f06..a52c2b488139c 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_validation.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_validation.tsx @@ -38,20 +38,20 @@ export const agentPolicyFormValidation = ( errors.namespace = [namespaceValidation.error]; } - if (agentPolicy.unenroll_timeout && agentPolicy.unenroll_timeout < 0) { + if (agentPolicy.unenroll_timeout !== undefined && agentPolicy.unenroll_timeout <= 0) { errors.unenroll_timeout = [ , ]; } - if (agentPolicy.inactivity_timeout && agentPolicy.inactivity_timeout < 0) { + if (agentPolicy.inactivity_timeout !== undefined && agentPolicy.inactivity_timeout <= 0) { errors.inactivity_timeout = [ , ]; } diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/confirm_deploy_modal.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/confirm_deploy_modal.test.tsx index acd3eca559937..1ac5e8c17cb5b 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/confirm_deploy_modal.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/confirm_deploy_modal.test.tsx @@ -55,4 +55,16 @@ describe('ConfirmDeployAgentPolicyModal', () => { 'Agent policies that will be updated to remove this integration policy:Agent policy 3' ); }); + + it('should render no agent policies message when not adding/removing agent policies', () => { + testRenderer = createFleetTestRendererMock(); + render({ + agentCount: 0, + agentPolicies: [], + agentPoliciesToRemove: [], + }); + const calloutText = renderResult.getByTestId('confirmNoPoliciesCallout').textContent; + expect(calloutText).toContain('No agent policies selected'); + expect(calloutText).toContain('This integration will not be added to any agent policies.'); + }); }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/confirm_deploy_modal.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/confirm_deploy_modal.tsx index 9c6aa70ee1ac4..e7a1494fdc016 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/confirm_deploy_modal.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/confirm_deploy_modal.tsx @@ -27,7 +27,46 @@ export const ConfirmDeployAgentPolicyModal: React.FunctionComponent<{ agentPoliciesToAdd = [], agentPoliciesToRemove = [], }) => { - return ( + return agentPolicies.length === 0 && agentPoliciesToRemove.length === 0 ? ( + + } + onCancel={onCancel} + onConfirm={onConfirm} + cancelButtonText={ + + } + confirmButtonText={ + + } + buttonColor="primary" + > + +
      + +
      +
      +
      + ) : ( { + const { data: agentPoliciesData, error: err } = useGetAgentPolicies({ + page: 1, + perPage: SO_SEARCH_LIMIT, + sortField: 'name', + sortOrder: 'asc', + full: false, // package_policies will always be empty + noAgentCount: true, // agentPolicy.agents will always be 0, + kuery: 'ingest-agent-policies.is_managed:false', + }); + if (err) { + // eslint-disable-next-line no-console + console.debug('Could not retrieve agent policies'); + } + return agentPoliciesData?.items || []; +}; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.test.tsx index 23a7ae4cc2fe4..dae4fee9d32af 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.test.tsx @@ -106,8 +106,6 @@ describe('step select agent policy', () => { await act(async () => { const select = renderResult.container.querySelector('[data-test-subj="agentPolicySelect"]'); expect((select as any)?.value).toEqual(''); - - expect(renderResult.getByText('At least one agent policy is required.')).toBeVisible(); }); }); @@ -179,8 +177,6 @@ describe('step select agent policy', () => { '[data-test-subj="agentPolicyMultiSelect"]' ); expect((select as any)?.value).toEqual(undefined); - - expect(renderResult.getByText('At least one agent policy is required.')).toBeVisible(); }); }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.tsx index ecfd18ef9aac4..eb5eb9a34b448 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.tsx @@ -101,19 +101,23 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ updateAgentPolicies([]); } }; - if (isLoading || selectedPolicyIds.length === 0) { + if (isLoading || isFirstLoad) { return; } + const agentPolicyIds = agentPolicies.map((policy) => policy.id); const agentPoliciesHaveAllSelectedIds = selectedPolicyIds.every((id) => - agentPolicies.map((policy) => policy.id).includes(id) + agentPolicyIds.includes(id) ); - if (agentPolicies.length === 0 || !agentPoliciesHaveAllSelectedIds) { + if ( + (agentPolicies.length === 0 && selectedPolicyIds.length !== 0) || + !agentPoliciesHaveAllSelectedIds + ) { fetchAgentPolicyInfo(); } else if (agentPoliciesHaveAllSelectedIds && selectedPolicyIds.length < agentPolicies.length) { setSelectedAgentPolicyError(undefined); updateAgentPolicies(agentPolicies.filter((policy) => selectedPolicyIds.includes(policy.id))); } - }, [selectedPolicyIds, agentPolicies, updateAgentPolicies, isLoading]); + }, [selectedPolicyIds, agentPolicies, updateAgentPolicies, isLoading, isFirstLoad]); // Try to select default agent policy useEffect(() => { @@ -152,9 +156,11 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ // Bubble up any issues with agent policy selection useEffect(() => { - if (selectedPolicyIds.length > 0 && !selectedAgentPolicyError) { + if (!selectedAgentPolicyError) { setHasAgentPolicyError(false); - } else setHasAgentPolicyError(true); + } else { + setHasAgentPolicyError(true); + } }, [selectedAgentPolicyError, selectedPolicyIds, setHasAgentPolicyError]); const onChange = useCallback( @@ -237,16 +243,9 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ /> ) : null } - isInvalid={Boolean( - selectedPolicyIds.length === 0 || someNewAgentPoliciesHaveLimitedPackage - )} + isInvalid={Boolean(someNewAgentPoliciesHaveLimitedPackage)} error={ - selectedPolicyIds.length === 0 ? ( - - ) : someNewAgentPoliciesHaveLimitedPackage ? ( + someNewAgentPoliciesHaveLimitedPackage ? ( { + return { + ...jest.requireActual('./components/use_policies'), + useAllNonManagedAgentPolicies: jest.fn(), + }; +}); jest.mock('../../../../../hooks', () => { return { @@ -121,6 +129,9 @@ describe('StepSelectHosts', () => { items: [{ id: '1', name: 'Agent policy 1', namespace: 'default' }], }, }); + (useAllNonManagedAgentPolicies as jest.MockedFunction).mockReturnValue([ + { id: '1', name: 'Agent policy 1', namespace: 'default' }, + ]); render(); @@ -140,6 +151,9 @@ describe('StepSelectHosts', () => { items: [{ id: '1', name: 'Agent policy 1', namespace: 'default' }], }, }); + (useAllNonManagedAgentPolicies as jest.MockedFunction).mockReturnValue([ + { id: '1', name: 'Agent policy 1', namespace: 'default' }, + ]); render(); @@ -155,7 +169,7 @@ describe('StepSelectHosts', () => { ).toContain('Agent policy 1'); }); - it('should display dropdown without preselected value when Existing hosts selected with mulitple agent policies', () => { + it('should display dropdown without preselected value when Existing hosts selected with mulitple agent policies', async () => { (useGetAgentPolicies as jest.MockedFunction).mockReturnValue({ data: { items: [ @@ -164,6 +178,10 @@ describe('StepSelectHosts', () => { ], }, }); + (useAllNonManagedAgentPolicies as jest.MockedFunction).mockReturnValue([ + { id: '1', name: 'Agent policy 1', namespace: 'default' }, + { id: '2', name: 'Agent policy 2', namespace: 'default' }, + ]); render(); @@ -174,8 +192,9 @@ describe('StepSelectHosts', () => { fireEvent.click(renderResult.getByText('Existing hosts').closest('button')!); }); - waitFor(() => { - expect(renderResult.getByText('At least one agent policy is required.')).toBeInTheDocument(); + await act(async () => { + const select = renderResult.container.querySelector('[data-test-subj="agentPolicySelect"]'); + expect((select as any)?.value).toEqual(''); }); }); }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_hosts.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_hosts.tsx index 4416b7340ef36..c4504e6596353 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_hosts.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_hosts.tsx @@ -5,20 +5,20 @@ * 2.0. */ -import React, { useEffect, useMemo } from 'react'; +import React, { useEffect } from 'react'; import type { EuiTabbedContentTab } from '@elastic/eui'; import { EuiTabbedContent } from '@elastic/eui'; import styled from 'styled-components'; -import { useGetAgentPolicies } from '../../../../../hooks'; import type { AgentPolicy, NewAgentPolicy, PackageInfo } from '../../../../../types'; -import { AgentPolicyIntegrationForm } from '../../../components'; -import { SO_SEARCH_LIMIT } from '../../../../../constants'; import type { ValidationResults } from '../../../components/agent_policy_validation'; import { incrementPolicyName } from '../../../../../services'; +import { AgentPolicyIntegrationForm } from '../../../components'; + import { StepSelectAgentPolicy } from './step_select_agent_policy'; +import { useAllNonManagedAgentPolicies } from './components/use_policies'; export enum SelectedPolicyTab { NEW = 'new', @@ -60,23 +60,7 @@ export const StepSelectHosts: React.FunctionComponent = ({ selectedAgentPolicyIds, initialSelectedTabIndex, }) => { - let existingAgentPolicies: AgentPolicy[] = []; - const { data: agentPoliciesData, error: err } = useGetAgentPolicies({ - page: 1, - perPage: SO_SEARCH_LIMIT, - sortField: 'name', - sortOrder: 'asc', - full: false, // package_policies will always be empty - noAgentCount: true, // agentPolicy.agents will always be 0 - }); - if (err) { - // eslint-disable-next-line no-console - console.debug('Could not retrieve agent policies'); - } - existingAgentPolicies = useMemo( - () => agentPoliciesData?.items.filter((policy) => !policy.is_managed) || [], - [agentPoliciesData?.items] - ); + const existingAgentPolicies: AgentPolicy[] = useAllNonManagedAgentPolicies(); useEffect(() => { if (existingAgentPolicies.length > 0) { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/hooks/navigation.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/hooks/navigation.tsx index c97392dce6ae1..8b9ca7886d236 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/hooks/navigation.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/hooks/navigation.tsx @@ -8,7 +8,8 @@ import { useCallback, useMemo, useEffect, useRef } from 'react'; import type { ApplicationStart } from '@kbn/core-application-browser'; -import { PLUGIN_ID } from '../../../../constants'; +import { PLUGIN_ID, INTEGRATIONS_PLUGIN_ID } from '../../../../constants'; +import { pkgKeyFromPackageInfo } from '../../../../services'; import { useStartServices, useLink, useIntraAppState } from '../../../../hooks'; import type { CreatePackagePolicyRouteState, @@ -35,7 +36,7 @@ export const useCancelAddPackagePolicy = (params: UseCancelParams) => { const { getHref } = useLink(); const cancelClickHandler = useCallback( - (ev) => { + (ev: React.SyntheticEvent) => { if (routeState?.onCancelNavigateTo) { ev.preventDefault(); navigateToApp(...routeState.onCancelNavigateTo); @@ -86,10 +87,14 @@ export const useOnSaveNavigate = (params: UseOnSaveNavigateParams) => { if (!doOnSaveNavigation.current) { return; } - const packagePolicyPath = getPath('policy_details', { - policyId: packagePolicy.policy_ids[0], // TODO navigates to first policy - }); - + const hasNoAgentPolicies = packagePolicy.policy_ids.length === 0; + const packagePolicyPath = hasNoAgentPolicies + ? getPath('integration_details_policies', { + pkgkey: pkgKeyFromPackageInfo(packagePolicy.package!), + }) + : getPath('policy_details', { + policyId: packagePolicy.policy_ids[0], // TODO navigates to first policy + }); const [onSaveNavigateTo, onSaveQueryParams]: [ Parameters, CreatePackagePolicyRouteState['onSaveQueryParams'] @@ -97,7 +102,7 @@ export const useOnSaveNavigate = (params: UseOnSaveNavigateParams) => { ? [routeState.onSaveNavigateTo, routeState?.onSaveQueryParams] : [ [ - PLUGIN_ID, + hasNoAgentPolicies ? INTEGRATIONS_PLUGIN_ID : PLUGIN_ID, { path: packagePolicyPath, }, @@ -123,7 +128,15 @@ export const useOnSaveNavigate = (params: UseOnSaveNavigateParams) => { navigateToApp(...onSaveNavigateTo); } }, - [packagePolicy.policy_ids, getPath, navigateToApp, routeState, queryParamsPolicyId] + [ + packagePolicy.policy_ids, + packagePolicy.package, + getPath, + routeState?.onSaveNavigateTo, + routeState?.onSaveQueryParams, + queryParamsPolicyId, + navigateToApp, + ] ); return onSaveNavigate; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/form.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/form.tsx index 697731f744721..f624bd5c843af 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/form.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/form.tsx @@ -26,6 +26,7 @@ import { sendCreatePackagePolicy, sendBulkInstallPackages, sendGetPackagePolicies, + useMultipleAgentPolicies, } from '../../../../../hooks'; import { isVerificationError, packageToPackagePolicy } from '../../../../../services'; import { @@ -154,6 +155,8 @@ export function useOnSubmit({ const { notifications } = useStartServices(); const confirmForceInstall = useConfirmForceInstall(); const spaceSettings = useSpaceSettingsContext(); + const { canUseMultipleAgentPolicies } = useMultipleAgentPolicies(); + // only used to store the resulting package policy once saved const [savedPackagePolicy, setSavedPackagePolicy] = useState(); // Form state @@ -184,14 +187,10 @@ export function useOnSubmit({ if (isEqual(updatedAgentPolicies, agentPolicies)) { return; } - if (updatedAgentPolicies.length > 0) { - setAgentPolicies(updatedAgentPolicies); - if (packageInfo) { - setHasAgentPolicyError(false); - } - } else { - setHasAgentPolicyError(true); - setAgentPolicies([]); + + setAgentPolicies(updatedAgentPolicies); + if (packageInfo) { + setHasAgentPolicyError(false); } // eslint-disable-next-line no-console @@ -235,18 +234,17 @@ export function useOnSubmit({ ? validationHasErrors(newValidationResults) : false; const hasAgentPolicy = - newPackagePolicy.policy_ids.length > 0 && newPackagePolicy.policy_ids[0] !== ''; - if ( - hasPackage && - (hasAgentPolicy || selectedPolicyTab === SelectedPolicyTab.NEW) && - !hasValidationErrors - ) { + (newPackagePolicy.policy_ids.length > 0 && newPackagePolicy.policy_ids[0] !== '') || + selectedPolicyTab === SelectedPolicyTab.NEW; + const isOrphaningPolicy = + canUseMultipleAgentPolicies && newPackagePolicy.policy_ids.length === 0; + if (hasPackage && (hasAgentPolicy || isOrphaningPolicy) && !hasValidationErrors) { setFormState('VALID'); } else { setFormState('INVALID'); } }, - [packagePolicy, setFormState, updatePackagePolicyValidation, selectedPolicyTab] + [packagePolicy, updatePackagePolicyValidation, selectedPolicyTab, canUseMultipleAgentPolicies] ); // Initial loading of package info @@ -315,7 +313,8 @@ export function useOnSubmit({ return; } if ( - agentCount !== 0 && + (agentCount !== 0 || + (agentPolicies.length === 0 && selectedPolicyTab !== SelectedPolicyTab.NEW)) && !(isAgentlessIntegration(packageInfo) || isAgentlessPackagePolicy(packagePolicy)) && formState !== 'CONFIRM' ) { @@ -401,7 +400,7 @@ export function useOnSubmit({ setSavedPackagePolicy(data!.item); const promptForAgentEnrollment = - !(agentCount && agentPolicies.length > 0) && + (createdPolicy || (agentPolicies.length > 0 && !agentCount)) && !isAgentlessConfigured && hasFleetAddAgentsPrivileges; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts index 5cafedee7db7b..141622410076d 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts @@ -102,7 +102,7 @@ export function useSetupTechnology({ const [newAgentlessPolicy, setNewAgentlessPolicy] = useState( generateNewAgentPolicyWithDefaults({ supports_agentless: true, - monitoring_enabled: [], + monitoring_enabled: ['logs', 'metrics'], }) ); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.test.tsx index 9dbdcafdc94bb..195d41221d424 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.test.tsx @@ -28,6 +28,20 @@ import { useConfig, } from '../../../../hooks'; +jest.mock('../components/steps/components/use_policies', () => { + return { + ...jest.requireActual('../components/steps/components/use_policies'), + useAllNonManagedAgentPolicies: jest.fn().mockReturnValue([ + { + id: 'agent-policy-1', + name: 'Agent policy 1', + namespace: 'default', + unprivileged_agents: 1, + }, + ]), + }; +}); + jest.mock('../../../../hooks', () => { return { ...jest.requireActual('../../../../hooks'), @@ -126,6 +140,8 @@ jest.mock('react-router-dom', () => ({ import { AGENTLESS_POLICY_ID } from '../../../../../../../common/constants'; +import { useAllNonManagedAgentPolicies } from '../components/steps/components/use_policies'; + import { CreatePackagePolicySinglePage } from '.'; import { SETUP_TECHNOLOGY_SELECTOR_TEST_SUBJ } from './components/setup_technology_selector'; @@ -702,6 +718,9 @@ describe('When on the package policy create page', () => { isLoading: false, resendRequest: jest.fn(), }); + (useAllNonManagedAgentPolicies as jest.MockedFunction).mockReturnValue([ + { id: AGENTLESS_POLICY_ID, name: 'Agentless CSPM', namespace: 'default' }, + ]); await act(async () => { render(); @@ -848,7 +867,7 @@ describe('When on the package policy create page', () => { expect(sendCreateAgentPolicy).toHaveBeenCalledWith( expect.objectContaining({ - monitoring_enabled: [], + monitoring_enabled: ['logs', 'metrics'], name: 'Agentless policy for nginx-1', supports_agentless: true, }), diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx index 99ed5592ac3ab..7a8cfe4e956aa 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx @@ -218,7 +218,7 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ ); const updateSelectedPolicyTab = useCallback( - (selectedTab) => { + (selectedTab: any) => { setSelectedPolicyTab(selectedTab); setPolicyValidation(selectedTab, newAgentPolicy); }, @@ -498,7 +498,7 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ }> - {formState === 'CONFIRM' && agentPolicies.length > 0 && ( + {formState === 'CONFIRM' && ( { + return { + ...jest.requireActual( + '../../create_package_policy_page/components/steps/components/use_policies' + ), + useAllNonManagedAgentPolicies: jest.fn(), + }; +}); + +jest.mock('../../../../hooks', () => { + return { + ...jest.requireActual('../../../../hooks'), + useGetAgentPolicies: jest.fn(), + useGetOutputs: jest.fn().mockResolvedValue({ + data: [], + isLoading: false, + }), + sendGetOneAgentPolicy: jest.fn().mockImplementation((id) => + Promise.resolve({ + data: { item: { id, name: `Agent policy ${id}` } }, + }) + ), + }; +}); + +describe('StepEditHosts', () => { + const packageInfo: PackageInfo = { + name: 'apache', + version: '1.0.0', + description: '', + format_version: '', + release: 'ga', + owner: { github: '' }, + title: 'Apache', + latestVersion: '', + assets: {} as any, + status: 'not_installed', + vars: [], + }; + const agentPolicies: AgentPolicy[] = [ + { + id: '1', + namespace: 'default', + name: 'Agent policy 1', + is_managed: false, + status: 'active', + updated_at: '', + updated_by: '', + revision: 1, + package_policies: [], + is_protected: false, + }, + { + id: '2', + namespace: 'default', + name: 'Agent policy 2', + is_managed: false, + status: 'active', + updated_at: '', + updated_by: '', + revision: 1, + package_policies: [], + is_protected: false, + }, + ]; + const newAgentPolicy = { + name: '', + namespace: 'default', + }; + const validation = {}; + + let testRenderer: TestRenderer; + let renderResult: ReturnType; + const render = () => + (renderResult = testRenderer.render( + + )); + beforeEach(() => { + testRenderer = createFleetTestRendererMock(); + }); + + it('should display create form when no agent policies', () => { + (useGetAgentPolicies as jest.MockedFunction).mockReturnValue({ + data: { + items: [], + }, + }); + + render(); + + waitFor(() => { + expect(renderResult.getByText('Agent policy 1')).toBeInTheDocument(); + }); + expect(renderResult.queryByRole('tablist')).not.toBeInTheDocument(); + }); + + it('should display new policy button and existing policies when agent policies exist', () => { + (useGetAgentPolicies as jest.MockedFunction).mockReturnValue({ + data: { + items: [{ id: '1', name: 'Agent policy 1', namespace: 'default' }], + }, + }); + (useAllNonManagedAgentPolicies as jest.MockedFunction).mockReturnValue([ + { id: '1', name: 'Agent policy 1', namespace: 'default' }, + ]); + + render(); + + expect(renderResult.getByTestId('createNewAgentPolicyButton')).toBeInTheDocument(); + expect( + renderResult.container.querySelector('[data-test-subj="agentPolicySelect"]')?.textContent + ).toContain('Agent policy 1'); + }); + + it('should display dropdown without preselected value when mulitple agent policies', () => { + (useGetAgentPolicies as jest.MockedFunction).mockReturnValue({ + data: { + items: [ + { id: '1', name: 'Agent policy 1', namespace: 'default' }, + { id: '2', name: 'Agent policy 2', namespace: 'default' }, + ], + }, + }); + + render(); + + waitFor(() => { + expect(renderResult.getByText('At least one agent policy is required.')).toBeInTheDocument(); + }); + }); + + it('should display delete button when add button clicked', () => { + (useGetAgentPolicies as jest.MockedFunction).mockReturnValue({ + data: { + items: [{ id: '1', name: 'Agent policy 1', namespace: 'default' }], + }, + }); + (useAllNonManagedAgentPolicies as jest.MockedFunction).mockReturnValue([ + { id: '1', name: 'Agent policy 1', namespace: 'default' }, + ]); + + render(); + + act(() => { + fireEvent.click(renderResult.getByTestId('createNewAgentPolicyButton').closest('button')!); + }); + + expect(renderResult.getByTestId('deleteNewAgentPolicyButton')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/components/step_edit_hosts.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/components/step_edit_hosts.tsx new file mode 100644 index 0000000000000..64d104172af53 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/components/step_edit_hosts.tsx @@ -0,0 +1,153 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect, useState } from 'react'; + +import { FormattedMessage } from '@kbn/i18n-react'; + +import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, EuiTitle } from '@elastic/eui'; + +import type { AgentPolicy, NewAgentPolicy, PackageInfo } from '../../../../types'; +import { AgentPolicyIntegrationForm } from '../../components'; +import type { ValidationResults } from '../../components/agent_policy_validation'; + +import { incrementPolicyName } from '../../../../services'; + +import { StepSelectAgentPolicy } from '../../create_package_policy_page/components/steps/step_select_agent_policy'; +import { SelectedPolicyTab } from '../../create_package_policy_page/components'; +import { useAllNonManagedAgentPolicies } from '../../create_package_policy_page/components/steps/components/use_policies'; + +interface Props { + agentPolicies: AgentPolicy[]; + updateAgentPolicies: (u: AgentPolicy[]) => void; + newAgentPolicy: Partial; + updateNewAgentPolicy: (u: Partial) => void; + withSysMonitoring: boolean; + updateSysMonitoring: (newValue: boolean) => void; + validation: ValidationResults; + packageInfo?: PackageInfo; + setHasAgentPolicyError: (hasError: boolean) => void; + selectedAgentPolicyIds: string[]; + updateSelectedTab: (tab: SelectedPolicyTab) => void; +} + +export const StepEditHosts: React.FunctionComponent = ({ + agentPolicies, + updateAgentPolicies, + newAgentPolicy, + updateNewAgentPolicy, + withSysMonitoring, + updateSysMonitoring, + validation, + packageInfo, + setHasAgentPolicyError, + selectedAgentPolicyIds, + updateSelectedTab, +}) => { + const [showCreateAgentPolicy, setShowCreateAgentPolicy] = useState(false); + const existingAgentPolicies: AgentPolicy[] = useAllNonManagedAgentPolicies(); + + useEffect(() => { + if (existingAgentPolicies.length > 0) { + updateNewAgentPolicy({ + ...newAgentPolicy, + name: incrementPolicyName(existingAgentPolicies), + }); + } + }, [existingAgentPolicies.length]); // eslint-disable-line react-hooks/exhaustive-deps + + return existingAgentPolicies.length > 0 ? ( + + + +

      + +

      +
      +
      + + + + + + + + +

      + +

      +
      +
      + {!showCreateAgentPolicy && ( + + { + setShowCreateAgentPolicy(true); + updateSelectedTab(SelectedPolicyTab.NEW); + }} + data-test-subj="createNewAgentPolicyButton" + > + + + + )} + {showCreateAgentPolicy && ( + <> + + + + + { + setShowCreateAgentPolicy(false); + updateSelectedTab(SelectedPolicyTab.EXISTING); + }} + data-test-subj="deleteNewAgentPolicyButton" + > + + + + + )} +
      + ) : ( + + ); +}; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy.tsx index bb1e2f10ad85e..49425e62e8a6b 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy.tsx @@ -174,15 +174,17 @@ export function usePackagePolicyWithRelatedData( throw packagePolicyError; } - const { data, error: agentPolicyError } = await sendBulkGetAgentPolicies( - packagePolicyData!.item.policy_ids - ); + if (packagePolicyData!.item.policy_ids && packagePolicyData!.item.policy_ids.length > 0) { + const { data, error: agentPolicyError } = await sendBulkGetAgentPolicies( + packagePolicyData!.item.policy_ids + ); - if (agentPolicyError) { - throw agentPolicyError; - } + if (agentPolicyError) { + throw agentPolicyError; + } - setAgentPolicies(data?.items ?? []); + setAgentPolicies(data?.items ?? []); + } const { data: upgradePackagePolicyDryRunData, error: upgradePackagePolicyDryRunError } = await sendUpgradePackagePolicyDryRun([packagePolicyId]); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy_steps.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy_steps.tsx index 5acd854a76f04..3d1e29240c733 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy_steps.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy_steps.tsx @@ -13,7 +13,7 @@ import type { EuiStepProps } from '@elastic/eui'; import { useSpaceSettingsContext } from '../../../../../../hooks/use_space_settings_context'; import type { AgentPolicy, NewAgentPolicy, NewPackagePolicy } from '../../../../../../../common'; import { generateNewAgentPolicyWithDefaults } from '../../../../../../../common/services'; -import { SelectedPolicyTab, StepSelectHosts } from '../../create_package_policy_page/components'; +import { SelectedPolicyTab } from '../../create_package_policy_page/components'; import type { PackageInfo } from '../../../../types'; import { SetupTechnology } from '../../../../types'; import { @@ -22,13 +22,14 @@ import { } from '../../create_package_policy_page/single_page_layout/hooks'; import { agentPolicyFormValidation } from '../../components'; import { createAgentPolicyIfNeeded } from '../../create_package_policy_page/single_page_layout/hooks/form'; +import { StepEditHosts } from '../components/step_edit_hosts'; interface Params { configureStep: React.ReactNode; packageInfo?: PackageInfo; existingAgentPolicies: AgentPolicy[]; setHasAgentPolicyError: (hasError: boolean) => void; - updatePackagePolicy: (data: { policy_ids: string[] }) => void; + updatePackagePolicy: (fields: Partial) => void; agentPolicies: AgentPolicy[]; setAgentPolicies: (agentPolicies: AgentPolicy[]) => void; isLoadingData: boolean; @@ -96,20 +97,12 @@ export function usePackagePolicySteps({ if (!isLoadingData && isEqual(updatedAgentPolicies, agentPolicies)) { return; } - if (updatedAgentPolicies.length > 0) { - setAgentPolicies(updatedAgentPolicies); - updatePackagePolicy({ - policy_ids: updatedAgentPolicies.map((policy) => policy.id), - }); - if (packageInfo) { - setHasAgentPolicyError(false); - } - } else { - setHasAgentPolicyError(true); - setAgentPolicies([]); - updatePackagePolicy({ - policy_ids: [], - }); + setAgentPolicies(updatedAgentPolicies); + updatePackagePolicy({ + policy_ids: updatedAgentPolicies.map((policy) => policy.id), + }); + if (packageInfo) { + setHasAgentPolicyError(false); } // eslint-disable-next-line no-console @@ -150,7 +143,7 @@ export function usePackagePolicySteps({ const stepSelectAgentPolicy = useMemo( () => ( - policy.id)} - initialSelectedTabIndex={1} /> ), [ diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.test.tsx index 6669f3dfa332f..f893f7a7e7aeb 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.test.tsx @@ -31,6 +31,15 @@ import { EditPackagePolicyPage } from '.'; type MockFn = jest.MockedFunction; +jest.mock('../create_package_policy_page/components/steps/components/use_policies', () => { + return { + ...jest.requireActual('../create_package_policy_page/components/steps/components/use_policies'), + useAllNonManagedAgentPolicies: jest + .fn() + .mockReturnValue([{ id: 'agent-policy-1', name: 'Agent policy 1' }]), + }; +}); + jest.mock('../../../hooks', () => { return { ...jest.requireActual('../../../hooks'), @@ -515,7 +524,7 @@ describe('edit package policy page', () => { jest.clearAllMocks(); }); - it('should create agent policy with sys monitoring when new hosts is selected', async () => { + it('should create agent policy with sys monitoring when new agent policy button is clicked', async () => { await act(async () => { render(); }); @@ -528,7 +537,7 @@ describe('edit package policy page', () => { }); await act(async () => { - fireEvent.click(renderResult.getByTestId('newHostsTab')); + fireEvent.click(renderResult.getByTestId('createNewAgentPolicyButton')); }); await act(async () => { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx index 8150a61b93fba..841c2184894f9 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx @@ -6,7 +6,6 @@ */ import React, { useState, useEffect, useCallback, useMemo, memo } from 'react'; -import { isEmpty } from 'lodash'; import { useRouteMatch } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; @@ -250,7 +249,10 @@ export const EditPackagePolicyForm = memo<{ return; } if ( - (agentCount !== 0 || agentPoliciesToAdd.length > 0 || agentPoliciesToRemove.length > 0) && + (agentCount !== 0 || + agentPolicies.length === 0 || + agentPoliciesToAdd.length > 0 || + agentPoliciesToRemove.length > 0) && !hasAgentlessAgentPolicy && formState !== 'CONFIRM' ) { @@ -485,7 +487,7 @@ export const EditPackagePolicyForm = memo<{ {isLoadingData ? ( - ) : loadingError || isEmpty(existingAgentPolicies) || !packageInfo ? ( + ) : loadingError || !packageInfo ? ( { // handling a special case of force unenrollment coming from an automatic task // we know what kind of action is from the actionId prefix if (actionId?.includes('UnenrollInactiveAgentsTask-')) - return actionNames.AUTOMATICAL_FORCE_UNENROLL; + return actionNames.AUTOMATIC_FORCE_UNENROLL; return actionNames[type ?? 'ACTION'] ?? actionNames.ACTION; }; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/status_badges.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/status_badges.tsx index af0bad093852e..44363d12088d1 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/status_badges.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/status_badges.tsx @@ -6,7 +6,7 @@ */ import { EuiFlexGroup, EuiHealth, EuiNotificationBadge, EuiFlexItem } from '@elastic/eui'; -import React, { memo, useMemo } from 'react'; +import React, { memo } from 'react'; import { AGENT_STATUSES, @@ -16,18 +16,11 @@ import { import type { SimplifiedAgentStatus } from '../../../../types'; export const AgentStatusBadges: React.FC<{ - showInactive?: boolean; agentStatus: { [k in SimplifiedAgentStatus]: number }; -}> = memo(({ agentStatus, showInactive }) => { - const agentStatuses = useMemo(() => { - return AGENT_STATUSES.filter((status) => - showInactive ? true : status !== 'inactive' && status !== 'unenrolled' - ); - }, [showInactive]); - +}> = memo(({ agentStatus }) => { return ( - {agentStatuses.map((status) => ( + {AGENT_STATUSES.map((status) => ( diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/table_header.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/table_header.tsx index a6375bec6a39a..bcac45801be05 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/table_header.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/table_header.tsx @@ -19,7 +19,6 @@ import type { SelectionMode } from './types'; export const AgentTableHeader: React.FunctionComponent<{ agentStatus?: { [k in SimplifiedAgentStatus]: number }; - showInactive: boolean; totalAgents: number; selectableAgents: number; managedAgentsOnCurrentPage: number; @@ -38,7 +37,6 @@ export const AgentTableHeader: React.FunctionComponent<{ setSelectionMode, selectedAgents, setSelectedAgents, - showInactive, clearFilters, isUsingFilter, }) => { @@ -69,9 +67,7 @@ export const AgentTableHeader: React.FunctionComponent<{ ) : null} - {agentStatus && ( - - )} + {agentStatus && }
      diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/index.tsx index 84884569071ce..c1e1f83f49103 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/index.tsx @@ -168,10 +168,6 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { setSortOrder(sort!.direction); }; - const showInactive = useMemo(() => { - return selectedStatus.some((status) => status === 'inactive' || status === 'unenrolled'); - }, [selectedStatus]); - const renderActions = (agent: Agent) => { const agentPolicy = typeof agent.policy_id === 'string' ? agentPoliciesIndexedById[agent.policy_id] : undefined; @@ -435,7 +431,6 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { {/* Agent total, bulk actions and status bar */} = ({ }, [value, onChange]); const onDragEndHandler = useCallback( - ({ source, destination }) => { + ({ source, destination }: any) => { if (source && destination) { const items = euiDragDropReorder(value, source.index, destination.index); const sourceErrors = indexedErrors[source.index]; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/hooks/use_confirm_modal.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/hooks/use_confirm_modal.tsx index 695047288e298..fa45e0969c601 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/hooks/use_confirm_modal.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/hooks/use_confirm_modal.tsx @@ -71,7 +71,7 @@ export const ConfirmModalProvider: React.FunctionComponent<{ children?: React.Re onConfirm: () => {}, }); - const showModal = useCallback(({ title, description, onConfirm, onCancel, options }) => { + const showModal = useCallback(({ title, description, onConfirm, onCancel, options }: any) => { setIsVisible(true); setModal({ title, diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx index 1b75311418ca7..b475c4d39d767 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx @@ -74,17 +74,6 @@ const IntegrationDetailsLink = memo<{ ); }); -const AgentPolicyNotFound = () => ( - - -   - - -); - export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps) => { const { search } = useLocation(); const history = useHistory(); @@ -235,7 +224,7 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps defaultMessage: 'Agent policies', }), truncateText: true, - render(id, { agentPolicies, packagePolicy }) { + render(ids, { agentPolicies, packagePolicy }) { return agentPolicies.length > 0 ? ( canShowMultiplePoliciesCell ? ( ) + ) : ids.length === 0 ? ( + + + ) : ( - + + +   + + ); }, }, @@ -282,7 +285,14 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps }), render({ agentPolicies, packagePolicy }: InMemoryPackagePolicyAndAgentPolicy) { if (agentPolicies.length === 0) { - return null; + return ( + + + + ); } const agentPolicy = agentPolicies[0]; // TODO: handle multiple agent policies const canAddAgentsForPolicy = policyHasFleetServer(agentPolicy) diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/persona.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/persona.tsx index c2a7e1530cbf5..aa1bbcc3dc838 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/persona.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/persona.tsx @@ -17,7 +17,7 @@ const MIN_WIDTH: CSSProperties = { minWidth: 0 }; export const Persona = memo( ({ name, className, 'data-test-subj': dataTestSubj, title, ...otherAvatarProps }) => { const getTestId = useCallback( - (suffix) => { + (suffix: any) => { if (dataTestSubj) { return `${dataTestSubj}-${suffix}`; } diff --git a/x-pack/plugins/fleet/public/components/manage_agent_policies_modal.test.tsx b/x-pack/plugins/fleet/public/components/manage_agent_policies_modal.test.tsx index 50e930820767e..afb7df056cc41 100644 --- a/x-pack/plugins/fleet/public/components/manage_agent_policies_modal.test.tsx +++ b/x-pack/plugins/fleet/public/components/manage_agent_policies_modal.test.tsx @@ -151,16 +151,24 @@ describe('ManageAgentPoliciesModal', () => { }); }); - it('should display callout and disable confirm if policy is removed', async () => { + it('should display callout and allow to submit if all policies are removed', async () => { const results = render(); await act(async () => { results.getByTestId('comboBoxClearButton').click(); }); - expect(results.getByText('Confirm').getAttribute('disabled')).toBeDefined(); + expect(results.getByText('Confirm').getAttribute('disabled')).toBeNull(); expect(results.getByTestId('confirmRemovePoliciesCallout')).toBeInTheDocument(); expect(results.getByTestId('confirmRemovePoliciesCallout').textContent).toContain( 'Test policy will no longer use this integration.' ); + + await act(async () => { + results.getByText('Confirm').click(); + }); + expect(usePackagePolicyWithRelatedData('', {}).savePackagePolicy).toHaveBeenCalledWith({ + policy_id: undefined, + policy_ids: [], + }); }); }); diff --git a/x-pack/plugins/fleet/public/components/manage_agent_policies_modal.tsx b/x-pack/plugins/fleet/public/components/manage_agent_policies_modal.tsx index 26e9421ed86fe..7677ba4931346 100644 --- a/x-pack/plugins/fleet/public/components/manage_agent_policies_modal.tsx +++ b/x-pack/plugins/fleet/public/components/manage_agent_policies_modal.tsx @@ -70,6 +70,11 @@ export const ManageAgentPoliciesModal: React.FunctionComponent = ({ setIsSubmitting(true); const { error } = await savePackagePolicy({ policy_ids: selectedPolicyIds, + ...(selectedPolicyIds.length === 0 + ? { + policy_id: undefined, + } + : {}), }); setIsSubmitting(false); if (!error) { @@ -138,11 +143,7 @@ export const ManageAgentPoliciesModal: React.FunctionComponent = ({ /> } buttonColor="primary" - confirmButtonDisabled={ - selectedPolicyIds.length === 0 || - isSubmitting || - isEqual(initialPolicyIds, selectedPolicyIds) - } + confirmButtonDisabled={isSubmitting || isEqual(initialPolicyIds, selectedPolicyIds)} data-test-subj="manageAgentPoliciesModal" > diff --git a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx index a41b3e265826a..90e680c2ff845 100644 --- a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx +++ b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx @@ -12,7 +12,7 @@ import { act, fireEvent } from '@testing-library/react'; import type { AgentPolicy, InMemoryPackagePolicy } from '../types'; import { createIntegrationsTestRendererMock } from '../mock'; -import { useMultipleAgentPolicies, useStartServices } from '../hooks'; +import { useMultipleAgentPolicies, useStartServices, useLink } from '../hooks'; import { PackagePolicyActionsMenu } from './package_policy_actions_menu'; @@ -203,10 +203,34 @@ describe('PackagePolicyActionsMenu', () => { const { utils } = renderMenu({ agentPolicies, packagePolicy }); await act(async () => { const editButton = utils.getByTestId('PackagePolicyActionsEditItem'); + expect(editButton).not.toHaveAttribute('disabled'); + expect(editButton).toHaveAttribute('href'); + expect(useLink().getHref as jest.Mock).toHaveBeenCalledWith('edit_integration', { + policyId: 'some-uuid1', + packagePolicyId: 'some-uuid2', + }); expect(editButton).toHaveAttribute( 'href', '/mock/app/fleet/policies/some-uuid1/edit-integration/some-uuid2' ); }); }); + + it('Should show Edit integration with correct href when there is no agent policy', async () => { + const packagePolicy = createMockPackagePolicy({ + policy_ids: [], + }); + const { utils } = renderMenu({ + agentPolicies: [], + packagePolicy, + }); + await act(async () => { + const editButton = utils.getByTestId('PackagePolicyActionsEditItem'); + expect(editButton).not.toHaveAttribute('disabled'); + expect(editButton).toHaveAttribute('href'); + expect(useLink().getHref as jest.Mock).toHaveBeenCalledWith('integration_policy_edit', { + packagePolicyId: 'some-uuid2', + }); + }); + }); }); diff --git a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx index 0eb0000af4fa4..fcebfcb2f2475 100644 --- a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx +++ b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx @@ -52,6 +52,7 @@ export const PackagePolicyActionsMenu: React.FunctionComponent<{ const isManaged = Boolean(packagePolicy.is_managed); const agentPolicyIsManaged = Boolean(agentPolicy?.is_managed); + const isOrphanedPolicy = !agentPolicy && packagePolicy.policy_ids.length === 0; const isAddAgentVisible = showAddAgent && agentPolicy && !agentPolicyIsManaged; @@ -92,12 +93,18 @@ export const PackagePolicyActionsMenu: React.FunctionComponent<{ : []), { esServer = await startES(); const startOrRestartKibana = async (kbnConfig: any = defaultKbnConfig) => { - if (kbnServer) { - await kbnServer.stop(); - } - - const root = createRootWithCorePlugins( - { - xpack: { - ...kbnConfig.xpack, - fleet: { - ...kbnConfig.xpack.fleet, - registryUrl, + const maxTries = 3; + let currentTry = 0; + + const startOrRestart = async () => { + if (kbnServer) { + await kbnServer.stop(); + } + + const root = createRootWithCorePlugins( + { + xpack: { + ...kbnConfig.xpack, + fleet: { + ...kbnConfig.xpack.fleet, + registryUrl, + }, }, - }, - logging: { - appenders: { - file: { - type: 'file', - fileName: logFilePath, - layout: { - type: 'json', + logging: { + appenders: { + file: { + type: 'file', + fileName: logFilePath, + layout: { + type: 'json', + }, }, }, + loggers: [ + { + name: 'root', + appenders: ['file'], + }, + { + name: 'plugins.fleet', + level: 'all', + }, + ], }, - loggers: [ - { - name: 'root', - appenders: ['file'], - }, - { - name: 'plugins.fleet', - level: 'all', - }, - ], }, - }, - { oss: false } - ); - - await root.preboot(); - const coreSetup = await root.setup(); - const coreStart = await root.start(); - - kbnServer = { - root, - coreSetup, - coreStart, - stop: async () => await root.shutdown(), + { oss: false } + ); + + await root.preboot(); + const coreSetup = await root.setup(); + const coreStart = await root.start(); + + kbnServer = { + root, + coreSetup, + coreStart, + stop: async () => await root.shutdown(), + }; + + await waitForFleetSetup(kbnServer.root); }; - await waitForFleetSetup(kbnServer.root); + + try { + currentTry++; + await startOrRestart(); + } catch (e) { + if (currentTry < maxTries) { + await startOrRestart(); + } else { + throw e; + } + } }; + await startOrRestartKibana(); return { diff --git a/x-pack/plugins/fleet/server/routes/package_policy/handlers.test.ts b/x-pack/plugins/fleet/server/routes/package_policy/handlers.test.ts index f42ed00360033..fbcf1ee80f206 100644 --- a/x-pack/plugins/fleet/server/routes/package_policy/handlers.test.ts +++ b/x-pack/plugins/fleet/server/routes/package_policy/handlers.test.ts @@ -20,14 +20,11 @@ import { } from '../../services'; import { createAppContextStartContractMock, xpackMocks } from '../../mocks'; import type { PackagePolicyClient, FleetRequestHandlerContext } from '../..'; -import type { - CreatePackagePolicyRequestSchema, - UpdatePackagePolicyRequestSchema, -} from '../../types/rest_spec'; +import type { UpdatePackagePolicyRequestSchema } from '../../types/rest_spec'; import type { AgentPolicy, FleetRequestHandler } from '../../types'; import type { PackagePolicy } from '../../types'; -import { createPackagePolicyHandler, getPackagePoliciesHandler } from './handlers'; +import { getPackagePoliciesHandler } from './handlers'; import { registerRoutes } from '.'; const packagePolicyServiceMock = packagePolicyService as jest.Mocked; @@ -170,59 +167,6 @@ describe('When calling package policy', () => { appContextService.stop(); }); - describe('Create api handler', () => { - const getCreateKibanaRequest = ( - newData?: typeof CreatePackagePolicyRequestSchema.body - ): KibanaRequest< - undefined, - typeof CreatePackagePolicyRequestSchema.query, - typeof CreatePackagePolicyRequestSchema.body - > => { - return httpServerMock.createKibanaRequest< - undefined, - typeof CreatePackagePolicyRequestSchema.query, - typeof CreatePackagePolicyRequestSchema.body - >({ - path: routeConfig.path, - method: 'post', - body: newData || {}, - query: { format: 'simplified' }, - }); - }; - - const newPolicy = { - name: 'endpoint-1', - description: 'desc', - enabled: true, - policy_ids: [], - inputs: [], - namespace: 'default', - package: { name: 'endpoint', title: 'Elastic Endpoint', version: '0.5.0' }, - }; - - beforeEach(() => { - jest.spyOn(licenseService, 'hasAtLeast').mockClear(); - // @ts-ignore - const postMock = routerMock.versioned.post.mock; - // @ts-ignore - routeConfig = postMock.calls.find(([{ path }]) => - path.startsWith(PACKAGE_POLICY_API_ROUTES.CREATE_PATTERN) - )!; - routeHandler = postMock.results[0].value.addVersion.mock.calls[0][1]; - }); - - it('should throw if no policy_id or policy_ids is provided', async () => { - const request = getCreateKibanaRequest(newPolicy as any); - await createPackagePolicyHandler(context, request as any, response); - expect(response.customError).toHaveBeenCalledWith({ - statusCode: 400, - body: { - message: 'Either policy_id or policy_ids must be provided', - }, - }); - }); - }); - describe('Update api handler', () => { const getUpdateKibanaRequest = ( newData?: typeof UpdatePackagePolicyRequestSchema.body diff --git a/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts b/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts index 5cc00ef014cde..3bc2f79d6afd7 100644 --- a/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts @@ -243,10 +243,6 @@ export const createPackagePolicyHandler: FleetRequestHandler< const spaceId = fleetContext.spaceId; try { - if (!newPolicy.policy_id && (!newPolicy.policy_ids || newPolicy.policy_ids.length === 0)) { - throw new PackagePolicyRequestError('Either policy_id or policy_ids must be provided'); - } - let newPackagePolicy: NewPackagePolicy; if (isSimplifiedCreatePackagePolicyRequest(newPolicy)) { if (!pkg) { @@ -390,7 +386,8 @@ export const updatePackagePolicyHandler: FleetRequestHandler< name: restOfBody.name ?? packagePolicy.name, description: restOfBody.description ?? packagePolicy.description, namespace: restOfBody.namespace ?? packagePolicy?.namespace, - policy_id: restOfBody.policy_id ?? packagePolicy.policy_id, + policy_id: + restOfBody.policy_id === undefined ? packagePolicy.policy_id : restOfBody.policy_id, enabled: 'enabled' in restOfBody ? restOfBody.enabled ?? packagePolicy.enabled @@ -406,10 +403,6 @@ export const updatePackagePolicyHandler: FleetRequestHandler< } newData.inputs = alignInputsAndStreams(newData.inputs); - if (newData.policy_ids && newData.policy_ids.length === 0) { - throw new PackagePolicyRequestError('At least one agent policy id must be provided'); - } - if ( newData.policy_ids && !isEmpty(packagePolicy.policy_ids) && diff --git a/x-pack/plugins/fleet/server/saved_objects/index.ts b/x-pack/plugins/fleet/server/saved_objects/index.ts index d955b10031536..3c224ee6ba881 100644 --- a/x-pack/plugins/fleet/server/saved_objects/index.ts +++ b/x-pack/plugins/fleet/server/saved_objects/index.ts @@ -986,7 +986,7 @@ export const getSavedObjectTypes = ( name: MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE, indexPattern: INGEST_SAVED_OBJECT_INDEX, hidden: true, - namespaceType: useSpaceAwareness ? 'single' : 'agnostic', + namespaceType: 'agnostic', management: { importableAndExportable: false, }, @@ -999,7 +999,7 @@ export const getSavedObjectTypes = ( name: UNINSTALL_TOKENS_SAVED_OBJECT_TYPE, indexPattern: INGEST_SAVED_OBJECT_INDEX, hidden: true, - namespaceType: useSpaceAwareness ? 'single' : 'agnostic', + namespaceType: 'agnostic', management: { importableAndExportable: false, }, @@ -1008,6 +1008,19 @@ export const getSavedObjectTypes = ( properties: { policy_id: { type: 'keyword' }, token_plain: { type: 'keyword' }, + namespaces: { type: 'keyword' }, + }, + }, + modelVersions: { + '1': { + changes: [ + { + type: 'mappings_addition', + addedMappings: { + namespaces: { type: 'keyword' }, + }, + }, + ], }, }, }, diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index 250cd867ee875..b5f885b6743bf 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -1615,7 +1615,7 @@ class AgentPolicyService { public async fetchAllAgentPolicyIds( soClient: SavedObjectsClientContract, - { perPage = 1000, kuery = undefined }: FetchAllAgentPolicyIdsOptions = {} + { perPage = 1000, kuery = undefined, spaceId = undefined }: FetchAllAgentPolicyIdsOptions = {} ): Promise> { const savedObjectType = await getAgentPolicySavedObjectType(); return createSoFindIterable<{}>({ @@ -1627,6 +1627,7 @@ class AgentPolicyService { sortOrder: 'asc', fields: ['id'], filter: kuery ? normalizeKuery(savedObjectType, kuery) : undefined, + namespaces: spaceId ? [spaceId] : undefined, }, resultsMapper: (data) => { return data.saved_objects.map((agentPolicySO) => { diff --git a/x-pack/plugins/fleet/server/services/package_policies/utils.test.ts b/x-pack/plugins/fleet/server/services/package_policies/utils.test.ts index 311bfeb339f20..9d68dde10a13e 100644 --- a/x-pack/plugins/fleet/server/services/package_policies/utils.test.ts +++ b/x-pack/plugins/fleet/server/services/package_policies/utils.test.ts @@ -86,6 +86,19 @@ describe('Package Policy Utils', () => { ); }); + it('should throw if no enterprise license and no policy_ids is provided', async () => { + jest.spyOn(licenseService, 'hasAtLeast').mockReturnValue(false); + jest + .spyOn(appContextService, 'getExperimentalFeatures') + .mockReturnValue({ enableReusableIntegrationPolicies: true } as any); + + await expect( + preflightCheckPackagePolicy(soClient, { ...testPolicy, policy_ids: [] }) + ).rejects.toThrowError( + 'Reusable integration policies are only available with an Enterprise license' + ); + }); + it('should throw if enterprise license and multiple policy_ids is provided but no feature flag', async () => { jest.spyOn(licenseService, 'hasAtLeast').mockReturnValue(true); jest @@ -107,6 +120,16 @@ describe('Package Policy Utils', () => { ).resolves.not.toThrow(); }); + it('should not throw if enterprise license and no policy_ids is provided', async () => { + jest.spyOn(licenseService, 'hasAtLeast').mockReturnValue(true); + jest + .spyOn(appContextService, 'getExperimentalFeatures') + .mockReturnValue({ enableReusableIntegrationPolicies: true } as any); + await expect( + preflightCheckPackagePolicy(soClient, { ...testPolicy, policy_ids: [] }) + ).resolves.not.toThrow(); + }); + it('should throw if no valid license and output_id is provided', async () => { jest.spyOn(licenseService, 'hasAtLeast').mockReturnValue(false); diff --git a/x-pack/plugins/fleet/server/services/package_policies/utils.ts b/x-pack/plugins/fleet/server/services/package_policies/utils.ts index 61ff380fec559..0d76fc307c74c 100644 --- a/x-pack/plugins/fleet/server/services/package_policies/utils.ts +++ b/x-pack/plugins/fleet/server/services/package_policies/utils.ts @@ -76,10 +76,11 @@ export async function preflightCheckPackagePolicy( soClient: SavedObjectsClientContract, packagePolicy: PackagePolicy | NewPackagePolicy ) { - // If package policy has multiple agent policies, check if they can be used + // If package policy has multiple agent policies IDs, or no agent policies (orphaned integration policy) + // check if user can use multiple agent policies feature const { canUseReusablePolicies, errorMessage: canUseMultipleAgentPoliciesErrorMessage } = canUseMultipleAgentPolicies(); - if ((packagePolicy.policy_ids ?? []).length > 1 && !canUseReusablePolicies) { + if (!canUseReusablePolicies && packagePolicy.policy_ids.length !== 1) { throw new PackagePolicyMultipleAgentPoliciesError(canUseMultipleAgentPoliciesErrorMessage); } diff --git a/x-pack/plugins/fleet/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts index a53334c893fec..f23ed5836afeb 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.ts @@ -415,9 +415,16 @@ class PackagePolicyClientImpl implements PackagePolicyClient { } keepPolicyIdInSync(packagePolicy: NewPackagePolicy): void { + if (packagePolicy.policy_ids) { + if (packagePolicy.policy_ids.length === 0 && packagePolicy.policy_id !== undefined) { + packagePolicy.policy_id = null; + } + } else { + packagePolicy.policy_ids = []; + } if (packagePolicy.policy_id && !packagePolicy.policy_ids?.[0]) { packagePolicy.policy_ids = [packagePolicy.policy_id]; - } else if (!packagePolicy.policy_id) { + } else if (!packagePolicy.policy_id && packagePolicy.policy_ids[0]) { packagePolicy.policy_id = packagePolicy.policy_ids[0]; } } @@ -891,6 +898,8 @@ class PackagePolicyClientImpl implements PackagePolicyClient { } if (!oldPackagePolicy) { throw new PackagePolicyNotFoundError('Package policy not found'); + } else { + this.keepPolicyIdInSync(oldPackagePolicy); } if ( @@ -1021,16 +1030,19 @@ class PackagePolicyClientImpl implements PackagePolicyClient { } } } - // Bump revision of associated agent policy - logger.debug(`Bumping revision of associated agent policies ${packagePolicy.policy_ids}`); + + // Bump revision of all associated agent policies (old and new) + const associatedPolicyIds = new Set([...oldPackagePolicy.policy_ids, ...newPolicy.policy_ids]); + logger.debug(`Bumping revision of associated agent policies ${associatedPolicyIds}`); const bumpPromises = []; - for (const policyId of packagePolicy.policy_ids) { + for (const policyId of associatedPolicyIds) { bumpPromises.push( agentPolicyService.bumpRevision(soClient, esClient, policyId, { user: options?.user, }) ); } + const assetRemovePromise = removeOldAssets({ soClient, pkgName: newPolicy.package!.name, @@ -1060,6 +1072,7 @@ class PackagePolicyClientImpl implements PackagePolicyClient { error: Error | SavedObjectError; }>; }> { + const logger = appContextService.getLogger(); const savedObjectType = await getPackagePolicySavedObjectType(); for (const packagePolicy of packagePolicyUpdates) { auditLoggingService.writeCustomSoAuditLog({ @@ -1081,7 +1094,7 @@ class PackagePolicyClientImpl implements PackagePolicyClient { const allSecretsToDelete: PolicySecretReference[] = []; const packageInfosandAssetsMap = await getPkgInfoAssetsMap({ - logger: appContextService.getLogger(), + logger, packageInfos: [...packageInfos.values()], savedObjectsClient: soClient, }); @@ -1103,6 +1116,8 @@ class PackagePolicyClientImpl implements PackagePolicyClient { const oldPackagePolicy = oldPackagePolicies.find((p) => p.id === id); if (!oldPackagePolicy) { throw new PackagePolicyNotFoundError('Package policy not found'); + } else { + this.keepPolicyIdInSync(oldPackagePolicy); } let secretReferences: PolicySecretReference[] | undefined; @@ -1188,10 +1203,13 @@ class PackagePolicyClientImpl implements PackagePolicyClient { policiesToUpdate ); - const agentPolicyIds = new Set(packagePolicyUpdates.flatMap((p) => p.policy_ids)); - - const bumpPromise = pMap(agentPolicyIds, async (agentPolicyId) => { - // Bump revision of associated agent policy + // Bump revision of all associated agent policies (old and new) + const associatedPolicyIds = new Set([ + ...packagePolicyUpdates.flatMap((p) => p.policy_ids), + ...oldPackagePolicies.flatMap((p) => p.policy_ids), + ]); + logger.debug(`Bumping revision of associated agent policies ${associatedPolicyIds}`); + const bumpPromise = pMap(associatedPolicyIds, async (agentPolicyId) => { await agentPolicyService.bumpRevision(soClient, esClient, agentPolicyId, { user: options?.user, }); @@ -1787,16 +1805,6 @@ class PackagePolicyClientImpl implements PackagePolicyClient { })), } as NewPackagePolicyInput; }); - let agentPolicyId; - // fallback to first agent policy id in case no policy_id is specified, BWC with 8.0 - if (!newPolicy.policy_id && !newPolicy.policy_ids[0]) { - const { items: agentPolicies } = await agentPolicyService.list(soClient, { - perPage: 1, - }); - if (agentPolicies.length > 0) { - agentPolicyId = agentPolicies[0].id; - } - } newPackagePolicy = { ...newPP, name: newPolicy.name, @@ -1807,8 +1815,8 @@ class PackagePolicyClientImpl implements PackagePolicyClient { ...newPP.package!, experimental_data_stream_features: newPolicy.package?.experimental_data_stream_features, }, - policy_id: newPolicy.policy_id ?? agentPolicyId, - policy_ids: newPolicy.policy_ids ?? [agentPolicyId], + policy_id: newPolicy.policy_id ?? undefined, + policy_ids: newPolicy.policy_ids ?? undefined, output_id: newPolicy.output_id, inputs: newPolicy.inputs[0]?.streams ? newPolicy.inputs : inputs, vars: newPolicy.vars || newPP.vars, @@ -2592,7 +2600,7 @@ function _enforceFrozenVars( export interface NewPackagePolicyWithId extends NewPackagePolicy { id?: string; - policy_id?: string; + policy_id?: string | null; version?: string; } diff --git a/x-pack/plugins/fleet/server/services/security/uninstall_token_service/index.test.ts b/x-pack/plugins/fleet/server/services/security/uninstall_token_service/index.test.ts index ee133f920ebe0..d2daf3ff46ae5 100644 --- a/x-pack/plugins/fleet/server/services/security/uninstall_token_service/index.test.ts +++ b/x-pack/plugins/fleet/server/services/security/uninstall_token_service/index.test.ts @@ -9,7 +9,11 @@ import { createHash } from 'crypto'; import type { KibanaRequest } from '@kbn/core-http-server'; -import type { SavedObjectsClientContract } from '@kbn/core/server'; +import { + SECURITY_EXTENSION_ID, + SPACES_EXTENSION_ID, + type SavedObjectsClientContract, +} from '@kbn/core/server'; import type { EncryptedSavedObjectsClient } from '@kbn/encrypted-saved-objects-plugin/server'; import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; @@ -29,6 +33,7 @@ import { UNINSTALL_TOKENS_SAVED_OBJECT_TYPE } from '../../../constants'; import { createAppContextStartContractMock, type MockedFleetAppContext } from '../../../mocks'; import { appContextService } from '../../app_context'; import { agentPolicyService } from '../../agent_policy'; +import { isSpaceAwarenessEnabled } from '../../spaces/helpers'; import { UninstallTokenService, type UninstallTokenServiceInterface } from '.'; @@ -42,6 +47,8 @@ interface TokenSO { created_at: string; } +jest.mock('../../spaces/helpers'); + describe('UninstallTokenService', () => { const now = new Date().toISOString(); const aDayAgo = new Date(Date.now() - 24 * 3600 * 1000).toISOString(); @@ -194,7 +201,7 @@ describe('UninstallTokenService', () => { ); } - function setupMocks(canEncrypt: boolean = true) { + function setupMocks(canEncrypt: boolean = true, scoppedInSpace?: string) { mockContext = createAppContextStartContractMock(); mockContext.encryptedSavedObjectsSetup = encryptedSavedObjectsMock.createSetup({ canEncrypt, @@ -204,13 +211,22 @@ describe('UninstallTokenService', () => { mockContext.encryptedSavedObjectsStart!.getClient() as jest.Mocked; soClientMock = appContextService .getSavedObjects() - .getScopedClient({} as unknown as KibanaRequest) as jest.Mocked; + .getScopedClient({} as unknown as KibanaRequest, { + excludedExtensions: [SECURITY_EXTENSION_ID, SPACES_EXTENSION_ID], + }) as jest.Mocked; agentPolicyService.deployPolicies = jest.fn(); getAgentPoliciesByIDsMock = jest.fn().mockResolvedValue([]); agentPolicyService.getByIDs = getAgentPoliciesByIDsMock; - uninstallTokenService = new UninstallTokenService(esoClientMock); + if (scoppedInSpace) { + soClientMock.getCurrentNamespace.mockReturnValue(scoppedInSpace); + } + + uninstallTokenService = new UninstallTokenService( + esoClientMock, + scoppedInSpace ? soClientMock : undefined + ); mockFind(canEncrypt); mockCreatePointInTimeFinder(canEncrypt); mockCreatePointInTimeFinderAsInternalUser(); @@ -240,6 +256,7 @@ describe('UninstallTokenService', () => { beforeEach(() => { setupMocks(canEncrypt); + jest.mocked(isSpaceAwarenessEnabled).mockResolvedValue(false); }); describe('get uninstall tokens', () => { @@ -277,6 +294,78 @@ describe('UninstallTokenService', () => { ); }); + it('filter namespace with scopped service and space awareneness enabled', async () => { + jest.mocked(isSpaceAwarenessEnabled).mockResolvedValue(true); + setupMocks(canEncrypt, 'test'); + + const so = getDefaultSO(canEncrypt); + mockCreatePointInTimeFinderAsInternalUser([so]); + getAgentPoliciesByIDsMock.mockResolvedValue([ + { id: so.attributes.policy_id, name: 'cheese' }, + ] as Array>); + + const token = await uninstallTokenService.getToken(so.id); + + const expectedItem: UninstallToken = { + id: so.id, + policy_id: so.attributes.policy_id, + policy_name: 'cheese', + token: getToken(so, canEncrypt), + created_at: so.created_at, + }; + + expect(token).toEqual(expectedItem); + + expect(esoClientMock.createPointInTimeFinderDecryptedAsInternalUser).toHaveBeenCalledWith( + { + type: UNINSTALL_TOKENS_SAVED_OBJECT_TYPE, + filter: `(${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}.attributes.namespaces:test) and (${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}.id: "${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}:${so.id}")`, + perPage: SO_SEARCH_LIMIT, + } + ); + expect(getAgentPoliciesByIDsMock).toHaveBeenCalledWith( + soClientMock, + [so.attributes.policy_id], + { ignoreMissing: true } + ); + }); + + it('do not filter namespace with scopped service and space awareneness disabled', async () => { + jest.mocked(isSpaceAwarenessEnabled).mockResolvedValue(false); + setupMocks(canEncrypt, 'test'); + + const so = getDefaultSO(canEncrypt); + mockCreatePointInTimeFinderAsInternalUser([so]); + getAgentPoliciesByIDsMock.mockResolvedValue([ + { id: so.attributes.policy_id, name: 'cheese' }, + ] as Array>); + + const token = await uninstallTokenService.getToken(so.id); + + const expectedItem: UninstallToken = { + id: so.id, + policy_id: so.attributes.policy_id, + policy_name: 'cheese', + token: getToken(so, canEncrypt), + created_at: so.created_at, + }; + + expect(token).toEqual(expectedItem); + + expect(esoClientMock.createPointInTimeFinderDecryptedAsInternalUser).toHaveBeenCalledWith( + { + type: UNINSTALL_TOKENS_SAVED_OBJECT_TYPE, + filter: `${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}.id: "${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}:${so.id}"`, + perPage: SO_SEARCH_LIMIT, + } + ); + expect(getAgentPoliciesByIDsMock).toHaveBeenCalledWith( + soClientMock, + [so.attributes.policy_id], + { ignoreMissing: true } + ); + }); + it('sets `policy_name` to `null` if linked policy does not exist', async () => { const so = getDefaultSO(canEncrypt); mockCreatePointInTimeFinderAsInternalUser([so]); @@ -341,6 +430,72 @@ describe('UninstallTokenService', () => { expect(actualItems).toEqual(expectedItems); }); + it('filter by namespace if service is scopped and space awareness is enabled', async () => { + setupMocks(canEncrypt, 'test'); + jest.mocked(isSpaceAwarenessEnabled).mockResolvedValue(true); + const so = getDefaultSO(canEncrypt); + const so2 = getDefaultSO2(canEncrypt); + getAgentPoliciesByIDsMock.mockResolvedValue([ + { id: so2.attributes.policy_id, name: 'only I have a name' }, + ] as Array>); + + const actualItems = (await uninstallTokenService.getTokenMetadata()).items; + const expectedItems: UninstallTokenMetadata[] = [ + { + id: so.id, + policy_id: so.attributes.policy_id, + policy_name: null, + created_at: so.created_at, + }, + { + id: so2.id, + policy_id: so2.attributes.policy_id, + policy_name: 'only I have a name', + created_at: so2.created_at, + }, + ]; + expect(actualItems).toEqual(expectedItems); + + expect(soClientMock.createPointInTimeFinder).toHaveBeenCalledWith( + expect.objectContaining({ + filter: `${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}.attributes.namespaces:test`, + }) + ); + }); + + it('do not filter by namespace if service is scopped and space awareness is disabled', async () => { + setupMocks(canEncrypt, 'test'); + jest.mocked(isSpaceAwarenessEnabled).mockResolvedValue(false); + const so = getDefaultSO(canEncrypt); + const so2 = getDefaultSO2(canEncrypt); + getAgentPoliciesByIDsMock.mockResolvedValue([ + { id: so2.attributes.policy_id, name: 'only I have a name' }, + ] as Array>); + + const actualItems = (await uninstallTokenService.getTokenMetadata()).items; + const expectedItems: UninstallTokenMetadata[] = [ + { + id: so.id, + policy_id: so.attributes.policy_id, + policy_name: null, + created_at: so.created_at, + }, + { + id: so2.id, + policy_id: so2.attributes.policy_id, + policy_name: 'only I have a name', + created_at: so2.created_at, + }, + ]; + expect(actualItems).toEqual(expectedItems); + + expect(soClientMock.createPointInTimeFinder).toHaveBeenCalledWith( + expect.objectContaining({ + filter: undefined, + }) + ); + }); + it('should throw error if created_at is missing', async () => { const defaultBuckets = getDefaultBuckets(canEncrypt); defaultBuckets[0].latest.hits.hits[0]._source.created_at = ''; diff --git a/x-pack/plugins/fleet/server/services/security/uninstall_token_service/index.ts b/x-pack/plugins/fleet/server/services/security/uninstall_token_service/index.ts index 0abad8961e47e..0a44a3df0f294 100644 --- a/x-pack/plugins/fleet/server/services/security/uninstall_token_service/index.ts +++ b/x-pack/plugins/fleet/server/services/security/uninstall_token_service/index.ts @@ -22,17 +22,16 @@ import type { } from '@elastic/elasticsearch/lib/api/types'; import type { EncryptedSavedObjectsClient } from '@kbn/encrypted-saved-objects-plugin/server'; import type { KibanaRequest } from '@kbn/core-http-server'; -import { SECURITY_EXTENSION_ID } from '@kbn/core-saved-objects-server'; +import { SECURITY_EXTENSION_ID, SPACES_EXTENSION_ID } from '@kbn/core-saved-objects-server'; import { asyncForEach, asyncMap } from '@kbn/std'; import type { AggregationsTermsInclude, AggregationsTermsExclude, } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; - import { isResponseError } from '@kbn/es-errors'; - import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; +import { DEFAULT_NAMESPACE_STRING } from '@kbn/core-saved-objects-utils-server'; import type { AgentPolicySOAttributes } from '../../../types'; import { UninstallTokenError } from '../../../../common/errors'; @@ -45,11 +44,13 @@ import type { import { UNINSTALL_TOKENS_SAVED_OBJECT_TYPE, SO_SEARCH_LIMIT } from '../../../constants'; import { appContextService } from '../../app_context'; import { agentPolicyService, getAgentPolicySavedObjectType } from '../../agent_policy'; +import { isSpaceAwarenessEnabled } from '../../spaces/helpers'; interface UninstallTokenSOAttributes { policy_id: string; token: string; token_plain: string; + namespaces?: string[]; } interface UninstallTokenSOAggregationBucket { @@ -61,6 +62,14 @@ interface UninstallTokenSOAggregation { by_policy_id: AggregationsMultiBucketAggregateBase; } +function getNamespaceFiltering(namespace: string) { + if (namespace === DEFAULT_NAMESPACE_STRING) { + return `(${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}.attributes.namespaces:default) or (not ${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}.attributes.namespaces:*)`; + } + + return `${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}.attributes.namespaces:${namespace}`; +} + export interface UninstallTokenInvalidError { error: UninstallTokenError; } @@ -189,11 +198,15 @@ export class UninstallTokenService implements UninstallTokenServiceInterface { } public async getToken(id: string): Promise { - const namespacePrefix = this.soClient.getCurrentNamespace() - ? `${this.soClient.getCurrentNamespace()}:` - : ''; - const filter = `${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}.id: "${namespacePrefix}${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}:${id}"`; - const tokenObjects = await this.getDecryptedTokenObjects({ filter }); + const useSpaceAwareness = this.isScoped && (await isSpaceAwarenessEnabled()); + const namespaceFilter = useSpaceAwareness + ? getNamespaceFiltering(this.soClient.getCurrentNamespace() ?? DEFAULT_SPACE_ID) + : undefined; + + const filter = `${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}.id: "${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}:${id}"`; + const tokenObjects = await this.getDecryptedTokenObjects({ + filter: namespaceFilter ? `(${namespaceFilter}) and (${filter})` : filter, + }); return tokenObjects.length === 1 ? this.convertTokenObjectToToken( await this.getPolicyIdNameDictionary([tokenObjects[0].attributes.policy_id]), @@ -278,14 +291,12 @@ export class UninstallTokenService implements UninstallTokenServiceInterface { this.assertCreatedAt(_source.created_at); const policyId = _source[UNINSTALL_TOKENS_SAVED_OBJECT_TYPE].policy_id; - const namespacePrefix = this.soClient.getCurrentNamespace() - ? `${this.soClient.getCurrentNamespace()}:` - : ''; return { - id: _id!.replace(`${namespacePrefix}${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}:`, ''), + id: _id!.replace(`${UNINSTALL_TOKENS_SAVED_OBJECT_TYPE}:`, ''), policy_id: policyId, policy_name: policyIdNameDictionary[policyId] ?? null, created_at: _source.created_at, + namespaces: _source.namespaces, }; } ); @@ -375,9 +386,6 @@ export class UninstallTokenService implements UninstallTokenServiceInterface { { type: UNINSTALL_TOKENS_SAVED_OBJECT_TYPE, perPage: SO_SEARCH_LIMIT, - namespaces: this.isScoped - ? [this.soClient.getCurrentNamespace() || DEFAULT_SPACE_ID] - : undefined, ...options, } ); @@ -415,6 +423,7 @@ export class UninstallTokenService implements UninstallTokenServiceInterface { policy_name: policyIdNameDictionary[attributes.policy_id] ?? null, token: attributes.token || attributes.token_plain, created_at: createdAt, + namespaces: attributes.namespaces, }; }; @@ -423,9 +432,18 @@ export class UninstallTokenService implements UninstallTokenServiceInterface { exclude?: AggregationsTermsExclude ): Promise>> { const bucketSize = 10000; + + const useSpaceAwareness = await isSpaceAwarenessEnabled(); + + const filter = + this.isScoped && useSpaceAwareness + ? getNamespaceFiltering(this.soClient.getCurrentNamespace() || DEFAULT_NAMESPACE_STRING) + : undefined; + const query: SavedObjectsCreatePointInTimeFinderOptions = { type: UNINSTALL_TOKENS_SAVED_OBJECT_TYPE, perPage: 0, + filter, aggs: { by_policy_id: { terms: { @@ -574,7 +592,9 @@ export class UninstallTokenService implements UninstallTokenServiceInterface { } private async getAllPolicyIds(): Promise { - const agentPolicyIdsFetcher = await agentPolicyService.fetchAllAgentPolicyIds(this.soClient); + const agentPolicyIdsFetcher = await agentPolicyService.fetchAllAgentPolicyIds(this.soClient, { + spaceId: '*', + }); const policyIds: string[] = []; for await (const agentPolicyId of agentPolicyIdsFetcher) { policyIds.push(...agentPolicyId); @@ -595,20 +615,27 @@ export class UninstallTokenService implements UninstallTokenServiceInterface { const batchSize = config?.setup?.agentPolicySchemaUpgradeBatchSize ?? 100; await asyncForEach(chunk(policyIds, batchSize), async (policyIdsBatch) => { + const policies = await agentPolicyService.getByIDs( + appContextService.getInternalUserSOClientWithoutSpaceExtension(), + policyIds.map((id) => ({ id, spaceId: '*' })) + ); + const policiesSpacesIndexedById = policies.reduce((acc, p) => { + acc[p.id] = p.space_ids; + return acc; + }, {} as { [k: string]: string[] | undefined }); await this.soClient.bulkCreate>( policyIdsBatch.map((policyId) => ({ type: UNINSTALL_TOKENS_SAVED_OBJECT_TYPE, - initialNamespaces: this.soClient.getCurrentNamespace() - ? [this.soClient.getCurrentNamespace() as string] - : undefined, attributes: this.isEncryptionAvailable ? { policy_id: policyId, token: tokensMap[policyId], + namespaces: policiesSpacesIndexedById[policyId], } : { policy_id: policyId, token_plain: tokensMap[policyId], + namespaces: policiesSpacesIndexedById[policyId], }, })) ); @@ -643,7 +670,7 @@ export class UninstallTokenService implements UninstallTokenServiceInterface { } as unknown as KibanaRequest; this._soClient = appContextService.getSavedObjects().getScopedClient(fakeRequest, { - excludedExtensions: [SECURITY_EXTENSION_ID], + excludedExtensions: [SECURITY_EXTENSION_ID, SPACES_EXTENSION_ID], includedHiddenTypes: [UNINSTALL_TOKENS_SAVED_OBJECT_TYPE], }); diff --git a/x-pack/plugins/fleet/server/types/models/package_policy.ts b/x-pack/plugins/fleet/server/types/models/package_policy.ts index c80cb45c84ff9..e105bc82b27db 100644 --- a/x-pack/plugins/fleet/server/types/models/package_policy.ts +++ b/x-pack/plugins/fleet/server/types/models/package_policy.ts @@ -96,7 +96,7 @@ const PackagePolicyBaseSchema = { name: schema.string(), description: schema.maybe(schema.string()), namespace: schema.maybe(PackagePolicyNamespaceSchema), - policy_id: schema.maybe(schema.string()), + policy_id: schema.nullable(schema.maybe(schema.string())), policy_ids: schema.maybe(schema.arrayOf(schema.string())), output_id: schema.nullable(schema.maybe(schema.string())), enabled: schema.boolean(), @@ -221,7 +221,7 @@ export const SimplifiedPackagePolicyPreconfiguredSchema = SimplifiedPackagePolic export const SimplifiedCreatePackagePolicyRequestBodySchema = SimplifiedPackagePolicyBaseSchema.extends({ - policy_id: schema.maybe(schema.string()), + policy_id: schema.nullable(schema.maybe(schema.string())), policy_ids: schema.maybe(schema.arrayOf(schema.string())), force: schema.maybe(schema.boolean()), package: schema.object({ diff --git a/x-pack/plugins/fleet/server/types/so_attributes.ts b/x-pack/plugins/fleet/server/types/so_attributes.ts index ef39759b206f5..1bb954cf990d2 100644 --- a/x-pack/plugins/fleet/server/types/so_attributes.ts +++ b/x-pack/plugins/fleet/server/types/so_attributes.ts @@ -119,7 +119,7 @@ export interface PackagePolicySOAttributes { created_at: string; created_by: string; inputs: PackagePolicyInput[]; - policy_id?: string; + policy_id?: string | null; policy_ids: string[]; // Nullable to allow user to reset to default outputs output_id?: string | null; diff --git a/x-pack/plugins/graph/common/content_management/v1/types.ts b/x-pack/plugins/graph/common/content_management/v1/types.ts index c6664cf5a162c..0a53afa4a4a24 100644 --- a/x-pack/plugins/graph/common/content_management/v1/types.ts +++ b/x-pack/plugins/graph/common/content_management/v1/types.ts @@ -17,7 +17,7 @@ import { CreateResult, UpdateResult, } from '@kbn/content-management-plugin/common'; -import { ContentManagementCrudTypes } from '@kbn/content-management-utils'; +import type { ContentManagementCrudTypes } from '@kbn/content-management-utils'; import { GraphContentType } from '../types'; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields_json_editor.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields_json_editor.tsx index 94d370082ca7e..751f4fb546c74 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields_json_editor.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields_json_editor.tsx @@ -18,7 +18,7 @@ export const DocumentFieldsJsonEditor = ({ defaultValue }: Props) => { const dispatch = useDispatch(); const defaultValueRef = useRef(defaultValue); const onUpdate = useCallback( - ({ data, isValid }) => + ({ data, isValid }: any) => dispatch({ type: 'fieldsJsonEditor.update', value: { json: data.format(), isValid }, diff --git a/x-pack/plugins/inference/common/chat_complete/tool_schema.ts b/x-pack/plugins/inference/common/chat_complete/tool_schema.ts index 5ca3e0ab57a49..b23c03aaad775 100644 --- a/x-pack/plugins/inference/common/chat_complete/tool_schema.ts +++ b/x-pack/plugins/inference/common/chat_complete/tool_schema.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Required, ValuesType, UnionToIntersection } from 'utility-types'; +import { Required, ValuesType } from 'utility-types'; interface ToolSchemaFragmentBase { description?: string; @@ -13,7 +13,7 @@ interface ToolSchemaFragmentBase { interface ToolSchemaTypeObject extends ToolSchemaFragmentBase { type: 'object'; - properties: Record; + properties: Record; required?: string[] | readonly string[]; } @@ -35,28 +35,18 @@ interface ToolSchemaTypeNumber extends ToolSchemaFragmentBase { enum?: string[] | readonly string[]; } -interface ToolSchemaAnyOf extends ToolSchemaFragmentBase { - anyOf: ToolSchemaType[]; -} - -interface ToolSchemaAllOf extends ToolSchemaFragmentBase { - allOf: ToolSchemaType[]; -} - interface ToolSchemaTypeArray extends ToolSchemaFragmentBase { type: 'array'; items: Exclude; } -type ToolSchemaType = +export type ToolSchemaType = | ToolSchemaTypeObject | ToolSchemaTypeString | ToolSchemaTypeBoolean | ToolSchemaTypeNumber | ToolSchemaTypeArray; -type ToolSchemaFragment = ToolSchemaType | ToolSchemaAnyOf | ToolSchemaAllOf; - type FromToolSchemaObject = Required< { [key in keyof TToolSchemaObject['properties']]?: FromToolSchema< @@ -79,17 +69,9 @@ type FromToolSchemaString = ? ValuesType : string; -type FromToolSchemaAnyOf = FromToolSchema< - ValuesType ->; - -type FromToolSchemaAllOf = UnionToIntersection< - FromToolSchema> ->; - export type ToolSchema = ToolSchemaTypeObject; -export type FromToolSchema = +export type FromToolSchema = TToolSchema extends ToolSchemaTypeObject ? FromToolSchemaObject : TToolSchema extends ToolSchemaTypeArray @@ -100,8 +82,4 @@ export type FromToolSchema = ? number : TToolSchema extends ToolSchemaTypeString ? FromToolSchemaString - : TToolSchema extends ToolSchemaAnyOf - ? FromToolSchemaAnyOf - : TToolSchema extends ToolSchemaAllOf - ? FromToolSchemaAllOf : never; diff --git a/x-pack/plugins/triggers_actions_ui/config.ts b/x-pack/plugins/inference/server/chat_complete/adapters/gemini/gemini_adapter.test.mocks.ts similarity index 51% rename from x-pack/plugins/triggers_actions_ui/config.ts rename to x-pack/plugins/inference/server/chat_complete/adapters/gemini/gemini_adapter.test.mocks.ts index 3f288f7e4ddb7..4b9d0b4648985 100644 --- a/x-pack/plugins/triggers_actions_ui/config.ts +++ b/x-pack/plugins/inference/server/chat_complete/adapters/gemini/gemini_adapter.test.mocks.ts @@ -5,10 +5,12 @@ * 2.0. */ -import { schema, TypeOf } from '@kbn/config-schema'; +export const processVertexStreamMock = jest.fn(); -export const configSchema = schema.object({ - enableGeoTrackingThresholdAlert: schema.maybe(schema.boolean({ defaultValue: false })), +jest.doMock('./process_vertex_stream', () => { + const actual = jest.requireActual('./process_vertex_stream'); + return { + ...actual, + processVertexStream: processVertexStreamMock, + }; }); - -export type ConfigSchema = TypeOf; diff --git a/x-pack/plugins/inference/server/chat_complete/adapters/gemini/gemini_adapter.test.ts b/x-pack/plugins/inference/server/chat_complete/adapters/gemini/gemini_adapter.test.ts new file mode 100644 index 0000000000000..3fe8c917c0015 --- /dev/null +++ b/x-pack/plugins/inference/server/chat_complete/adapters/gemini/gemini_adapter.test.ts @@ -0,0 +1,396 @@ +/* + * 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 { processVertexStreamMock } from './gemini_adapter.test.mocks'; +import { PassThrough } from 'stream'; +import { noop, tap, lastValueFrom, toArray, Subject } from 'rxjs'; +import type { InferenceExecutor } from '../../utils/inference_executor'; +import { observableIntoEventSourceStream } from '../../../util/observable_into_event_source_stream'; +import { MessageRole } from '../../../../common/chat_complete'; +import { ToolChoiceType } from '../../../../common/chat_complete/tools'; +import { geminiAdapter } from './gemini_adapter'; + +describe('geminiAdapter', () => { + const executorMock = { + invoke: jest.fn(), + } as InferenceExecutor & { invoke: jest.MockedFn }; + + beforeEach(() => { + executorMock.invoke.mockReset(); + processVertexStreamMock.mockReset().mockImplementation(() => tap(noop)); + }); + + function getCallParams() { + const params = executorMock.invoke.mock.calls[0][0].subActionParams as Record; + return { + messages: params.messages, + tools: params.tools, + toolConfig: params.toolConfig, + systemInstruction: params.systemInstruction, + }; + } + + describe('#chatComplete()', () => { + beforeEach(() => { + executorMock.invoke.mockImplementation(async () => { + return { + actionId: '', + status: 'ok', + data: new PassThrough(), + }; + }); + }); + + it('calls `executor.invoke` with the right fixed parameters', () => { + geminiAdapter.chatComplete({ + executor: executorMock, + messages: [ + { + role: MessageRole.User, + content: 'question', + }, + ], + }); + + expect(executorMock.invoke).toHaveBeenCalledTimes(1); + expect(executorMock.invoke).toHaveBeenCalledWith({ + subAction: 'invokeStream', + subActionParams: { + messages: [ + { + parts: [{ text: 'question' }], + role: 'user', + }, + ], + tools: [], + temperature: 0, + stopSequences: ['\n\nHuman:'], + }, + }); + }); + + it('correctly format tools', () => { + geminiAdapter.chatComplete({ + executor: executorMock, + messages: [ + { + role: MessageRole.User, + content: 'question', + }, + ], + tools: { + myFunction: { + description: 'myFunction', + }, + myFunctionWithArgs: { + description: 'myFunctionWithArgs', + schema: { + type: 'object', + properties: { + foo: { + type: 'string', + description: 'foo', + }, + }, + required: ['foo'], + }, + }, + }, + }); + + expect(executorMock.invoke).toHaveBeenCalledTimes(1); + + const { tools } = getCallParams(); + expect(tools).toEqual([ + { + functionDeclarations: [ + { + description: 'myFunction', + name: 'myFunction', + parameters: { + properties: {}, + type: 'OBJECT', + }, + }, + { + description: 'myFunctionWithArgs', + name: 'myFunctionWithArgs', + parameters: { + properties: { + foo: { + description: 'foo', + enum: undefined, + type: 'STRING', + }, + }, + required: ['foo'], + type: 'OBJECT', + }, + }, + ], + }, + ]); + }); + + it('correctly format messages', () => { + geminiAdapter.chatComplete({ + executor: executorMock, + messages: [ + { + role: MessageRole.User, + content: 'question', + }, + { + role: MessageRole.Assistant, + content: 'answer', + }, + { + role: MessageRole.User, + content: 'another question', + }, + { + role: MessageRole.Assistant, + content: null, + toolCalls: [ + { + function: { + name: 'my_function', + arguments: { + foo: 'bar', + }, + }, + toolCallId: '0', + }, + ], + }, + { + role: MessageRole.Tool, + toolCallId: '0', + response: { + bar: 'foo', + }, + }, + ], + }); + + expect(executorMock.invoke).toHaveBeenCalledTimes(1); + + const { messages } = getCallParams(); + expect(messages).toEqual([ + { + parts: [ + { + text: 'question', + }, + ], + role: 'user', + }, + { + parts: [ + { + text: 'answer', + }, + ], + role: 'assistant', + }, + { + parts: [ + { + text: 'another question', + }, + ], + role: 'user', + }, + { + parts: [ + { + functionCall: { + args: { + foo: 'bar', + }, + name: 'my_function', + }, + }, + ], + role: 'assistant', + }, + { + parts: [ + { + functionResponse: { + name: '0', + response: { + bar: 'foo', + }, + }, + }, + ], + role: 'user', + }, + ]); + }); + + it('groups messages from the same user', () => { + geminiAdapter.chatComplete({ + executor: executorMock, + messages: [ + { + role: MessageRole.User, + content: 'question', + }, + { + role: MessageRole.User, + content: 'another question', + }, + { + role: MessageRole.Assistant, + content: 'answer', + }, + { + role: MessageRole.Assistant, + content: null, + toolCalls: [ + { + function: { + name: 'my_function', + arguments: { + foo: 'bar', + }, + }, + toolCallId: '0', + }, + ], + }, + ], + }); + + expect(executorMock.invoke).toHaveBeenCalledTimes(1); + + const { messages } = getCallParams(); + expect(messages).toEqual([ + { + parts: [ + { + text: 'question', + }, + { + text: 'another question', + }, + ], + role: 'user', + }, + { + parts: [ + { + text: 'answer', + }, + { + functionCall: { + args: { + foo: 'bar', + }, + name: 'my_function', + }, + }, + ], + role: 'assistant', + }, + ]); + }); + + it('correctly format system message', () => { + geminiAdapter.chatComplete({ + executor: executorMock, + system: 'Some system message', + messages: [ + { + role: MessageRole.User, + content: 'question', + }, + ], + }); + + expect(executorMock.invoke).toHaveBeenCalledTimes(1); + + const { systemInstruction } = getCallParams(); + expect(systemInstruction).toEqual('Some system message'); + }); + + it('correctly format tool choice', () => { + geminiAdapter.chatComplete({ + executor: executorMock, + messages: [ + { + role: MessageRole.User, + content: 'question', + }, + ], + toolChoice: ToolChoiceType.required, + }); + + expect(executorMock.invoke).toHaveBeenCalledTimes(1); + + const { toolConfig } = getCallParams(); + expect(toolConfig).toEqual({ mode: 'ANY' }); + }); + + it('correctly format tool choice for named function', () => { + geminiAdapter.chatComplete({ + executor: executorMock, + messages: [ + { + role: MessageRole.User, + content: 'question', + }, + ], + toolChoice: { function: 'foobar' }, + }); + + expect(executorMock.invoke).toHaveBeenCalledTimes(1); + + const { toolConfig } = getCallParams(); + expect(toolConfig).toEqual({ mode: 'ANY', allowedFunctionNames: ['foobar'] }); + }); + + it('process response events via processVertexStream', async () => { + const source$ = new Subject>(); + + const tapFn = jest.fn(); + processVertexStreamMock.mockImplementation(() => tap(tapFn)); + + executorMock.invoke.mockImplementation(async () => { + return { + actionId: '', + status: 'ok', + data: observableIntoEventSourceStream(source$), + }; + }); + + const response$ = geminiAdapter.chatComplete({ + executor: executorMock, + messages: [ + { + role: MessageRole.User, + content: 'question', + }, + ], + }); + + source$.next({ chunk: 1 }); + source$.next({ chunk: 2 }); + source$.complete(); + + const allChunks = await lastValueFrom(response$.pipe(toArray())); + + expect(allChunks).toEqual([{ chunk: 1 }, { chunk: 2 }]); + + expect(tapFn).toHaveBeenCalledTimes(2); + expect(tapFn).toHaveBeenCalledWith({ chunk: 1 }); + expect(tapFn).toHaveBeenCalledWith({ chunk: 2 }); + }); + }); +}); diff --git a/x-pack/plugins/inference/server/chat_complete/adapters/gemini/gemini_adapter.ts b/x-pack/plugins/inference/server/chat_complete/adapters/gemini/gemini_adapter.ts new file mode 100644 index 0000000000000..8f6d02da0e3f8 --- /dev/null +++ b/x-pack/plugins/inference/server/chat_complete/adapters/gemini/gemini_adapter.ts @@ -0,0 +1,213 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as Gemini from '@google/generative-ai'; +import { from, map, switchMap } from 'rxjs'; +import { Readable } from 'stream'; +import type { InferenceConnectorAdapter } from '../../types'; +import { Message, MessageRole } from '../../../../common/chat_complete'; +import { ToolChoiceType, ToolOptions } from '../../../../common/chat_complete/tools'; +import type { ToolSchema, ToolSchemaType } from '../../../../common/chat_complete/tool_schema'; +import { eventSourceStreamIntoObservable } from '../../../util/event_source_stream_into_observable'; +import { processVertexStream } from './process_vertex_stream'; +import type { GenerateContentResponseChunk, GeminiMessage, GeminiToolConfig } from './types'; + +export const geminiAdapter: InferenceConnectorAdapter = { + chatComplete: ({ executor, system, messages, toolChoice, tools }) => { + return from( + executor.invoke({ + subAction: 'invokeStream', + subActionParams: { + messages: messagesToGemini({ messages }), + systemInstruction: system, + tools: toolsToGemini(tools), + toolConfig: toolChoiceToConfig(toolChoice), + temperature: 0, + stopSequences: ['\n\nHuman:'], + }, + }) + ).pipe( + switchMap((response) => { + const readable = response.data as Readable; + return eventSourceStreamIntoObservable(readable); + }), + map((line) => { + return JSON.parse(line) as GenerateContentResponseChunk; + }), + processVertexStream() + ); + }, +}; + +function toolChoiceToConfig(toolChoice: ToolOptions['toolChoice']): GeminiToolConfig | undefined { + if (toolChoice === ToolChoiceType.required) { + return { + mode: 'ANY', + }; + } else if (toolChoice === ToolChoiceType.none) { + return { + mode: 'NONE', + }; + } else if (toolChoice === ToolChoiceType.auto) { + return { + mode: 'AUTO', + }; + } else if (toolChoice) { + return { + mode: 'ANY', + allowedFunctionNames: [toolChoice.function], + }; + } + return undefined; +} + +function toolsToGemini(tools: ToolOptions['tools']): Gemini.Tool[] { + return tools + ? [ + { + functionDeclarations: Object.entries(tools ?? {}).map( + ([toolName, { description, schema }]) => { + return { + name: toolName, + description, + parameters: schema + ? toolSchemaToGemini({ schema }) + : { + type: Gemini.FunctionDeclarationSchemaType.OBJECT, + properties: {}, + }, + }; + } + ), + }, + ] + : []; +} + +function toolSchemaToGemini({ schema }: { schema: ToolSchema }): Gemini.FunctionDeclarationSchema { + const convertSchemaType = ({ + def, + }: { + def: ToolSchemaType; + }): Gemini.FunctionDeclarationSchemaProperty => { + switch (def.type) { + case 'array': + return { + type: Gemini.FunctionDeclarationSchemaType.ARRAY, + description: def.description, + items: convertSchemaType({ def: def.items }) as Gemini.FunctionDeclarationSchema, + }; + case 'object': + return { + type: Gemini.FunctionDeclarationSchemaType.OBJECT, + description: def.description, + required: def.required as string[], + properties: Object.entries(def.properties).reduce< + Record + >((properties, [key, prop]) => { + properties[key] = convertSchemaType({ def: prop }) as Gemini.FunctionDeclarationSchema; + return properties; + }, {}), + }; + case 'string': + return { + type: Gemini.FunctionDeclarationSchemaType.STRING, + description: def.description, + enum: def.enum ? (def.enum as string[]) : def.const ? [def.const] : undefined, + }; + case 'boolean': + return { + type: Gemini.FunctionDeclarationSchemaType.BOOLEAN, + description: def.description, + enum: def.enum ? (def.enum as string[]) : def.const ? [def.const] : undefined, + }; + case 'number': + return { + type: Gemini.FunctionDeclarationSchemaType.NUMBER, + description: def.description, + enum: def.enum ? (def.enum as string[]) : def.const ? [def.const] : undefined, + }; + } + }; + + return { + type: Gemini.FunctionDeclarationSchemaType.OBJECT, + required: schema.required as string[], + properties: Object.entries(schema.properties).reduce< + Record + >((properties, [key, def]) => { + properties[key] = convertSchemaType({ def }); + return properties; + }, {}), + }; +} + +function messagesToGemini({ messages }: { messages: Message[] }): GeminiMessage[] { + return messages.map(messageToGeminiMapper()).reduce((output, message) => { + // merging consecutive messages from the same user, as Gemini requires multi-turn messages + const previousMessage = output.length ? output[output.length - 1] : undefined; + if (previousMessage?.role === message.role) { + previousMessage.parts.push(...message.parts); + } else { + output.push(message); + } + return output; + }, []); +} + +function messageToGeminiMapper() { + return (message: Message): GeminiMessage => { + const role = message.role; + + switch (role) { + case MessageRole.Assistant: + const assistantMessage: GeminiMessage = { + role: 'assistant', + parts: [ + ...(message.content ? [{ text: message.content }] : []), + ...(message.toolCalls ?? []).map((toolCall) => { + return { + functionCall: { + name: toolCall.function.name, + args: ('arguments' in toolCall.function + ? toolCall.function.arguments + : {}) as object, + }, + }; + }), + ], + }; + return assistantMessage; + + case MessageRole.User: + const userMessage: GeminiMessage = { + role: 'user', + parts: [ + { + text: message.content, + }, + ], + }; + return userMessage; + + case MessageRole.Tool: + // tool responses are provided as user messages + const toolMessage: GeminiMessage = { + role: 'user', + parts: [ + { + functionResponse: { + name: message.toolCallId, + response: message.response as object, + }, + }, + ], + }; + return toolMessage; + } + }; +} diff --git a/x-pack/packages/kbn-cloud-security-posture-common/schema/index.ts b/x-pack/plugins/inference/server/chat_complete/adapters/gemini/index.ts similarity index 73% rename from x-pack/packages/kbn-cloud-security-posture-common/schema/index.ts rename to x-pack/plugins/inference/server/chat_complete/adapters/gemini/index.ts index 981633d2a3fad..abd7c3e552c0f 100644 --- a/x-pack/packages/kbn-cloud-security-posture-common/schema/index.ts +++ b/x-pack/plugins/inference/server/chat_complete/adapters/gemini/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { ruleStateAttributes, cspBenchmarkRuleMetadataSchema, rulesStates } from './rules'; +export { geminiAdapter } from './gemini_adapter'; diff --git a/x-pack/plugins/inference/server/chat_complete/adapters/gemini/process_vertex_stream.test.ts b/x-pack/plugins/inference/server/chat_complete/adapters/gemini/process_vertex_stream.test.ts new file mode 100644 index 0000000000000..78e0da0a384b8 --- /dev/null +++ b/x-pack/plugins/inference/server/chat_complete/adapters/gemini/process_vertex_stream.test.ts @@ -0,0 +1,155 @@ +/* + * 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 { TestScheduler } from 'rxjs/testing'; +import { ChatCompletionEventType } from '../../../../common/chat_complete'; +import { processVertexStream } from './process_vertex_stream'; +import type { GenerateContentResponseChunk } from './types'; + +describe('processVertexStream', () => { + const getTestScheduler = () => + new TestScheduler((actual, expected) => { + expect(actual).toEqual(expected); + }); + + it('completes when the source completes', () => { + getTestScheduler().run(({ expectObservable, hot }) => { + const source$ = hot('----|'); + + const processed$ = source$.pipe(processVertexStream()); + + expectObservable(processed$).toBe('----|'); + }); + }); + + it('emits a chunk event when the source emits content', () => { + getTestScheduler().run(({ expectObservable, hot }) => { + const chunk: GenerateContentResponseChunk = { + candidates: [{ index: 0, content: { role: 'model', parts: [{ text: 'some chunk' }] } }], + }; + + const source$ = hot('--a', { a: chunk }); + + const processed$ = source$.pipe(processVertexStream()); + + expectObservable(processed$).toBe('--a', { + a: { + content: 'some chunk', + tool_calls: [], + type: ChatCompletionEventType.ChatCompletionChunk, + }, + }); + }); + }); + + it('emits a chunk event when the source emits a function call', () => { + getTestScheduler().run(({ expectObservable, hot }) => { + const chunk: GenerateContentResponseChunk = { + candidates: [ + { + index: 0, + content: { + role: 'model', + parts: [{ functionCall: { name: 'func1', args: { arg1: true } } }], + }, + }, + ], + }; + + const source$ = hot('--a', { a: chunk }); + + const processed$ = source$.pipe(processVertexStream()); + + expectObservable(processed$).toBe('--a', { + a: { + content: '', + tool_calls: [ + { + index: 0, + toolCallId: expect.any(String), + function: { name: 'func1', arguments: JSON.stringify({ arg1: true }) }, + }, + ], + type: ChatCompletionEventType.ChatCompletionChunk, + }, + }); + }); + }); + + it('emits a token count event when the source emits content with usageMetadata', () => { + getTestScheduler().run(({ expectObservable, hot }) => { + const chunk: GenerateContentResponseChunk = { + candidates: [{ index: 0, content: { role: 'model', parts: [{ text: 'last chunk' }] } }], + usageMetadata: { + candidatesTokenCount: 1, + promptTokenCount: 2, + totalTokenCount: 3, + }, + }; + + const source$ = hot('--a', { a: chunk }); + + const processed$ = source$.pipe(processVertexStream()); + + expectObservable(processed$).toBe('--(ab)', { + a: { + tokens: { + completion: 1, + prompt: 2, + total: 3, + }, + type: ChatCompletionEventType.ChatCompletionTokenCount, + }, + b: { + content: 'last chunk', + tool_calls: [], + type: ChatCompletionEventType.ChatCompletionChunk, + }, + }); + }); + }); + + it('emits for multiple chunks', () => { + getTestScheduler().run(({ expectObservable, hot }) => { + const chunkA: GenerateContentResponseChunk = { + candidates: [{ index: 0, content: { role: 'model', parts: [{ text: 'chunk A' }] } }], + }; + const chunkB: GenerateContentResponseChunk = { + candidates: [{ index: 0, content: { role: 'model', parts: [{ text: 'chunk B' }] } }], + }; + const chunkC: GenerateContentResponseChunk = { + candidates: [{ index: 0, content: { role: 'model', parts: [{ text: 'chunk C' }] } }], + }; + + const source$ = hot('-a--b---c-|', { + a: chunkA, + b: chunkB, + c: chunkC, + }); + + const processed$ = source$.pipe(processVertexStream()); + + expectObservable(processed$).toBe('-a--b---c-|', { + a: { + content: 'chunk A', + tool_calls: [], + type: ChatCompletionEventType.ChatCompletionChunk, + }, + b: { + content: 'chunk B', + tool_calls: [], + type: ChatCompletionEventType.ChatCompletionChunk, + }, + c: { + content: 'chunk C', + tool_calls: [], + type: ChatCompletionEventType.ChatCompletionChunk, + }, + }); + }); + }); +}); diff --git a/x-pack/plugins/inference/server/chat_complete/adapters/gemini/process_vertex_stream.ts b/x-pack/plugins/inference/server/chat_complete/adapters/gemini/process_vertex_stream.ts new file mode 100644 index 0000000000000..ec3fa8e82eed6 --- /dev/null +++ b/x-pack/plugins/inference/server/chat_complete/adapters/gemini/process_vertex_stream.ts @@ -0,0 +1,70 @@ +/* + * 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 { Observable } from 'rxjs'; +import { + ChatCompletionChunkEvent, + ChatCompletionTokenCountEvent, + ChatCompletionEventType, +} from '../../../../common/chat_complete'; +import { generateFakeToolCallId } from '../../utils'; +import type { GenerateContentResponseChunk } from './types'; + +export function processVertexStream() { + return (source: Observable) => + new Observable((subscriber) => { + function handleNext(value: GenerateContentResponseChunk) { + // completion: only present on last chunk + if (value.usageMetadata) { + subscriber.next({ + type: ChatCompletionEventType.ChatCompletionTokenCount, + tokens: { + prompt: value.usageMetadata.promptTokenCount, + completion: value.usageMetadata.candidatesTokenCount, + total: value.usageMetadata.totalTokenCount, + }, + }); + } + + const contentPart = value.candidates?.[0].content.parts[0]; + const completion = contentPart?.text; + const toolCall = contentPart?.functionCall; + + if (completion || toolCall) { + subscriber.next({ + type: ChatCompletionEventType.ChatCompletionChunk, + content: completion ?? '', + tool_calls: toolCall + ? [ + { + index: 0, + toolCallId: generateFakeToolCallId(), + function: { name: toolCall.name, arguments: JSON.stringify(toolCall.args) }, + }, + ] + : [], + }); + } + } + + source.subscribe({ + next: (value) => { + try { + handleNext(value); + } catch (error) { + subscriber.error(error); + } + }, + error: (err) => { + subscriber.error(err); + }, + complete: () => { + subscriber.complete(); + }, + }); + }); +} diff --git a/x-pack/plugins/inference/server/chat_complete/adapters/gemini/types.ts b/x-pack/plugins/inference/server/chat_complete/adapters/gemini/types.ts new file mode 100644 index 0000000000000..7d00057d8b801 --- /dev/null +++ b/x-pack/plugins/inference/server/chat_complete/adapters/gemini/types.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { GenerateContentResponse, Part } from '@google/generative-ai'; + +export interface GenerateContentResponseUsageMetadata { + promptTokenCount: number; + candidatesTokenCount: number; + totalTokenCount: number; +} + +/** + * Actual type for chunks, as the type from the google package is missing the + * usage metadata. + */ +export type GenerateContentResponseChunk = GenerateContentResponse & { + usageMetadata?: GenerateContentResponseUsageMetadata; +}; + +/** + * We need to use the connector's format, not directly Gemini's... + * In practice, 'parts' get mapped to 'content' + * + * See x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.ts + */ +export interface GeminiMessage { + role: 'assistant' | 'user'; + parts: Part[]; +} + +export interface GeminiToolConfig { + mode: 'AUTO' | 'ANY' | 'NONE'; + allowedFunctionNames?: string[]; +} diff --git a/x-pack/plugins/inference/server/chat_complete/adapters/get_inference_adapter.test.ts b/x-pack/plugins/inference/server/chat_complete/adapters/get_inference_adapter.test.ts index 272ad76538898..9e0b0da6d5894 100644 --- a/x-pack/plugins/inference/server/chat_complete/adapters/get_inference_adapter.test.ts +++ b/x-pack/plugins/inference/server/chat_complete/adapters/get_inference_adapter.test.ts @@ -8,17 +8,18 @@ import { InferenceConnectorType } from '../../../common/connectors'; import { getInferenceAdapter } from './get_inference_adapter'; import { openAIAdapter } from './openai'; +import { geminiAdapter } from './gemini'; describe('getInferenceAdapter', () => { it('returns the openAI adapter for OpenAI type', () => { expect(getInferenceAdapter(InferenceConnectorType.OpenAI)).toBe(openAIAdapter); }); - it('returns undefined for Bedrock type', () => { - expect(getInferenceAdapter(InferenceConnectorType.Bedrock)).toBe(undefined); + it('returns the gemini adapter for Gemini type', () => { + expect(getInferenceAdapter(InferenceConnectorType.Gemini)).toBe(geminiAdapter); }); - it('returns undefined for Gemini type', () => { - expect(getInferenceAdapter(InferenceConnectorType.Gemini)).toBe(undefined); + it('returns undefined for Bedrock type', () => { + expect(getInferenceAdapter(InferenceConnectorType.Bedrock)).toBe(undefined); }); }); diff --git a/x-pack/plugins/inference/server/chat_complete/adapters/get_inference_adapter.ts b/x-pack/plugins/inference/server/chat_complete/adapters/get_inference_adapter.ts index a62ec8b795608..0538d828a473a 100644 --- a/x-pack/plugins/inference/server/chat_complete/adapters/get_inference_adapter.ts +++ b/x-pack/plugins/inference/server/chat_complete/adapters/get_inference_adapter.ts @@ -8,6 +8,7 @@ import { InferenceConnectorType } from '../../../common/connectors'; import type { InferenceConnectorAdapter } from '../types'; import { openAIAdapter } from './openai'; +import { geminiAdapter } from './gemini'; export const getInferenceAdapter = ( connectorType: InferenceConnectorType @@ -16,11 +17,10 @@ export const getInferenceAdapter = ( case InferenceConnectorType.OpenAI: return openAIAdapter; - case InferenceConnectorType.Bedrock: - // not implemented yet - break; - case InferenceConnectorType.Gemini: + return geminiAdapter; + + case InferenceConnectorType.Bedrock: // not implemented yet break; } diff --git a/x-pack/plugins/inference/server/chat_complete/adapters/openai/index.ts b/x-pack/plugins/inference/server/chat_complete/adapters/openai/index.ts index 80fa9bfb781f5..d72ceb2020e8a 100644 --- a/x-pack/plugins/inference/server/chat_complete/adapters/openai/index.ts +++ b/x-pack/plugins/inference/server/chat_complete/adapters/openai/index.ts @@ -25,7 +25,7 @@ import type { ToolOptions } from '../../../../common/chat_complete/tools'; import { createTokenLimitReachedError } from '../../../../common/chat_complete/errors'; import { createInferenceInternalError } from '../../../../common/errors'; import { eventSourceStreamIntoObservable } from '../../../util/event_source_stream_into_observable'; -import { InferenceConnectorAdapter } from '../../types'; +import type { InferenceConnectorAdapter } from '../../types'; export const openAIAdapter: InferenceConnectorAdapter = { chatComplete: ({ executor, system, messages, toolChoice, tools }) => { @@ -76,6 +76,7 @@ export const openAIAdapter: InferenceConnectorAdapter = { const delta = chunk.choices[0].delta; return { + type: ChatCompletionEventType.ChatCompletionChunk, content: delta.content ?? '', tool_calls: delta.tool_calls?.map((toolCall) => { @@ -88,7 +89,6 @@ export const openAIAdapter: InferenceConnectorAdapter = { index: toolCall.index, }; }) ?? [], - type: ChatCompletionEventType.ChatCompletionChunk, }; }) ); diff --git a/x-pack/plugins/inference/server/chat_complete/utils/generate_fake_tool_call_id.ts b/x-pack/plugins/inference/server/chat_complete/utils/generate_fake_tool_call_id.ts new file mode 100644 index 0000000000000..1da675b61c4ec --- /dev/null +++ b/x-pack/plugins/inference/server/chat_complete/utils/generate_fake_tool_call_id.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { v4 } from 'uuid'; + +export function generateFakeToolCallId() { + return v4().substr(0, 6); +} diff --git a/x-pack/plugins/inference/server/chat_complete/utils/index.ts b/x-pack/plugins/inference/server/chat_complete/utils/index.ts index dea2ac65f4755..d9344164eff46 100644 --- a/x-pack/plugins/inference/server/chat_complete/utils/index.ts +++ b/x-pack/plugins/inference/server/chat_complete/utils/index.ts @@ -12,3 +12,4 @@ export { type InferenceExecutor, } from './inference_executor'; export { chunksIntoMessage } from './chunks_into_message'; +export { generateFakeToolCallId } from './generate_fake_tool_call_id'; diff --git a/x-pack/plugins/inference/server/routes/chat_complete.ts b/x-pack/plugins/inference/server/routes/chat_complete.ts index 6b5aea7b71696..bfa95fdbb9213 100644 --- a/x-pack/plugins/inference/server/routes/chat_complete.ts +++ b/x-pack/plugins/inference/server/routes/chat_complete.ts @@ -57,7 +57,7 @@ const chatCompleteBodySchema: Type = schema.object({ schema.object({ role: schema.literal(MessageRole.Assistant), content: schema.oneOf([schema.string(), schema.literal(null)]), - toolCalls: toolCallSchema, + toolCalls: schema.maybe(toolCallSchema), }), schema.object({ role: schema.literal(MessageRole.User), diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx index 9edef3e800a98..1c236ea7e78d6 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx @@ -98,7 +98,7 @@ export const PipelineProcessorsEditorItem: FunctionComponent = memo( ); const onDescriptionChange = useCallback( - (nextDescription) => { + (nextDescription: any) => { let nextOptions: Record; if (!nextDescription) { const { description: _description, ...restOptions } = processor.options; diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/drag_and_drop_text_list.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/drag_and_drop_text_list.tsx index ea9f460a5899a..915054b053baf 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/drag_and_drop_text_list.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/drag_and_drop_text_list.tsx @@ -78,7 +78,7 @@ function DragAndDropTextListComponent({ const [firstItemId] = useState(() => uuidv4()); const onDragEnd = useCallback( - ({ source, destination }) => { + ({ source, destination }: any) => { if (source && destination) { onMove(source.index, destination.index); } diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/xjson_editor.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/xjson_editor.tsx index 73aff739b1eef..5134df09ac93b 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/xjson_editor.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/xjson_editor.tsx @@ -28,7 +28,7 @@ export const XJsonEditor: FunctionComponent = ({ field, editorProps }) => const { xJson, setXJson, convertToJson } = useXJsonMode(value); const onChange = useCallback( - (s) => { + (s: any) => { setXJson(s); setValue(convertToJson(s)); }, diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processor_form.container.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processor_form.container.tsx index ff34c88a7179e..e6a47c52657ed 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processor_form.container.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processor_form.container.tsx @@ -74,7 +74,7 @@ export const ProcessorFormContainer: FunctionComponent = ({ }, [processor, unsavedFormState]); const formSerializer = useCallback( - (formState) => { + (formState: any) => { return { type: formState.type, fields: formState.customOptions diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processors_tree/processors_tree.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processors_tree/processors_tree.tsx index 1dd2bec158453..9e5281ea4a853 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processors_tree/processors_tree.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processors_tree/processors_tree.tsx @@ -61,7 +61,7 @@ export const ProcessorsTree: FunctionComponent = memo((props) => { onAction({ type: 'cancelMove' }); } }; - const cancelMoveClickListener = (ev: any) => { + const cancelMoveClickListener = () => { onAction({ type: 'cancelMove' }); }; // Give the browser a chance to flush any click events including the click diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/test_pipeline/test_pipeline_tabs/tab_documents/tab_documents.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/test_pipeline/test_pipeline_tabs/tab_documents/tab_documents.tsx index fc731f6be078d..6d5cc2b582e8d 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/test_pipeline/test_pipeline_tabs/tab_documents/tab_documents.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/test_pipeline/test_pipeline_tabs/tab_documents/tab_documents.tsx @@ -152,7 +152,7 @@ export const DocumentsTab: FunctionComponent = ({ const { getFormData, reset } = form; const onAddDocumentHandler = useCallback( - (document) => { + (document: any) => { const { documents: existingDocuments = [] } = getFormData(); reset({ defaultValue: { documents: [...existingDocuments, document] } }); diff --git a/x-pack/plugins/integration_assistant/__jest__/fixtures/ecs_mapping.ts b/x-pack/plugins/integration_assistant/__jest__/fixtures/ecs_mapping.ts index e0c2054a49e84..514012761e8d8 100644 --- a/x-pack/plugins/integration_assistant/__jest__/fixtures/ecs_mapping.ts +++ b/x-pack/plugins/integration_assistant/__jest__/fixtures/ecs_mapping.ts @@ -452,6 +452,8 @@ export const ecsTestState = { results: { test: 'testresults' }, samplesFormat: 'testsamplesFormat', ecsVersion: 'testversion', + chunkMapping: { test1: 'test1' }, + useFinalMapping: false, currentMapping: { test1: 'test1' }, lastExecutedChain: 'testchain', rawSamples: ['{"test1": "test1"}'], diff --git a/x-pack/plugins/integration_assistant/__jest__/fixtures/log_type_detection.ts b/x-pack/plugins/integration_assistant/__jest__/fixtures/log_type_detection.ts new file mode 100644 index 0000000000000..db570a6c181b5 --- /dev/null +++ b/x-pack/plugins/integration_assistant/__jest__/fixtures/log_type_detection.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SamplesFormatName } from '../../common/api/model/common_attributes'; + +export const logFormatDetectionTestState = { + lastExecutedChain: 'testchain', + logSamples: ['{"test1": "test1"}'], + exAnswer: 'testanswer', + packageName: 'testPackage', + dataStreamName: 'testDatastream', + finalized: false, + samplesFormat: { name: SamplesFormatName.Values.json }, + ecsVersion: 'testVersion', + results: { test1: 'test1' }, +}; diff --git a/x-pack/plugins/integration_assistant/common/api/analyze_logs/analyze_logs_route.schema.yaml b/x-pack/plugins/integration_assistant/common/api/analyze_logs/analyze_logs_route.schema.yaml new file mode 100644 index 0000000000000..944828e63f764 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/analyze_logs/analyze_logs_route.schema.yaml @@ -0,0 +1,36 @@ +openapi: 3.0.3 +info: + title: Auto Import Analyze Logs API endpoint + version: "1" +paths: + /api/integration_assistant/analyzelogs: + post: + summary: Analyzes log samples and processes them. + operationId: AnalyzeLogs + x-codegen-enabled: false + description: Analyzes log samples and processes them + tags: + - Analyze Logs API + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - logSamples + - connectorId + properties: + logSamples: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/LogSamples" + connectorId: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/Connector" + langSmithOptions: + $ref: "../model/common_attributes.schema.yaml#/components/schemas/LangSmithOptions" + responses: + 200: + description: Indicates a successful call. + content: + application/json: + schema: + $ref: "../model/response_schemas.schema.yaml#/components/schemas/AnalyzeLogsAPIResponse" diff --git a/x-pack/plugins/integration_assistant/common/api/analyze_logs/analyze_logs_route.ts b/x-pack/plugins/integration_assistant/common/api/analyze_logs/analyze_logs_route.ts new file mode 100644 index 0000000000000..d2f15525177d1 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/analyze_logs/analyze_logs_route.ts @@ -0,0 +1,31 @@ +/* + * 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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Auto Import Analyze Logs API endpoint + * version: 1 + */ + +import { z } from '@kbn/zod'; + +import { LogSamples, Connector, LangSmithOptions } from '../model/common_attributes'; +import { AnalyzeLogsAPIResponse } from '../model/response_schemas'; + +export type AnalyzeLogsRequestBody = z.infer; +export const AnalyzeLogsRequestBody = z.object({ + logSamples: LogSamples, + connectorId: Connector, + langSmithOptions: LangSmithOptions.optional(), +}); +export type AnalyzeLogsRequestBodyInput = z.input; + +export type AnalyzeLogsResponse = z.infer; +export const AnalyzeLogsResponse = AnalyzeLogsAPIResponse; diff --git a/x-pack/plugins/integration_assistant/common/api/model/common_attributes.schema.yaml b/x-pack/plugins/integration_assistant/common/api/model/common_attributes.schema.yaml index 7839a2dd3eaf7..eafd318b40c33 100644 --- a/x-pack/plugins/integration_assistant/common/api/model/common_attributes.schema.yaml +++ b/x-pack/plugins/integration_assistant/common/api/model/common_attributes.schema.yaml @@ -16,6 +16,12 @@ components: minLength: 1 description: DataStream name for the integration to be built. + LogSamples: + type: array + items: + type: string + description: String form of the input logsamples. + RawSamples: type: array items: @@ -42,6 +48,10 @@ components: enum: - ndjson - json + - csv + - structured + - unstructured + - unsupported SamplesFormat: type: object diff --git a/x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts b/x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts index 07d5323dc0969..4a82a3fd97534 100644 --- a/x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts +++ b/x-pack/plugins/integration_assistant/common/api/model/common_attributes.ts @@ -21,6 +21,12 @@ export const PackageName = z.string().min(1); export type DataStreamName = z.infer; export const DataStreamName = z.string().min(1); +/** + * String form of the input logsamples. + */ +export type LogSamples = z.infer; +export const LogSamples = z.array(z.string()); + /** * String array containing the json raw samples that are used for ecs mapping. */ @@ -49,7 +55,14 @@ export const Docs = z.array(z.object({}).passthrough()); * The name of the log samples format. */ export type SamplesFormatName = z.infer; -export const SamplesFormatName = z.enum(['ndjson', 'json']); +export const SamplesFormatName = z.enum([ + 'ndjson', + 'json', + 'csv', + 'structured', + 'unstructured', + 'unsupported', +]); export type SamplesFormatNameEnum = typeof SamplesFormatName.enum; export const SamplesFormatNameEnum = SamplesFormatName.enum; diff --git a/x-pack/plugins/integration_assistant/common/api/model/response_schemas.schema.yaml b/x-pack/plugins/integration_assistant/common/api/model/response_schemas.schema.yaml index 8afbab533a6d3..039945fb7ba0b 100644 --- a/x-pack/plugins/integration_assistant/common/api/model/response_schemas.schema.yaml +++ b/x-pack/plugins/integration_assistant/common/api/model/response_schemas.schema.yaml @@ -66,3 +66,20 @@ components: properties: docs: $ref: "./common_attributes.schema.yaml#/components/schemas/Docs" + + AnalyzeLogsAPIResponse: + type: object + required: + - results + properties: + results: + type: object + required: + - parsedSamples + properties: + samplesFormat: + $ref: "./common_attributes.schema.yaml#/components/schemas/SamplesFormat" + parsedSamples: + type: array + items: + type: string diff --git a/x-pack/plugins/integration_assistant/common/api/model/response_schemas.ts b/x-pack/plugins/integration_assistant/common/api/model/response_schemas.ts index 7341d7aa0c287..de1b23ae5e8e3 100644 --- a/x-pack/plugins/integration_assistant/common/api/model/response_schemas.ts +++ b/x-pack/plugins/integration_assistant/common/api/model/response_schemas.ts @@ -16,7 +16,7 @@ import { z } from '@kbn/zod'; -import { Docs, Mapping, Pipeline } from './common_attributes'; +import { Docs, Mapping, Pipeline, SamplesFormat } from './common_attributes'; export type EcsMappingAPIResponse = z.infer; export const EcsMappingAPIResponse = z.object({ @@ -48,3 +48,11 @@ export const CheckPipelineAPIResponse = z.object({ docs: Docs, }), }); + +export type AnalyzeLogsAPIResponse = z.infer; +export const AnalyzeLogsAPIResponse = z.object({ + results: z.object({ + samplesFormat: SamplesFormat, + parsedSamples: z.array(z.string()), + }), +}); diff --git a/x-pack/plugins/integration_assistant/common/constants.ts b/x-pack/plugins/integration_assistant/common/constants.ts index 69b383d882869..296e38c01e71c 100644 --- a/x-pack/plugins/integration_assistant/common/constants.ts +++ b/x-pack/plugins/integration_assistant/common/constants.ts @@ -18,6 +18,7 @@ export const INTEGRATION_ASSISTANT_BASE_PATH = '/api/integration_assistant'; export const ECS_GRAPH_PATH = `${INTEGRATION_ASSISTANT_BASE_PATH}/ecs`; export const CATEGORIZATION_GRAPH_PATH = `${INTEGRATION_ASSISTANT_BASE_PATH}/categorization`; +export const ANALYZE_LOGS_PATH = `${INTEGRATION_ASSISTANT_BASE_PATH}/analyzelogs`; export const RELATED_GRAPH_PATH = `${INTEGRATION_ASSISTANT_BASE_PATH}/related`; export const CHECK_PIPELINE_PATH = `${INTEGRATION_ASSISTANT_BASE_PATH}/pipeline`; export const INTEGRATION_BUILDER_PATH = `${INTEGRATION_ASSISTANT_BASE_PATH}/build`; diff --git a/x-pack/plugins/integration_assistant/common/index.ts b/x-pack/plugins/integration_assistant/common/index.ts index 6a473d976fa88..5310fa67c8cac 100644 --- a/x-pack/plugins/integration_assistant/common/index.ts +++ b/x-pack/plugins/integration_assistant/common/index.ts @@ -15,6 +15,7 @@ export { } from './api/check_pipeline/check_pipeline'; export { EcsMappingRequestBody, EcsMappingResponse } from './api/ecs/ecs_route'; export { RelatedRequestBody, RelatedResponse } from './api/related/related_route'; +export { AnalyzeLogsRequestBody, AnalyzeLogsResponse } from './api/analyze_logs/analyze_logs_route'; export type { DataStream, @@ -35,4 +36,5 @@ export { PLUGIN_ID, RELATED_GRAPH_PATH, CHECK_PIPELINE_PATH, + ANALYZE_LOGS_PATH, } from './constants'; diff --git a/x-pack/plugins/integration_assistant/public/common/lib/api.ts b/x-pack/plugins/integration_assistant/public/common/lib/api.ts index 68c93f4f51a33..ea9fba83dc094 100644 --- a/x-pack/plugins/integration_assistant/public/common/lib/api.ts +++ b/x-pack/plugins/integration_assistant/public/common/lib/api.ts @@ -16,6 +16,8 @@ import type { CheckPipelineRequestBody, CheckPipelineResponse, BuildIntegrationRequestBody, + AnalyzeLogsRequestBody, + AnalyzeLogsResponse, } from '../../../common'; import { INTEGRATION_BUILDER_PATH, @@ -24,7 +26,7 @@ import { RELATED_GRAPH_PATH, CHECK_PIPELINE_PATH, } from '../../../common'; -import { FLEET_PACKAGES_PATH } from '../../../common/constants'; +import { ANALYZE_LOGS_PATH, FLEET_PACKAGES_PATH } from '../../../common/constants'; export interface EpmPackageResponse { response: [{ id: string; name: string }]; @@ -42,6 +44,16 @@ export interface RequestDeps { abortSignal: AbortSignal; } +export const runAnalyzeLogsGraph = async ( + body: AnalyzeLogsRequestBody, + { http, abortSignal }: RequestDeps +): Promise => + http.post(ANALYZE_LOGS_PATH, { + headers: defaultHeaders, + body: JSON.stringify(body), + signal: abortSignal, + }); + export const runEcsGraph = async ( body: EcsMappingRequestBody, { http, abortSignal }: RequestDeps diff --git a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/mocks/state.ts b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/mocks/state.ts index aa310f034290c..c842d097fa7c3 100644 --- a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/mocks/state.ts +++ b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/mocks/state.ts @@ -5,11 +5,11 @@ * 2.0. */ -import type { Pipeline, Docs } from '../../../../../common'; +import type { Pipeline, Docs, SamplesFormat } from '../../../../../common'; import type { Actions, State } from '../state'; import type { AIConnector } from '../types'; -const result: { pipeline: Pipeline; docs: Docs } = { +const result: { pipeline: Pipeline; docs: Docs; samplesFormat: SamplesFormat } = { pipeline: { description: 'Pipeline to process my_integration my_data_stream_title logs', processors: [ @@ -389,6 +389,7 @@ const result: { pipeline: Pipeline; docs: Docs } = { ], }, ], + samplesFormat: { name: 'json' }, }; const rawSamples = [ @@ -419,8 +420,7 @@ export const mockState: State = { dataStreamName: 'mocked_datastream_name', dataStreamDescription: 'Mocked Data Stream Description', inputTypes: ['filestream'], - logsSampleParsed: rawSamples, - samplesFormat: { name: 'ndjson', multiline: false }, + logSamples: rawSamples, }, isGenerating: false, result, diff --git a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/state.ts b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/state.ts index 161d1b0646541..bef5b35624df4 100644 --- a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/state.ts +++ b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/state.ts @@ -5,7 +5,7 @@ * 2.0. */ import { createContext, useContext } from 'react'; -import type { Pipeline, Docs } from '../../../../common'; +import type { Pipeline, Docs, SamplesFormat } from '../../../../common'; import type { AIConnector, IntegrationSettings } from './types'; export interface State { @@ -16,6 +16,7 @@ export interface State { result?: { pipeline: Pipeline; docs: Docs; + samplesFormat?: SamplesFormat; }; } diff --git a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/generation_modal.test.tsx b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/generation_modal.test.tsx index 1c1cf3c881cdf..4d0f6eee1c407 100644 --- a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/generation_modal.test.tsx +++ b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/generation_modal.test.tsx @@ -17,9 +17,14 @@ import { TelemetryEventType } from '../../../../../services/telemetry/types'; const integrationSettings = mockState.integrationSettings!; const connector = mockState.connector!; +const mockAnalyzeLogsResults = { + parsedSamples: [{ test: 'analyzeLogsResponse' }], + sampleLogsFormat: { name: 'json' }, +}; const mockEcsMappingResults = { pipeline: { test: 'ecsMappingResponse' }, docs: [] }; const mockCategorizationResults = { pipeline: { test: 'categorizationResponse' }, docs: [] }; const mockRelatedResults = { pipeline: { test: 'relatedResponse' }, docs: [] }; +const mockRunAnalyzeLogsGraph = jest.fn((_: unknown) => ({ results: mockAnalyzeLogsResults })); const mockRunEcsGraph = jest.fn((_: unknown) => ({ results: mockEcsMappingResults })); const mockRunCategorizationGraph = jest.fn((_: unknown) => ({ results: mockCategorizationResults, @@ -27,13 +32,12 @@ const mockRunCategorizationGraph = jest.fn((_: unknown) => ({ const mockRunRelatedGraph = jest.fn((_: unknown) => ({ results: mockRelatedResults })); const defaultRequest = { - packageName: integrationSettings.name ?? '', - dataStreamName: integrationSettings.dataStreamName ?? '', - rawSamples: integrationSettings.logsSampleParsed ?? [], connectorId: connector.id, + LangSmithOptions: undefined, }; jest.mock('../../../../../common/lib/api', () => ({ + runAnalyzeLogsGraph: (params: unknown) => mockRunAnalyzeLogsGraph(params), runEcsGraph: (params: unknown) => mockRunEcsGraph(params), runCategorizationGraph: (params: unknown) => mockRunCategorizationGraph(params), runRelatedGraph: (params: unknown) => mockRunRelatedGraph(params), @@ -74,14 +78,29 @@ describe('GenerationModal', () => { expect(result.queryByTestId('generationModal')).toBeInTheDocument(); }); + it('should call runAnalyzeLogsGraph with correct parameters', () => { + expect(mockRunAnalyzeLogsGraph).toHaveBeenCalledWith({ + ...defaultRequest, + logSamples: integrationSettings.logSamples ?? [], + }); + }); + it('should call runEcsGraph with correct parameters', () => { - expect(mockRunEcsGraph).toHaveBeenCalledWith(defaultRequest); + expect(mockRunEcsGraph).toHaveBeenCalledWith({ + ...defaultRequest, + rawSamples: mockAnalyzeLogsResults.parsedSamples, + packageName: integrationSettings.name ?? '', + dataStreamName: integrationSettings.dataStreamName ?? '', + }); }); it('should call runCategorizationGraph with correct parameters', () => { expect(mockRunCategorizationGraph).toHaveBeenCalledWith({ ...defaultRequest, currentPipeline: mockEcsMappingResults.pipeline, + rawSamples: mockAnalyzeLogsResults.parsedSamples, + packageName: integrationSettings.name ?? '', + dataStreamName: integrationSettings.dataStreamName ?? '', }); }); @@ -89,6 +108,9 @@ describe('GenerationModal', () => { expect(mockRunRelatedGraph).toHaveBeenCalledWith({ ...defaultRequest, currentPipeline: mockCategorizationResults.pipeline, + rawSamples: mockAnalyzeLogsResults.parsedSamples, + packageName: integrationSettings.name ?? '', + dataStreamName: integrationSettings.dataStreamName ?? '', }); }); @@ -101,7 +123,7 @@ describe('GenerationModal', () => { TelemetryEventType.IntegrationAssistantGenerationComplete, { sessionId: expect.any(String), - sampleRows: integrationSettings.logsSampleParsed?.length ?? 0, + sampleRows: integrationSettings.logSamples?.length ?? 0, actionTypeId: connector.actionTypeId, model: expect.anything(), provider: connector.apiProvider ?? 'unknown', @@ -147,7 +169,7 @@ describe('GenerationModal', () => { TelemetryEventType.IntegrationAssistantGenerationComplete, { sessionId: expect.any(String), - sampleRows: integrationSettings.logsSampleParsed?.length ?? 0, + sampleRows: integrationSettings.logSamples?.length ?? 0, actionTypeId: connector.actionTypeId, model: expect.anything(), provider: connector.apiProvider ?? 'unknown', diff --git a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/generation_modal.tsx b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/generation_modal.tsx index b83c5315bd619..f25423390fb6d 100644 --- a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/generation_modal.tsx +++ b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/generation_modal.tsx @@ -25,15 +25,17 @@ import { isEmpty } from 'lodash/fp'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { css } from '@emotion/react'; import { getLangSmithOptions } from '../../../../../common/lib/lang_smith'; -import type { - CategorizationRequestBody, - EcsMappingRequestBody, - RelatedRequestBody, +import { + type AnalyzeLogsRequestBody, + type CategorizationRequestBody, + type EcsMappingRequestBody, + type RelatedRequestBody, } from '../../../../../../common'; import { runCategorizationGraph, runEcsGraph, runRelatedGraph, + runAnalyzeLogsGraph, } from '../../../../../common/lib/api'; import { useKibana } from '../../../../../common/hooks/use_kibana'; import type { State } from '../../state'; @@ -46,6 +48,7 @@ const ProgressOrder = ['ecs', 'categorization', 'related']; type ProgressItem = (typeof ProgressOrder)[number]; const progressText: Record = { + analyzeLogs: i18n.PROGRESS_ANALYZE_LOGS, ecs: i18n.PROGRESS_ECS_MAPPING, categorization: i18n.PROGRESS_CATEGORIZATION, related: i18n.PROGRESS_RELATED_GRAPH, @@ -83,10 +86,31 @@ export const useGeneration = ({ (async () => { try { + let logSamples = integrationSettings.logSamples; + let samplesFormat = integrationSettings.samplesFormat; + + if (integrationSettings.samplesFormat === undefined) { + const analyzeLogsRequest: AnalyzeLogsRequestBody = { + logSamples: integrationSettings.logSamples ?? [], + connectorId: connector.id, + langSmithOptions: getLangSmithOptions(), + }; + + setProgress('analyzeLogs'); + const analyzeLogsResult = await runAnalyzeLogsGraph(analyzeLogsRequest, deps); + if (abortController.signal.aborted) return; + if (isEmpty(analyzeLogsResult?.results)) { + setError('No results from Analyze Logs Graph'); + return; + } + logSamples = analyzeLogsResult.results.parsedSamples; + samplesFormat = analyzeLogsResult.results.samplesFormat; + } + const ecsRequest: EcsMappingRequestBody = { packageName: integrationSettings.name ?? '', dataStreamName: integrationSettings.dataStreamName ?? '', - rawSamples: integrationSettings.logsSampleParsed ?? [], + rawSamples: logSamples ?? [], connectorId: connector.id, langSmithOptions: getLangSmithOptions(), }; @@ -125,7 +149,13 @@ export const useGeneration = ({ durationMs: Date.now() - generationStartedAt, }); - onComplete(relatedGraphResult.results); + const result = { + pipeline: relatedGraphResult.results.pipeline, + docs: relatedGraphResult.results.docs, + samplesFormat, + }; + + onComplete(result); } catch (e) { if (abortController.signal.aborted) return; const errorMessage = `${e.message}${ diff --git a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/is_step_ready.ts b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/is_step_ready.ts index 43e0006275fa9..4a40334a72ab2 100644 --- a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/is_step_ready.ts +++ b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/is_step_ready.ts @@ -12,5 +12,5 @@ export const isDataStreamStepReady = ({ integrationSettings }: State) => integrationSettings?.dataStreamTitle && integrationSettings?.dataStreamDescription && integrationSettings?.dataStreamName && - integrationSettings?.logsSampleParsed + integrationSettings?.logSamples ); diff --git a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/sample_logs_input.test.tsx b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/sample_logs_input.test.tsx index 4c15aa8a4785c..2d994f9030764 100644 --- a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/sample_logs_input.test.tsx +++ b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/sample_logs_input.test.tsx @@ -161,7 +161,7 @@ describe('SampleLogsInput', () => { it('should set the integrationSetting correctly', () => { expect(mockActions.setIntegrationSettings).toBeCalledWith({ - logsSampleParsed: logsSampleRaw.split(','), + logSamples: logsSampleRaw.split(','), samplesFormat: { name: 'json', json_path: [] }, }); }); @@ -174,7 +174,7 @@ describe('SampleLogsInput', () => { it('should truncate the logs sample', () => { expect(mockActions.setIntegrationSettings).toBeCalledWith({ - logsSampleParsed: tooLargeLogsSample.split(',').slice(0, 10), + logSamples: tooLargeLogsSample.split(',').slice(0, 10), samplesFormat: { name: 'json', json_path: [] }, }); }); @@ -193,7 +193,7 @@ describe('SampleLogsInput', () => { it('should set the integrationSetting correctly', () => { expect(mockActions.setIntegrationSettings).toBeCalledWith({ - logsSampleParsed: splitNDJSON, + logSamples: splitNDJSON, samplesFormat: { name: 'json', json_path: ['events'] }, }); }); @@ -201,10 +201,6 @@ describe('SampleLogsInput', () => { describe('when the file is invalid', () => { describe.each([ - [ - '[{"message":"test message 1"}', - 'Cannot parse the logs sample file as either a JSON or NDJSON file', - ], ['["test message 1"]', 'The logs sample file contains non-object entries'], ['[]', 'The logs sample file is empty'], ])('with logs content %s', (logsSample, errorMessage) => { @@ -218,7 +214,7 @@ describe('SampleLogsInput', () => { it('should set the integrationSetting correctly', () => { expect(mockActions.setIntegrationSettings).toBeCalledWith({ - logsSampleParsed: undefined, + logSamples: undefined, samplesFormat: undefined, }); }); @@ -236,7 +232,7 @@ describe('SampleLogsInput', () => { it('should set the integrationSetting correctly', () => { expect(mockActions.setIntegrationSettings).toBeCalledWith({ - logsSampleParsed: splitNDJSON, + logSamples: splitNDJSON, samplesFormat: { name: 'ndjson', multiline: false }, }); }); @@ -249,7 +245,7 @@ describe('SampleLogsInput', () => { it('should truncate the logs sample', () => { expect(mockActions.setIntegrationSettings).toBeCalledWith({ - logsSampleParsed: tooLargeLogsSample.split('\n').slice(0, 10), + logSamples: tooLargeLogsSample.split('\n').slice(0, 10), samplesFormat: { name: 'ndjson', multiline: false }, }); }); @@ -268,7 +264,7 @@ describe('SampleLogsInput', () => { it('should set the integrationSetting correctly', () => { expect(mockActions.setIntegrationSettings).toBeCalledWith({ - logsSampleParsed: [splitNDJSON[0]], + logSamples: [splitNDJSON[0]], samplesFormat: { name: 'ndjson', multiline: false }, }); }); @@ -281,7 +277,7 @@ describe('SampleLogsInput', () => { it('should set the integrationSetting correctly', () => { expect(mockActions.setIntegrationSettings).toBeCalledWith({ - logsSampleParsed: splitNDJSON, + logSamples: splitNDJSON, samplesFormat: { name: 'ndjson', multiline: true }, }); }); @@ -289,10 +285,6 @@ describe('SampleLogsInput', () => { describe('when the file is invalid', () => { describe.each([ - [ - '{"message":"test message 1"}\n{"message": }', - 'Cannot parse the logs sample file as either a JSON or NDJSON file', - ], ['"test message 1"', 'The logs sample file contains non-object entries'], ['', 'The logs sample file is empty'], ])('with logs content %s', (logsSample, errorMessage) => { @@ -306,7 +298,7 @@ describe('SampleLogsInput', () => { it('should set the integrationSetting correctly', () => { expect(mockActions.setIntegrationSettings).toBeCalledWith({ - logsSampleParsed: undefined, + logSamples: undefined, samplesFormat: undefined, }); }); diff --git a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/sample_logs_input.tsx b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/sample_logs_input.tsx index fd9c2e3f8c362..51ad4543bb30a 100644 --- a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/sample_logs_input.tsx +++ b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/sample_logs_input.tsx @@ -7,8 +7,8 @@ import React, { useCallback, useState } from 'react'; import { EuiCallOut, EuiFilePicker, EuiFormRow, EuiSpacer, EuiText } from '@elastic/eui'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; import { isPlainObject } from 'lodash/fp'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; import type { IntegrationSettings } from '../../types'; import * as i18n from './translations'; import { useActions } from '../../state'; @@ -68,16 +68,12 @@ export const parseJSONArray = ( * Parse the logs sample file content (json or ndjson) and return the parsed logs sample */ const parseLogsContent = ( - fileContent: string | undefined + fileContent: string ): { error?: string; - isTruncated?: boolean; - logsSampleParsed?: string[]; + logSamples: string[]; samplesFormat?: SamplesFormat; } => { - if (fileContent == null) { - return { error: i18n.LOGS_SAMPLE_ERROR.CAN_NOT_READ }; - } let parsedContent: unknown[]; let samplesFormat: SamplesFormat; @@ -97,7 +93,7 @@ const parseLogsContent = ( try { const { entries, pathToEntries, errorNoArrayFound } = parseJSONArray(fileContent); if (errorNoArrayFound) { - return { error: i18n.LOGS_SAMPLE_ERROR.NOT_ARRAY }; + return { error: i18n.LOGS_SAMPLE_ERROR.NOT_ARRAY, logSamples: [] }; } parsedContent = entries; samplesFormat = { name: 'json', json_path: pathToEntries }; @@ -106,32 +102,29 @@ const parseLogsContent = ( parsedContent = parseNDJSON(fileContent, true); samplesFormat = { name: 'ndjson', multiline: true }; } catch (parseMultilineNDJSONError) { - return { error: i18n.LOGS_SAMPLE_ERROR.CAN_NOT_PARSE }; + return { + logSamples: fileContent.split('\n').filter((line) => line.trim() !== ''), + }; } } } if (parsedContent.length === 0) { - return { error: i18n.LOGS_SAMPLE_ERROR.EMPTY }; - } - - let isTruncated = false; - if (parsedContent.length > MaxLogsSampleRows) { - parsedContent = parsedContent.slice(0, MaxLogsSampleRows); - isTruncated = true; + return { error: i18n.LOGS_SAMPLE_ERROR.EMPTY, logSamples: [] }; } if (parsedContent.some((log) => !isPlainObject(log))) { - return { error: i18n.LOGS_SAMPLE_ERROR.NOT_OBJECT }; + return { error: i18n.LOGS_SAMPLE_ERROR.NOT_OBJECT, logSamples: [] }; } - const logsSampleParsed = parsedContent.map((log) => JSON.stringify(log)); - return { isTruncated, logsSampleParsed, samplesFormat }; + const logSamples = parsedContent.map((log) => JSON.stringify(log)); + return { logSamples, samplesFormat }; }; interface SampleLogsInputProps { integrationSettings: IntegrationSettings | undefined; } + export const SampleLogsInput = React.memo(({ integrationSettings }) => { const { notifications } = useKibana().services; const { setIntegrationSettings } = useActions(); @@ -145,7 +138,7 @@ export const SampleLogsInput = React.memo(({ integrationSe setSampleFileError(undefined); setIntegrationSettings({ ...integrationSettings, - logsSampleParsed: undefined, + logSamples: undefined, samplesFormat: undefined, }); return; @@ -154,26 +147,32 @@ export const SampleLogsInput = React.memo(({ integrationSe const reader = new FileReader(); reader.onload = function (e) { const fileContent = e.target?.result as string | undefined; // We can safely cast to string since we call `readAsText` to load the file. - const { error, isTruncated, logsSampleParsed, samplesFormat } = - parseLogsContent(fileContent); + if (fileContent == null) { + return { error: i18n.LOGS_SAMPLE_ERROR.CAN_NOT_READ }; + } + let samples; + const { error, logSamples, samplesFormat } = parseLogsContent(fileContent); setIsParsing(false); - setSampleFileError(error); + samples = logSamples; + if (error) { + setSampleFileError(error); setIntegrationSettings({ ...integrationSettings, - logsSampleParsed: undefined, + logSamples: undefined, samplesFormat: undefined, }); return; } - if (isTruncated) { + if (samples.length > MaxLogsSampleRows) { + samples = samples.slice(0, MaxLogsSampleRows); notifications?.toasts.addInfo(i18n.LOGS_SAMPLE_TRUNCATED(MaxLogsSampleRows)); } setIntegrationSettings({ ...integrationSettings, - logsSampleParsed, + logSamples: samples, samplesFormat, }); }; diff --git a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/translations.ts b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/translations.ts index 0af9f803f71fc..bbc7000073f52 100644 --- a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/translations.ts +++ b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/data_stream_step/translations.ts @@ -149,6 +149,12 @@ export const LOGS_SAMPLE_ERROR = { export const ANALYZING = i18n.translate('xpack.integrationAssistant.step.dataStream.analyzing', { defaultMessage: 'Analyzing', }); +export const PROGRESS_ANALYZE_LOGS = i18n.translate( + 'xpack.integrationAssistant.step.dataStream.progress.analyzeLogs', + { + defaultMessage: 'Analyzing Sample logs', + } +); export const PROGRESS_ECS_MAPPING = i18n.translate( 'xpack.integrationAssistant.step.dataStream.progress.ecsMapping', { diff --git a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/deploy_step/deploy_step.test.tsx b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/deploy_step/deploy_step.test.tsx index d4920ba927d20..1a35c9e4f02c9 100644 --- a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/deploy_step/deploy_step.test.tsx +++ b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/deploy_step/deploy_step.test.tsx @@ -31,10 +31,10 @@ const parameters: BuildIntegrationRequestBody = { description: integrationSettings.dataStreamDescription!, name: integrationSettings.dataStreamName!, inputTypes: integrationSettings.inputTypes!, - rawSamples: integrationSettings.logsSampleParsed!, + rawSamples: integrationSettings.logSamples!, docs: results.docs!, pipeline: results.pipeline, - samplesFormat: integrationSettings.samplesFormat!, + samplesFormat: results.samplesFormat!, }, ], }, diff --git a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/deploy_step/use_deploy_integration.ts b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/deploy_step/use_deploy_integration.ts index c1451a9d81a9d..5ec27b4e6de65 100644 --- a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/deploy_step/use_deploy_integration.ts +++ b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/deploy_step/use_deploy_integration.ts @@ -37,7 +37,8 @@ export const useDeployIntegration = ({ connector == null || integrationSettings == null || notifications?.toasts == null || - result?.pipeline == null + result?.pipeline == null || + result?.samplesFormat == null ) { return; } @@ -46,12 +47,6 @@ export const useDeployIntegration = ({ (async () => { try { - if (integrationSettings.samplesFormat == null) { - throw new Error( - 'Logic error: samplesFormat is required and cannot be null or undefined when creating integration.' - ); - } - const parameters: BuildIntegrationRequestBody = { integration: { title: integrationSettings.title ?? '', @@ -64,10 +59,10 @@ export const useDeployIntegration = ({ description: integrationSettings.dataStreamDescription ?? '', name: integrationSettings.dataStreamName ?? '', inputTypes: integrationSettings.inputTypes ?? [], - rawSamples: integrationSettings.logsSampleParsed ?? [], + rawSamples: integrationSettings.logSamples ?? [], docs: result.docs ?? [], + samplesFormat: result.samplesFormat ?? { name: 'json' }, pipeline: result.pipeline, - samplesFormat: integrationSettings.samplesFormat, }, ], }, @@ -123,6 +118,7 @@ export const useDeployIntegration = ({ notifications?.toasts, result?.docs, result?.pipeline, + result?.samplesFormat, telemetry, ]); diff --git a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/review_step/review_step.test.tsx b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/review_step/review_step.test.tsx index 2c8fd73f16998..8a9da9295a8f0 100644 --- a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/review_step/review_step.test.tsx +++ b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/review_step/review_step.test.tsx @@ -25,7 +25,7 @@ const customPipeline = { }; const defaultRequest = { pipeline: customPipeline, - rawSamples: integrationSettings.logsSampleParsed!, + rawSamples: integrationSettings.logSamples!, }; const mockRunCheckPipelineResults = jest.fn((_: unknown) => ({ results: mockResults })); jest.mock('../../../../../common/lib/api', () => ({ diff --git a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/review_step/use_check_pipeline.ts b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/review_step/use_check_pipeline.ts index 953b8c442abb0..a166e7c73fcc3 100644 --- a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/review_step/use_check_pipeline.ts +++ b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/steps/review_step/use_check_pipeline.ts @@ -38,7 +38,7 @@ export const useCheckPipeline = ({ integrationSettings, customPipeline }: CheckP try { const parameters: CheckPipelineRequestBody = { pipeline: customPipeline, - rawSamples: integrationSettings.logsSampleParsed ?? [], + rawSamples: integrationSettings.logSamples ?? [], }; setIsGenerating(true); diff --git a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/types.ts b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/types.ts index c924415ec53e1..6ba7b2945b7a8 100644 --- a/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/types.ts +++ b/x-pack/plugins/integration_assistant/public/components/create_integration/create_integration_assistant/types.ts @@ -33,6 +33,6 @@ export interface IntegrationSettings { dataStreamDescription?: string; dataStreamName?: string; inputTypes?: InputType[]; - logsSampleParsed?: string[]; + logSamples?: string[]; samplesFormat?: SamplesFormat; } diff --git a/x-pack/plugins/integration_assistant/public/components/create_integration/telemetry.tsx b/x-pack/plugins/integration_assistant/public/components/create_integration/telemetry.tsx index 54988e238bd4d..f4dd6d7d436be 100644 --- a/x-pack/plugins/integration_assistant/public/components/create_integration/telemetry.tsx +++ b/x-pack/plugins/integration_assistant/public/components/create_integration/telemetry.tsx @@ -102,7 +102,7 @@ export const TelemetryContextProvider = React.memo>(({ chi ({ connector, integrationSettings, durationMs, error }) => { telemetry.reportEvent(TelemetryEventType.IntegrationAssistantGenerationComplete, { sessionId: sessionData.current.sessionId, - sampleRows: integrationSettings?.logsSampleParsed?.length ?? 0, + sampleRows: integrationSettings?.logSamples?.length ?? 0, actionTypeId: connector.actionTypeId, model: getConnectorModel(connector), provider: connector.apiProvider ?? 'unknown', diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/duplicates.test.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/duplicates.test.ts index f3a51c80a5241..346947cd1a38a 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/duplicates.test.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/duplicates.test.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { FakeLLM } from '@langchain/core/utils/testing'; -import { handleDuplicates } from './duplicates'; -import type { EcsMappingState } from '../../types'; -import { ecsTestState } from '../../../__jest__/fixtures/ecs_mapping'; import { ActionsClientChatOpenAI, ActionsClientSimpleChatModel, } from '@kbn/langchain/server/language_models'; +import { FakeLLM } from '@langchain/core/utils/testing'; +import { ecsTestState } from '../../../__jest__/fixtures/ecs_mapping'; +import type { EcsMappingState } from '../../types'; +import { handleDuplicates } from './duplicates'; const model = new FakeLLM({ response: '{ "message": "ll callback later."}', diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/duplicates.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/duplicates.ts index 5c66168fc0bfe..2d59bd1c241d5 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/duplicates.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/duplicates.ts @@ -6,9 +6,9 @@ */ import { JsonOutputParser } from '@langchain/core/output_parsers'; -import type { EcsNodeParams } from './types'; import type { EcsMappingState } from '../../types'; import { ECS_DUPLICATES_PROMPT } from './prompts'; +import type { EcsNodeParams } from './types'; export async function handleDuplicates({ state, @@ -16,13 +16,18 @@ export async function handleDuplicates({ }: EcsNodeParams): Promise> { const outputParser = new JsonOutputParser(); const ecsDuplicatesGraph = ECS_DUPLICATES_PROMPT.pipe(model).pipe(outputParser); + const usesFinalMapping = state?.useFinalMapping; + const mapping = usesFinalMapping ? state.finalMapping : state.currentMapping; - const currentMapping = await ecsDuplicatesGraph.invoke({ + const result = await ecsDuplicatesGraph.invoke({ ecs: state.ecs, - current_mapping: JSON.stringify(state.currentMapping, null, 2), + current_mapping: JSON.stringify(mapping, null, 2), ex_answer: state.exAnswer, duplicate_fields: state.duplicateFields, }); - return { currentMapping, lastExecutedChain: 'duplicateFields' }; + return { + [usesFinalMapping ? 'finalMapping' : 'currentMapping']: result, + lastExecutedChain: 'duplicateFields', + }; } diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/graph.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/graph.ts index 86b0561a22e44..f9bc489607628 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/graph.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/graph.ts @@ -5,16 +5,16 @@ * 2.0. */ -import { END, START, StateGraph, Send } from '@langchain/langgraph'; +import { END, Send, START, StateGraph } from '@langchain/langgraph'; import type { EcsMappingState } from '../../types'; -import type { EcsGraphParams, EcsBaseNodeParams } from './types'; -import { modelInput, modelOutput, modelSubOutput } from './model'; import { handleDuplicates } from './duplicates'; import { handleInvalidEcs } from './invalid'; import { handleEcsMapping } from './mapping'; import { handleMissingKeys } from './missing'; -import { handleValidateMappings } from './validate'; +import { modelInput, modelMergedInputFromSubGraph, modelOutput, modelSubOutput } from './model'; import { graphState } from './state'; +import type { EcsBaseNodeParams, EcsGraphParams } from './types'; +import { handleValidateMappings } from './validate'; const handleCreateMappingChunks = async ({ state }: EcsBaseNodeParams) => { // Cherrypick a shallow copy of state to pass to subgraph @@ -44,7 +44,7 @@ function chainRouter({ state }: EcsBaseNodeParams): string { return 'invalidEcsFields'; } if (!state.finalized) { - return 'modelSubOutput'; + return 'modelOutput'; } return END; } @@ -69,7 +69,7 @@ async function getEcsSubGraph({ model }: EcsGraphParams) { duplicateFields: 'handleDuplicates', missingKeys: 'handleMissingKeys', invalidEcsFields: 'handleInvalidEcs', - modelSubOutput: 'modelSubOutput', + modelOutput: 'modelSubOutput', }) .addEdge('modelSubOutput', END); @@ -85,12 +85,29 @@ export async function getEcsGraph({ model }: EcsGraphParams) { }) .addNode('modelInput', (state: EcsMappingState) => modelInput({ state })) .addNode('modelOutput', (state: EcsMappingState) => modelOutput({ state })) + .addNode('handleValidation', (state: EcsMappingState) => handleValidateMappings({ state })) + .addNode('handleDuplicates', (state: EcsMappingState) => handleDuplicates({ state, model })) + .addNode('handleMissingKeys', (state: EcsMappingState) => handleMissingKeys({ state, model })) + .addNode('handleInvalidEcs', (state: EcsMappingState) => handleInvalidEcs({ state, model })) + .addNode('handleMergedSubGraphResponse', (state: EcsMappingState) => + modelMergedInputFromSubGraph({ state }) + ) .addNode('subGraph', subGraph) .addEdge(START, 'modelInput') - .addEdge('subGraph', 'modelOutput') + .addEdge('subGraph', 'handleMergedSubGraphResponse') + .addEdge('handleDuplicates', 'handleValidation') + .addEdge('handleMissingKeys', 'handleValidation') + .addEdge('handleInvalidEcs', 'handleValidation') + .addEdge('handleMergedSubGraphResponse', 'handleValidation') .addConditionalEdges('modelInput', (state: EcsMappingState) => handleCreateMappingChunks({ state }) ) + .addConditionalEdges('handleValidation', (state: EcsMappingState) => chainRouter({ state }), { + duplicateFields: 'handleDuplicates', + missingKeys: 'handleMissingKeys', + invalidEcsFields: 'handleInvalidEcs', + modelOutput: 'modelOutput', + }) .addEdge('modelOutput', END); const compiledEcsGraph = workflow.compile(); diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/invalid.test.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/invalid.test.ts index ad10aa5b030df..0986452d171a2 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/invalid.test.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/invalid.test.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { FakeLLM } from '@langchain/core/utils/testing'; -import { handleInvalidEcs } from './invalid'; -import type { EcsMappingState } from '../../types'; -import { ecsTestState } from '../../../__jest__/fixtures/ecs_mapping'; import { ActionsClientChatOpenAI, ActionsClientSimpleChatModel, } from '@kbn/langchain/server/language_models'; +import { FakeLLM } from '@langchain/core/utils/testing'; +import { ecsTestState } from '../../../__jest__/fixtures/ecs_mapping'; +import type { EcsMappingState } from '../../types'; +import { handleInvalidEcs } from './invalid'; const model = new FakeLLM({ response: '{ "message": "ll callback later."}', diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/invalid.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/invalid.ts index 4b050fac3ccf4..5440b5bc9b125 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/invalid.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/invalid.ts @@ -5,9 +5,9 @@ * 2.0. */ import { JsonOutputParser } from '@langchain/core/output_parsers'; -import type { EcsNodeParams } from './types'; import type { EcsMappingState } from '../../types'; import { ECS_INVALID_PROMPT } from './prompts'; +import type { EcsNodeParams } from './types'; export async function handleInvalidEcs({ state, @@ -15,14 +15,19 @@ export async function handleInvalidEcs({ }: EcsNodeParams): Promise> { const outputParser = new JsonOutputParser(); const ecsInvalidEcsGraph = ECS_INVALID_PROMPT.pipe(model).pipe(outputParser); + const usesFinalMapping = state?.useFinalMapping; + const mapping = usesFinalMapping ? state.finalMapping : state.currentMapping; - const currentMapping = await ecsInvalidEcsGraph.invoke({ + const result = await ecsInvalidEcsGraph.invoke({ ecs: state.ecs, - current_mapping: JSON.stringify(state.currentMapping, null, 2), + current_mapping: JSON.stringify(mapping, null, 2), ex_answer: state.exAnswer, combined_samples: state.combinedSamples, invalid_ecs_fields: state.invalidEcsFields, }); - return { currentMapping, lastExecutedChain: 'invalidEcs' }; + return { + [usesFinalMapping ? 'finalMapping' : 'currentMapping']: result, + lastExecutedChain: 'invalidEcs', + }; } diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/mapping.test.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/mapping.test.ts index 92954b83863bf..3e8bf31fc1ebb 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/mapping.test.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/mapping.test.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { FakeLLM } from '@langchain/core/utils/testing'; -import { handleEcsMapping } from './mapping'; -import type { EcsMappingState } from '../../types'; -import { ecsTestState } from '../../../__jest__/fixtures/ecs_mapping'; import { ActionsClientChatOpenAI, ActionsClientSimpleChatModel, } from '@kbn/langchain/server/language_models'; +import { FakeLLM } from '@langchain/core/utils/testing'; +import { ecsTestState } from '../../../__jest__/fixtures/ecs_mapping'; +import type { EcsMappingState } from '../../types'; +import { handleEcsMapping } from './mapping'; const model = new FakeLLM({ response: '{ "message": "ll callback later."}', diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/missing.test.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/missing.test.ts index 35fbc51bbb2e7..dc24226e54421 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/missing.test.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/missing.test.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { FakeLLM } from '@langchain/core/utils/testing'; -import { handleMissingKeys } from './missing'; -import type { EcsMappingState } from '../../types'; -import { ecsTestState } from '../../../__jest__/fixtures/ecs_mapping'; import { ActionsClientChatOpenAI, ActionsClientSimpleChatModel, } from '@kbn/langchain/server/language_models'; +import { FakeLLM } from '@langchain/core/utils/testing'; +import { ecsTestState } from '../../../__jest__/fixtures/ecs_mapping'; +import type { EcsMappingState } from '../../types'; +import { handleMissingKeys } from './missing'; const model = new FakeLLM({ response: '{ "message": "ll callback later."}', diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/missing.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/missing.ts index 649c9a5d1facf..0c22af98a41bc 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/missing.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/missing.ts @@ -6,9 +6,9 @@ */ import { JsonOutputParser } from '@langchain/core/output_parsers'; -import { EcsNodeParams } from './types'; import { EcsMappingState } from '../../types'; import { ECS_MISSING_KEYS_PROMPT } from './prompts'; +import { EcsNodeParams } from './types'; export async function handleMissingKeys({ state, @@ -16,14 +16,19 @@ export async function handleMissingKeys({ }: EcsNodeParams): Promise> { const outputParser = new JsonOutputParser(); const ecsMissingGraph = ECS_MISSING_KEYS_PROMPT.pipe(model).pipe(outputParser); + const usesFinalMapping = state?.useFinalMapping; + const mapping = usesFinalMapping ? state.finalMapping : state.currentMapping; - const currentMapping = await ecsMissingGraph.invoke({ + const result = await ecsMissingGraph.invoke({ ecs: state.ecs, - current_mapping: JSON.stringify(state.currentMapping, null, 2), + current_mapping: JSON.stringify(mapping, null, 2), ex_answer: state.exAnswer, combined_samples: state.combinedSamples, missing_keys: state?.missingKeys, }); - return { currentMapping, lastExecutedChain: 'missingKeys' }; + return { + [usesFinalMapping ? 'finalMapping' : 'currentMapping']: result, + lastExecutedChain: 'missingKeys', + }; } diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/model.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/model.ts index 44508bca4ff1a..67dbc747152f5 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/model.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/model.ts @@ -4,17 +4,27 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import type { EcsMappingState } from '../../types'; import { prefixSamples } from '../../util/samples'; +import { mergeAndChunkSamples } from './chunk'; import { ECS_EXAMPLE_ANSWER, ECS_FIELDS } from './constants'; import { createPipeline } from './pipeline'; -import { mergeAndChunkSamples } from './chunk'; -import type { EcsMappingState } from '../../types'; import type { EcsBaseNodeParams } from './types'; export function modelSubOutput({ state }: EcsBaseNodeParams): Partial { return { - lastExecutedChain: 'ModelSubOutput', - finalMapping: state.currentMapping, + lastExecutedChain: 'modelSubOutput', + chunkMapping: state.currentMapping, + }; +} + +export function modelMergedInputFromSubGraph({ + state, +}: EcsBaseNodeParams): Partial { + return { + lastExecutedChain: 'modelMergedInputFromSubGraph', + useFinalMapping: true, + finalMapping: state.chunkMapping, }; } diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/pipeline.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/pipeline.ts index 35c1fb4d31f42..7a13572169540 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/pipeline.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/pipeline.ts @@ -163,7 +163,7 @@ function generateProcessors(ecsMapping: object, samples: object, basePath: strin export function createPipeline(state: EcsMappingState): IngestPipeline { const samples = JSON.parse(state.combinedSamples); - const processors = generateProcessors(state.currentMapping, samples); + const processors = generateProcessors(state.finalMapping, samples); // Retrieve all source field names from convert processors to populate single remove processor: const fieldsToRemove = processors .map((p: any) => p.convert?.field) diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/prompts.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/prompts.ts index 4e5e4794d5b8f..5df21295c8e29 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/prompts.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/prompts.ts @@ -166,10 +166,17 @@ Here is some context for you to reference for your task, read it carefully as yo {duplicate_fields} - + +Go through each ECS field in the above list of duplicate fields step by step and and modify the current mapping following this process: +1. For each duplicate ECS field there is 2 or more source fields that has target set to the same ECS field, identify which of these it is. +2. For each of the source fields that has the same target set, choose only one of them to have the target set to the ECS field, for the rest you should either find another matching ECS field or set the source to be null. +3. Make sure that all of the ECS fields mentioned in the duplicate fields above have been resolved and return the updated current mapping object. + To resolve the duplicate mappings, go through each key and value defined in the duplicate fields, and modify the current mapping step by step, and ensure they follow these guidelines: -- Multiple keys should not have the same value (ECS field it will be mapped to). If multiple keys do have the same value then always choose the best match for the ECS field, while the other duplicates should have their value changed to null. +- Only focus on ECS fields reported as duplicate fields, do not modify any other fields. +- For all fields that are marked duplicate, when the best target is choosen, remember to set the value of the source field to null. +- The value "target" should not have a null value, but rather the source object itself should be set to null, use the existing current mapping for reference. - Do not respond with anything except the updated current mapping JSON object enclosed with 3 backticks (\`). See example response below. diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/state.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/state.ts index 35a307f1de934..079f35a4cc1b8 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/state.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/state.ts @@ -16,7 +16,7 @@ export const graphState: StateGraphArgs['channels'] = { }, chunkSize: { value: (x: number, y?: number) => y ?? x, - default: () => 10, + default: () => 25, }, lastExecutedChain: { value: (x: string, y?: string) => y ?? x, @@ -58,10 +58,18 @@ export const graphState: StateGraphArgs['channels'] = { value: (x: object, y?: object) => y ?? x, default: () => ({}), }, - finalMapping: { + chunkMapping: { reducer: merge, default: () => ({}), }, + finalMapping: { + value: (x: object, y?: object) => y ?? x, + default: () => ({}), + }, + useFinalMapping: { + value: (x: boolean, y?: boolean) => y ?? x, + default: () => false, + }, currentPipeline: { value: (x: object, y?: object) => y ?? x, default: () => ({}), diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/validate.test.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/validate.test.ts index 052c0d6bf11b3..20074bc4f1047 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/validate.test.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/validate.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { findInvalidEcsFields, processMapping } from './validate'; +import { findDuplicateFields, findInvalidEcsFields, processMapping } from './validate'; describe('Testing ecs handler', () => { it('processMapping()', async () => { @@ -90,3 +90,35 @@ describe('findInvalidEcsFields', () => { expect(invalid.length).toBe(1); }); }); + +describe('findDuplicateFields', () => { + it('duplicates: samples with duplicates', async () => { + const finalMapping = { + teleport_log: { + audit: { + ei: null, + event: { + target: 'event.action', + confidence: 0.9, + type: 'string', + date_formats: [], + }, + uid: { + target: 'event.action', + confidence: 0.8, + type: 'string', + date_formats: [], + }, + }, + }, + }; + const samples = [ + '{"teleport_log":{"audit":{"ei":0,"event":"user.login","uid":"8c815e54-c83b-43d7-b578-2bcf5b6775fa","code":"T1000W","time":"2024-05-09T20:58:57.77Z","cluster_name":"teleport.ericbeahan.com","user":"root","success":false,"error":"invalid username, password or second factor","method":"local","user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36","addr.remote":"136.32.177.60:52457"}}}', + '{"teleport_log":{"audit":{"ei":0,"event":"user.login","uid":"6bf237a0-2753-418d-b01b-2d82ebf42636","code":"T1000W","time":"2024-05-09T21:00:22.747Z","cluster_name":"teleport.ericbeahan.com","user":"teleport-admin","success":false,"error":"invalid username, password or second factor","method":"local","user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36","addr.remote":"136.32.177.60:52818"}}}', + ]; + const duplicates = findDuplicateFields(samples, finalMapping); + expect(duplicates).toStrictEqual([ + "One or more samples have matching fields for ECS field 'event.action': teleport_log.audit.event, teleport_log.audit.uid", + ]); + }); +}); diff --git a/x-pack/plugins/integration_assistant/server/graphs/ecs/validate.ts b/x-pack/plugins/integration_assistant/server/graphs/ecs/validate.ts index 6c3fe06699aa3..87005e3553e90 100644 --- a/x-pack/plugins/integration_assistant/server/graphs/ecs/validate.ts +++ b/x-pack/plugins/integration_assistant/server/graphs/ecs/validate.ts @@ -6,8 +6,9 @@ */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { ECS_FULL } from '../../../common/ecs'; -import type { EcsBaseNodeParams } from './types'; +import { mergeSamples } from '../../util/samples'; import { ECS_RESERVED } from './constants'; +import type { EcsBaseNodeParams } from './types'; const valueFieldKeys = new Set(['target', 'confidence', 'date_formats', 'type']); type AnyObject = Record; @@ -22,15 +23,10 @@ function extractKeys(data: AnyObject, prefix: string = ''): Set { // Directly add the key for arrays without iterating over elements keys.add(fullKey); } else if (typeof value === 'object' && value !== null) { - const valueKeys = new Set(Object.keys(value)); - - if ([...valueFieldKeys].every((k) => valueKeys.has(k))) { - keys.add(fullKey); - } else { - // Recursively extract keys if the current value is a nested object - for (const nestedKey of extractKeys(value, fullKey)) { - keys.add(nestedKey); - } + keys.add(fullKey); + // Recursively extract keys if the current value is a nested object + for (const nestedKey of extractKeys(value, fullKey)) { + keys.add(nestedKey); } } else { // Add the key if the value is not an object or is null @@ -94,7 +90,7 @@ function getValueFromPath(obj: AnyObject, path: string[]): unknown { return path.reduce((acc, key) => (acc && acc[key] !== undefined ? acc[key] : null), obj); } -function findDuplicateFields(prefixedSamples: string[], ecsMapping: AnyObject): string[] { +export function findDuplicateFields(prefixedSamples: string[], ecsMapping: AnyObject): string[] { const parsedSamples = prefixedSamples.map((sample) => JSON.parse(sample)); const results: string[] = []; const output: Record = {}; @@ -153,9 +149,13 @@ export function findInvalidEcsFields(currentMapping: AnyObject): string[] { } export function handleValidateMappings({ state }: EcsBaseNodeParams): AnyObject { - const missingKeys = findMissingFields(state?.combinedSamples, state?.currentMapping); - const duplicateFields = findDuplicateFields(state?.prefixedSamples, state?.currentMapping); - const invalidEcsFields = findInvalidEcsFields(state?.currentMapping); + const usesFinalMapping = state?.useFinalMapping; + const mapping = usesFinalMapping ? state.finalMapping : state.currentMapping; + const samples = usesFinalMapping ? mergeSamples(state.prefixedSamples) : state.combinedSamples; + + const missingKeys = findMissingFields(samples, mapping); + const duplicateFields = findDuplicateFields(state?.prefixedSamples, mapping); + const invalidEcsFields = findInvalidEcsFields(mapping); return { missingKeys, duplicateFields, diff --git a/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/constants.ts b/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/constants.ts new file mode 100644 index 0000000000000..b7814b390f8ac --- /dev/null +++ b/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/constants.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const EX_ANSWER_LOG_TYPE = { + log_type: 'structured', +}; diff --git a/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/detection.test.ts b/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/detection.test.ts new file mode 100644 index 0000000000000..5008f5fa3ef34 --- /dev/null +++ b/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/detection.test.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FakeLLM } from '@langchain/core/utils/testing'; +import { handleLogFormatDetection } from './detection'; +import type { LogFormatDetectionState } from '../../types'; +import { logFormatDetectionTestState } from '../../../__jest__/fixtures/log_type_detection'; +import { + ActionsClientChatOpenAI, + ActionsClientSimpleChatModel, +} from '@kbn/langchain/server/language_models'; + +const mockLLM = new FakeLLM({ + response: '{ "log_type": "structured"}', +}) as unknown as ActionsClientChatOpenAI | ActionsClientSimpleChatModel; + +const testState: LogFormatDetectionState = logFormatDetectionTestState; + +describe('Testing log type detection handler', () => { + it('handleLogFormatDetection()', async () => { + const response = await handleLogFormatDetection(testState, mockLLM); + expect(response.logFormat).toStrictEqual('structured'); + expect(response.lastExecutedChain).toBe('logFormatDetection'); + }); +}); diff --git a/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/detection.ts b/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/detection.ts new file mode 100644 index 0000000000000..c41b66263c7f4 --- /dev/null +++ b/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/detection.ts @@ -0,0 +1,36 @@ +/* + * 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 { + ActionsClientChatOpenAI, + ActionsClientSimpleChatModel, +} from '@kbn/langchain/server/language_models'; +import { JsonOutputParser } from '@langchain/core/output_parsers'; +import type { LogFormatDetectionState } from '../../types'; +import { LOG_FORMAT_DETECTION_PROMPT } from './prompts'; + +const MaxLogSamplesInPrompt = 5; + +export async function handleLogFormatDetection( + state: LogFormatDetectionState, + model: ActionsClientChatOpenAI | ActionsClientSimpleChatModel +) { + const outputParser = new JsonOutputParser(); + const logFormatDetectionNode = LOG_FORMAT_DETECTION_PROMPT.pipe(model).pipe(outputParser); + + const samples = + state.logSamples.length > MaxLogSamplesInPrompt + ? state.logSamples.slice(0, MaxLogSamplesInPrompt) + : state.logSamples; + + const detectedLogFormatAnswer = await logFormatDetectionNode.invoke({ + ex_answer: state.exAnswer, + log_samples: samples, + }); + const logFormat = detectedLogFormatAnswer.log_type; + + return { logFormat, lastExecutedChain: 'logFormatDetection' }; +} diff --git a/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/graph.test.ts b/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/graph.test.ts new file mode 100644 index 0000000000000..3a14239a1c8f2 --- /dev/null +++ b/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/graph.test.ts @@ -0,0 +1,31 @@ +/* + * 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 { FakeLLM } from '@langchain/core/utils/testing'; +import { getLogFormatDetectionGraph } from './graph'; +import { + ActionsClientChatOpenAI, + ActionsClientSimpleChatModel, +} from '@kbn/langchain/server/language_models'; + +const mockLLM = new FakeLLM({ + response: '{"log_type": "structured"}', +}) as unknown as ActionsClientChatOpenAI | ActionsClientSimpleChatModel; + +describe('LogFormatDetectionGraph', () => { + describe('Compiling and Running', () => { + it('Ensures that the graph compiles', async () => { + // When getLogFormatDetectionGraph runs, langgraph compiles the graph it will error if the graph has any issues. + // Common issues for example detecting a node has no next step, or there is a infinite loop between them. + try { + await getLogFormatDetectionGraph(mockLLM); + } catch (error) { + fail(`getLogFormatDetectionGraph threw an error: ${error}`); + } + }); + }); +}); diff --git a/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/graph.ts b/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/graph.ts new file mode 100644 index 0000000000000..e0773b556e844 --- /dev/null +++ b/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/graph.ts @@ -0,0 +1,110 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { + ActionsClientChatOpenAI, + ActionsClientSimpleChatModel, +} from '@kbn/langchain/server/language_models'; +import type { StateGraphArgs } from '@langchain/langgraph'; +import { END, START, StateGraph } from '@langchain/langgraph'; +import type { LogFormatDetectionState } from '../../types'; +import { EX_ANSWER_LOG_TYPE } from './constants'; +import { handleLogFormatDetection } from './detection'; +import { SamplesFormat } from '../../../common'; + +const graphState: StateGraphArgs['channels'] = { + lastExecutedChain: { + value: (x: string, y?: string) => y ?? x, + default: () => '', + }, + logSamples: { + value: (x: string[], y?: string[]) => y ?? x, + default: () => [], + }, + exAnswer: { + value: (x: string, y?: string) => y ?? x, + default: () => '', + }, + finalized: { + value: (x: boolean, y?: boolean) => y ?? x, + default: () => false, + }, + samplesFormat: { + value: (x: SamplesFormat, y?: SamplesFormat) => y ?? x, + default: () => ({ name: 'unsupported' }), + }, + ecsVersion: { + value: (x: string, y?: string) => y ?? x, + default: () => '8.11.0', + }, + results: { + value: (x: object, y?: object) => y ?? x, + default: () => ({}), + }, +}; + +function modelInput(state: LogFormatDetectionState): Partial { + return { + exAnswer: JSON.stringify(EX_ANSWER_LOG_TYPE, null, 2), + finalized: false, + lastExecutedChain: 'modelInput', + }; +} + +function modelOutput(state: LogFormatDetectionState): Partial { + return { + finalized: true, + lastExecutedChain: 'modelOutput', + results: { + samplesFormat: state.samplesFormat, + parsedSamples: state.logSamples, // TODO: Add parsed samples + }, + }; +} + +function logFormatRouter(state: LogFormatDetectionState): string { + // if (state.samplesFormat === LogFormat.STRUCTURED) { + // return 'structured'; + // } + // if (state.samplesFormat === LogFormat.UNSTRUCTURED) { + // return 'unstructured'; + // } + // if (state.samplesFormat === LogFormat.CSV) { + // return 'csv'; + // } + return 'unsupported'; +} + +export async function getLogFormatDetectionGraph( + model: ActionsClientChatOpenAI | ActionsClientSimpleChatModel +) { + const workflow = new StateGraph({ + channels: graphState, + }) + .addNode('modelInput', modelInput) + .addNode('modelOutput', modelOutput) + .addNode('handleLogFormatDetection', (state: LogFormatDetectionState) => + handleLogFormatDetection(state, model) + ) + // .addNode('handleKVGraph', (state: LogFormatDetectionState) => getCompiledKvGraph(state, model)) + // .addNode('handleUnstructuredGraph', (state: LogFormatDetectionState) => getCompiledUnstructuredGraph(state, model)) + // .addNode('handleCsvGraph', (state: LogFormatDetectionState) => getCompiledCsvGraph(state, model)) + .addEdge(START, 'modelInput') + .addEdge('modelInput', 'handleLogFormatDetection') + .addEdge('modelOutput', END) + .addConditionalEdges('handleLogFormatDetection', logFormatRouter, { + // TODO: Add structured, unstructured, csv nodes + // structured: 'handleKVGraph', + // unstructured: 'handleUnstructuredGraph', + // csv: 'handleCsvGraph', + unsupported: 'modelOutput', + }); + + const compiledLogFormatDetectionGraph = workflow.compile(); + + return compiledLogFormatDetectionGraph; +} diff --git a/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/prompts.ts b/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/prompts.ts new file mode 100644 index 0000000000000..9ad06d7592c0f --- /dev/null +++ b/x-pack/plugins/integration_assistant/server/graphs/log_type_detection/prompts.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { ChatPromptTemplate } from '@langchain/core/prompts'; +export const LOG_FORMAT_DETECTION_PROMPT = ChatPromptTemplate.fromMessages([ + [ + 'system', + `You are a helpful, expert assistant in identifying different log types based on the format. + +Here is some context for you to reference for your task, read it carefully as you will get questions about it later: + + +{log_samples} + +`, + ], + [ + 'human', + `Looking at the log samples , our goal is to identify the syslog type based on the guidelines below. + +- Go through each log sample and identify the log format type. +- If the syslog samples have header and structured body then classify it as "structured". +- If the syslog samples have header and unstructured body then classify it as "unstructured". +- If the syslog samples follow a csv format then classify it as "csv". +- If you do not find the log format in any of the above categories then classify it as "unsupported". +- Do not respond with anything except the updated current mapping JSON object enclosed with 3 backticks (\`). See example response below. + + +Example response format: + +A: Please find the JSON object below: +\`\`\`json +{ex_answer} +\`\`\` +`, + ], + ['ai', 'Please find the JSON object below:'], +]); diff --git a/x-pack/plugins/integration_assistant/server/routes/analyze_logs_routes.ts b/x-pack/plugins/integration_assistant/server/routes/analyze_logs_routes.ts new file mode 100644 index 0000000000000..85826e56c2004 --- /dev/null +++ b/x-pack/plugins/integration_assistant/server/routes/analyze_logs_routes.ts @@ -0,0 +1,95 @@ +/* + * 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 { IKibanaResponse, IRouter } from '@kbn/core/server'; +import { getRequestAbortedSignal } from '@kbn/data-plugin/server'; +import { + ActionsClientChatOpenAI, + ActionsClientSimpleChatModel, +} from '@kbn/langchain/server/language_models'; +import { APMTracer } from '@kbn/langchain/server/tracers/apm'; +import { getLangSmithTracer } from '@kbn/langchain/server/tracers/langsmith'; +import { ANALYZE_LOGS_PATH, AnalyzeLogsRequestBody, AnalyzeLogsResponse } from '../../common'; +import { ROUTE_HANDLER_TIMEOUT } from '../constants'; +import type { IntegrationAssistantRouteHandlerContext } from '../plugin'; +import { buildRouteValidationWithZod } from '../util/route_validation'; +import { withAvailability } from './with_availability'; +import { getLogFormatDetectionGraph } from '../graphs/log_type_detection/graph'; + +export function registerAnalyzeLogsRoutes( + router: IRouter +) { + router.versioned + .post({ + path: ANALYZE_LOGS_PATH, + access: 'internal', + options: { + timeout: { + idleSocket: ROUTE_HANDLER_TIMEOUT, + }, + }, + }) + .addVersion( + { + version: '1', + validate: { + request: { + body: buildRouteValidationWithZod(AnalyzeLogsRequestBody), + }, + }, + }, + withAvailability(async (context, req, res): Promise> => { + const { logSamples, langSmithOptions } = req.body; + const { getStartServices, logger } = await context.integrationAssistant; + const [, { actions: actionsPlugin }] = await getStartServices(); + try { + const actionsClient = await actionsPlugin.getActionsClientWithRequest(req); + const connector = req.body.connectorId + ? await actionsClient.get({ id: req.body.connectorId }) + : (await actionsClient.getAll()).filter( + (connectorItem) => connectorItem.actionTypeId === '.bedrock' + )[0]; + const abortSignal = getRequestAbortedSignal(req.events.aborted$); + const isOpenAI = connector.actionTypeId === '.gen-ai'; + const llmClass = isOpenAI ? ActionsClientChatOpenAI : ActionsClientSimpleChatModel; + const model = new llmClass({ + actionsClient, + connectorId: connector.id, + logger, + llmType: isOpenAI ? 'openai' : 'bedrock', + model: connector.config?.defaultModel, + temperature: 0.05, + maxTokens: 4096, + signal: abortSignal, + streaming: false, + }); + const options = { + callbacks: [ + new APMTracer({ projectName: langSmithOptions?.projectName ?? 'default' }, logger), + ...getLangSmithTracer({ ...langSmithOptions, logger }), + ], + }; + + const logFormatParameters = { + logSamples, + }; + const graph = await getLogFormatDetectionGraph(model); + const graphResults = await graph.invoke(logFormatParameters, options); + const graphLogFormat = graphResults.results.samplesFormat.name; + if (graphLogFormat === 'unsupported') { + return res.customError({ + statusCode: 501, + body: { message: `Unsupported log samples format` }, + }); + } + return res.ok({ body: AnalyzeLogsResponse.parse(graphResults) }); + } catch (e) { + return res.badRequest({ body: e }); + } + }) + ); +} diff --git a/x-pack/plugins/integration_assistant/server/routes/register_routes.ts b/x-pack/plugins/integration_assistant/server/routes/register_routes.ts index a8ccc39ff2a0f..781010972ddcb 100644 --- a/x-pack/plugins/integration_assistant/server/routes/register_routes.ts +++ b/x-pack/plugins/integration_assistant/server/routes/register_routes.ts @@ -12,8 +12,10 @@ import { registerCategorizationRoutes } from './categorization_routes'; import { registerRelatedRoutes } from './related_routes'; import { registerPipelineRoutes } from './pipeline_routes'; import type { IntegrationAssistantRouteHandlerContext } from '../plugin'; +import { registerAnalyzeLogsRoutes } from './analyze_logs_routes'; export function registerRoutes(router: IRouter) { + registerAnalyzeLogsRoutes(router); registerEcsRoutes(router); registerIntegrationBuilderRoutes(router); registerCategorizationRoutes(router); diff --git a/x-pack/plugins/integration_assistant/server/types.ts b/x-pack/plugins/integration_assistant/server/types.ts index 2f5d9f1237870..44af5afcd10e7 100644 --- a/x-pack/plugins/integration_assistant/server/types.ts +++ b/x-pack/plugins/integration_assistant/server/types.ts @@ -5,13 +5,14 @@ * 2.0. */ -import type { LicensingPluginSetup, LicensingPluginStart } from '@kbn/licensing-plugin/server'; import { - ActionsClientChatOpenAI, ActionsClientBedrockChatModel, - ActionsClientSimpleChatModel, + ActionsClientChatOpenAI, ActionsClientGeminiChatModel, + ActionsClientSimpleChatModel, } from '@kbn/langchain/server'; +import type { LicensingPluginSetup, LicensingPluginStart } from '@kbn/licensing-plugin/server'; +import { SamplesFormat } from '../common'; export interface IntegrationAssistantPluginSetup { setIsAvailable: (isAvailable: boolean) => void; @@ -75,6 +76,8 @@ export interface EcsMappingState { finalized: boolean; currentMapping: object; finalMapping: object; + chunkMapping: object; + useFinalMapping: boolean; currentPipeline: object; duplicateFields: string[]; missingKeys: string[]; @@ -84,6 +87,16 @@ export interface EcsMappingState { ecsVersion: string; } +export interface LogFormatDetectionState { + lastExecutedChain: string; + logSamples: string[]; + exAnswer: string; + finalized: boolean; + samplesFormat: SamplesFormat; + ecsVersion: string; + results: object; +} + export interface RelatedState { rawSamples: string[]; samples: string[]; diff --git a/x-pack/plugins/kubernetes_security/public/components/container_name_widget/index.tsx b/x-pack/plugins/kubernetes_security/public/components/container_name_widget/index.tsx index e907e0dc9dbef..57d3e3288d613 100644 --- a/x-pack/plugins/kubernetes_security/public/components/container_name_widget/index.tsx +++ b/x-pack/plugins/kubernetes_security/public/components/container_name_widget/index.tsx @@ -86,7 +86,7 @@ export const ContainerNameWidget = ({ sortDirection ); - const onTableChange = useCallback(({ sort = {} }) => { + const onTableChange = useCallback(({ sort = {} }: any) => { // @ts-ignore const { field: sortingField, direction: sortingDirection } = sort; diff --git a/x-pack/plugins/lens/common/expressions/datatable/datatable.ts b/x-pack/plugins/lens/common/expressions/datatable/datatable.ts index 6b73b63d30c63..11faf78dc3b4b 100644 --- a/x-pack/plugins/lens/common/expressions/datatable/datatable.ts +++ b/x-pack/plugins/lens/common/expressions/datatable/datatable.ts @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; import type { ExecutionContext } from '@kbn/expressions-plugin/common'; import type { FormatFactory, RowHeightMode } from '../../types'; -import type { ColumnConfigArg } from './datatable_column'; +import type { DatatableColumnResult } from './datatable_column'; import type { DatatableExpressionFunction } from './types'; export interface SortingState { @@ -24,7 +24,7 @@ export interface PagingState { export interface DatatableArgs { title: string; description?: string; - columns: ColumnConfigArg[]; + columns: DatatableColumnResult[]; sortingColumnId: SortingState['columnId']; sortingDirection: SortingState['direction']; fitRowToContent?: boolean; diff --git a/x-pack/plugins/lens/common/expressions/datatable/datatable_column.ts b/x-pack/plugins/lens/common/expressions/datatable/datatable_column.ts index 267671a062655..6f4702c8b32c1 100644 --- a/x-pack/plugins/lens/common/expressions/datatable/datatable_column.ts +++ b/x-pack/plugins/lens/common/expressions/datatable/datatable_column.ts @@ -6,23 +6,25 @@ */ import type { Direction } from '@elastic/eui'; -import type { PaletteOutput, CustomPaletteParams } from '@kbn/coloring'; +import type { PaletteOutput, CustomPaletteParams, ColorMapping } from '@kbn/coloring'; import type { CustomPaletteState } from '@kbn/charts-plugin/common'; import type { ExpressionFunctionDefinition, DatatableColumn } from '@kbn/expressions-plugin/common'; import type { SortingHint } from '../../types'; import { CollapseFunction } from '../collapse'; +const LENS_DATATABLE_COLUMN = 'lens_datatable_column'; + export type LensGridDirection = 'none' | Direction; -export interface ColumnConfig { - columns: ColumnConfigArg[]; +export interface DatatableColumnConfig { + columns: DatatableColumnResult[]; sortingColumnId: string | undefined; sortingDirection: LensGridDirection; } -export type ColumnConfigArg = Omit & { - type: 'lens_datatable_column'; +export type DatatableColumnArgs = Omit & { palette?: PaletteOutput; + colorMapping?: string; summaryRowValue?: unknown; sortingHint?: SortingHint; }; @@ -41,6 +43,7 @@ export interface ColumnState { bucketValues?: Array<{ originalBucketColumn: DatatableColumn; value: unknown }>; alignment?: 'left' | 'right' | 'center'; palette?: PaletteOutput; + colorMapping?: ColorMapping.Config; colorMode?: 'none' | 'cell' | 'text'; summaryRow?: 'none' | 'sum' | 'avg' | 'count' | 'min' | 'max'; summaryLabel?: string; @@ -48,18 +51,21 @@ export interface ColumnState { isMetric?: boolean; } -export type DatatableColumnResult = ColumnState & { type: 'lens_datatable_column' }; -export type DatatableColumnFunction = ExpressionFunctionDefinition< - 'lens_datatable_column', +export type DatatableColumnResult = DatatableColumnArgs & { + type: typeof LENS_DATATABLE_COLUMN; +}; + +export type DatatableColumnFn = ExpressionFunctionDefinition< + typeof LENS_DATATABLE_COLUMN, null, - ColumnState & { sortingHint?: SortingHint }, + DatatableColumnArgs, DatatableColumnResult >; -export const datatableColumn: DatatableColumnFunction = { - name: 'lens_datatable_column', +export const datatableColumn: DatatableColumnFn = { + name: LENS_DATATABLE_COLUMN, aliases: [], - type: 'lens_datatable_column', + type: LENS_DATATABLE_COLUMN, help: '', inputTypes: ['null'], args: { @@ -76,12 +82,16 @@ export const datatableColumn: DatatableColumnFunction = { types: ['palette'], help: '', }, + colorMapping: { + types: ['string'], + help: '', + }, summaryRow: { types: ['string'], help: '' }, summaryLabel: { types: ['string'], help: '' }, }, - fn: function fn(input: unknown, args: ColumnState) { + fn: function fn(input, args) { return { - type: 'lens_datatable_column', + type: LENS_DATATABLE_COLUMN, ...args, }; }, diff --git a/x-pack/plugins/lens/common/expressions/datatable/datatable_fn.ts b/x-pack/plugins/lens/common/expressions/datatable/datatable_fn.ts index a5b8ef9a24013..b528bde76e220 100644 --- a/x-pack/plugins/lens/common/expressions/datatable/datatable_fn.ts +++ b/x-pack/plugins/lens/common/expressions/datatable/datatable_fn.ts @@ -72,6 +72,7 @@ export const datatableFn = value: { data: table, untransposedData, + syncColors: context.isSyncColorsEnabled?.() ?? false, args: { ...args, title: (context.variables.embeddableTitle as string) ?? args.title, diff --git a/x-pack/plugins/lens/common/expressions/datatable/index.ts b/x-pack/plugins/lens/common/expressions/datatable/index.ts index 7003fd8d486b8..4b27aa90d5190 100644 --- a/x-pack/plugins/lens/common/expressions/datatable/index.ts +++ b/x-pack/plugins/lens/common/expressions/datatable/index.ts @@ -7,5 +7,6 @@ export * from './datatable_column'; export * from './datatable'; +export { isTransposeId, getOriginalId } from './transpose_helpers'; export type { DatatableProps, DatatableExpressionFunction } from './types'; diff --git a/x-pack/plugins/lens/common/expressions/datatable/summary.test.ts b/x-pack/plugins/lens/common/expressions/datatable/summary.test.ts index 207bf5779bbee..b772c3a51208c 100644 --- a/x-pack/plugins/lens/common/expressions/datatable/summary.test.ts +++ b/x-pack/plugins/lens/common/expressions/datatable/summary.test.ts @@ -72,7 +72,7 @@ describe('Summary row helpers', () => { it(`should return formatted value for a ${op} summary function`, () => { expect( computeSummaryRowForColumn( - { summaryRow: op, columnId: 'myColumn', type: 'lens_datatable_column' }, + { summaryRow: op, columnId: 'myColumn' }, mockNumericTable, { myColumn: customNumericFormatter, @@ -86,7 +86,7 @@ describe('Summary row helpers', () => { it('should ignore the column formatter, rather return the raw value for count operation', () => { expect( computeSummaryRowForColumn( - { summaryRow: 'count', columnId: 'myColumn', type: 'lens_datatable_column' }, + { summaryRow: 'count', columnId: 'myColumn' }, mockNumericTable, { myColumn: customNumericFormatter, @@ -99,7 +99,7 @@ describe('Summary row helpers', () => { it('should only count non-null/empty values', () => { expect( computeSummaryRowForColumn( - { summaryRow: 'count', columnId: 'myColumn', type: 'lens_datatable_column' }, + { summaryRow: 'count', columnId: 'myColumn' }, { ...mockNumericTable, rows: [...mockNumericTable.rows, { myColumn: null }] }, { myColumn: customNumericFormatter, @@ -112,7 +112,7 @@ describe('Summary row helpers', () => { it('should count numeric arrays as valid and distinct values', () => { expect( computeSummaryRowForColumn( - { summaryRow: 'count', columnId: 'myColumn', type: 'lens_datatable_column' }, + { summaryRow: 'count', columnId: 'myColumn' }, mockNumericTableWithArray, { myColumn: defaultFormatter, diff --git a/x-pack/plugins/lens/common/expressions/datatable/summary.ts b/x-pack/plugins/lens/common/expressions/datatable/summary.ts index 4516abfabb06c..f4ae186fc1d2f 100644 --- a/x-pack/plugins/lens/common/expressions/datatable/summary.ts +++ b/x-pack/plugins/lens/common/expressions/datatable/summary.ts @@ -8,15 +8,15 @@ import { i18n } from '@kbn/i18n'; import type { FieldFormat } from '@kbn/field-formats-plugin/common'; import type { Datatable } from '@kbn/expressions-plugin/common'; -import { ColumnConfigArg } from './datatable_column'; +import { DatatableColumnArgs } from './datatable_column'; import { getOriginalId } from './transpose_helpers'; import { isNumericFieldForDatatable } from './utils'; -type SummaryRowType = Extract; +type SummaryRowType = Extract; export function getFinalSummaryConfiguration( columnId: string, - columnArgs: Pick | undefined, + columnArgs: Pick | undefined, table: Datatable | undefined ) { const isNumeric = isNumericFieldForDatatable(table, columnId); @@ -87,13 +87,13 @@ export function getSummaryRowOptions(): Array<{ /** @internal **/ export function computeSummaryRowForColumn( - columnArgs: ColumnConfigArg, + columnArgs: DatatableColumnArgs, table: Datatable, formatters: Record, defaultFormatter: FieldFormat ) { const summaryValue = computeFinalValue(columnArgs.summaryRow, columnArgs.columnId, table.rows); - // ignore the coluymn formatter for the count case + // ignore the column formatter for the count case if (columnArgs.summaryRow === 'count') { return defaultFormatter.convert(summaryValue); } @@ -101,7 +101,7 @@ export function computeSummaryRowForColumn( } function computeFinalValue( - type: ColumnConfigArg['summaryRow'], + type: DatatableColumnArgs['summaryRow'], columnId: string, rows: Datatable['rows'] ) { diff --git a/x-pack/plugins/lens/common/expressions/datatable/transpose_helpers.ts b/x-pack/plugins/lens/common/expressions/datatable/transpose_helpers.ts index ef07a87cfb9e1..7f7e4d467f250 100644 --- a/x-pack/plugins/lens/common/expressions/datatable/transpose_helpers.ts +++ b/x-pack/plugins/lens/common/expressions/datatable/transpose_helpers.ts @@ -8,16 +8,20 @@ import type { Datatable, DatatableColumn, DatatableRow } from '@kbn/expressions-plugin/common'; import type { FieldFormat } from '@kbn/field-formats-plugin/common'; import type { DatatableArgs } from './datatable'; -import type { ColumnConfig, ColumnConfigArg } from './datatable_column'; +import type { DatatableColumnConfig, DatatableColumnArgs } from './datatable_column'; const TRANSPOSE_SEPARATOR = '---'; const TRANSPOSE_VISUAL_SEPARATOR = '›'; -function getTransposeId(value: string, columnId: string) { +export function getTransposeId(value: string, columnId: string) { return `${value}${TRANSPOSE_SEPARATOR}${columnId}`; } +export function isTransposeId(id: string): boolean { + return id.split(TRANSPOSE_SEPARATOR).length > 1; +} + export function getOriginalId(id: string) { if (id.includes(TRANSPOSE_SEPARATOR)) { const idParts = id.split(TRANSPOSE_SEPARATOR); @@ -87,11 +91,11 @@ export function transposeTable( function transposeRows( firstTable: Datatable, - bucketsColumnArgs: ColumnConfigArg[], + bucketsColumnArgs: DatatableColumnArgs[], formatters: Record, transposedColumnFormatter: FieldFormat, transposedColumnId: string, - metricsColumnArgs: ColumnConfigArg[] + metricsColumnArgs: DatatableColumnArgs[] ) { const rowsByBucketColumns: Record = groupRowsByBucketColumns( firstTable, @@ -113,8 +117,8 @@ function transposeRows( */ function updateColumnArgs( args: DatatableArgs, - bucketsColumnArgs: ColumnConfig['columns'], - transposedColumnGroups: Array + bucketsColumnArgs: DatatableColumnConfig['columns'], + transposedColumnGroups: Array ) { args.columns = [...bucketsColumnArgs]; // add first column from each group, then add second column for each group, ... @@ -151,8 +155,8 @@ function getUniqueValues(table: Datatable, formatter: FieldFormat, columnId: str */ function transposeColumns( args: DatatableArgs, - bucketsColumnArgs: ColumnConfig['columns'], - metricColumns: ColumnConfig['columns'], + bucketsColumnArgs: DatatableColumnConfig['columns'], + metricColumns: DatatableColumnConfig['columns'], firstTable: Datatable, uniqueValues: string[], uniqueRawValues: unknown[], @@ -196,10 +200,10 @@ function transposeColumns( */ function mergeRowGroups( rowsByBucketColumns: Record, - bucketColumns: ColumnConfigArg[], + bucketColumns: DatatableColumnArgs[], formatter: FieldFormat, transposedColumnId: string, - metricColumns: ColumnConfigArg[] + metricColumns: DatatableColumnArgs[] ) { return Object.values(rowsByBucketColumns).map((rows) => { const mergedRow: DatatableRow = {}; @@ -222,7 +226,7 @@ function mergeRowGroups( */ function groupRowsByBucketColumns( firstTable: Datatable, - bucketColumns: ColumnConfigArg[], + bucketColumns: DatatableColumnArgs[], formatters: Record ) { const rowsByBucketColumns: Record = {}; diff --git a/x-pack/plugins/lens/common/expressions/datatable/types.ts b/x-pack/plugins/lens/common/expressions/datatable/types.ts index 7de3bdde894dc..7f03a1f4fb19b 100644 --- a/x-pack/plugins/lens/common/expressions/datatable/types.ts +++ b/x-pack/plugins/lens/common/expressions/datatable/types.ts @@ -10,6 +10,7 @@ import type { DatatableArgs } from './datatable'; export interface DatatableProps { data: Datatable; + syncColors: boolean; untransposedData?: Datatable; args: DatatableArgs; } diff --git a/x-pack/plugins/lens/common/expressions/datatable/utils.ts b/x-pack/plugins/lens/common/expressions/datatable/utils.ts index 3b60b7e4834fe..71c3d92126b33 100644 --- a/x-pack/plugins/lens/common/expressions/datatable/utils.ts +++ b/x-pack/plugins/lens/common/expressions/datatable/utils.ts @@ -8,10 +8,11 @@ import type { Datatable } from '@kbn/expressions-plugin/common'; import { getOriginalId } from './transpose_helpers'; -export function isNumericFieldForDatatable(currentData: Datatable | undefined, accessor: string) { - const column = currentData?.columns.find( - (col) => col.id === accessor || getOriginalId(col.id) === accessor - ); +export function isNumericFieldForDatatable(table: Datatable | undefined, accessor: string) { + return getFieldTypeFromDatatable(table, accessor) === 'number'; +} - return column?.meta.type === 'number'; +export function getFieldTypeFromDatatable(table: Datatable | undefined, accessor: string) { + return table?.columns.find((col) => col.id === accessor || getOriginalId(col.id) === accessor) + ?.meta.type; } diff --git a/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx b/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx index 3f12c6f63ca95..da99d693539b8 100644 --- a/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx +++ b/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx @@ -8,9 +8,9 @@ import { cloneDeep, isEqual } from 'lodash'; import { i18n } from '@kbn/i18n'; import React, { useCallback, useEffect, useMemo, useState, useRef } from 'react'; -import { isOfAggregateQueryType } from '@kbn/es-query'; +import { AggregateQuery, isOfAggregateQueryType, Query } from '@kbn/es-query'; import { useStore } from 'react-redux'; -import { TopNavMenuData } from '@kbn/navigation-plugin/public'; +import { TopNavMenuData, TopNavMenuProps } from '@kbn/navigation-plugin/public'; import { getEsQueryConfig } from '@kbn/data-plugin/public'; import type { DataView, DataViewSpec } from '@kbn/data-views-plugin/public'; import { useKibana } from '@kbn/kibana-react-plugin/public'; @@ -803,7 +803,9 @@ export const LensTopNavMenu = ({ startServices, ]); - const onQuerySubmitWrapped = useCallback( + const onQuerySubmitWrapped = useCallback< + Required>['onQuerySubmit'] + >( (payload) => { const { dateRange, query: newQuery } = payload; const currentRange = data.query.timefilter.timefilter.getTime(); @@ -819,7 +821,7 @@ export const LensTopNavMenu = ({ } if (newQuery) { if (!isEqual(newQuery, query)) { - dispatchSetState({ query: newQuery }); + dispatchSetState({ query: newQuery as Query }); // check if query is text-based (esql etc) and switchAndCleanDatasource if (isOfAggregateQueryType(newQuery) && !isOnTextBasedMode) { setIsOnTextBasedMode(true); @@ -846,14 +848,16 @@ export const LensTopNavMenu = ({ ] ); - const onSavedWrapped = useCallback( + const onSavedWrapped = useCallback>['onSaved']>( (newSavedQuery) => { dispatchSetState({ savedQuery: newSavedQuery }); }, [dispatchSetState] ); - const onSavedQueryUpdatedWrapped = useCallback( + const onSavedQueryUpdatedWrapped = useCallback< + Required>['onSavedQueryUpdated'] + >( (newSavedQuery) => { // If the user tries to load the same saved query that is already loaded, // we will receive the same object reference which was previously frozen diff --git a/x-pack/plugins/lens/public/app_plugin/show_underlying_data.ts b/x-pack/plugins/lens/public/app_plugin/show_underlying_data.ts index 5b6712ed23862..fa9268c0374eb 100644 --- a/x-pack/plugins/lens/public/app_plugin/show_underlying_data.ts +++ b/x-pack/plugins/lens/public/app_plugin/show_underlying_data.ts @@ -15,6 +15,7 @@ import { TimeRange, EsQueryConfig, isOfQueryType, + AggregateQuery, } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; import { RecursiveReadonly } from '@kbn/utility-types'; @@ -203,7 +204,7 @@ type QueryLanguage = 'lucene' | 'kuery'; * extra filter pill. */ export function combineQueryAndFilters( - query: Query | Query[] | undefined, + query: Query | Query[] | AggregateQuery | undefined, filters: Filter[], meta: LayerMetaInfo, dataViews: DataViewBase[] | undefined, diff --git a/x-pack/plugins/lens/public/datasources/form_based/datapanel.tsx b/x-pack/plugins/lens/public/datasources/form_based/datapanel.tsx index ba047564a1f07..c666c23d667c3 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/datapanel.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/datapanel.tsx @@ -241,7 +241,7 @@ export const InnerFormBasedDataPanel = function InnerFormBasedDataPanel({ [layerFields] ); - const onOverrideFieldGroupDetails = useCallback((groupName) => { + const onOverrideFieldGroupDetails = useCallback((groupName: string) => { if (groupName === FieldsGroupNames.AvailableFields) { return { helpText: i18n.translate('xpack.lens.indexPattern.allFieldsLabelHelp', { diff --git a/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/dimension_editor.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/dimension_editor.tsx index faf00ff6350fb..98086df2e5ba1 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/dimension_editor.tsx @@ -48,9 +48,9 @@ import { getReferencedField, hasField } from '../pure_utils'; import { fieldIsInvalid, getSamplingValue, isSamplingValueEnabled } from '../utils'; import { BucketNestingEditor } from './bucket_nesting_editor'; import type { FormBasedLayer } from '../types'; -import { FormatSelector } from './format_selector'; +import { FormatSelector, FormatSelectorProps } from './format_selector'; import { ReferenceEditor } from './reference_editor'; -import { TimeScaling } from './time_scaling'; +import { TimeScaling, TimeScalingProps } from './time_scaling'; import { Filtering } from './filtering'; import { ReducedTimeRange } from './reduced_time_range'; import { AdvancedOptions } from './advanced_options'; @@ -144,7 +144,8 @@ export function DimensionEditor(props: DimensionEditorProps) { const { euiTheme } = useEuiTheme(); const updateLayer = useCallback( - (newLayer) => setState((prevState) => mergeLayer({ state: prevState, layerId, newLayer })), + (newLayer: Partial) => + setState((prevState) => mergeLayer({ state: prevState, layerId, newLayer })), [layerId, setState] ); @@ -499,7 +500,7 @@ export function DimensionEditor(props: DimensionEditorProps) { position="left" size="s" type="dot" - color="warning" + color={euiTheme.colors.warning} /> )} @@ -843,7 +844,7 @@ export function DimensionEditor(props: DimensionEditorProps) { updateLayer({ ...layer, // clean up the incomplete column data for the referenced id - incompleteColumns: { ...layer.incompleteColumns, [referenceId]: null }, + incompleteColumns: { ...layer.incompleteColumns, [referenceId]: undefined }, }); }} onDeleteColumn={() => { @@ -993,7 +994,7 @@ export function DimensionEditor(props: DimensionEditorProps) { const ButtonGroupContent = showQuickFunctions ? quickFunctions : customParamEditor; - const onFormatChange = useCallback( + const onFormatChange = useCallback( (newFormat) => { updateLayer( updateColumnParam({ @@ -1098,7 +1099,7 @@ export function DimensionEditor(props: DimensionEditorProps) { * Advanced options can cause side effects on other columns (i.e. formulas) * so before updating the layer the full insertOrReplaceColumn needs to be performed */ - const updateAdvancedOption = useCallback( + const updateAdvancedOption = useCallback( (newLayer) => { if (selectedColumn) { setStateWrapper( diff --git a/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/filtering.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/filtering.tsx index e79ead1e5536a..c4585a51e6b0d 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/filtering.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/filtering.tsx @@ -9,6 +9,7 @@ import { isEqual } from 'lodash'; import type { Query } from '@kbn/es-query'; import { validateQuery, FilterQueryInput } from '@kbn/visualization-ui-components'; import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { FilterQueryInputProps } from '@kbn/visualization-ui-components/components/query_input/filter_query_input'; import { LENS_APP_NAME } from '../../../../common/constants'; import { GenericIndexPatternColumn, operationDefinitionMap } from '../operations'; import type { FormBasedLayer } from '../types'; @@ -44,7 +45,7 @@ export function Filtering({ helpMessage: string | null; }) { const inputFilter = selectedColumn.filter; - const onChange = useCallback( + const onChange = useCallback( (query) => { const { isValid } = validateQuery(query, indexPattern); if (isValid && !isEqual(inputFilter, query)) { diff --git a/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/format_selector.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/format_selector.tsx index 08972b236240d..0e978e439a701 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/format_selector.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/format_selector.tsx @@ -17,6 +17,7 @@ import { EuiFormLabel, EuiLink, useEuiTheme, + EuiComboBoxOptionOption, } from '@elastic/eui'; import { useDebouncedValue } from '@kbn/visualization-utils'; import { useKibana } from '@kbn/kibana-react-plugin/public'; @@ -227,7 +228,7 @@ export function FormatSelector(props: FormatSelectorProps) { ); const onChangeWrapped = useCallback( - (choices) => { + (choices: Array>) => { if (choices.length === 0) { return; } diff --git a/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/time_scaling.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/time_scaling.tsx index 003407649622e..5cf3bde50bec3 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/time_scaling.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/time_scaling.tsx @@ -54,17 +54,14 @@ export function setTimeScaling( }; } -export function TimeScaling({ - selectedColumn, - columnId, - layer, - updateLayer, -}: { +export interface TimeScalingProps { selectedColumn: GenericIndexPatternColumn; columnId: string; layer: FormBasedLayer; updateLayer: (newLayer: FormBasedLayer) => void; -}) { +} + +export function TimeScaling({ selectedColumn, columnId, layer, updateLayer }: TimeScalingProps) { const selectedOperation = operationDefinitionMap[selectedColumn.operationType]; if (!selectedOperation.timeScalingMode || selectedOperation.timeScalingMode === 'disabled') { diff --git a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile.tsx index ad9a1067dcae7..7896f1f2950bc 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiFieldNumber, EuiRange } from '@elastic/eui'; +import { EuiFieldNumber, EuiRange, EuiRangeProps } from '@elastic/eui'; import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { AggFunctionsMapping } from '@kbn/data-plugin/public'; @@ -344,7 +344,7 @@ export const percentileOperation: OperationDefinition< const step = isInline ? 1 : 0.0001; const upperBound = isInline ? 99 : 99.9999; const onChange = useCallback( - (value) => { + (value?: string) => { if ( !isValidNumber(value, isInline, upperBound, step, ALLOWED_DECIMAL_DIGITS) || Number(value) === currentColumn.params.percentile @@ -384,7 +384,12 @@ export const percentileOperation: OperationDefinition< ALLOWED_DECIMAL_DIGITS ); - const handleInputChange = useCallback( + const handleInputChange = useCallback>( + (e) => handleInputChangeWithoutValidation(String(e.currentTarget.value)), + [handleInputChangeWithoutValidation] + ); + + const handleRangeChange = useCallback>( (e) => handleInputChangeWithoutValidation(String(e.currentTarget.value)), [handleInputChangeWithoutValidation] ); @@ -420,7 +425,7 @@ export const percentileOperation: OperationDefinition< min={step} max={upperBound} step={step} - onChange={handleInputChange} + onChange={handleRangeChange} showInput aria-label={percentileLabel} /> diff --git a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile_ranks.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile_ranks.tsx index 575bcc2ec0ed0..a7d8896ea050b 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile_ranks.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile_ranks.tsx @@ -185,7 +185,7 @@ export const percentileRanksOperation: OperationDefinition< defaultMessage: 'Percentile ranks value', }); const onChange = useCallback( - (value) => { + (value?: string) => { if (!isValidNumber(value, isInline) || Number(value) === currentColumn.params.value) { return; } diff --git a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/static_value.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/static_value.tsx index 715889b896ced..6b2b2166c02ba 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/static_value.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/static_value.tsx @@ -167,7 +167,7 @@ export const staticValueOperation: OperationDefinition< paramEditorCustomProps, }) { const onChange = useCallback( - (newValue) => { + (newValue?: string) => { // even if debounced it's triggering for empty string with the previous valid value if ( currentColumn.params.value === newValue || diff --git a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/terms/field_inputs.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/terms/field_inputs.tsx index 2a88a72029648..960aeea67b237 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/terms/field_inputs.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/terms/field_inputs.tsx @@ -16,7 +16,7 @@ import { } from '@kbn/visualization-ui-components'; import { useDebouncedValue } from '@kbn/visualization-utils'; import { IndexPattern } from '../../../../../types'; -import { FieldSelect } from '../../../dimension_panel/field_select'; +import { FieldChoiceWithOperationType, FieldSelect } from '../../../dimension_panel/field_select'; import type { TermsIndexPatternColumn } from './types'; import type { OperationSupportMatrix } from '../../../dimension_panel'; import { supportedTypes } from './constants'; @@ -72,7 +72,7 @@ export function FieldInputs({ }); const onFieldSelectChange = useCallback( - (choice, index = 0) => { + (choice: FieldChoiceWithOperationType, index = 0) => { const fields = [...localValues]; if (indexPattern.getFieldByName(choice.field)) { diff --git a/x-pack/plugins/lens/public/datasources/form_based/types.ts b/x-pack/plugins/lens/public/datasources/form_based/types.ts index 5abec15c31d61..1241429cf785c 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/types.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/types.ts @@ -53,7 +53,7 @@ export interface FormBasedLayer { indexPatternId: string; linkToLayers?: string[]; // Partial columns represent the temporary invalid states - incompleteColumns?: Record; + incompleteColumns?: Record; sampling?: number; ignoreGlobalFilters?: boolean; } diff --git a/x-pack/plugins/lens/public/datasources/text_based/components/datapanel.tsx b/x-pack/plugins/lens/public/datasources/text_based/components/datapanel.tsx index bda5df0e34882..fd61c0d063452 100644 --- a/x-pack/plugins/lens/public/datasources/text_based/components/datapanel.tsx +++ b/x-pack/plugins/lens/public/datasources/text_based/components/datapanel.tsx @@ -24,6 +24,7 @@ import { GetCustomFieldType, useGroupedFields, } from '@kbn/unified-field-list'; +import { OverrideFieldGroupDetails } from '@kbn/unified-field-list/src/types'; import type { DatasourceDataPanelProps } from '../../../types'; import type { TextBasedPrivateState } from '../types'; import { getStateFromAggregateQuery } from '../utils'; @@ -83,7 +84,7 @@ export function TextBasedDataPanel({ [layerFields] ); - const onOverrideFieldGroupDetails = useCallback((groupName) => { + const onOverrideFieldGroupDetails = useCallback((groupName) => { if (groupName === FieldsGroupNames.AvailableFields) { return { helpText: i18n.translate('xpack.lens.indexPattern.allFieldsForTextBasedLabelHelp', { diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/buttons/draggable_dimension_button.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/buttons/draggable_dimension_button.tsx index aa3315972b719..4218eb6426d20 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/buttons/draggable_dimension_button.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/buttons/draggable_dimension_button.tsx @@ -13,6 +13,7 @@ import { DropTargetSwapDuplicateCombine, Draggable, Droppable, + DroppableProps, } from '@kbn/dom-drag-drop'; import { isDraggedField } from '../../../../utils'; import { @@ -125,11 +126,11 @@ export function DraggableDimensionButton({ ); const registerNewButtonRefMemoized = useCallback( - (el) => registerNewButtonRef(target.columnId, el), + (el: HTMLDivElement | null) => registerNewButtonRef(target.columnId, el), [registerNewButtonRef, target.columnId] ); - const handleOnDrop = useCallback( + const handleOnDrop = useCallback>( (source, selectedDropType) => onDrop(source, value, selectedDropType), [value, onDrop] ); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/buttons/empty_dimension_button.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/buttons/empty_dimension_button.tsx index f8562a161c2a7..836365effc3dc 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/buttons/empty_dimension_button.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/buttons/empty_dimension_button.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useMemo, useState, useEffect } from 'react'; +import React, { useCallback, useMemo, useState, useEffect } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { @@ -14,6 +14,7 @@ import { DropType, DropTargetSwapDuplicateCombine, Droppable, + DroppableProps, } from '@kbn/dom-drag-drop'; import { EmptyDimensionButton as EmptyDimensionButtonInner } from '@kbn/visualization-ui-components'; import { css } from '@emotion/react'; @@ -167,7 +168,7 @@ export function EmptyDimensionButton({ [newColumnId, target, nextLabel, canDuplicate] ); - const handleOnDrop = React.useCallback( + const handleOnDrop = useCallback>( (source, selectedDropType) => onDrop(source, value, selectedDropType), [value, onDrop] ); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx index 5f66bd2e838c0..e83323a36fadf 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx @@ -23,7 +23,7 @@ import { import { AddLayerFunction, DragDropOperation, Visualization } from '../../../types'; import { LayerPanel } from './layer_panel'; import { generateId } from '../../../id_generator'; -import { ConfigPanelWrapperProps } from './types'; +import { ConfigPanelWrapperProps, LayerPanelProps } from './types'; import { useFocusUpdate } from './use_focus_update'; import { setLayerDefaultDimension, @@ -245,10 +245,9 @@ export function LayerPanels( setNextFocusedLayerId(layerId); }; - const registerLibraryAnnotationGroupFunction = useCallback( - (groupInfo) => dispatchLens(registerLibraryAnnotationGroup(groupInfo)), - [dispatchLens] - ); + const registerLibraryAnnotationGroupFunction = useCallback< + LayerPanelProps['registerLibraryAnnotationGroup'] + >((groupInfo) => dispatchLens(registerLibraryAnnotationGroup(groupInfo)), [dispatchLens]); const hideAddLayerButton = query && isOfAggregateQueryType(query); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx index cad1dd351c3ca..2847af1ca4375 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx @@ -91,7 +91,7 @@ export function LayerPanel(props: LayerPanelProps) { const settingsPanelRef = useRef(null); const registerLayerRef = useCallback( - (el) => registerNewLayerRef(layerId, el), + (el: HTMLDivElement | null) => registerNewLayerRef(layerId, el), [layerId, registerNewLayerRef] ); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/use_focus_update.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/use_focus_update.tsx index 7065c37c1daf2..4a6234a7cf6b1 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/use_focus_update.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/use_focus_update.tsx @@ -35,7 +35,7 @@ export function useFocusUpdate(ids: string[]) { } }, [ids, refsById, nextFocusedId]); - const registerNewRef = useCallback((id, el) => { + const registerNewRef = useCallback((id: string, el: HTMLElement | null) => { if (el) { setRefsById((refs) => { return new Map(refs.set(id, el)); @@ -44,7 +44,7 @@ export function useFocusUpdate(ids: string[]) { }, []); const removeRef = useCallback( - (id) => { + (id: string) => { if (ids.length <= 1) { return setNextFocusedId(id); } diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx index e0736b149fcbb..d5173998dc462 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx @@ -97,7 +97,7 @@ export function EditorFrame(props: EditorFrameProps) { ); const dropOntoWorkspace = useCallback( - (field) => { + (field: DragDropIdentifier) => { const suggestion = getSuggestionForField.current!(field); if (suggestion) { trackUiCounterEvents('drop_onto_workspace'); diff --git a/x-pack/plugins/lens/public/embeddable/embeddable.tsx b/x-pack/plugins/lens/public/embeddable/embeddable.tsx index faa617f081d8f..7baf35c4eb140 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable.tsx +++ b/x-pack/plugins/lens/public/embeddable/embeddable.tsx @@ -162,7 +162,7 @@ interface PreventableEvent { export type Simplify = { [KeyType in keyof T]: T[KeyType] } & {}; -interface LensBaseEmbeddableInput extends EmbeddableInput { +export interface LensBaseEmbeddableInput extends EmbeddableInput { filters?: Filter[]; query?: Query; timeRange?: TimeRange; diff --git a/x-pack/plugins/lens/public/shared_components/axis/ticks/axis_ticks_settings.tsx b/x-pack/plugins/lens/public/shared_components/axis/ticks/axis_ticks_settings.tsx index 1ac1c84f70633..8f47307d19d36 100644 --- a/x-pack/plugins/lens/public/shared_components/axis/ticks/axis_ticks_settings.tsx +++ b/x-pack/plugins/lens/public/shared_components/axis/ticks/axis_ticks_settings.tsx @@ -33,7 +33,7 @@ export const AxisTicksSettings: React.FunctionComponent updateTicksVisibilityState, }) => { const onTicksStatusChange = useCallback( - (visible) => updateTicksVisibilityState(visible, axis), + (visible: boolean) => updateTicksVisibilityState(visible, axis), [axis, updateTicksVisibilityState] ); diff --git a/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_accessor.test.ts b/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_accessor.test.ts new file mode 100644 index 0000000000000..139c6ced456bc --- /dev/null +++ b/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_accessor.test.ts @@ -0,0 +1,36 @@ +/* + * 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 { getColorAccessorFn } from './color_mapping_accessor'; + +jest.mock('@kbn/coloring', () => ({ + ...jest.requireActual('@kbn/coloring'), + getColorFactory: jest + .fn() + .mockReturnValue((v: string | number) => (v === '123' ? 'blue' : 'red')), +})); + +describe('getColorAccessorFn', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const getColorAccessor = getColorAccessorFn('{}', {} as any, false); + + it('should return null for null values', () => { + expect(getColorAccessor(null)).toBe(null); + }); + + it('should return null for undefined values', () => { + expect(getColorAccessor(undefined)).toBe(null); + }); + + it('should return stringified value for numbers', () => { + expect(getColorAccessor(123)).toBe('blue'); + }); + + it('should return color for string values', () => { + expect(getColorAccessor('testing')).toBe('red'); + }); +}); diff --git a/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_accessor.ts b/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_accessor.ts new file mode 100644 index 0000000000000..116b21bb2245d --- /dev/null +++ b/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_accessor.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + AVAILABLE_PALETTES, + getColorFactory, + getPalette, + NeutralPalette, + ColorMappingInputCategoricalData, +} from '@kbn/coloring'; +import { CellColorFn } from './get_cell_color_fn'; + +/** + * Return a color accessor function for XY charts depending on the split accessors received. + */ +export function getColorAccessorFn( + colorMapping: string, + data: ColorMappingInputCategoricalData, + isDarkMode: boolean +): CellColorFn { + const getColor = getColorFactory( + JSON.parse(colorMapping), + getPalette(AVAILABLE_PALETTES, NeutralPalette), + isDarkMode, + data + ); + + return (value) => { + if (value === undefined || value === null) return null; + + return getColor(String(value)); + }; +} diff --git a/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_by_terms.tsx b/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_by_terms.tsx new file mode 100644 index 0000000000000..1eec5a4093275 --- /dev/null +++ b/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_by_terms.tsx @@ -0,0 +1,141 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { MutableRefObject, useState } from 'react'; + +import { + EuiBadge, + EuiFlexGroup, + EuiFlexItem, + EuiFormRow, + EuiSpacer, + EuiSwitch, + EuiText, +} from '@elastic/eui'; +import { + ColorMapping, + DEFAULT_COLOR_MAPPING_CONFIG, + CategoricalColorMapping, + SPECIAL_TOKENS_STRING_CONVERSION, + AVAILABLE_PALETTES, + PaletteOutput, + PaletteRegistry, + CustomPaletteParams, +} from '@kbn/coloring'; +import { i18n } from '@kbn/i18n'; +import { trackUiCounterEvents } from '../../lens_ui_telemetry'; +import { PalettePicker } from '../palette_picker'; +import { PalettePanelContainer } from './palette_panel_container'; +import { getColorStops } from './utils'; + +interface ColorMappingByTermsProps { + isDarkMode: boolean; + colorMapping?: ColorMapping.Config; + palette?: PaletteOutput; + isInlineEditing?: boolean; + setPalette: (palette: PaletteOutput) => void; + setColorMapping: (colorMapping?: ColorMapping.Config) => void; + paletteService: PaletteRegistry; + panelRef: MutableRefObject; + categories: Array; +} + +export function ColorMappingByTerms({ + isDarkMode, + colorMapping, + palette, + isInlineEditing, + setPalette, + setColorMapping, + paletteService, + panelRef, + categories, +}: ColorMappingByTermsProps) { + const [useNewColorMapping, setUseNewColorMapping] = useState(Boolean(colorMapping)); + + return ( + + +
      + + + + + {i18n.translate('xpack.lens.colorMapping.tryLabel', { + defaultMessage: 'Use the new Color Mapping feature', + })}{' '} + + {i18n.translate('xpack.lens.colorMapping.techPreviewLabel', { + defaultMessage: 'Tech preview', + })} + + + + } + data-test-subj="lns_colorMappingOrLegacyPalette_switch" + compressed + checked={useNewColorMapping} + onChange={({ target: { checked } }) => { + trackUiCounterEvents(`color_mapping_switch_${checked ? 'enabled' : 'disabled'}`); + setColorMapping(checked ? { ...DEFAULT_COLOR_MAPPING_CONFIG } : undefined); + setUseNewColorMapping(checked); + }} + /> + + + + {useNewColorMapping ? ( + + ) : ( + + )} + + +
      +
      +
      + ); +} diff --git a/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_by_values.tsx b/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_by_values.tsx new file mode 100644 index 0000000000000..9e18f6ae149a8 --- /dev/null +++ b/x-pack/plugins/lens/public/shared_components/coloring/color_mapping_by_values.tsx @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { MutableRefObject } from 'react'; + +import { EuiFormRow } from '@elastic/eui'; +import { + PaletteOutput, + PaletteRegistry, + CustomizablePalette, + DataBounds, + CustomPaletteParams, +} from '@kbn/coloring'; +import { i18n } from '@kbn/i18n'; +import { PalettePanelContainer } from './palette_panel_container'; + +interface ColorMappingByValuesProps { + palette: PaletteOutput; + isInlineEditing?: boolean; + setPalette: (palette: PaletteOutput) => void; + paletteService: PaletteRegistry; + panelRef: MutableRefObject; + dataBounds?: DataBounds; +} + +export function ColorMappingByValues({ + palette, + isInlineEditing, + setPalette, + paletteService, + panelRef, + dataBounds, +}: ColorMappingByValuesProps) { + const colors = palette.params?.stops?.map(({ color }) => color) ?? []; + + return ( + + +
      + { + setPalette(p); + }} + /> +
      +
      +
      + ); +} diff --git a/x-pack/plugins/lens/public/shared_components/coloring/get_cell_color_fn.ts b/x-pack/plugins/lens/public/shared_components/coloring/get_cell_color_fn.ts new file mode 100644 index 0000000000000..bb7e25220f793 --- /dev/null +++ b/x-pack/plugins/lens/public/shared_components/coloring/get_cell_color_fn.ts @@ -0,0 +1,71 @@ +/* + * 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 { + ColorMappingInputData, + PaletteOutput, + PaletteRegistry, + getSpecialString, +} from '@kbn/coloring'; +import { CustomPaletteState } from '@kbn/charts-plugin/common'; +import { getColorAccessorFn } from './color_mapping_accessor'; + +export type CellColorFn = (value?: number | string | null) => string | null; + +export function getCellColorFn( + paletteService: PaletteRegistry, + data: ColorMappingInputData, + colorByTerms: boolean, + isDarkMode: boolean, + syncColors: boolean, + palette?: PaletteOutput, + colorMapping?: string +): CellColorFn { + if (!colorByTerms && palette && data.type === 'ranges') { + return (value) => { + if (value === null || value === undefined || typeof value !== 'number') return null; + + return ( + paletteService.get(palette.name).getColorForValue?.(value, palette.params, data) ?? null + ); + }; + } + + if (colorByTerms && data.type === 'categories') { + if (colorMapping) { + return getColorAccessorFn(colorMapping, data, isDarkMode); + } else if (palette) { + return (category) => { + if (category === undefined || category === null) return null; + + const strCategory = String(category); // can be a number as a string + + return paletteService.get(palette.name).getCategoricalColor( + [ + { + name: getSpecialString(strCategory), // needed to sync special categories (i.e. '') + rankAtDepth: Math.max( + data.categories.findIndex((v) => v === strCategory), + 0 + ), + totalSeriesAtDepth: data.categories.length || 1, + }, + ], + { + maxDepth: 1, + totalSeries: data.categories.length || 1, + behindText: false, + syncColors, + }, + palette?.params ?? { colors: [] } + ); + }; + } + } + + return () => null; +} diff --git a/x-pack/plugins/lens/public/shared_components/coloring/utils.test.ts b/x-pack/plugins/lens/public/shared_components/coloring/utils.test.ts index 04306ffdfa326..5a126565c251f 100644 --- a/x-pack/plugins/lens/public/shared_components/coloring/utils.test.ts +++ b/x-pack/plugins/lens/public/shared_components/coloring/utils.test.ts @@ -6,7 +6,12 @@ */ import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; -import { applyPaletteParams, findMinMaxByColumnId, getContrastColor } from './utils'; +import { + applyPaletteParams, + findMinMaxByColumnId, + getContrastColor, + shouldColorByTerms, +} from './utils'; describe('applyPaletteParams', () => { const paletteRegistry = chartPluginMock.createPaletteRegistry(); @@ -108,3 +113,17 @@ describe('findMinMaxByColumnId', () => { ).toEqual({ b: { min: 2, max: 53 } }); }); }); + +describe('shouldColorByTerms', () => { + it('should return true if bucketed regardless of value', () => { + expect(shouldColorByTerms('number', true)).toBe(true); + }); + + it('should return false if not bucketed and numeric', () => { + expect(shouldColorByTerms('number', false)).toBe(false); + }); + + it('should return true if not bucketed and non-numeric', () => { + expect(shouldColorByTerms('string', false)).toBe(true); + }); +}); diff --git a/x-pack/plugins/lens/public/shared_components/coloring/utils.ts b/x-pack/plugins/lens/public/shared_components/coloring/utils.ts index 9436dec74be04..211628a096189 100644 --- a/x-pack/plugins/lens/public/shared_components/coloring/utils.ts +++ b/x-pack/plugins/lens/public/shared_components/coloring/utils.ts @@ -17,8 +17,40 @@ import { getPaletteStops, CUSTOM_PALETTE, enforceColorContrast, + ColorMapping, + getColorsFromMapping, + DEFAULT_FALLBACK_PALETTE, } from '@kbn/coloring'; -import { Datatable } from '@kbn/expressions-plugin/common'; +import { Datatable, DatatableColumnType } from '@kbn/expressions-plugin/common'; +import { DataType } from '../../types'; + +/** + * Returns array of colors for provided palette or colorMapping + */ +export function getColorStops( + paletteService: PaletteRegistry, + isDarkMode: boolean, + palette?: PaletteOutput, + colorMapping?: ColorMapping.Config +): string[] { + return colorMapping + ? getColorsFromMapping(isDarkMode, colorMapping) + : palette?.name === CUSTOM_PALETTE + ? palette?.params?.stops?.map(({ color }) => color) ?? [] + : paletteService + .get(palette?.name || DEFAULT_FALLBACK_PALETTE) + .getCategoricalColors(10, palette); +} + +/** + * Bucketed numerical columns should be treated as categorical + */ +export function shouldColorByTerms( + dataType?: DataType | DatatableColumnType, + isBucketed?: boolean +) { + return isBucketed || dataType !== 'number'; +} export function getContrastColor( color: string, @@ -37,11 +69,8 @@ export function getContrastColor( return enforceColorContrast(color, backgroundColor) ? lightColor : darkColor; } -export function getNumericValue(rowValue: number | number[] | undefined) { - if (rowValue == null || Array.isArray(rowValue)) { - return; - } - return rowValue; +export function getNumericValue(rowValue?: unknown) { + return typeof rowValue === 'number' ? rowValue : undefined; } export function applyPaletteParams>( diff --git a/x-pack/plugins/lens/public/shared_components/palette_picker.tsx b/x-pack/plugins/lens/public/shared_components/palette_picker.tsx index 6796eee37a542..24c6b05e6b6e1 100644 --- a/x-pack/plugins/lens/public/shared_components/palette_picker.tsx +++ b/x-pack/plugins/lens/public/shared_components/palette_picker.tsx @@ -12,17 +12,14 @@ import { EuiColorPalettePicker, EuiColorPalettePickerPaletteProps } from '@elast import { EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -export function PalettePicker({ - palettes, - activePalette, - setPalette, -}: { +interface PalettePickerProps { palettes: PaletteRegistry; - activePalette?: PaletteOutput; + activePalette?: PaletteOutput; setPalette: (palette: PaletteOutput) => void; -}) { - const paletteName = getActivePaletteName(activePalette?.name); +} +export function PalettePicker({ palettes, activePalette, setPalette }: PalettePickerProps) { + const paletteName = getActivePaletteName(activePalette?.name); const palettesToShow: EuiColorPalettePickerPaletteProps[] = palettes .getAll() .filter(({ internal }) => !internal) @@ -34,6 +31,7 @@ export function PalettePicker({ palette: getCategoricalColors(10, id === paletteName ? activePalette?.params : undefined), }; }); + return ( { const { datasourceState: syncedDatasourceState, visualizationState: syncedVisualizationState, + frame, } = syncLinkedDimensions( currentState, visualizationMap, @@ -627,7 +628,11 @@ export const makeLensReducer = (storeDeps: LensStoreDeps) => { payload.datasourceId ); - state.visualization.state = syncedVisualizationState; + const visualization = visualizationMap[state.visualization.activeId!]; + + state.visualization.state = + visualization.onDatasourceUpdate?.(syncedVisualizationState, frame) ?? + syncedVisualizationState; state.datasourceStates[payload.datasourceId].state = syncedDatasourceState; }) .addCase(updateVisualizationState, (state, { payload }) => { @@ -1227,14 +1232,14 @@ function syncLinkedDimensions( const linkedDimensions = activeVisualization.getLinkedDimensions?.(visualizationState); const frame = selectFramePublicAPI({ lens: state }, datasourceMap); - const getDimensionGroups = (layerId: string) => - activeVisualization.getConfiguration({ - state: visualizationState, - layerId, - frame, - }).groups; - if (linkedDimensions) { + const getDimensionGroups = (layerId: string) => + activeVisualization.getConfiguration({ + state: visualizationState, + layerId, + frame, + }).groups; + const idAssuredLinks = linkedDimensions.map((link) => ({ ...link, to: { ...link.to, columnId: link.to.columnId ?? generateId() }, @@ -1276,5 +1281,5 @@ function syncLinkedDimensions( }); } - return { datasourceState, visualizationState }; + return { datasourceState, visualizationState, frame }; } diff --git a/x-pack/plugins/lens/public/types.ts b/x-pack/plugins/lens/public/types.ts index 6af614357b89b..65a27f0afea25 100644 --- a/x-pack/plugins/lens/public/types.ts +++ b/x-pack/plugins/lens/public/types.ts @@ -1317,6 +1317,8 @@ export interface Visualization) => T; + onDatasourceUpdate?: (state: T, frame?: FramePublicAPI) => T; + /** * Some visualization track indexPattern changes (i.e. annotations) * This method makes it aware of the change and produces a new updated state diff --git a/x-pack/plugins/lens/public/utils.test.ts b/x-pack/plugins/lens/public/utils.test.ts index e775059586aff..58366d38161b0 100644 --- a/x-pack/plugins/lens/public/utils.test.ts +++ b/x-pack/plugins/lens/public/utils.test.ts @@ -7,7 +7,7 @@ import { createDatatableUtilitiesMock } from '@kbn/data-plugin/common/mocks'; import { Datatable } from '@kbn/expressions-plugin/public'; -import { getUniqueLabelGenerator, inferTimeField, renewIDs } from './utils'; +import { getUniqueLabelGenerator, inferTimeField, isLensRange, renewIDs } from './utils'; const datatableUtilities = createDatatableUtilitiesMock(); @@ -187,4 +187,24 @@ describe('utils', () => { expect([' ', ' '].map(labelGenerator)).toEqual(['[Untitled]', '[Untitled] [1]']); }); }); + + describe('isRange', () => { + it.each<[expected: boolean, input: unknown]>([ + [true, { from: 0, to: 100, label: '' }], + [true, { from: 0, to: null, label: '' }], + [true, { from: null, to: 100, label: '' }], + [false, { from: 0, to: 100 }], + [false, { from: 0, to: null }], + [false, { from: null, to: 100 }], + [false, { from: 0 }], + [false, { to: 100 }], + [false, null], + [false, undefined], + [false, 123], + [false, 'string'], + [false, {}], + ])('should return %s for %j', (expected, input) => { + expect(isLensRange(input)).toBe(expected); + }); + }); }); diff --git a/x-pack/plugins/lens/public/utils.ts b/x-pack/plugins/lens/public/utils.ts index 83d0b841d0b2a..43129161adde1 100644 --- a/x-pack/plugins/lens/public/utils.ts +++ b/x-pack/plugins/lens/public/utils.ts @@ -39,6 +39,7 @@ import { import type { DatasourceStates, VisualizationState } from './state_management'; import type { IndexPatternServiceAPI } from './data_views_service/service'; import { COLOR_MAPPING_OFF_BY_DEFAULT } from '../common/constants'; +import type { RangeTypeLens } from './datasources/form_based/operations/definitions/ranges'; export function getVisualizeGeoFieldMessage(fieldType: string) { return i18n.translate('xpack.lens.visualizeGeoFieldMessage', { @@ -47,6 +48,17 @@ export function getVisualizeGeoFieldMessage(fieldType: string) { }); } +export const isLensRange = (range: unknown = {}): range is RangeTypeLens => { + if (!range || typeof range !== 'object') return false; + const { from, to, label } = range as RangeTypeLens; + + return ( + label !== undefined && + (typeof from === 'number' || from === null) && + (typeof to === 'number' || to === null) + ); +}; + export const getResolvedDateRange = function (timefilter: TimefilterContract) { const { from, to } = timefilter.getTime(); return { fromDate: from, toDate: to }; diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/cell_value.test.tsx b/x-pack/plugins/lens/public/visualizations/datatable/components/cell_value.test.tsx index ba436f0a588fa..76b8fc7b61740 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/cell_value.test.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/cell_value.test.tsx @@ -10,13 +10,16 @@ import { DataContext } from './table_basic'; import { createGridCell } from './cell_value'; import type { FieldFormat } from '@kbn/field-formats-plugin/common'; import { Datatable } from '@kbn/expressions-plugin/public'; -import { coreMock } from '@kbn/core/public/mocks'; -import { DatatableArgs, ColumnConfigArg } from '../../../../common/expressions'; +import { DatatableArgs } from '../../../../common/expressions'; import { DataContextType } from './types'; -import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import { render, screen } from '@testing-library/react'; +import { getTransposeId } from '../../../../common/expressions/datatable/transpose_helpers'; describe('datatable cell renderer', () => { + const innerCellColorFnMock = jest.fn().mockReturnValue('blue'); + const cellColorFnMock = jest.fn().mockReturnValue(innerCellColorFnMock); + const setCellProps = jest.fn(); + const table: Datatable = { type: 'datatable', columns: [ @@ -30,18 +33,16 @@ describe('datatable cell renderer', () => { ], rows: [{ a: 123 }], }; - const { theme: setUpMockTheme } = coreMock.createSetup(); const CellRenderer = createGridCell( { a: { convert: (x) => `formatted ${x}` } as FieldFormat, }, { columns: [], sortingColumnId: '', sortingDirection: 'none' }, DataContext, - setUpMockTheme + false, + cellColorFnMock ); - const setCellProps = jest.fn(); - afterEach(() => { jest.clearAllMocks(); }); @@ -101,7 +102,8 @@ describe('datatable cell renderer', () => { }, { columns: [], sortingColumnId: '', sortingDirection: 'none' }, DataContext, - setUpMockTheme, + false, + cellColorFnMock, true ); render( @@ -137,7 +139,8 @@ describe('datatable cell renderer', () => { sortingDirection: 'none', }, DataContext, - setUpMockTheme, + false, + cellColorFnMock, true ); render( @@ -156,9 +159,6 @@ describe('datatable cell renderer', () => { }); describe('dynamic coloring', () => { - const paletteRegistry = chartPluginMock.createPaletteRegistry(); - const customPalette = paletteRegistry.get('custom'); - function getCellRenderer(columnConfig: DatatableArgs) { return createGridCell( { @@ -166,7 +166,8 @@ describe('datatable cell renderer', () => { }, columnConfig, DataContext, - setUpMockTheme + false, + cellColorFnMock ); } function getColumnConfiguration(): DatatableArgs { @@ -189,7 +190,7 @@ describe('datatable cell renderer', () => { }, }, type: 'lens_datatable_column', - } as ColumnConfigArg, + }, ], sortingColumnId: '', sortingDirection: 'none', @@ -207,7 +208,7 @@ describe('datatable cell renderer', () => { { { wrapper: DataContextProviderWrapper({ table, - minMaxByColumnId: { a: { min: 12, max: 155 /* > 123 */ } }, - getColorForValue: customPalette.getColorForValue, + minMaxByColumnId: { a: { min: 12, max: 155 } }, ...context, }), } @@ -241,6 +241,27 @@ describe('datatable cell renderer', () => { }); }); + it('should call getCellColor with full columnId of transpose column', () => { + const columnId = getTransposeId('test', 'a'); + const columnConfig = getColumnConfiguration(); + columnConfig.columns[0].colorMode = 'cell'; + columnConfig.columns[0].columnId = columnId; + + renderCellComponent(columnConfig, { + table: { + ...table, + columns: [ + { + ...table.columns[0], + id: columnId, + }, + ], + }, + }); + + expect(cellColorFnMock.mock.calls[0][0]).toBe(columnId); + }); + it('should set the coloring of the text when enabled', () => { const columnConfig = getColumnConfiguration(); columnConfig.columns[0].colorMode = 'text'; @@ -252,14 +273,23 @@ describe('datatable cell renderer', () => { }); }); - it('should not color the cell when the value is an array', () => { + it('should not color the cell when color function returns null', () => { setCellProps.mockClear(); + innerCellColorFnMock.mockReturnValueOnce(null); const columnConfig = getColumnConfiguration(); columnConfig.columns[0].colorMode = 'cell'; - renderCellComponent(columnConfig, { - table: { ...table, rows: [{ a: [10, 123] }] }, - }); + renderCellComponent(columnConfig, {}); + + expect(setCellProps).not.toHaveBeenCalled(); + }); + + it('should not color the cell when color function returns empty string', () => { + innerCellColorFnMock.mockReturnValueOnce(''); + const columnConfig = getColumnConfiguration(); + columnConfig.columns[0].colorMode = 'cell'; + + renderCellComponent(columnConfig, {}); expect(setCellProps).not.toHaveBeenCalled(); }); diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/cell_value.tsx b/x-pack/plugins/lens/public/visualizations/datatable/components/cell_value.tsx index a0a01f795ca19..0761c7904e75f 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/cell_value.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/cell_value.tsx @@ -6,63 +6,73 @@ */ import React, { useContext, useEffect } from 'react'; -import useObservable from 'react-use/lib/useObservable'; import { EuiDataGridCellValueElementProps, EuiLink } from '@elastic/eui'; -import type { CoreSetup } from '@kbn/core/public'; import classNames from 'classnames'; +import { PaletteOutput } from '@kbn/coloring'; +import { CustomPaletteState } from '@kbn/charts-plugin/common'; import type { FormatFactory } from '../../../../common/types'; -import { getOriginalId } from '../../../../common/expressions/datatable/transpose_helpers'; -import type { ColumnConfig } from '../../../../common/expressions'; +import type { DatatableColumnConfig } from '../../../../common/expressions'; import type { DataContextType } from './types'; -import { getContrastColor, getNumericValue } from '../../../shared_components/coloring/utils'; +import { getContrastColor } from '../../../shared_components/coloring/utils'; +import { CellColorFn } from '../../../shared_components/coloring/get_cell_color_fn'; + +import { isLensRange } from '../../../utils'; + +const getParsedValue = (v: unknown) => { + if (v == null || typeof v === 'number') { + return v; + } + if (isLensRange(v)) { + return v.toString(); + } + return String(v); +}; export const createGridCell = ( formatters: Record>, - columnConfig: ColumnConfig, + columnConfig: DatatableColumnConfig, DataContext: React.Context, - theme: CoreSetup['theme'], + isDarkMode: boolean, + getCellColor: ( + originalId: string, + palette?: PaletteOutput, + colorMapping?: string + ) => CellColorFn, fitRowToContent?: boolean ) => { return ({ rowIndex, columnId, setCellProps, isExpanded }: EuiDataGridCellValueElementProps) => { - const { table, alignments, minMaxByColumnId, getColorForValue, handleFilterClick } = - useContext(DataContext); - const IS_DARK_THEME: boolean = useObservable(theme.theme$, { darkMode: false }).darkMode; - - const rowValue = table?.rows[rowIndex]?.[columnId]; - + const { table, alignments, handleFilterClick } = useContext(DataContext); + const rawRowValue = table?.rows[rowIndex]?.[columnId]; + const rowValue = getParsedValue(rawRowValue); const colIndex = columnConfig.columns.findIndex(({ columnId: id }) => id === columnId); - const { colorMode = 'none', palette, oneClickFilter } = columnConfig.columns[colIndex] || {}; + const { + oneClickFilter, + colorMode = 'none', + palette, + colorMapping, + } = columnConfig.columns[colIndex] ?? {}; const filterOnClick = oneClickFilter && handleFilterClick; - - const content = formatters[columnId]?.convert(rowValue, filterOnClick ? 'text' : 'html'); + const content = formatters[columnId]?.convert(rawRowValue, filterOnClick ? 'text' : 'html'); const currentAlignment = alignments && alignments[columnId]; useEffect(() => { let colorSet = false; - const originalId = getOriginalId(columnId); - if (minMaxByColumnId?.[originalId]) { - if (colorMode !== 'none' && palette?.params && getColorForValue) { - // workout the bucket the value belongs to - const color = getColorForValue( - getNumericValue(rowValue), - palette.params, - minMaxByColumnId[originalId] - ); - if (color) { - const style = { [colorMode === 'cell' ? 'backgroundColor' : 'color']: color }; - if (colorMode === 'cell' && color) { - style.color = getContrastColor(color, IS_DARK_THEME); - } - colorSet = true; - setCellProps({ - style, - }); + if (colorMode !== 'none' && (palette || colorMapping)) { + const color = getCellColor(columnId, palette, colorMapping)(rowValue); + + if (color) { + const style = { [colorMode === 'cell' ? 'backgroundColor' : 'color']: color }; + if (colorMode === 'cell' && color) { + style.color = getContrastColor(color, isDarkMode); } + colorSet = true; + setCellProps({ style }); } } + // Clean up styles when something changes, this avoids cell's styling to stick forever // Checks isExpanded to prevent clearing style after expanding cell - if (colorMode !== 'none' && minMaxByColumnId?.[originalId] && colorSet && !isExpanded) { + if (colorSet && !isExpanded) { return () => { setCellProps({ style: { @@ -72,17 +82,7 @@ export const createGridCell = ( }); }; } - }, [ - rowValue, - columnId, - setCellProps, - colorMode, - palette, - minMaxByColumnId, - getColorForValue, - IS_DARK_THEME, - isExpanded, - ]); + }, [rowValue, columnId, setCellProps, colorMode, palette, colorMapping, isExpanded]); if (filterOnClick) { return ( @@ -95,7 +95,7 @@ export const createGridCell = ( > { - handleFilterClick?.(columnId, rowValue, colIndex, rowIndex); + handleFilterClick?.(columnId, rawRowValue, colIndex, rowIndex); }} > {content} @@ -103,6 +103,7 @@ export const createGridCell = (
); } + return (
diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/columns.tsx b/x-pack/plugins/lens/public/visualizations/datatable/components/columns.tsx index 99bc648f8bf6d..6cd8c32db4b6d 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/columns.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/columns.tsx @@ -18,7 +18,7 @@ import { EuiDataGridColumnCellAction } from '@elastic/eui/src/components/datagri import { FILTER_CELL_ACTION_TYPE } from '@kbn/cell-actions/constants'; import type { FormatFactory } from '../../../../common/types'; import { RowHeightMode } from '../../../../common/types'; -import type { ColumnConfig } from '../../../../common/expressions'; +import type { DatatableColumnConfig } from '../../../../common/expressions'; import { LensCellValueAction } from '../../../types'; import { buildColumnsMetaLookup } from './helpers'; import { DEFAULT_HEADER_ROW_HEIGHT } from './constants'; @@ -46,7 +46,7 @@ export const createGridColumns = ( ) => void) | undefined, isReadOnly: boolean, - columnConfig: ColumnConfig, + columnConfig: DatatableColumnConfig, visibleColumns: string[], formatFactory: FormatFactory, onColumnResize: (eventData: { columnId: string; width: number | undefined }) => void, diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor.test.tsx b/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor.test.tsx index 133b18bb3ce67..f58b66dba20d3 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor.test.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor.test.tsx @@ -6,28 +6,36 @@ */ import React from 'react'; -import type { PaletteRegistry } from '@kbn/coloring'; -import { render, screen } from '@testing-library/react'; +import { DEFAULT_COLOR_MAPPING_CONFIG, type PaletteRegistry } from '@kbn/coloring'; +import { act, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; -import { getSelectedButtonInGroup } from '@kbn/test-eui-helpers'; +import { EuiButtonGroupTestHarness } from '@kbn/test-eui-helpers'; import { FramePublicAPI, OperationDescriptor, VisualizationDimensionEditorProps, DatasourcePublicAPI, + DataType, } from '../../../types'; import { DatatableVisualizationState } from '../visualization'; import { createMockDatasource, createMockFramePublicAPI } from '../../../mocks'; import { TableDimensionEditor } from './dimension_editor'; +import { ColumnState } from '../../../../common/expressions'; +import { capitalize } from 'lodash'; describe('data table dimension editor', () => { let frame: FramePublicAPI; let state: DatatableVisualizationState; - let setState: (newState: DatatableVisualizationState) => void; + let btnGroups: { + colorMode: EuiButtonGroupTestHarness; + alignment: EuiButtonGroupTestHarness; + }; + let mockOperationForFirstColumn: (overrides?: Partial) => void; let props: VisualizationDimensionEditorProps & { paletteService: PaletteRegistry; + isDarkMode: boolean; }; function testState(): DatatableVisualizationState { @@ -42,7 +50,19 @@ describe('data table dimension editor', () => { }; } + beforeAll(() => { + jest.useFakeTimers(); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + beforeEach(() => { + btnGroups = { + colorMode: new EuiButtonGroupTestHarness('lnsDatatable_dynamicColoring_groups'), + alignment: new EuiButtonGroupTestHarness('lnsDatatable_alignment_groups'), + }; state = testState(); frame = createMockFramePublicAPI(); frame.datasourceLayers = { @@ -63,21 +83,32 @@ describe('data table dimension editor', () => { rows: [], }, }; - setState = jest.fn(); - props = { accessor: 'foo', frame, groupId: 'columns', layerId: 'first', state, - setState, + setState: jest.fn(), + isDarkMode: false, paletteService: chartPluginMock.createPaletteRegistry(), panelRef: React.createRef(), addLayer: jest.fn(), removeLayer: jest.fn(), datasource: {} as DatasourcePublicAPI, }; + + mockOperationForFirstColumn = (overrides: Partial = {}) => { + frame!.datasourceLayers!.first!.getOperationForColumnId = jest.fn().mockReturnValue({ + label: 'label', + isBucketed: false, + dataType: 'string', + hasTimeShift: false, + hasReducedTimeRange: false, + ...overrides, + } satisfies OperationDescriptor); + }; + mockOperationForFirstColumn(); }); const renderTableDimensionEditor = ( @@ -99,19 +130,19 @@ describe('data table dimension editor', () => { it('should render default alignment', () => { renderTableDimensionEditor(); - expect(getSelectedButtonInGroup('lnsDatatable_alignment_groups')()).toHaveTextContent('Left'); + expect(btnGroups.alignment.selected).toHaveTextContent('Left'); }); it('should render default alignment for number', () => { - frame.activeData!.first.columns[0].meta.type = 'number'; + mockOperationForFirstColumn({ dataType: 'number' }); renderTableDimensionEditor(); - expect(getSelectedButtonInGroup('lnsDatatable_alignment_groups')()).toHaveTextContent('Right'); + expect(btnGroups.alignment.selected).toHaveTextContent('Right'); }); it('should render specific alignment', () => { state.columns[0].alignment = 'center'; renderTableDimensionEditor(); - expect(getSelectedButtonInGroup('lnsDatatable_alignment_groups')()).toHaveTextContent('Center'); + expect(btnGroups.alignment.selected).toHaveTextContent('Center'); }); it('should set state for the right column', () => { @@ -125,7 +156,8 @@ describe('data table dimension editor', () => { ]; renderTableDimensionEditor(); userEvent.click(screen.getByRole('button', { name: 'Center' })); - expect(setState).toHaveBeenCalledWith({ + jest.advanceTimersByTime(256); + expect(props.setState).toHaveBeenCalledWith({ ...state, columns: [ { @@ -139,44 +171,49 @@ describe('data table dimension editor', () => { }); }); - it('should not show the dynamic coloring option for non numeric columns', () => { - renderTableDimensionEditor(); - expect(screen.queryByTestId('lnsDatatable_dynamicColoring_groups')).not.toBeInTheDocument(); - expect(screen.queryByTestId('lns_dynamicColoring_edit')).not.toBeInTheDocument(); - }); - it('should set the dynamic coloring default to "none"', () => { - frame.activeData!.first.columns[0].meta.type = 'number'; + state.columns[0].colorMode = undefined; renderTableDimensionEditor(); - expect(getSelectedButtonInGroup('lnsDatatable_dynamicColoring_groups')()).toHaveTextContent( - 'None' - ); + expect(btnGroups.colorMode.selected).toHaveTextContent('None'); expect(screen.queryByTestId('lns_dynamicColoring_edit')).not.toBeInTheDocument(); }); - it('should show the dynamic palette display ony when colorMode is different from "none"', () => { - frame.activeData!.first.columns[0].meta.type = 'number'; - state.columns[0].colorMode = 'text'; - renderTableDimensionEditor(); - expect(getSelectedButtonInGroup('lnsDatatable_dynamicColoring_groups')()).toHaveTextContent( - 'Text' - ); - expect(screen.getByTestId('lns_dynamicColoring_edit')).toBeInTheDocument(); - }); + it.each(['date'])( + 'should not show the dynamic coloring option for "%s" columns', + (dataType) => { + mockOperationForFirstColumn({ dataType }); + renderTableDimensionEditor(); + expect(screen.queryByTestId('lnsDatatable_dynamicColoring_groups')).not.toBeInTheDocument(); + expect(screen.queryByTestId('lns_dynamicColoring_edit')).not.toBeInTheDocument(); + } + ); + + it.each(['cell', 'text'])( + 'should show the palette options ony when colorMode is "%s"', + (colorMode) => { + state.columns[0].colorMode = colorMode; + renderTableDimensionEditor(); + expect(btnGroups.colorMode.selected).toHaveTextContent(capitalize(colorMode)); + expect(screen.getByTestId('lns_dynamicColoring_edit')).toBeInTheDocument(); + } + ); + + it.each(['none', undefined])( + 'should not show the palette options when colorMode is "%s"', + (colorMode) => { + state.columns[0].colorMode = colorMode; + renderTableDimensionEditor(); + expect(btnGroups.colorMode.selected).toHaveTextContent(capitalize(colorMode ?? 'none')); + expect(screen.queryByTestId('lns_dynamicColoring_edit')).not.toBeInTheDocument(); + } + ); it('should set the coloring mode to the right column', () => { - frame.activeData!.first.columns[0].meta.type = 'number'; - state.columns = [ - { - columnId: 'foo', - }, - { - columnId: 'bar', - }, - ]; + state.columns = [{ columnId: 'foo' }, { columnId: 'bar' }]; renderTableDimensionEditor(); userEvent.click(screen.getByRole('button', { name: 'Cell' })); - expect(setState).toHaveBeenCalledWith({ + jest.advanceTimersByTime(256); + expect(props.setState).toHaveBeenCalledWith({ ...state, columns: [ { @@ -191,31 +228,73 @@ describe('data table dimension editor', () => { }); }); - it('should open the palette panel when "Settings" link is clicked in the palette input', () => { - frame.activeData!.first.columns[0].meta.type = 'number'; + it.each<{ flyout: 'terms' | 'values'; isBucketed: boolean; dataType: DataType }>([ + { flyout: 'terms', isBucketed: true, dataType: 'number' }, + { flyout: 'terms', isBucketed: false, dataType: 'string' }, + { flyout: 'values', isBucketed: false, dataType: 'number' }, + ])( + 'should show color by $flyout flyout when bucketing is $isBucketed with $dataType column', + ({ flyout, isBucketed, dataType }) => { + state.columns[0].colorMode = 'cell'; + mockOperationForFirstColumn({ isBucketed, dataType }); + renderTableDimensionEditor(); + + userEvent.click(screen.getByLabelText('Edit colors')); + + expect(screen.getByTestId(`lns-palettePanel-${flyout}`)).toBeInTheDocument(); + } + ); + + it('should show the dynamic coloring option for a bucketed operation', () => { state.columns[0].colorMode = 'cell'; + mockOperationForFirstColumn({ isBucketed: true }); renderTableDimensionEditor(); - userEvent.click(screen.getByLabelText('Edit colors')); - expect(screen.getByTestId('lns-palettePanelFlyout')).toBeInTheDocument(); + expect(screen.queryByTestId('lnsDatatable_dynamicColoring_groups')).toBeInTheDocument(); + expect(screen.queryByTestId('lns_dynamicColoring_edit')).toBeInTheDocument(); }); - it('should not show the dynamic coloring option for a bucketed operation', () => { - frame.activeData!.first.columns[0].meta.type = 'number'; - const datasourceLayers = frame.datasourceLayers as Record; - datasourceLayers.first.getOperationForColumnId = jest.fn( - () => ({ isBucketed: true } as OperationDescriptor) - ); + it('should clear palette and colorMapping when colorMode is set to "none"', () => { state.columns[0].colorMode = 'cell'; + state.columns[0].palette = { + type: 'palette', + name: 'default', + }; + state.columns[0].colorMapping = DEFAULT_COLOR_MAPPING_CONFIG; renderTableDimensionEditor(); - expect(screen.queryByTestId('lnsDatatable_dynamicColoring_groups')).not.toBeInTheDocument(); - expect(screen.queryByTestId('lns_dynamicColoring_edit')).not.toBeInTheDocument(); + + act(() => { + // this throws an error about state update even in act() + btnGroups.colorMode.select('None'); + }); + + jest.advanceTimersByTime(256); + expect(props.setState).toBeCalledWith({ + ...state, + columns: [ + expect.objectContaining({ + colorMode: 'none', + palette: undefined, + colorMapping: undefined, + }), + ], + }); }); - it('should not show the summary field for non numeric columns', () => { - renderTableDimensionEditor(); - expect(screen.queryByTestId('lnsDatatable_summaryrow_function')).not.toBeInTheDocument(); - expect(screen.queryByTestId('lnsDatatable_summaryrow_label')).not.toBeInTheDocument(); + [true, false].forEach((isTransposed) => { + it(`should${isTransposed ? ' not' : ''} show hidden switch when column is${ + !isTransposed ? ' not' : '' + } transposed`, () => { + state.columns[0].isTransposed = isTransposed; + renderTableDimensionEditor(); + + const hiddenSwitch = screen.queryByTestId('lns-table-column-hidden'); + if (isTransposed) { + expect(hiddenSwitch).not.toBeInTheDocument(); + } else { + expect(hiddenSwitch).toBeInTheDocument(); + } + }); }); }); diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor.tsx index 2ffe06144ff48..c1e097276cf3d 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor.tsx @@ -5,37 +5,40 @@ * 2.0. */ -import React from 'react'; +import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFormRow, EuiSwitch, EuiButtonGroup, htmlIdGenerator } from '@elastic/eui'; -import { CustomizablePalette, PaletteRegistry } from '@kbn/coloring'; +import { PaletteRegistry } from '@kbn/coloring'; +import { getColorCategories } from '@kbn/chart-expressions-common'; +import { useDebouncedValue } from '@kbn/visualization-utils'; import type { VisualizationDimensionEditorProps } from '../../../types'; import type { DatatableVisualizationState } from '../visualization'; import { applyPaletteParams, defaultPaletteParams, - PalettePanelContainer, findMinMaxByColumnId, + shouldColorByTerms, } from '../../../shared_components'; -import { isNumericFieldForDatatable } from '../../../../common/expressions/datatable/utils'; import { getOriginalId } from '../../../../common/expressions/datatable/transpose_helpers'; import './dimension_editor.scss'; import { CollapseSetting } from '../../../shared_components/collapse_setting'; +import { ColorMappingByValues } from '../../../shared_components/coloring/color_mapping_by_values'; +import { ColorMappingByTerms } from '../../../shared_components/coloring/color_mapping_by_terms'; const idPrefix = htmlIdGenerator()(); type ColumnType = DatatableVisualizationState['columns'][number]; -function updateColumnWith( +function updateColumn( state: DatatableVisualizationState, columnId: string, - newColumnProps: Partial + newColumn: Partial ) { return state.columns.map((currentColumn) => { if (currentColumn.columnId === columnId) { - return { ...currentColumn, ...newColumnProps }; + return { ...currentColumn, ...newColumn }; } else { return currentColumn; } @@ -45,30 +48,41 @@ function updateColumnWith( export function TableDimensionEditor( props: VisualizationDimensionEditorProps & { paletteService: PaletteRegistry; + isDarkMode: boolean; } ) { - const { state, setState, frame, accessor, isInlineEditing } = props; - const column = state.columns.find(({ columnId }) => accessor === columnId); + const { frame, accessor, isInlineEditing, isDarkMode } = props; + const column = props.state.columns.find(({ columnId }) => accessor === columnId); + const { inputValue: localState, handleInputChange: setLocalState } = + useDebouncedValue({ + value: props.state, + onChange: props.setState, + }); + + const updateColumnState = useCallback( + (columnId: string, newColumn: Partial) => { + setLocalState({ + ...localState, + columns: updateColumn(localState, columnId, newColumn), + }); + }, + [setLocalState, localState] + ); if (!column) return null; if (column.isTransposed) return null; - const currentData = frame.activeData?.[state.layerId]; - - // either read config state or use same logic as chart itself - const isNumeric = isNumericFieldForDatatable(currentData, accessor); - const currentAlignment = column?.alignment || (isNumeric ? 'right' : 'left'); + const currentData = frame.activeData?.[localState.layerId]; + const datasource = frame.datasourceLayers?.[localState.layerId]; + const { dataType, isBucketed } = datasource?.getOperationForColumnId(accessor) ?? {}; + const showColorByTerms = shouldColorByTerms(dataType, isBucketed); + const currentAlignment = column?.alignment || (dataType === 'number' ? 'right' : 'left'); const currentColorMode = column?.colorMode || 'none'; const hasDynamicColoring = currentColorMode !== 'none'; + const showDynamicColoringFeature = dataType !== 'date'; + const visibleColumnsCount = localState.columns.filter((c) => !c.hidden).length; - const datasource = frame.datasourceLayers[state.layerId]; - const showDynamicColoringFeature = Boolean( - isNumeric && !datasource?.getOperationForColumnId(accessor)?.isBucketed - ); - - const visibleColumnsCount = state.columns.filter((c) => !c.hidden).length; - - const hasTransposedColumn = state.columns.some(({ isTransposed }) => isTransposed); + const hasTransposedColumn = localState.columns.some(({ isTransposed }) => isTransposed); const columnsToCheck = hasTransposedColumn ? currentData?.columns.filter(({ id }) => getOriginalId(id) === accessor).map(({ id }) => id) || [] @@ -76,12 +90,13 @@ export function TableDimensionEditor( const minMaxByColumnId = findMinMaxByColumnId(columnsToCheck, currentData, getOriginalId); const currentMinMax = minMaxByColumnId[accessor]; - const activePalette = column?.palette || { + const activePalette = column?.palette ?? { type: 'palette', - name: defaultPaletteParams.name, + name: showColorByTerms ? 'default' : defaultPaletteParams.name, }; // need to tell the helper that the colorStops are required to display const displayStops = applyPaletteParams(props.paletteService, activePalette, currentMinMax); + const categories = getColorCategories(currentData?.rows ?? [], accessor, false, [null]); return ( <> @@ -125,10 +140,7 @@ export function TableDimensionEditor( idSelected={`${idPrefix}${currentAlignment}`} onChange={(id) => { const newMode = id.replace(idPrefix, '') as ColumnType['alignment']; - setState({ - ...state, - columns: updateColumnWith(state, accessor, { alignment: newMode }), - }); + updateColumnState(accessor, { alignment: newMode }); }} /> @@ -187,45 +199,46 @@ export function TableDimensionEditor( }, }; } + // clear up when switching to no coloring - if (column?.palette && newMode === 'none') { + if (newMode === 'none') { params.palette = undefined; + params.colorMapping = undefined; } - setState({ - ...state, - columns: updateColumnWith(state, accessor, params), - }); + updateColumnState(accessor, params); }} /> - {hasDynamicColoring && ( - - color)} - siblingRef={props.panelRef} + + {hasDynamicColoring && + (showColorByTerms ? ( + { + updateColumnState(accessor, { palette }); + }} + setColorMapping={(colorMapping) => { + updateColumnState(accessor, { colorMapping }); + }} + paletteService={props.paletteService} + panelRef={props.panelRef} + categories={categories} + /> + ) : ( + - { - setState({ - ...state, - columns: updateColumnWith(state, accessor, { palette: newPalette }), - }); - }} - /> - - - )} + setPalette={(newPalette) => { + updateColumnState(accessor, { palette: newPalette }); + }} + paletteService={props.paletteService} + panelRef={props.panelRef} + dataBounds={currentMinMax} + /> + ))} )} {!column.isTransposed && ( @@ -247,8 +260,8 @@ export function TableDimensionEditor( disabled={!column.hidden && visibleColumnsCount <= 1} onChange={() => { const newState = { - ...state, - columns: state.columns.map((currentColumn) => { + ...localState, + columns: localState.columns.map((currentColumn) => { if (currentColumn.columnId === accessor) { return { ...currentColumn, @@ -259,7 +272,7 @@ export function TableDimensionEditor( } }), }; - setState(newState); + setLocalState(newState); }} /> @@ -283,8 +296,8 @@ export function TableDimensionEditor( disabled={column.hidden} onChange={() => { const newState = { - ...state, - columns: state.columns.map((currentColumn) => { + ...localState, + columns: localState.columns.map((currentColumn) => { if (currentColumn.columnId === accessor) { return { ...currentColumn, @@ -295,7 +308,7 @@ export function TableDimensionEditor( } }), }; - setState(newState); + setLocalState(newState); }} /> @@ -323,7 +336,7 @@ export function TableDimensionDataExtraEditor( onChange={(collapseFn) => { setState({ ...state, - columns: updateColumnWith(state, accessor, { collapseFn }), + columns: updateColumn(state, accessor, { collapseFn }), }); }} /> diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor_additional_section.test.tsx b/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor_additional_section.test.tsx index b55f637f3cbb3..a12e10d4585c2 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor_additional_section.test.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor_additional_section.test.tsx @@ -18,11 +18,11 @@ import { import { DatatableVisualizationState } from '../visualization'; import { createMockDatasource, createMockFramePublicAPI } from '../../../mocks'; import { TableDimensionEditorAdditionalSection } from './dimension_editor_addtional_section'; +import { ColumnState } from '../../../../common/expressions'; describe('data table dimension editor additional section', () => { let frame: FramePublicAPI; let state: DatatableVisualizationState; - let setState: (newState: DatatableVisualizationState) => void; let props: VisualizationDimensionEditorProps & { paletteService: PaletteRegistry; }; @@ -34,6 +34,7 @@ describe('data table dimension editor additional section', () => { columns: [ { columnId: 'foo', + summaryRow: undefined, }, ], }; @@ -53,21 +54,20 @@ describe('data table dimension editor additional section', () => { id: 'foo', name: 'foo', meta: { - type: 'string', + type: 'number', }, }, ], rows: [], }, }; - setState = jest.fn(); props = { accessor: 'foo', frame, groupId: 'columns', layerId: 'first', state, - setState, + setState: jest.fn(), paletteService: chartPluginMock.createPaletteRegistry(), panelRef: React.createRef(), addLayer: jest.fn(), @@ -76,27 +76,50 @@ describe('data table dimension editor additional section', () => { }; }); - it('should set the summary row function default to "none"', () => { - frame.activeData!.first.columns[0].meta.type = 'number'; - render(); + const renderComponent = ( + overrideProps?: Partial< + VisualizationDimensionEditorProps & { + paletteService: PaletteRegistry; + } + > + ) => { + return render(); + }; + + it('should set the summary row fn default to "none"', () => { + state.columns[0].summaryRow = undefined; + renderComponent(); expect(screen.getByRole('combobox')).toHaveValue('None'); expect(screen.queryByTestId('lnsDatatable_summaryrow_label')).not.toBeInTheDocument(); }); - it('should show the summary row label input ony when summary row is different from "none"', () => { - frame.activeData!.first.columns[0].meta.type = 'number'; - state.columns[0].summaryRow = 'sum'; - render(); - expect(screen.getByRole('combobox')).toHaveValue('Sum'); - expect(screen.getByTestId('lnsDatatable_summaryrow_label')).toHaveValue('Sum'); - }); + it.each<[summaryRow: ColumnState['summaryRow'], label: string]>([ + ['sum', 'Sum'], + ['avg', 'Average'], + ['count', 'Value count'], + ['min', 'Minimum'], + ['max', 'Maximum'], + ])( + 'should show the summary row label input ony when summary row fn is "%s"', + (summaryRow, label) => { + state.columns[0].summaryRow = summaryRow; + renderComponent(); + expect(screen.getByRole('combobox')).toHaveValue(label); + expect(screen.getByTestId('lnsDatatable_summaryrow_label')).toHaveValue(label); + } + ); it("should show the correct summary row name when user's changes summary label", () => { - frame.activeData!.first.columns[0].meta.type = 'number'; state.columns[0].summaryRow = 'sum'; state.columns[0].summaryLabel = 'MySum'; - render(); + renderComponent(); expect(screen.getByRole('combobox')).toHaveValue('Sum'); expect(screen.getByTestId('lnsDatatable_summaryrow_label')).toHaveValue('MySum'); }); + + it('should not show the summary field for non numeric columns', () => { + frame.activeData!.first.columns[0].meta.type = 'string'; + expect(screen.queryByTestId('lnsDatatable_summaryrow_function')).not.toBeInTheDocument(); + expect(screen.queryByTestId('lnsDatatable_summaryrow_label')).not.toBeInTheDocument(); + }); }); diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor_addtional_section.tsx b/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor_addtional_section.tsx index 62e038d71090c..92268d052cd44 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor_addtional_section.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/dimension_editor_addtional_section.tsx @@ -21,7 +21,6 @@ import { getFinalSummaryConfiguration, getSummaryRowOptions, } from '../../../../common/expressions/datatable/summary'; - import { isNumericFieldForDatatable } from '../../../../common/expressions/datatable/utils'; import './dimension_editor.scss'; @@ -76,7 +75,6 @@ export function TableDimensionEditorAdditionalSection( const currentData = frame.activeData?.[state.layerId]; - // either read config state or use same logic as chart itself const isNumeric = isNumericFieldForDatatable(currentData, accessor); // when switching from one operation to another, make sure to keep the configuration consistent const { summaryRow, summaryLabel: fallbackSummaryLabel } = getFinalSummaryConfiguration( diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/table_actions.test.ts b/x-pack/plugins/lens/public/visualizations/datatable/components/table_actions.test.ts index 2a517acc33084..3b89f32b22ffc 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/table_actions.test.ts +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/table_actions.test.ts @@ -17,9 +17,9 @@ import { createGridHideHandler, createTransposeColumnFilterHandler, } from './table_actions'; -import type { LensGridDirection, ColumnConfig } from '../../../../common/expressions'; +import type { LensGridDirection, DatatableColumnConfig } from '../../../../common/expressions'; -function getDefaultConfig(): ColumnConfig { +function getDefaultConfig(): DatatableColumnConfig { return { columns: [ { columnId: 'a', type: 'lens_datatable_column' }, diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/table_actions.ts b/x-pack/plugins/lens/public/visualizations/datatable/components/table_actions.ts index 8c1c56343b2f5..e53713069fb8f 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/table_actions.ts +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/table_actions.ts @@ -19,19 +19,15 @@ import { ClickTriggerEvent } from '@kbn/charts-plugin/public'; import { getSortingCriteria } from '@kbn/sort-predicates'; import { i18n } from '@kbn/i18n'; import type { LensResizeAction, LensSortAction, LensToggleAction } from './types'; -import type { - ColumnConfig, - ColumnConfigArg, - LensGridDirection, -} from '../../../../common/expressions'; +import type { DatatableColumnConfig, LensGridDirection } from '../../../../common/expressions'; import { getOriginalId } from '../../../../common/expressions/datatable/transpose_helpers'; import type { FormatFactory } from '../../../../common/types'; import { buildColumnsMetaLookup } from './helpers'; export const createGridResizeHandler = ( - columnConfig: ColumnConfig, - setColumnConfig: React.Dispatch>, + columnConfig: DatatableColumnConfig, + setColumnConfig: React.Dispatch>, onEditAction: (data: LensResizeAction['data']) => void ) => (eventData: { columnId: string; width: number | undefined }) => { @@ -59,8 +55,8 @@ export const createGridResizeHandler = export const createGridHideHandler = ( - columnConfig: ColumnConfig, - setColumnConfig: React.Dispatch>, + columnConfig: DatatableColumnConfig, + setColumnConfig: React.Dispatch>, onEditAction: (data: LensToggleAction['data']) => void ) => (eventData: { columnId: string }) => { @@ -177,7 +173,7 @@ function getColumnType({ columnId, lookup, }: { - columnConfig: ColumnConfig; + columnConfig: DatatableColumnConfig; columnId: string; lookup: Record< string, @@ -194,11 +190,7 @@ function getColumnType({ export const buildSchemaDetectors = ( columns: EuiDataGridColumn[], - columnConfig: { - columns: ColumnConfigArg[]; - sortingColumnId: string | undefined; - sortingDirection: 'none' | 'asc' | 'desc'; - }, + columnConfig: DatatableColumnConfig, table: Datatable, formatters: Record> ): EuiDataGridSchemaDetector[] => { diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.test.tsx b/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.test.tsx index 8f3060c037808..3c0243e1b980e 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.test.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.test.tsx @@ -20,6 +20,18 @@ import { DatatableComponent } from './table_basic'; import type { DatatableProps } from '../../../../common/expressions'; import { LENS_EDIT_PAGESIZE_ACTION } from './constants'; import { DatatableRenderProps } from './types'; +import { PaletteOutput } from '@kbn/coloring'; +import { CustomPaletteState } from '@kbn/charts-plugin/common'; +import { getCellColorFn } from '../../../shared_components/coloring/get_cell_color_fn'; +import { getTransposeId } from '../../../../common/expressions/datatable/transpose_helpers'; + +jest.mock('../../../shared_components/coloring/get_cell_color_fn', () => { + const mod = jest.requireActual('../../../shared_components/coloring/get_cell_color_fn'); + return { + ...mod, + getCellColorFn: jest.fn(mod.getCellColorFn), + }; +}); const { theme: setUpMockTheme } = coreMock.createSetup(); @@ -97,8 +109,12 @@ describe('DatatableComponent', () => { args = sample.args; }); + afterEach(() => { + jest.clearAllMocks(); + }); + const renderDatatableComponent = (propsOverrides: Partial = {}) => { - const props = { + const props: DatatableRenderProps = { data, args, formatFactory: () => ({ convert: (x) => x } as IFieldFormat), @@ -108,6 +124,7 @@ describe('DatatableComponent', () => { theme: setUpMockTheme, renderMode: 'edit' as const, interactive: true, + syncColors: false, renderComplete, ...propsOverrides, }; @@ -345,9 +362,9 @@ describe('DatatableComponent', () => { args: { ...args, columns: [ - { columnId: 'a', alignment: 'center', type: 'lens_datatable_column' }, - { columnId: 'b', type: 'lens_datatable_column' }, - { columnId: 'c', type: 'lens_datatable_column' }, + { columnId: 'a', alignment: 'center', type: 'lens_datatable_column', colorMode: 'none' }, + { columnId: 'b', type: 'lens_datatable_column', colorMode: 'none' }, + { columnId: 'c', type: 'lens_datatable_column', colorMode: 'none' }, ], sortingColumnId: 'b', sortingDirection: 'desc', @@ -358,44 +375,10 @@ describe('DatatableComponent', () => { .map((cell) => cell.className); expect(alignmentsClassNames).toEqual([ - // set via args - 'lnsTableCell--center', - // default for date - 'lnsTableCell--left', - // default for number - 'lnsTableCell--right', + 'lnsTableCell--center', // set via args + 'lnsTableCell--left', // default for date + 'lnsTableCell--right', // default for number ]); - // ({ convert: (x) => x } as IFieldFormat)} - // dispatchEvent={onDispatchEvent} - // getType={jest.fn()} - // renderMode="view" - // paletteService={chartPluginMock.createPaletteRegistry()} - // theme={setUpMockTheme} - // interactive - // renderComplete={renderComplete} - // /> - // ); - - // expect(wrapper.find(DataContext.Provider).prop('value').alignments).toEqual({ - // // set via args - // a: 'center', - // // default for date - // b: 'left', - // // default for number - // c: 'right', - // }); }); test('it should refresh the table header when the datatable data changes', () => { @@ -633,4 +616,106 @@ describe('DatatableComponent', () => { ); }); }); + + describe('renderCellValue', () => { + describe('getCellColor', () => { + const palette: PaletteOutput = { + type: 'palette', + name: 'default', + params: { + colors: [], + gradient: false, + stops: [], + range: 'number', + rangeMin: 0, + rangeMax: 100, + }, + }; + + describe('caching', () => { + test('caches getCellColorFn by columnId', () => { + args.columns[0].palette = palette; + args.columns[0].colorMode = 'cell'; + data.rows.push( + ...[ + { a: 'pants', b: 1588024800000, c: 4 }, + { a: 'hat', b: 1588024800000, c: 5 }, + { a: 'bag', b: 1588024800000, c: 6 }, + ] + ); + + renderDatatableComponent(); + + expect(getCellColorFn).toBeCalledTimes(2); // 2 initial renders of table + }); + + test('caches getCellColorFn by columnId with transpose columns', () => { + const columnId1 = getTransposeId('a', 'test'); + const columnId2 = getTransposeId('b', 'test'); + + renderDatatableComponent({ + data: { + ...data, + rows: [{ [columnId1]: 'shoe', [columnId2]: 'hat' }], + columns: [columnId1, columnId2].map((id) => ({ + ...data.columns[0], + id, + })), + }, + args: { + ...args, + columns: [columnId1, columnId2].map((columnId) => ({ + ...args.columns[0], + palette, + colorMode: 'cell', + columnId, + })), + }, + }); + + expect(getCellColorFn).toBeCalledTimes(2); // 2 initial renders of table + }); + }); + + const color = 'red'; + + test('should correctly color numerical values', () => { + args.columns[0].palette = palette; + args.columns[0].colorMode = 'cell'; + + (getCellColorFn as jest.Mock).mockReturnValue(() => color); + + renderDatatableComponent(); + + const cellColors = screen + .queryAllByRole('gridcell') + .map((cell) => [cell.textContent, cell.style.backgroundColor]); + + expect(cellColors).toEqual([ + ['shoes- a, column 1, row 1', 'red'], + ['1588024800000- b, column 2, row 1', ''], + ['3- c, column 3, row 1', ''], + ]); + }); + + test('should correctly color string values', () => { + args.columns[2].palette = palette; + args.columns[2].colorMode = 'cell'; + + (getCellColorFn as jest.Mock).mockReturnValue(() => color); + + renderDatatableComponent(); + + const cellColors = screen + .queryAllByRole('gridcell') + .map((cell) => [cell.textContent, cell.style.backgroundColor]); + + expect(cellColors).toEqual([ + ['shoes- a, column 1, row 1', ''], + ['1588024800000- b, column 2, row 1', ''], + ['3- c, column 3, row 1', 'red'], + ]); + }); + }); + }); }); diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.tsx b/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.tsx index 07c095ecc87ab..83249f86ffa79 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.tsx @@ -6,7 +6,7 @@ */ import './table_basic.scss'; -import { CUSTOM_PALETTE } from '@kbn/coloring'; +import { ColorMappingInputData, PaletteOutput } from '@kbn/coloring'; import React, { useLayoutEffect, useCallback, @@ -27,15 +27,17 @@ import { EuiDataGridSorting, EuiDataGridStyle, } from '@elastic/eui'; -import { EmptyPlaceholder } from '@kbn/charts-plugin/public'; +import { CustomPaletteState, EmptyPlaceholder } from '@kbn/charts-plugin/public'; import { ClickTriggerEvent } from '@kbn/charts-plugin/public'; import { IconChartDatatable } from '@kbn/chart-icons'; +import useObservable from 'react-use/lib/useObservable'; +import { getColorCategories } from '@kbn/chart-expressions-common'; import type { LensTableRowContextMenuEvent } from '../../../types'; import type { FormatFactory } from '../../../../common/types'; import { RowHeightMode } from '../../../../common/types'; -import type { LensGridDirection } from '../../../../common/expressions'; +import { getOriginalId, isTransposeId, LensGridDirection } from '../../../../common/expressions'; import { VisualizationContainer } from '../../../visualization_container'; -import { findMinMaxByColumnId } from '../../../shared_components'; +import { findMinMaxByColumnId, shouldColorByTerms } from '../../../shared_components'; import type { DataContextType, DatatableRenderProps, @@ -55,8 +57,9 @@ import { createTransposeColumnFilterHandler, } from './table_actions'; import { getFinalSummaryConfiguration } from '../../../../common/expressions/datatable/summary'; -import { getOriginalId } from '../../../../common/expressions/datatable/transpose_helpers'; import { DEFAULT_HEADER_ROW_HEIGHT, DEFAULT_HEADER_ROW_HEIGHT_LINES } from './constants'; +import { getFieldTypeFromDatatable } from '../../../../common/expressions/datatable/utils'; +import { CellColorFn, getCellColorFn } from '../../../shared_components/coloring/get_cell_color_fn'; export const DataContext = React.createContext({}); @@ -72,6 +75,7 @@ export const DatatableComponent = (props: DatatableRenderProps) => { const dataGridRef = useRef(null); const isInteractive = props.interactive; + const isDarkMode = useObservable(props.theme.theme$, { darkMode: false }).darkMode; const [columnConfig, setColumnConfig] = useState({ columns: props.args.columns, @@ -144,7 +148,7 @@ export const DatatableComponent = (props: DatatableRenderProps) => { const hasAtLeastOneRowClickAction = props.rowHasRowClickTriggerActions?.some((x) => x); - const { getType, dispatchEvent, renderMode, formatFactory } = props; + const { getType, dispatchEvent, renderMode, formatFactory, syncColors } = props; const formatters: Record> = useMemo( () => @@ -179,13 +183,13 @@ export const DatatableComponent = (props: DatatableRenderProps) => { ); const onChangeItemsPerPage = useCallback( - (pageSize) => onEditAction({ action: 'pagesize', size: pageSize }), + (pageSize: number) => onEditAction({ action: 'pagesize', size: pageSize }), [onEditAction] ); // active page isn't persisted, so we manage this state locally const onChangePage = useCallback( - (pageIndex) => { + (pageIndex: number) => { setPagination((_pagination) => { if (_pagination) { return { pageSize: _pagination?.pageSize, pageIndex }; @@ -220,7 +224,7 @@ export const DatatableComponent = (props: DatatableRenderProps) => { [onClickValue, untransposedDataRef, isInteractive] ); - const bucketColumns = useMemo( + const bucketedColumns = useMemo( () => columnConfig.columns .filter((_col, index) => { @@ -236,8 +240,8 @@ export const DatatableComponent = (props: DatatableRenderProps) => { const isEmpty = firstLocalTable.rows.length === 0 || - (bucketColumns.length && - props.data.rows.every((row) => bucketColumns.every((col) => row[col] == null))); + (bucketedColumns.length && + props.data.rows.every((row) => bucketedColumns.every((col) => row[col] == null))); const visibleColumns = useMemo( () => @@ -302,7 +306,7 @@ export const DatatableComponent = (props: DatatableRenderProps) => { const columns: EuiDataGridColumn[] = useMemo( () => createGridColumns( - bucketColumns, + bucketedColumns, firstLocalTable, handleFilterClick, handleTransposedColumnClick, @@ -320,7 +324,7 @@ export const DatatableComponent = (props: DatatableRenderProps) => { props.columnFilterable ), [ - bucketColumns, + bucketedColumns, firstLocalTable, handleFilterClick, handleTransposedColumnClick, @@ -385,17 +389,71 @@ export const DatatableComponent = (props: DatatableRenderProps) => { isInteractive, ]); - const renderCellValue = useMemo( - () => - createGridCell( - formatters, - columnConfig, - DataContext, - props.theme, - props.args.fitRowToContent - ), - [formatters, columnConfig, props.theme, props.args.fitRowToContent] - ); + const renderCellValue = useMemo(() => { + const cellColorFnMap = new Map(); + const getCellColor = ( + columnId: string, + palette?: PaletteOutput, + colorMapping?: string + ): CellColorFn => { + const originalId = getOriginalId(columnId); // workout what bucket the value belongs to + + if (cellColorFnMap.has(originalId)) { + return cellColorFnMap.get(originalId)!; + } + + const dataType = getFieldTypeFromDatatable(firstLocalTable, originalId); + const isBucketed = bucketedColumns.some((id) => id === columnId); + const colorByTerms = shouldColorByTerms(dataType, isBucketed); + + const data: ColorMappingInputData = colorByTerms + ? { + type: 'categories', + categories: getColorCategories( + firstLocalTable.rows, + originalId, + isTransposeId(columnId), + [null] + ), + } + : { + type: 'ranges', + bins: 0, + ...minMaxByColumnId[originalId], + }; + const colorFn = getCellColorFn( + props.paletteService, + data, + colorByTerms, + isDarkMode, + syncColors, + palette, + colorMapping + ); + cellColorFnMap.set(originalId, colorFn); + + return colorFn; + }; + + return createGridCell( + formatters, + columnConfig, + DataContext, + isDarkMode, + getCellColor, + props.args.fitRowToContent + ); + }, [ + formatters, + columnConfig, + isDarkMode, + props.args.fitRowToContent, + props.paletteService, + firstLocalTable, + bucketedColumns, + minMaxByColumnId, + syncColors, + ]); const columnVisibility = useMemo( () => ({ @@ -471,7 +529,6 @@ export const DatatableComponent = (props: DatatableRenderProps) => { rowHasRowClickTriggerActions: props.rowHasRowClickTriggerActions, alignments, minMaxByColumnId, - getColorForValue: props.paletteService.get(CUSTOM_PALETTE).getColorForValue!, handleFilterClick, }} > diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/toolbar.tsx b/x-pack/plugins/lens/public/visualizations/datatable/components/toolbar.tsx index b27dc0305c684..be5a81ef33dc0 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/toolbar.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/toolbar.tsx @@ -24,9 +24,9 @@ export function DataTableToolbar(props: VisualizationToolbarProps { const rowHeightLines = @@ -45,7 +45,7 @@ export function DataTableToolbar(props: VisualizationToolbarProps { + (newRowHeightLines: number, heightLinesProperty: string) => { setState({ ...state, [heightLinesProperty]: newRowHeightLines, diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/types.ts b/x-pack/plugins/lens/public/visualizations/datatable/components/types.ts index 987d852161f2c..b884a2c716be9 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/types.ts +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/types.ts @@ -7,7 +7,6 @@ import { CoreSetup } from '@kbn/core/public'; import type { PaletteRegistry } from '@kbn/coloring'; -import { CustomPaletteState } from '@kbn/charts-plugin/public'; import type { IAggType } from '@kbn/data-plugin/public'; import type { Datatable, RenderMode } from '@kbn/expressions-plugin/common'; import type { @@ -82,9 +81,4 @@ export interface DataContextType { rowIndex: number, negate?: boolean ) => void; - getColorForValue?: ( - value: number | undefined, - state: CustomPaletteState, - minMax: { min: number; max: number } - ) => string | undefined; } diff --git a/x-pack/plugins/lens/public/visualizations/datatable/expression.test.tsx b/x-pack/plugins/lens/public/visualizations/datatable/expression.test.tsx index e8d450fdb6b59..715cfdf526aed 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/expression.test.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/expression.test.tsx @@ -18,7 +18,7 @@ const cellValueAction: LensCellValueAction = { iconType: 'test-icon', execute: () => {}, }; -function sampleArgs() { +function sampleArgs(): DatatableProps { const indexPatternId = 'indexPatternId'; const data: Datatable = { type: 'datatable', @@ -80,13 +80,13 @@ function sampleArgs() { sortingDirection: 'none', }; - return { data, args }; + return { data, args, syncColors: false }; } describe('datatable_expression', () => { describe('datatable renders', () => { test('it renders with the specified data and args', async () => { - const { data, args } = sampleArgs(); + const { data, args, ...rest } = sampleArgs(); const result = await getDatatable(() => Promise.resolve((() => {}) as FormatFactory)).fn( data, args, @@ -96,7 +96,7 @@ describe('datatable_expression', () => { expect(result).toEqual({ type: 'render', as: 'lens_datatable_renderer', - value: { data, args }, + value: { data, args, ...rest }, }); }); }); diff --git a/x-pack/plugins/lens/public/visualizations/datatable/expression.tsx b/x-pack/plugins/lens/public/visualizations/datatable/expression.tsx index d58f0cbb04208..652abec75695e 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/expression.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/expression.tsx @@ -168,6 +168,7 @@ export const getDatatableRenderer = (dependencies: { interactive={isInteractive()} theme={dependencies.core.theme} renderComplete={renderComplete} + syncColors={config.syncColors} /> , domNode diff --git a/x-pack/plugins/lens/public/visualizations/datatable/index.ts b/x-pack/plugins/lens/public/visualizations/datatable/index.ts index 78a8e6e43dfe8..f68f167ea5f02 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/index.ts +++ b/x-pack/plugins/lens/public/visualizations/datatable/index.ts @@ -44,7 +44,7 @@ export class DatatableVisualization { }) ); - return getDatatableVisualization({ paletteService: palettes, theme: core.theme }); + return getDatatableVisualization({ paletteService: palettes, kibanaTheme: core.theme }); }); } } diff --git a/x-pack/plugins/lens/public/visualizations/datatable/visualization.test.tsx b/x-pack/plugins/lens/public/visualizations/datatable/visualization.test.tsx index 877fed8a4016e..c6670d933e729 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/visualization.test.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/visualization.test.tsx @@ -7,13 +7,7 @@ import { Ast } from '@kbn/interpreter'; import { buildExpression } from '@kbn/expressions-plugin/public'; -import { - createMockDatasource, - createMockFramePublicAPI, - DatasourceMock, - generateActiveData, -} from '../../mocks'; -import faker from 'faker'; +import { createMockDatasource, createMockFramePublicAPI, DatasourceMock } from '../../mocks'; import { DatatableVisualizationState, getDatatableVisualization } from './visualization'; import { Operation, @@ -27,6 +21,20 @@ import { RowHeightMode } from '../../../common/types'; import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; import { themeServiceMock } from '@kbn/core/public/mocks'; +import { ColorMapping, CUSTOM_PALETTE, CustomPaletteParams, PaletteOutput } from '@kbn/coloring'; +import { + ColumnState, + DatatableColumnFn, + DatatableExpressionFunction, +} from '../../../common/expressions'; +import { getColorStops } from '../../shared_components/coloring'; + +jest.mock('../../shared_components/coloring', () => { + return { + ...jest.requireActual('../../shared_components/coloring'), + getColorStops: jest.fn().mockReturnValue([]), + }; +}); function mockFrame(): FramePublicAPI { return { @@ -35,12 +43,18 @@ function mockFrame(): FramePublicAPI { }; } -const datatableVisualization = getDatatableVisualization({ +const mockServices = { paletteService: chartPluginMock.createPaletteRegistry(), - theme: themeServiceMock.createStartContract(), -}); + kibanaTheme: themeServiceMock.createStartContract(), +}; + +const datatableVisualization = getDatatableVisualization(mockServices); describe('Datatable Visualization', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + describe('#initialize', () => { it('should initialize from the empty state', () => { expect(datatableVisualization.initialize(() => 'aaa', undefined)).toEqual({ @@ -417,64 +431,122 @@ describe('Datatable Visualization', () => { }); describe('with palette', () => { + const mockStops = ['red', 'white', 'blue']; + const datasource = createMockDatasource('test'); let params: VisualizationConfigProps; + beforeEach(() => { - const datasource = createMockDatasource('test'); - datasource.publicAPIMock.getTableSpec.mockReturnValue([{ columnId: 'b', fields: [] }]); - params = { - layerId: 'a', - state: { - layerId: 'a', - layerType: LayerTypes.DATA, - columns: [ - { - columnId: 'b', - palette: { - type: 'palette' as const, - name: '', - params: { stops: [{ color: 'blue', stop: 0 }] }, - }, - }, - ], - }, - frame: { - ...mockFrame(), - activeData: generateActiveData([ - { - id: 'a', - rows: Array(3).fill({ - b: faker.random.number(), - }), - }, - ]), - datasourceLayers: { a: datasource.publicAPIMock }, - }, - }; + (getColorStops as jest.Mock).mockReturnValue(mockStops); }); - it('does include palette for accessor config if the values are numeric and palette exists', () => { - expect(datatableVisualization.getConfiguration(params).groups[2].accessors).toEqual([ - { columnId: 'b', palette: ['blue'], triggerIconType: 'colorBy' }, - ]); - }); - it('does not include palette for accessor config if the values are not numeric and palette exists', () => { - params.frame.activeData = generateActiveData([ - { - id: 'a', - rows: Array(3).fill({ - b: faker.random.word(), - }), - }, - ]); - expect(datatableVisualization.getConfiguration(params).groups[2].accessors).toEqual([ - { columnId: 'b' }, - ]); + describe('rows', () => { + beforeEach(() => { + datasource.publicAPIMock.getOperationForColumnId.mockReturnValueOnce({ + dataType: 'string', + isBucketed: true, + label: 'label', + isStaticValue: false, + hasTimeShift: false, + hasReducedTimeRange: false, + }); + datasource.publicAPIMock.getTableSpec.mockReturnValue([ + { columnId: 'b', fields: [] }, + { columnId: 'c', fields: [] }, + ]); + + params = { + layerId: 'a', + state: { + layerId: 'a', + layerType: LayerTypes.DATA, + columns: [{ columnId: 'b' }, { columnId: 'c' }], + }, + frame: { + ...mockFrame(), + datasourceLayers: { a: datasource.publicAPIMock }, + }, + }; + }); + + it.each(['cell', 'text'])( + 'should include palette if colorMode is %s and has stops', + (colorMode) => { + params.state.columns[0].colorMode = colorMode; + expect(datatableVisualization.getConfiguration(params).groups[0].accessors).toEqual([ + { columnId: 'b', palette: mockStops, triggerIconType: 'colorBy' }, + ]); + } + ); + + it.each(['cell', 'text'])( + 'should not include palette if colorMode is %s but stops is empty', + (colorMode) => { + (getColorStops as jest.Mock).mockReturnValue([]); + params.state.columns[0].colorMode = colorMode; + expect(datatableVisualization.getConfiguration(params).groups[0].accessors).toEqual([ + { columnId: 'b' }, + ]); + } + ); + + it.each(['none', undefined])( + 'should not include palette if colorMode is %s even if stops exist', + (colorMode) => { + params.state.columns[0].colorMode = colorMode; + expect(datatableVisualization.getConfiguration(params).groups[0].accessors).toEqual([ + { columnId: 'b' }, + ]); + } + ); }); - it('does not include palette for accessor config if the values are numeric but palette exists', () => { - params.state.columns[0].palette = undefined; - expect(datatableVisualization.getConfiguration(params).groups[2].accessors).toEqual([ - { columnId: 'b' }, - ]); + + describe('metrics', () => { + beforeEach(() => { + datasource.publicAPIMock.getTableSpec.mockReturnValue([{ columnId: 'b', fields: [] }]); + params = { + layerId: 'a', + state: { + layerId: 'a', + layerType: LayerTypes.DATA, + columns: [{ columnId: 'b' }], + }, + frame: { + ...mockFrame(), + datasourceLayers: { a: datasource.publicAPIMock }, + }, + }; + }); + + it.each(['cell', 'text'])( + 'should include palette if colorMode is %s and has stops', + (colorMode) => { + params.state.columns[0].colorMode = colorMode; + expect(datatableVisualization.getConfiguration(params).groups[2].accessors).toEqual([ + { columnId: 'b', palette: mockStops, triggerIconType: 'colorBy' }, + ]); + } + ); + + it.each(['cell', 'text'])( + 'should not include palette if colorMode is %s but stops is empty', + (colorMode) => { + (getColorStops as jest.Mock).mockReturnValue([]); + params.state.columns[0].colorMode = colorMode; + expect(datatableVisualization.getConfiguration(params).groups[2].accessors).toEqual([ + { columnId: 'b' }, + ]); + } + ); + + it.each(['none', undefined])( + 'should not include palette if colorMode is %s even if stops exist', + (colorMode) => { + params.state.columns[0].colorMode = colorMode; + expect(datatableVisualization.getConfiguration(params).groups[2].accessors).toEqual([ + { columnId: 'b' }, + ]); + } + ); }); }); @@ -629,13 +701,12 @@ describe('Datatable Visualization', () => { datatableVisualization.toExpression( state, frame.datasourceLayers, - {}, { '1': { type: 'expression', chain: [] } } ) as Ast - ).findFunction('lens_datatable')[0].arguments; + ).findFunction('lens_datatable')[0].arguments; - const defaultExpressionTableState = { + const defaultExpressionTableState: DatatableVisualizationState = { layerId: 'a', layerType: LayerTypes.DATA, columns: [{ columnId: 'b' }, { columnId: 'c' }], @@ -881,6 +952,104 @@ describe('Datatable Visualization', () => { }) ); }); + + describe('palette/colorMapping/colorMode', () => { + const colorMapping: ColorMapping.Config = { + paletteId: 'default', + colorMode: { type: 'categorical' }, + assignments: [], + specialAssignments: [], + }; + const palette: PaletteOutput = { + type: 'palette', + name: 'default', + }; + const colorExpressionTableState = ( + colorMode?: 'cell' | 'text' | 'none' + ): DatatableVisualizationState => ({ + ...defaultExpressionTableState, + columns: [{ columnId: 'b', colorMapping, palette, colorMode }], + }); + + beforeEach(() => { + datasource.publicAPIMock.getTableSpec.mockReturnValue([{ columnId: 'b', fields: [] }]); + }); + + it.each<[DataType, string]>([ + ['string', palette.name], + ['number', CUSTOM_PALETTE], // required to property handle toExpression + ])( + 'should call paletteService.get with correct palette name for %s dataType', + (dataType, paletteName) => { + datasource.publicAPIMock.getOperationForColumnId.mockReturnValue({ + dataType, + isBucketed: false, + label: 'label', + hasTimeShift: false, + hasReducedTimeRange: false, + }); + + getDatatableExpressionArgs(colorExpressionTableState()); + + expect(mockServices.paletteService.get).toBeCalledWith(paletteName); + } + ); + + describe.each<'cell' | 'text' | 'none' | undefined>(['cell', 'text', 'none', undefined])( + 'colorMode - %s', + (colorMode) => { + it.each<{ dataType: DataType; disallowed?: boolean }>([ + // allowed types + { dataType: 'document' }, + { dataType: 'ip' }, + { dataType: 'histogram' }, + { dataType: 'geo_point' }, + { dataType: 'geo_shape' }, + { dataType: 'counter' }, + { dataType: 'gauge' }, + { dataType: 'murmur3' }, + { dataType: 'string' }, + { dataType: 'number' }, + { dataType: 'boolean' }, + // disallowed types + { dataType: 'date', disallowed: true }, + ])( + 'should apply correct palette, colorMapping & colorMode for $dataType', + ({ dataType, disallowed = false }) => { + datasource.publicAPIMock.getOperationForColumnId.mockReturnValue({ + dataType, + isBucketed: false, + label: 'label', + hasTimeShift: false, + hasReducedTimeRange: false, + }); + + const expression = datatableVisualization.toExpression( + colorExpressionTableState(colorMode), + frame.datasourceLayers, + {}, + { '1': { type: 'expression', chain: [] } } + ) as Ast; + + const columnArgs = + buildExpression(expression).findFunction( + 'lens_datatable_column' + )[0].arguments; + + if (disallowed) { + expect(columnArgs.colorMode).toEqual(['none']); + expect(columnArgs.palette).toBeUndefined(); + expect(columnArgs.colorMapping).toBeUndefined(); + } else { + expect(columnArgs.colorMode).toEqual([colorMode ?? 'none']); + expect(columnArgs.palette).toEqual([expect.any(Object)]); + expect(columnArgs.colorMapping).toEqual([expect.any(String)]); + } + } + ); + } + ); + }); }); describe('#onEditAction', () => { diff --git a/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx b/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx index 534ece1785af4..d5c8684b3f2e0 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx @@ -8,13 +8,13 @@ import React from 'react'; import { Ast } from '@kbn/interpreter'; import { i18n } from '@kbn/i18n'; -import { PaletteRegistry, CUSTOM_PALETTE } from '@kbn/coloring'; +import { PaletteRegistry, CUSTOM_PALETTE, PaletteOutput, CustomPaletteParams } from '@kbn/coloring'; import { ThemeServiceStart } from '@kbn/core/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { IconChartDatatable } from '@kbn/chart-icons'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/common'; -import { isNumericFieldForDatatable } from '../../../common/expressions/datatable/utils'; +import useObservable from 'react-use/lib/useObservable'; import type { FormBasedPersistedState } from '../../datasources/form_based/types'; import type { SuggestionRequest, @@ -28,13 +28,14 @@ import { TableDimensionEditorAdditionalSection } from './components/dimension_ed import type { LayerType } from '../../../common/types'; import { RowHeightMode } from '../../../common/types'; import { getDefaultSummaryLabel } from '../../../common/expressions/datatable/summary'; -import type { - ColumnState, - SortingState, - PagingState, - CollapseExpressionFunction, - DatatableColumnFunction, - DatatableExpressionFunction, +import { + type ColumnState, + type SortingState, + type PagingState, + type CollapseExpressionFunction, + type DatatableColumnFn, + type DatatableExpressionFunction, + getOriginalId, } from '../../../common/expressions'; import { DataTableToolbar } from './components/toolbar'; import { @@ -42,6 +43,14 @@ import { DEFAULT_HEADER_ROW_HEIGHT_LINES, DEFAULT_ROW_HEIGHT, } from './components/constants'; +import { + applyPaletteParams, + defaultPaletteParams, + findMinMaxByColumnId, + getColorStops, + shouldColorByTerms, +} from '../../shared_components'; +import { getColorMappingTelemetryEvents } from '../../lens_ui_telemetry/color_telemetry_helpers'; export interface DatatableVisualizationState { columns: ColumnState[]; layerId: string; @@ -60,10 +69,10 @@ const visualizationLabel = i18n.translate('xpack.lens.datatable.label', { export const getDatatableVisualization = ({ paletteService, - theme, + kibanaTheme, }: { paletteService: PaletteRegistry; - theme: ThemeServiceStart; + kibanaTheme: ThemeServiceStart; }): Visualization => ({ id: 'lnsDatatable', @@ -115,6 +124,56 @@ export const getDatatableVisualization = ({ ); }, + onDatasourceUpdate(state, frame) { + const datasource = frame?.datasourceLayers?.[state.layerId]; + const paletteMap = new Map( + paletteService + .getAll() + .filter((p) => !p.internal) + .map((p) => [p.id, p]) + ); + + const hasTransposedColumn = state.columns.some(({ isTransposed }) => isTransposed); + const columns = state.columns.map((column) => { + if (column.palette) { + const accessor = column.columnId; + const currentData = frame?.activeData?.[state.layerId]; + const { dataType, isBucketed } = datasource?.getOperationForColumnId(column.columnId) ?? {}; + const showColorByTerms = shouldColorByTerms(dataType, isBucketed); + const palette = paletteMap.get(column.palette?.name ?? ''); + const columnsToCheck = hasTransposedColumn + ? currentData?.columns + .filter(({ id }) => getOriginalId(id) === accessor) + .map(({ id }) => id) || [] + : [accessor]; + const minMaxByColumnId = findMinMaxByColumnId(columnsToCheck, currentData, getOriginalId); + + if (palette && !showColorByTerms && !palette?.canDynamicColoring) { + const newPalette: PaletteOutput = { + type: 'palette', + name: showColorByTerms ? 'default' : defaultPaletteParams.name, + }; + return { + ...column, + palette: { + ...newPalette, + params: { + stops: applyPaletteParams(paletteService, newPalette, minMaxByColumnId[accessor]), + }, + }, + }; + } + } + + return column; + }); + + return { + ...state, + columns, + }; + }, + getSuggestions({ table, state, @@ -197,15 +256,16 @@ export const getDatatableVisualization = ({ }, /* - Datatable works differently on text based datasource and form based - - Form based: It relies on the isBucketed flag to identify groups. It allows only numeric fields + Datatable works differently on text-based datasource and form-based + - Form-based: It relies on the isBucketed flag to identify groups. It allows only numeric fields on the Metrics dimension - - Text based: It relies on the isMetric flag to identify groups. It allows all type of fields + - Text-based: It relies on the isMetric flag to identify groups. It allows all type of fields on the Metric dimension in cases where there are no numeric columns **/ - getConfiguration({ state, frame, layerId }) { + getConfiguration({ state, frame }) { + const isDarkMode = kibanaTheme.getTheme().darkMode; const { sortedColumns, datasource } = - getDataSourceAndSortedColumns(state, frame.datasourceLayers, layerId) || {}; + getDataSourceAndSortedColumns(state, frame.datasourceLayers) || {}; const columnMap: Record = {}; state.columns.forEach((column) => { @@ -245,14 +305,29 @@ export const getDatatableVisualization = ({ } return datasource!.getOperationForColumnId(c)?.isBucketed && !column?.isTransposed; }) - .map((accessor) => ({ - columnId: accessor, - triggerIconType: columnMap[accessor].hidden - ? 'invisible' - : columnMap[accessor].collapseFn - ? 'aggregate' - : undefined, - })), + .map((accessor) => { + const { + colorMode = 'none', + palette, + colorMapping, + hidden, + collapseFn, + } = columnMap[accessor] ?? {}; + const stops = getColorStops(paletteService, isDarkMode, palette, colorMapping); + const hasColoring = colorMode !== 'none' && stops.length > 0; + + return { + columnId: accessor, + triggerIconType: hidden + ? 'invisible' + : hasColoring + ? 'colorBy' + : collapseFn + ? 'aggregate' + : undefined, + palette: hasColoring ? stops : undefined, + }; + }), supportsMoreColumns: true, filterOperations: (op) => op.isBucketed, dataTestSubj: 'lnsDatatable_rows', @@ -319,22 +394,19 @@ export const getDatatableVisualization = ({ return !operation?.isBucketed; }) .map((accessor) => { - const columnConfig = columnMap[accessor]; - const stops = columnConfig?.palette?.params?.stops; - const isNumeric = Boolean( - accessor && isNumericFieldForDatatable(frame.activeData?.[state.layerId], accessor) - ); - const hasColoring = Boolean(columnConfig?.colorMode !== 'none' && stops); + const { + colorMode = 'none', + palette, + colorMapping, + hidden, + } = columnMap[accessor] ?? {}; + const stops = getColorStops(paletteService, isDarkMode, palette, colorMapping); + const hasColoring = colorMode !== 'none' && stops.length > 0; return { columnId: accessor, - triggerIconType: columnConfig?.hidden - ? 'invisible' - : hasColoring && isNumeric - ? 'colorBy' - : undefined, - palette: - hasColoring && isNumeric && stops ? stops.map(({ color }) => color) : undefined, + triggerIconType: hidden ? 'invisible' : hasColoring ? 'colorBy' : undefined, + palette: hasColoring ? stops : undefined, }; }), supportsMoreColumns: true, @@ -386,7 +458,11 @@ export const getDatatableVisualization = ({ }; }, DimensionEditorComponent(props) { - return ; + const isDarkMode = useObservable(kibanaTheme.theme$, { darkMode: false }).darkMode; + + return ( + + ); }, DimensionEditorAdditionalSectionComponent(props) { @@ -421,7 +497,7 @@ export const getDatatableVisualization = ({ datasourceExpressionsByLayers = {} ): Ast | null { const { sortedColumns, datasource } = - getDataSourceAndSortedColumns(state, datasourceLayers, state.layerId) || {}; + getDataSourceAndSortedColumns(state, datasourceLayers) || {}; const isTextBasedLanguage = datasource?.isTextBasedLanguage(); if ( @@ -481,23 +557,20 @@ export const getDatatableVisualization = ({ : [], reverse: false, // managed at UI level }; - const sortingHint = datasource!.getOperationForColumnId(column.columnId)!.sortingHint; - + const { dataType, isBucketed, sortingHint, inMetricDimension } = + datasource?.getOperationForColumnId(column.columnId) ?? {}; const hasNoSummaryRow = column.summaryRow == null || column.summaryRow === 'none'; - - const canColor = - datasource!.getOperationForColumnId(column.columnId)?.dataType === 'number'; - + const canColor = dataType !== 'date'; + const colorByTerms = shouldColorByTerms(dataType, isBucketed); let isTransposable = !isTextBasedLanguage && !datasource!.getOperationForColumnId(column.columnId)?.isBucketed; if (isTextBasedLanguage) { - const operation = datasource!.getOperationForColumnId(column.columnId); - isTransposable = Boolean(column?.isMetric || operation?.inMetricDimension); + isTransposable = Boolean(column?.isMetric || inMetricDimension); } - const datatableColumnFn = buildExpressionFunction( + const datatableColumnFn = buildExpressionFunction( 'lens_datatable_column', { columnId: column.columnId, @@ -507,8 +580,15 @@ export const getDatatableVisualization = ({ isTransposed: column.isTransposed, transposable: isTransposable, alignment: column.alignment, - colorMode: canColor && column.colorMode ? column.colorMode : 'none', - palette: paletteService.get(CUSTOM_PALETTE).toExpression(paletteParams), + colorMode: canColor ? column.colorMode ?? 'none' : 'none', + palette: !canColor + ? undefined + : paletteService + // The by value palette is a pseudo custom palette that is only custom from params level + .get(colorByTerms ? column.palette?.name || CUSTOM_PALETTE : CUSTOM_PALETTE) + .toExpression(paletteParams), + colorMapping: + canColor && column.colorMapping ? JSON.stringify(column.colorMapping) : undefined, summaryRow: hasNoSummaryRow ? undefined : column.summaryRow!, summaryLabel: hasNoSummaryRow ? undefined @@ -537,6 +617,15 @@ export const getDatatableVisualization = ({ }; }, + getTelemetryEventsOnSave(state, prevState) { + const colorMappingEvents = state.columns.flatMap((col) => { + const prevColumn = prevState?.columns?.find((prevCol) => prevCol.columnId === col.columnId); + return getColorMappingTelemetryEvents(col.colorMapping, prevColumn?.colorMapping); + }); + + return colorMappingEvents; + }, + getRenderEventCounters(state) { const events = { color_by_value: false, @@ -642,8 +731,7 @@ export const getDatatableVisualization = ({ }, getSortedColumns(state, datasourceLayers) { - const { sortedColumns } = - getDataSourceAndSortedColumns(state, datasourceLayers || {}, state.layerId) || {}; + const { sortedColumns } = getDataSourceAndSortedColumns(state, datasourceLayers || {}) || {}; return sortedColumns; }, @@ -696,8 +784,7 @@ export const getDatatableVisualization = ({ function getDataSourceAndSortedColumns( state: DatatableVisualizationState, - datasourceLayers: DatasourceLayers, - layerId: string + datasourceLayers: DatasourceLayers ) { const datasource = datasourceLayers[state.layerId]; const originalOrder = datasource?.getTableSpec().map(({ columnId }) => columnId); diff --git a/x-pack/plugins/lens/public/visualizations/gauge/dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/gauge/dimension_editor.tsx index 86eaf39479ff5..b30e36cfefa37 100644 --- a/x-pack/plugins/lens/public/visualizations/gauge/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/visualizations/gauge/dimension_editor.tsx @@ -110,13 +110,16 @@ export function GaugeDimensionEditor( display="columnCompressed" fullWidth label={i18n.translate('xpack.lens.paletteMetricGradient.label', { - defaultMessage: 'Color', + defaultMessage: 'Color mapping', })} > color)} siblingRef={props.panelRef} isInlineEditing={isInlineEditing} + title={i18n.translate('xpack.lens.paletteMetricGradient.label', { + defaultMessage: 'Color mapping', + })} > color)} siblingRef={props.panelRef} isInlineEditing={isInlineEditing} + title={i18n.translate('xpack.lens.paletteMetricGradient.label', { + defaultMessage: 'Color mapping', + })} > { /> ); - const colorModeGroup = screen.queryByRole('group', { name: /color mode/i }); + const colorModeGroup = screen.queryByRole('group', { name: /Color by value/i }); const staticColorPicker = screen.queryByTestId(SELECTORS.COLOR_PICKER); const typeColor = (color: string) => { @@ -170,6 +170,7 @@ describe('dimension editor', () => { expect(screen.queryByTestId(SELECTORS.MAX_EDITOR)).not.toBeInTheDocument(); expect(screen.queryByTestId(SELECTORS.BREAKDOWN_EDITOR)).not.toBeInTheDocument(); }); + it('Color mode switch is shown when the primary metric is numeric', () => { const { colorModeGroup } = renderPrimaryMetricEditor(); expect(colorModeGroup).toBeInTheDocument(); diff --git a/x-pack/plugins/lens/public/visualizations/metric/dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/metric/dimension_editor.tsx index 24248621c0982..2b6c1f4476006 100644 --- a/x-pack/plugins/lens/public/visualizations/metric/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/visualizations/metric/dimension_editor.tsx @@ -258,15 +258,15 @@ function PrimaryMetricEditor(props: SubProps) { ) : ( ) : ( l.layerId === props.layerId)!; const dimensionEditor = isReferenceLayer(layer) ? ( ) : isAnnotationsLayer(layer) ? ( ) : ( - + ); return dimensionEditor; diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/axis_settings_popover.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/axis_settings_popover.tsx index 47178886dc531..1bf00cb0afb6f 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/axis_settings_popover.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/axis_settings_popover.tsx @@ -245,7 +245,7 @@ export const AxisSettingsPopover: React.FunctionComponent { + (newExtent: AxisExtentConfig | undefined) => { if (setExtent && newExtent && !isEqual(newExtent, extent)) { const { errorMsg } = validateExtent(hasBarOrAreaOnAxis, newExtent, scale); if (axis === 'x' || newExtent.mode !== 'custom' || !errorMsg) { diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/dimension_editor.tsx index e53bc9164b0c3..c0916b823466e 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/dimension_editor.tsx @@ -5,81 +5,68 @@ * 2.0. */ -import React, { useCallback, useMemo, useState } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { useDebouncedValue } from '@kbn/visualization-utils'; import { ColorPicker } from '@kbn/visualization-ui-components'; -import { - EuiBadge, - EuiButtonGroup, - EuiFlexGroup, - EuiFlexItem, - EuiFormRow, - EuiSpacer, - EuiSwitch, - EuiText, - htmlIdGenerator, -} from '@elastic/eui'; -import { - PaletteRegistry, - ColorMapping, - DEFAULT_COLOR_MAPPING_CONFIG, - CategoricalColorMapping, - PaletteOutput, - SPECIAL_TOKENS_STRING_CONVERTION, - AVAILABLE_PALETTES, - getColorsFromMapping, -} from '@kbn/coloring'; +import { EuiButtonGroup, EuiFormRow, htmlIdGenerator } from '@elastic/eui'; +import { PaletteRegistry, ColorMapping, PaletteOutput } from '@kbn/coloring'; import { getColorCategories } from '@kbn/chart-expressions-common'; +import type { ValuesType } from 'utility-types'; import type { VisualizationDimensionEditorProps } from '../../../types'; import { State, XYState, XYDataLayerConfig, YConfig, YAxisMode } from '../types'; import { FormatFactory } from '../../../../common/types'; import { getSeriesColor, isHorizontalChart } from '../state_helpers'; -import { PalettePanelContainer, PalettePicker } from '../../../shared_components'; import { getDataLayers } from '../visualization_helpers'; import { CollapseSetting } from '../../../shared_components/collapse_setting'; import { getSortedAccessors } from '../to_expression'; import { getColorAssignments, getAssignedColorConfig } from '../color_assignment'; -import { trackUiCounterEvents } from '../../../lens_ui_telemetry'; +import { ColorMappingByTerms } from '../../../shared_components/coloring/color_mapping_by_terms'; -type UnwrapArray = T extends Array ? P : T; +export const idPrefix = htmlIdGenerator()(); -export function updateLayer( +function updateLayer( state: State, - layer: UnwrapArray, - index: number -): State { + index: number, + layer: ValuesType, + newLayer: Partial> +): State['layers'] { const newLayers = [...state.layers]; - newLayers[index] = layer; + newLayers[index] = { + ...layer, + ...newLayer, + } as ValuesType; - return { - ...state, - layers: newLayers, - }; + return newLayers; } -export const idPrefix = htmlIdGenerator()(); - export function DataDimensionEditor( props: VisualizationDimensionEditorProps & { formatFactory: FormatFactory; paletteService: PaletteRegistry; - darkMode: boolean; + isDarkMode: boolean; } ) { - const { state, layerId, accessor, darkMode, isInlineEditing } = props; + const { state, layerId, accessor, isDarkMode, isInlineEditing } = props; const index = state.layers.findIndex((l) => l.layerId === layerId); const layer = state.layers[index] as XYDataLayerConfig; - const canUseColorMapping = layer.colorMapping ? true : false; - - const [useNewColorMapping, setUseNewColorMapping] = useState(canUseColorMapping); const { inputValue: localState, handleInputChange: setLocalState } = useDebouncedValue({ value: props.state, onChange: props.setState, }); + const updateLayerState = useCallback( + (layerIndex: number, newLayer: Partial>) => { + setLocalState({ + ...localState, + layers: updateLayer(localState, layerIndex, layer, newLayer), + }); + }, + [layer, setLocalState, localState] + ); + const localYConfig = layer?.yConfig?.find((yAxisConfig) => yAxisConfig.forAccessor === accessor); const axisMode = localYConfig?.axisMode || 'auto'; @@ -100,22 +87,22 @@ export function DataDimensionEditor( ...yConfig, }); } - setLocalState(updateLayer(localState, { ...layer, yConfig: newYConfigs }, index)); + updateLayerState(index, { yConfig: newYConfigs }); }, - [accessor, index, localState, layer, setLocalState] + [layer.yConfig, updateLayerState, index, accessor] ); const setColorMapping = useCallback( (colorMapping?: ColorMapping.Config) => { - setLocalState(updateLayer(localState, { ...layer, colorMapping }, index)); + updateLayerState(index, { colorMapping }); }, - [index, localState, layer, setLocalState] + [updateLayerState, index] ); const setPalette = useCallback( (palette: PaletteOutput) => { - setLocalState(updateLayer(localState, { ...layer, palette }, index)); + updateLayerState(index, { palette }); }, - [index, localState, layer, setLocalState] + [updateLayerState, index] ); const overwriteColor = getSeriesColor(layer, accessor); @@ -143,105 +130,28 @@ export function DataDimensionEditor( ).color; }, [props.frame, props.paletteService, state.layers, accessor, props.formatFactory, layer]); - const localLayer: XYDataLayerConfig = layer; - - const colors = layer.colorMapping - ? getColorsFromMapping(props.darkMode, layer.colorMapping) - : props.paletteService - .get(layer.palette?.name || 'default') - .getCategoricalColors(10, layer.palette); - const table = props.frame.activeData?.[layer.layerId]; const { splitAccessor } = layer; const splitCategories = getColorCategories(table?.rows ?? [], splitAccessor); if (props.groupId === 'breakdown' && !layer.collapseFn) { return ( - - -
- - - - - {i18n.translate('xpack.lens.colorMapping.tryLabel', { - defaultMessage: 'Use the new Color Mapping feature', - })}{' '} - - {i18n.translate('xpack.lens.colorMapping.techPreviewLabel', { - defaultMessage: 'Tech preview', - })} - - - - } - data-test-subj="lns_colorMappingOrLegacyPalette_switch" - compressed - checked={useNewColorMapping} - onChange={({ target: { checked } }) => { - trackUiCounterEvents( - `color_mapping_switch_${checked ? 'enabled' : 'disabled'}` - ); - setColorMapping(checked ? { ...DEFAULT_COLOR_MAPPING_CONFIG } : undefined); - setUseNewColorMapping(checked); - }} - /> - - - - {canUseColorMapping || useNewColorMapping ? ( - setColorMapping(model)} - palettes={AVAILABLE_PALETTES} - data={{ - type: 'categories', - categories: splitCategories, - }} - specialTokens={SPECIAL_TOKENS_STRING_CONVERTION} - /> - ) : ( - { - setPalette(newPalette); - }} - /> - )} - - -
-
-
+ ); } const isHorizontal = isHorizontalChart(state.layers); - const disabledMessage = Boolean(!localLayer.collapseFn && localLayer.splitAccessor) + const disabledMessage = Boolean(!layer.collapseFn && layer.splitAccessor) ? i18n.translate('xpack.lens.xyChart.colorPicker.tooltip.disabled', { defaultMessage: 'You are unable to apply custom colors to individual series when the layer includes a "Break down by" field.', @@ -329,13 +239,23 @@ export function DataDimensionEditorDataSectionExtra( onChange: props.setState, }); + const updateLayerState = useCallback( + (layerIndex: number, newLayer: Partial>) => { + setLocalState({ + ...localState, + layers: updateLayer(localState, layerIndex, layer, newLayer), + }); + }, + [layer, setLocalState, localState] + ); + if (props.groupId === 'breakdown') { return ( <> { - setLocalState(updateLayer(localState, { ...layer, collapseFn }, index)); + updateLayerState(index, { collapseFn }); }} /> diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/xy_config_panel.test.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/xy_config_panel.test.tsx index 9a98f5bae168b..b0f553969e058 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/xy_config_panel.test.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/xy_config_panel.test.tsx @@ -272,7 +272,7 @@ describe('XY Config panels', () => { addLayer={jest.fn()} removeLayer={jest.fn()} datasource={{} as DatasourcePublicAPI} - darkMode={false} + isDarkMode={false} /> ); @@ -300,7 +300,7 @@ describe('XY Config panels', () => { addLayer={jest.fn()} removeLayer={jest.fn()} datasource={{} as DatasourcePublicAPI} - darkMode={false} + isDarkMode={false} /> ); @@ -349,7 +349,7 @@ describe('XY Config panels', () => { addLayer={jest.fn()} removeLayer={jest.fn()} datasource={{} as DatasourcePublicAPI} - darkMode={false} + isDarkMode={false} /> ); @@ -395,7 +395,7 @@ describe('XY Config panels', () => { addLayer={jest.fn()} removeLayer={jest.fn()} datasource={{} as DatasourcePublicAPI} - darkMode={false} + isDarkMode={false} /> ); @@ -441,7 +441,7 @@ describe('XY Config panels', () => { addLayer={jest.fn()} removeLayer={jest.fn()} datasource={{} as DatasourcePublicAPI} - darkMode={false} + isDarkMode={false} /> ); diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/_index.scss b/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/_index.scss index 264dfe5e24843..28da88491f1cc 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/_index.scss +++ b/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/_index.scss @@ -5,9 +5,10 @@ bottom: $euiSizeM; pointer-events: none; color: $euiTextColor; - border-left: 2px solid $euiTextColor; - border-bottom: 2px solid $euiTextColor; + border-left: 2px solid rgba($euiTextColor, .6); + border-bottom: 2px solid rgba($euiTextColor, .6); text-align: right; + @include mapOverlayIsTextOnly; } .mapScaleControlFullScreen { diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/_mixins.scss b/x-pack/plugins/maps/public/connected_components/right_side_controls/_mixins.scss index 97557f1312e86..640545c065418 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/_mixins.scss +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/_mixins.scss @@ -1,8 +1,6 @@ @mixin mapOverlayIsTextOnly { - text-shadow: - 0 0 2px $euiColorEmptyShade, - 0 0 1px $euiColorEmptyShade, - 0 0 1px $euiColorEmptyShade, - 0 0 1px $euiColorEmptyShade, - 0 0 1px $euiColorEmptyShade 0 0 1px $euiColorEmptyShade 0 0 1px $euiColorEmptyShade; + background-color: $euiPageBackgroundColor; + + padding-left: $euiSizeXS; + padding-right: $euiSizeXS; } diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/attribution_control/_attribution_control.scss b/x-pack/plugins/maps/public/connected_components/right_side_controls/attribution_control/_attribution_control.scss index e319535b4a45c..51c82fd7aa443 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/attribution_control/_attribution_control.scss +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/attribution_control/_attribution_control.scss @@ -2,7 +2,6 @@ @include mapOverlayIsTextOnly; @include euiTextBreakWord; pointer-events: all; - padding-left: $euiSizeM; } .mapAttributionControl__fullScreen { diff --git a/x-pack/plugins/maps/public/index.ts b/x-pack/plugins/maps/public/index.ts index fc6c3b0fc7616..90eee7980501c 100644 --- a/x-pack/plugins/maps/public/index.ts +++ b/x-pack/plugins/maps/public/index.ts @@ -8,7 +8,7 @@ import { PluginInitializer } from '@kbn/core/public'; import { PluginInitializerContext } from '@kbn/core/public'; import { MapsPlugin, MapsPluginSetup, MapsPluginStart } from './plugin'; -import { MapsXPackConfig } from '../config'; +import type { MapsXPackConfig } from '../server/config'; export const plugin: PluginInitializer = ( initContext: PluginInitializerContext diff --git a/x-pack/plugins/maps/public/kibana_services.ts b/x-pack/plugins/maps/public/kibana_services.ts index 9c11f56a7f5c7..e6f65fc67866d 100644 --- a/x-pack/plugins/maps/public/kibana_services.ts +++ b/x-pack/plugins/maps/public/kibana_services.ts @@ -9,7 +9,7 @@ import type { CoreStart } from '@kbn/core/public'; import type { EMSSettings } from '@kbn/maps-ems-plugin/common/ems_settings'; import { MapsEmsPluginPublicStart } from '@kbn/maps-ems-plugin/public'; import { BehaviorSubject } from 'rxjs'; -import type { MapsConfigType } from '../config'; +import type { MapsConfigType } from '../server/config'; import type { MapsPluginStartDependencies } from './plugin'; const servicesReady$ = new BehaviorSubject(false); diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index 169731af566fe..cc4cc4bcc91e8 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -68,7 +68,7 @@ import { MapsStartApi, suggestEMSTermJoinConfig, } from './api'; -import { MapsXPackConfig, MapsConfigType } from '../config'; +import type { MapsXPackConfig, MapsConfigType } from '../server/config'; import { filterByMapExtentAction } from './trigger_actions/filter_by_map_extent/action'; import { synchronizeMovementAction } from './trigger_actions/synchronize_movement/action'; import { visualizeGeoFieldAction } from './trigger_actions/visualize_geo_field_action'; diff --git a/x-pack/plugins/maps/config.ts b/x-pack/plugins/maps/server/config.ts similarity index 100% rename from x-pack/plugins/maps/config.ts rename to x-pack/plugins/maps/server/config.ts diff --git a/x-pack/plugins/maps/server/content_management/maps_storage.ts b/x-pack/plugins/maps/server/content_management/maps_storage.ts index 66d72646385e9..6a4df61a8c485 100644 --- a/x-pack/plugins/maps/server/content_management/maps_storage.ts +++ b/x-pack/plugins/maps/server/content_management/maps_storage.ts @@ -9,7 +9,7 @@ import { SOContentStorage, tagsToFindOptions } from '@kbn/content-management-uti import { SavedObjectsFindOptions } from '@kbn/core-saved-objects-api-server'; import type { Logger } from '@kbn/logging'; import { CONTENT_ID } from '../../common/content_management'; -import { cmServicesDefinition } from '../../common/content_management/cm_services'; +import { cmServicesDefinition } from './schema/cm_services'; import type { MapCrudTypes } from '../../common/content_management'; const searchArgsToSOFindOptions = (args: MapCrudTypes['SearchIn']): SavedObjectsFindOptions => { diff --git a/x-pack/plugins/maps/common/content_management/cm_services.ts b/x-pack/plugins/maps/server/content_management/schema/cm_services.ts similarity index 100% rename from x-pack/plugins/maps/common/content_management/cm_services.ts rename to x-pack/plugins/maps/server/content_management/schema/cm_services.ts diff --git a/x-pack/plugins/maps/common/content_management/v1/cm_services.ts b/x-pack/plugins/maps/server/content_management/schema/v1/cm_services.ts similarity index 100% rename from x-pack/plugins/maps/common/content_management/v1/cm_services.ts rename to x-pack/plugins/maps/server/content_management/schema/v1/cm_services.ts diff --git a/x-pack/plugins/maps/server/index.ts b/x-pack/plugins/maps/server/index.ts index eadb5ccd3eaf9..b6a7bd090a699 100644 --- a/x-pack/plugins/maps/server/index.ts +++ b/x-pack/plugins/maps/server/index.ts @@ -7,7 +7,7 @@ import { PluginInitializerContext } from '@kbn/core/server'; import { PluginConfigDescriptor } from '@kbn/core/server'; -import { configSchema, MapsXPackConfig } from '../config'; +import { configSchema, MapsXPackConfig } from './config'; export const config: PluginConfigDescriptor = { // exposeToBrowser specifies kibana.yml settings to expose to the browser diff --git a/x-pack/plugins/maps/server/plugin.ts b/x-pack/plugins/maps/server/plugin.ts index 8d926952d1bd0..2366731c3826e 100644 --- a/x-pack/plugins/maps/server/plugin.ts +++ b/x-pack/plugins/maps/server/plugin.ts @@ -24,7 +24,7 @@ import { getFlightsSavedObjects } from './sample_data/flights_saved_objects'; import { getWebLogsSavedObjects } from './sample_data/web_logs_saved_objects'; import { registerMapsUsageCollector } from './maps_telemetry/collectors/register'; import { APP_ID, APP_ICON, MAP_SAVED_OBJECT_TYPE, getFullPath } from '../common/constants'; -import { MapsXPackConfig } from '../config'; +import { MapsXPackConfig } from './config'; import { setStartServices } from './kibana_server_services'; import { emsBoundariesSpecProvider } from './tutorials/ems'; import { initRoutes } from './routes'; diff --git a/x-pack/plugins/maps/tsconfig.json b/x-pack/plugins/maps/tsconfig.json index cfd635f23d58d..dfee193ed0a25 100644 --- a/x-pack/plugins/maps/tsconfig.json +++ b/x-pack/plugins/maps/tsconfig.json @@ -8,8 +8,8 @@ "common/**/*", "public/**/*", "server/**/*", - "config.ts", - "../../../typings/**/*", + "server/config.ts", + "../../../typings/**/*" ], "kbn_references": [ "@kbn/core", diff --git a/x-pack/plugins/ml/common/util/group_color_utils.ts b/x-pack/plugins/ml/common/util/group_color_utils.ts index 3c2398a18684f..77d16b8aaad50 100644 --- a/x-pack/plugins/ml/common/util/group_color_utils.ts +++ b/x-pack/plugins/ml/common/util/group_color_utils.ts @@ -24,7 +24,7 @@ const COLORS = [ euiVars.euiColorPrimary, ]; -const colorMap: Record = {}; +const colorMap: Record = Object.create(null); export function tabColor(name: string): string { if (colorMap[name] === undefined) { diff --git a/x-pack/plugins/ml/public/alerting/anomaly_detection_rule/ml_anomaly_alert_trigger.tsx b/x-pack/plugins/ml/public/alerting/anomaly_detection_rule/ml_anomaly_alert_trigger.tsx index 2f36f3f687caf..7404646db7195 100644 --- a/x-pack/plugins/ml/public/alerting/anomaly_detection_rule/ml_anomaly_alert_trigger.tsx +++ b/x-pack/plugins/ml/public/alerting/anomaly_detection_rule/ml_anomaly_alert_trigger.tsx @@ -199,7 +199,6 @@ const MlAnomalyAlertTrigger: FC = ({ errors={Array.isArray(errors.jobSelection) ? errors.jobSelection : []} shouldUseDropdownJobCreate /> - = ({ alertParams={resultParams} maxNumberOfBuckets={maxNumberOfBuckets} /> - = ({ onChange={useCallback(onAlertParamChange('includeInterim'), [])} /> - { + onChange={useCallback((update: any) => { Object.keys(update).forEach((k) => { setRuleParams(k, update[k as keyof MlAnomalyDetectionAlertAdvancedSettings]); }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [])} /> - - - ); diff --git a/x-pack/plugins/ml/public/alerting/jobs_health_rule/anomaly_detection_jobs_health_rule_trigger.tsx b/x-pack/plugins/ml/public/alerting/jobs_health_rule/anomaly_detection_jobs_health_rule_trigger.tsx index 4e8d88f8b33ef..54d25e9fcb30b 100644 --- a/x-pack/plugins/ml/public/alerting/jobs_health_rule/anomaly_detection_jobs_health_rule_trigger.tsx +++ b/x-pack/plugins/ml/public/alerting/jobs_health_rule/anomaly_detection_jobs_health_rule_trigger.tsx @@ -125,13 +125,11 @@ const AnomalyDetectionJobsHealthRuleTrigger: FC = ({ } shouldUseDropdownJobCreate /> - - { + onChange={useCallback((update: any) => { const callback = onAlertParamChange('excludeJobs'); if (isPopulatedObject(update)) { callback(update); @@ -151,9 +149,7 @@ const AnomalyDetectionJobsHealthRuleTrigger: FC = ({ options={excludeJobsOptions} shouldUseDropdownJobCreate /> - - { const useUserTimeSettings = useUiSettings().get(ANOMALY_DETECTION_ENABLE_TIME_RANGE); const userTimeSettings = useUiSettings().get(ANOMALY_DETECTION_DEFAULT_TIME_RANGE); const createLinkWithUserDefaults = useCallback( - (location, jobList) => { + (location: any, jobList: any) => { const resultsUrl = mlJobService.createResultsUrlForJobs( jobList, location, diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_data_grid.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_data_grid.ts index 8ed2b2fd3b2a2..5a8d29422a9d5 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_data_grid.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_data_grid.ts @@ -36,20 +36,20 @@ export const useExplorationDataGrid = ( }), [pageUrlState.pageSize, pageUrlState.pageIndex] ); - dataGrid.setPagination = useCallback( + dataGrid.setPagination = useCallback( (u) => { setPageUrlState({ ...u }); }, [setPageUrlState] ); dataGrid.onChangePage = useCallback( - (pageIndex) => { + (pageIndex: number) => { setPageUrlState({ pageIndex }); }, [setPageUrlState] ); dataGrid.onChangeItemsPerPage = useCallback( - (pageSize) => { + (pageSize: number) => { setPageUrlState({ pageSize }); }, [setPageUrlState] diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/decision_path_chart.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/decision_path_chart.tsx index 954b85ce2793e..2805563eeb7fd 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/decision_path_chart.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/decision_path_chart.tsx @@ -122,7 +122,7 @@ export const DecisionPathChart = ({ ); // if regression, guarantee up to num_precision significant digits without having it in scientific notation // if classification, hide the numeric values since we only want to show the path - const tickFormatter = useCallback((d) => formatSingleValue(d, '').toString(), []); + const tickFormatter = useCallback((d: any) => formatSingleValue(d, '').toString(), []); return (
diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/total_feature_importance_summary/feature_importance_summary.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/total_feature_importance_summary/feature_importance_summary.tsx index e4c1b92433b88..9e7371580b12d 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/total_feature_importance_summary/feature_importance_summary.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/total_feature_importance_summary/feature_importance_summary.tsx @@ -200,7 +200,7 @@ export const FeatureImportanceSummaryPanel: FC Number(d.toPrecision(3)).toString(), []); + const tickFormatter = useCallback((d: any) => Number(d.toPrecision(3)).toString(), []); // do not expand by default if no feature importance data const noDataCallOut = useMemo(() => { diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/analytics_list.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/analytics_list.tsx index e0a12f4187ab3..9cf3636604450 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/analytics_list.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/analytics_list.tsx @@ -100,7 +100,7 @@ export const DataFrameAnalyticsList: FC = ({ const searchQueryText = pageState.queryText ?? ''; const setSearchQueryText = useCallback( - (value) => { + (value: any) => { updatePageState({ queryText: value }); }, [updatePageState] @@ -278,6 +278,7 @@ export const DataFrameAnalyticsList: FC = ({
+ rowHeader={DataFrameAnalyticsListColumn.id} allowNeutralSort={false} columns={columns} itemIdToExpandedRowMap={itemIdToExpandedRowMap} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_columns.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_columns.tsx index 0f9b1dab9e491..fb9731c347aca 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_columns.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_columns.tsx @@ -216,7 +216,6 @@ export const useColumns = ( sortable: (item: DataFrameAnalyticsListRow) => item.id, truncateText: { lines: TRUNCATE_TEXT_LINES }, 'data-test-subj': 'mlAnalyticsTableColumnId', - scope: 'row', render: (id: string) => { return {id}; }, diff --git a/x-pack/plugins/ml/public/application/explorer/actions/load_explorer_data.ts b/x-pack/plugins/ml/public/application/explorer/actions/load_explorer_data.ts index 8d710e0a83b6c..faa2b009c131d 100644 --- a/x-pack/plugins/ml/public/application/explorer/actions/load_explorer_data.ts +++ b/x-pack/plugins/ml/public/application/explorer/actions/load_explorer_data.ts @@ -224,7 +224,7 @@ export const useExplorerData = (): [Partial | undefined, (d: any) const explorerData$ = useMemo(() => loadExplorerData$.pipe(switchMap(loadExplorerData)), []); const explorerData = useObservable(explorerData$); - const update = useCallback((c) => { + const update = useCallback((c: any) => { loadExplorerData$.next(c); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); diff --git a/x-pack/plugins/ml/public/application/explorer/anomaly_timeline.tsx b/x-pack/plugins/ml/public/application/explorer/anomaly_timeline.tsx index 2b164985f022a..ae12b8b1fa4ac 100644 --- a/x-pack/plugins/ml/public/application/explorer/anomaly_timeline.tsx +++ b/x-pack/plugins/ml/public/application/explorer/anomaly_timeline.tsx @@ -465,7 +465,7 @@ export const AnomalyTimeline: FC = React.memo( { + onChange={useCallback((update: any) => { setSeverityUpdate(update); }, [])} /> diff --git a/x-pack/plugins/ml/public/application/explorer/explorer.tsx b/x-pack/plugins/ml/public/application/explorer/explorer.tsx index 23a4cbed76bbc..65b862bc548e6 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer.tsx +++ b/x-pack/plugins/ml/public/application/explorer/explorer.tsx @@ -232,7 +232,7 @@ export const Explorer: FC = ({ ); const onPanelWidthChange = useCallback( - (newSizes) => { + (newSizes: any) => { setAnomalyExplorerPanelState({ mainPage: { size: newSizes.mainPage, diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js index c746d8003ce6b..b72bbf41269cc 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js @@ -170,7 +170,6 @@ export class JobsList extends Component { sortable: true, truncateText: false, width: '15%', - scope: 'row', render: (id, item) => { if (!isManagedJob(item)) return id; @@ -395,6 +394,7 @@ export class JobsList extends Component { 'data-test-subj': `mlJobListRow row-${item.id}`, })} css={{ '.euiTableRow-isExpandedRow .euiTableCellContent': { animation: 'none' } }} + rowHeader="id" /> ); } diff --git a/x-pack/plugins/ml/server/lib/alerts/register_anomaly_detection_alert_type.ts b/x-pack/plugins/ml/server/lib/alerts/register_anomaly_detection_alert_type.ts index 93b6daac5081e..deb7c9d2cc657 100644 --- a/x-pack/plugins/ml/server/lib/alerts/register_anomaly_detection_alert_type.ts +++ b/x-pack/plugins/ml/server/lib/alerts/register_anomaly_detection_alert_type.ts @@ -255,7 +255,7 @@ export function registerAnomalyDetectionAlertType({ spaceId, rule, }: ExecutorOptions) => { - const fakeRequest = {} as KibanaRequest; + const fakeRequest = Object.create(null) as KibanaRequest; const alertingService = mlSharedServices.alertingServiceProvider( services.savedObjectsClient, fakeRequest diff --git a/x-pack/plugins/ml/server/lib/alerts/register_jobs_monitoring_rule_type.ts b/x-pack/plugins/ml/server/lib/alerts/register_jobs_monitoring_rule_type.ts index b311a637eb2d7..7d50f99a42128 100644 --- a/x-pack/plugins/ml/server/lib/alerts/register_jobs_monitoring_rule_type.ts +++ b/x-pack/plugins/ml/server/lib/alerts/register_jobs_monitoring_rule_type.ts @@ -266,7 +266,7 @@ export function registerJobsMonitoringRuleType({ throw new AlertsClientError(); } - const fakeRequest = {} as KibanaRequest; + const fakeRequest = Object.create(null) as KibanaRequest; const { getTestsResults } = mlServicesProviders.jobsHealthServiceProvider( services.savedObjectsClient, fakeRequest, diff --git a/x-pack/plugins/ml/server/lib/capabilities/__mocks__/ml_capabilities.ts b/x-pack/plugins/ml/server/lib/capabilities/__mocks__/ml_capabilities.ts index ebc90c1f208ac..a27556faa6450 100644 --- a/x-pack/plugins/ml/server/lib/capabilities/__mocks__/ml_capabilities.ts +++ b/x-pack/plugins/ml/server/lib/capabilities/__mocks__/ml_capabilities.ts @@ -13,7 +13,7 @@ import { } from '../../../../common/types/capabilities'; export function getAdminCapabilities() { - const caps: any = {}; + const caps: any = Object.create(null); Object.keys(adminMlCapabilities).forEach((k) => { caps[k] = true; }); @@ -21,7 +21,7 @@ export function getAdminCapabilities() { } export function getUserCapabilities() { - const caps: any = {}; + const caps: any = Object.create(null); Object.keys(userMlCapabilities).forEach((k) => { caps[k] = true; }); diff --git a/x-pack/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.ts b/x-pack/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.ts index 868a1c5709224..c36e569a6eb3a 100644 --- a/x-pack/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.ts +++ b/x-pack/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.ts @@ -65,8 +65,8 @@ const cardinalityCheckProvider = (client: IScopedClusterClient) => { const { detectors, influencers, bucket_span: bucketSpan } = analysisConfig; - let overallCardinality = {}; - let maxBucketCardinality = {}; + let overallCardinality = Object.create(null); + let maxBucketCardinality = Object.create(null); // Get fields required for the model memory estimation const overallCardinalityFields: Set = detectors.reduce( diff --git a/x-pack/plugins/ml/server/models/data_frame_analytics/analytics_manager.ts b/x-pack/plugins/ml/server/models/data_frame_analytics/analytics_manager.ts index f959683b6ae88..4e112a2ff313b 100644 --- a/x-pack/plugins/ml/server/models/data_frame_analytics/analytics_manager.ts +++ b/x-pack/plugins/ml/server/models/data_frame_analytics/analytics_manager.ts @@ -228,7 +228,7 @@ export class AnalyticsManager { private async getInitialElementsModelRoot(modelId: string): Promise { const resultElements = []; const modelElements = []; - const details: any = {}; + const details: any = Object.create(null); let data: estypes.MlTrainedModelConfig | estypes.MlDataframeAnalyticsSummary | undefined; // fetch model data and create model elements data = this.findTrainedModel(modelId); @@ -296,7 +296,7 @@ export class AnalyticsManager { ): Promise { const resultElements = []; const modelElements = []; - const details: any = {}; + const details: any = Object.create(null); const data = this.findJob(jobId); const nextLinkId = data?.source?.index[0]; @@ -351,7 +351,7 @@ export class AnalyticsManager { try { await this.initData(); // Create first node for incoming analyticsId or modelId - let initialData: InitialElementsReturnType = {} as InitialElementsReturnType; + let initialData: InitialElementsReturnType = Object.create(null) as InitialElementsReturnType; const job = analyticsId === undefined ? undefined : this.findJob(analyticsId); if (analyticsId !== undefined && job !== undefined) { const jobCreateTime = job.create_time!; diff --git a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts index 07eebe6aaa66a..d54976a37ecd1 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts +++ b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts @@ -355,7 +355,7 @@ export class DataRecognizer { const jobs: ModuleJob[] = []; const datafeeds: ModuleDatafeed[] = []; - const kibana: KibanaObjects = {}; + const kibana: KibanaObjects = Object.create(null); // load all of the job configs if (isModule(module)) { const tempJobs: ModuleJob[] = module.jobs.map((j) => ({ @@ -595,7 +595,7 @@ export class DataRecognizer { } public async dataRecognizerJobsExist(moduleId: string): Promise { - const results = {} as JobExistResult; + const results = Object.create(null) as JobExistResult; // Load the module with the specified ID and check if the jobs // in the module have been created. @@ -851,7 +851,7 @@ export class DataRecognizer { start?: number, end?: number ): Promise<{ [key: string]: DatafeedResponse }> { - const results = {} as { [key: string]: DatafeedResponse }; + const results = Object.create(null) as { [key: string]: DatafeedResponse }; for (const datafeed of datafeeds) { results[datafeed.id] = await this._startDatafeed(datafeed, start, end); } @@ -957,7 +957,9 @@ export class DataRecognizer { // creates an empty results object, // listing each job/datafeed/savedObject with a save success boolean private _createResultsTemplate(moduleConfig: Module): DataRecognizerConfigResponse { - const results: DataRecognizerConfigResponse = {} as DataRecognizerConfigResponse; + const results: DataRecognizerConfigResponse = Object.create( + null + ) as DataRecognizerConfigResponse; const reducedConfig = { jobs: moduleConfig.jobs, datafeeds: moduleConfig.datafeeds, @@ -982,7 +984,7 @@ export class DataRecognizer { if (Array.isArray(reducedConfig[i])) { createResultsItems(reducedConfig[i] as any[], results, i); } else { - results[i] = {} as any; + results[i] = Object.create(null); Object.keys(reducedConfig[i]).forEach((k) => { createResultsItems((reducedConfig[i] as Module['kibana'])[k] as any[], results[i], k); }); @@ -1174,7 +1176,7 @@ export class DataRecognizer { ); if (!job.config.analysis_limits) { - job.config.analysis_limits = {} as AnalysisLimits; + job.config.analysis_limits = Object.create(null) as AnalysisLimits; } job.config.analysis_limits.model_memory_limit = modelMemoryLimit; @@ -1206,7 +1208,7 @@ export class DataRecognizer { // so set the jobs mml to be the max if (!job.config.analysis_limits) { - job.config.analysis_limits = {} as AnalysisLimits; + job.config.analysis_limits = Object.create(null) as AnalysisLimits; } job.config.analysis_limits.model_memory_limit = maxMml; diff --git a/x-pack/plugins/ml/server/models/data_visualizer/data_visualizer.ts b/x-pack/plugins/ml/server/models/data_visualizer/data_visualizer.ts index 720a39193b9a7..fa84a271e84bd 100644 --- a/x-pack/plugins/ml/server/models/data_visualizer/data_visualizer.ts +++ b/x-pack/plugins/ml/server/models/data_visualizer/data_visualizer.ts @@ -246,7 +246,7 @@ export class DataVisualizer { ): Promise { // Batch up fields by type, getting stats for multiple fields at a time. const batches: Field[][] = []; - const batchedFields: { [key: string]: Field[][] } = {}; + const batchedFields: { [key: string]: Field[][] } = Object.create(null); each(fields, (field) => { if (field.fieldName === undefined) { // undefined fieldName is used for a document count request. @@ -584,7 +584,7 @@ export class DataVisualizer { { maxRetries: 0 } ); - const buckets: { [key: string]: number } = {}; + const buckets: { [key: string]: number } = Object.create(null); const dataByTimeBucket: Array<{ key: string; doc_count: number }> = get( body, ['aggregations', 'eventRate', 'buckets'], @@ -628,7 +628,7 @@ export class DataVisualizer { () => (count += PERCENTILE_SPACING) ); - const aggs: { [key: string]: any } = {}; + const aggs: { [key: string]: any } = Object.create(null); fields.forEach((field, i) => { const safeFieldName = getSafeAggregationName(field.fieldName, i); aggs[`${safeFieldName}_field_stats`] = { @@ -757,7 +757,7 @@ export class DataVisualizer { const size = 0; const filterCriteria = buildBaseFilterCriteria(timeFieldName, earliestMs, latestMs, query); - const aggs: Aggs = {}; + const aggs: Aggs = Object.create(null); fields.forEach((field, i) => { const safeFieldName = getSafeAggregationName(field.fieldName, i); const top = { @@ -839,7 +839,7 @@ export class DataVisualizer { const size = 0; const filterCriteria = buildBaseFilterCriteria(timeFieldName, earliestMs, latestMs, query); - const aggs: Aggs = {}; + const aggs: Aggs = Object.create(null); fields.forEach((field, i) => { const safeFieldName = getSafeAggregationName(field.fieldName, i); aggs[`${safeFieldName}_field_stats`] = { @@ -910,7 +910,7 @@ export class DataVisualizer { const size = 0; const filterCriteria = buildBaseFilterCriteria(timeFieldName, earliestMs, latestMs, query); - const aggs: Aggs = {}; + const aggs: Aggs = Object.create(null); fields.forEach((field, i) => { const safeFieldName = getSafeAggregationName(field.fieldName, i); aggs[`${safeFieldName}_value_count`] = { diff --git a/x-pack/plugins/ml/server/models/fields_service/fields_service.ts b/x-pack/plugins/ml/server/models/fields_service/fields_service.ts index cba34e2cbb8e3..a7e1812888c2f 100644 --- a/x-pack/plugins/ml/server/models/fields_service/fields_service.ts +++ b/x-pack/plugins/ml/server/models/fields_service/fields_service.ts @@ -146,7 +146,7 @@ export function fieldsServiceProvider({ asCurrentUser }: IScopedClusterClient) { mustCriteria.push(query); } - const runtimeMappings: any = {}; + const runtimeMappings: any = Object.create(null); const aggs = fieldsToAgg.reduce( (obj, field) => { if ( diff --git a/x-pack/plugins/ml/server/models/filter/filter_manager.ts b/x-pack/plugins/ml/server/models/filter/filter_manager.ts index 84f5ae9d7e5a7..3aed4b80a792d 100644 --- a/x-pack/plugins/ml/server/models/filter/filter_manager.ts +++ b/x-pack/plugins/ml/server/models/filter/filter_manager.ts @@ -77,7 +77,7 @@ export class FilterManager { ]); // Build a map of filter_ids against jobs and detectors using that filter. - let filtersInUse: FiltersInUse = {}; + let filtersInUse: FiltersInUse = Object.create(null); if (results[JOBS] && (results[JOBS] as estypes.MlGetJobsResponse).jobs) { filtersInUse = this.buildFiltersInUse((results[JOBS] as estypes.MlGetJobsResponse).jobs); } @@ -136,7 +136,7 @@ export class FilterManager { buildFiltersInUse(jobsList: Job[]) { // Build a map of filter_ids against jobs and detectors using that filter. - const filtersInUse: FiltersInUse = {}; + const filtersInUse: FiltersInUse = Object.create(null); jobsList.forEach((job) => { const detectors = job.analysis_config.detectors; detectors.forEach((detector) => { diff --git a/x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.ts b/x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.ts index 43125551e8339..52f2f9b0cadae 100644 --- a/x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.ts +++ b/x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.ts @@ -89,7 +89,7 @@ export function jobAuditMessagesProvider( gte = `now-${from}`; } - let timeFilter = {}; + let timeFilter = Object.create(null); if (from !== null) { timeFilter = { range: { diff --git a/x-pack/plugins/ml/server/models/job_service/datafeeds.ts b/x-pack/plugins/ml/server/models/job_service/datafeeds.ts index 50400054a4e04..5c2c44c326c8c 100644 --- a/x-pack/plugins/ml/server/models/job_service/datafeeds.ts +++ b/x-pack/plugins/ml/server/models/job_service/datafeeds.ts @@ -41,7 +41,7 @@ export function datafeedsProvider(client: IScopedClusterClient, mlClient: MlClie return acc; }, {} as { [id: string]: boolean }); - const results: Results = {}; + const results: Results = Object.create(null); async function doStart(datafeedId: string): Promise<{ started: boolean; error?: string }> { if (doStartsCalled[datafeedId] === false) { @@ -114,7 +114,7 @@ export function datafeedsProvider(client: IScopedClusterClient, mlClient: MlClie } async function stopDatafeeds(datafeedIds: string[]) { - const results: Results = {}; + const results: Results = Object.create(null); for (const datafeedId of datafeedIds) { try { diff --git a/x-pack/plugins/ml/server/models/job_service/groups.ts b/x-pack/plugins/ml/server/models/job_service/groups.ts index cdb5d373393bb..06641fff9795f 100644 --- a/x-pack/plugins/ml/server/models/job_service/groups.ts +++ b/x-pack/plugins/ml/server/models/job_service/groups.ts @@ -22,8 +22,8 @@ export function groupsProvider(mlClient: MlClient) { const calMngr = new CalendarManager(mlClient); async function getAllGroups() { - const groups: { [id: string]: Group } = {}; - const jobIds: { [id: string]: undefined | null } = {}; + const groups: { [id: string]: Group } = Object.create(null); + const jobIds: { [id: string]: undefined | null } = Object.create(null); const [body, calendars] = await Promise.all([mlClient.getJobs(), calMngr.getAllCalendars()]); const { jobs } = body; @@ -70,7 +70,7 @@ export function groupsProvider(mlClient: MlClient) { } async function updateGroups(jobs: UpdateGroupsRequest['jobs']) { - const results: Results = {}; + const results: Results = Object.create(null); for (const job of jobs) { const { jobId, groups } = job; try { diff --git a/x-pack/plugins/ml/server/models/job_service/jobs.ts b/x-pack/plugins/ml/server/models/job_service/jobs.ts index d9cebc84bb742..7e29fe8966151 100644 --- a/x-pack/plugins/ml/server/models/job_service/jobs.ts +++ b/x-pack/plugins/ml/server/models/job_service/jobs.ts @@ -89,7 +89,7 @@ export function jobsProvider( deleteUserAnnotations = false, deleteAlertingRules = false ) { - const results: Results = {}; + const results: Results = Object.create(null); const datafeedIds = await getDatafeedIdsByJobId(); if (deleteAlertingRules && rulesClient) { @@ -149,7 +149,7 @@ export function jobsProvider( } async function closeJobs(jobIds: string[]) { - const results: Results = {}; + const results: Results = Object.create(null); for (const jobId of jobIds) { try { await mlClient.closeJob({ job_id: jobId }); @@ -185,7 +185,7 @@ export function jobsProvider( } async function resetJobs(jobIds: string[], deleteUserAnnotations = false) { - const results: ResetJobsResponse = {}; + const results: ResetJobsResponse = Object.create(null); for (const jobId of jobIds) { try { // @ts-expect-error @elastic-elasticsearch resetJob response incorrect, missing task @@ -229,7 +229,7 @@ export function jobsProvider( async function jobsSummary(jobIds: string[] = []) { const fullJobsList: CombinedJobWithStats[] = await createFullJobsList(); const fullJobsIds = fullJobsList.map((job) => job.job_id); - let auditMessagesByJob: { [id: string]: AuditMessage } = {}; + let auditMessagesByJob: { [id: string]: AuditMessage } = Object.create(null); // even if there are errors getting the audit messages, we still want to show the full list try { @@ -309,12 +309,12 @@ export function jobsProvider( async function jobsWithTimerange() { const fullJobsList = await createFullJobsList(); - const jobsMap: { [id: string]: string[] } = {}; + const jobsMap: { [id: string]: string[] } = Object.create(null); const jobs = fullJobsList.map((job) => { jobsMap[job.job_id] = job.groups || []; const hasDatafeed = isPopulatedObject(job.datafeed_config); - const timeRange: { to?: number; from?: number } = {}; + const timeRange: { to?: number; from?: number } = Object.create(null); const dataCounts = job.data_counts; if (dataCounts !== undefined) { @@ -378,9 +378,9 @@ export function jobsProvider( async function createFullJobsList(jobIds: string[] = []) { const jobs: CombinedJobWithStats[] = []; - const groups: { [jobId: string]: string[] } = {}; - const datafeeds: { [id: string]: DatafeedWithStats } = {}; - const calendarsByJobId: { [jobId: string]: string[] } = {}; + const groups: { [jobId: string]: string[] } = Object.create(null); + const datafeeds: { [id: string]: DatafeedWithStats } = Object.create(null); + const calendarsByJobId: { [jobId: string]: string[] } = Object.create(null); const globalCalendars: string[] = []; const jobIdsString = jobIds.join(); @@ -583,7 +583,7 @@ export function jobsProvider( jobIds: string[] = [], allSpaces: boolean = false ): Promise { - const results: JobsExistResponse = {}; + const results: JobsExistResponse = Object.create(null); for (const jobId of jobIds) { try { if (jobId === '') { @@ -669,7 +669,7 @@ export function jobsProvider( jobs: Array<{ job: Job; datafeed: Datafeed }>, authHeader: AuthorizationHeader ) { - const results: BulkCreateResults = {}; + const results: BulkCreateResults = Object.create(null); await Promise.all( jobs.map(async ({ job, datafeed }) => { results[job.job_id] = { job: { success: false }, datafeed: { success: false } }; diff --git a/x-pack/plugins/ml/server/models/job_service/new_job/line_chart.ts b/x-pack/plugins/ml/server/models/job_service/new_job/line_chart.ts index 6a439a3711c6d..d95808bef1bc0 100644 --- a/x-pack/plugins/ml/server/models/job_service/new_job/line_chart.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job/line_chart.ts @@ -69,7 +69,7 @@ export function newJobLineChartProvider({ asCurrentUser }: IScopedClusterClient) function processSearchResults(resp: any, fields: string[]): ProcessedResults { const aggregationsByTime = get(resp, ['aggregations', 'times', 'buckets'], []); - const tempResults: Record = {}; + const tempResults: Record = Object.create(null); fields.forEach((f, i) => (tempResults[i] = [])); aggregationsByTime.forEach((dataForTime: any) => { @@ -166,7 +166,10 @@ function getSearchJsonFromConfig( json.body.query = query; - const aggs: Record> = {}; + const aggs: Record< + number, + Record + > = Object.create(null); aggFieldNamePairs.forEach(({ agg, field }, i) => { if (field !== null && field !== EVENT_RATE_FIELD_ID) { diff --git a/x-pack/plugins/ml/server/models/job_service/new_job/population_chart.ts b/x-pack/plugins/ml/server/models/job_service/new_job/population_chart.ts index 03daf69a3813a..de450ea697ea8 100644 --- a/x-pack/plugins/ml/server/models/job_service/new_job/population_chart.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job/population_chart.ts @@ -75,7 +75,7 @@ export function newJobPopulationChartProvider({ asCurrentUser }: IScopedClusterC function processSearchResults(resp: any, fields: string[]): ProcessedResults { const aggregationsByTime = get(resp, ['aggregations', 'times', 'buckets'], []); - const tempResults: Record = {}; + const tempResults: Record = Object.create(null); fields.forEach((f, i) => (tempResults[i] = [])); aggregationsByTime.forEach((dataForTime: any) => { @@ -188,7 +188,7 @@ function getPopulationSearchJsonFromConfig( json.body.query = query; - const aggs: any = {}; + const aggs: any = Object.create(null); aggFieldNamePairs.forEach(({ agg, field, by }, i) => { if (field === EVENT_RATE_FIELD_ID) { diff --git a/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts b/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts index 6cfd847403852..74065222a529d 100644 --- a/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts @@ -125,7 +125,7 @@ class FieldsService { // the _indexPattern will be replaced with a comma separated list // of index patterns from all of the rollup jobs public async getData(includeNested: boolean = false): Promise { - let rollupFields: RollupFields = {}; + let rollupFields: RollupFields = Object.create(null); if (this._isRollup) { const rollupService = await rollupServiceProvider( @@ -159,7 +159,7 @@ class FieldsService { function combineAllRollupFields( rollupConfigs: estypes.RollupGetRollupCapsRollupCapabilitySummary[] ): RollupFields { - const rollupFields: RollupFields = {}; + const rollupFields: RollupFields = Object.create(null); rollupConfigs.forEach((conf) => { Object.keys(conf.fields).forEach((fieldName) => { if (rollupFields[fieldName] === undefined) { diff --git a/x-pack/plugins/ml/server/models/job_validation/job_validation.test.ts b/x-pack/plugins/ml/server/models/job_validation/job_validation.test.ts index f31f708100d4e..98fb5ce52e240 100644 --- a/x-pack/plugins/ml/server/models/job_validation/job_validation.test.ts +++ b/x-pack/plugins/ml/server/models/job_validation/job_validation.test.ts @@ -23,7 +23,7 @@ callAs.search.mockResponse({ hits: { total: { value: 1, relation: ES_CLIENT_TOTAL_HITS_RELATION.EQ } }, }); -const authHeader: AuthorizationHeader = {}; +const authHeader: AuthorizationHeader = Object.create(null); const mlClusterClient = { asCurrentUser: callAs, diff --git a/x-pack/plugins/ml/server/models/results_service/anomaly_charts.ts b/x-pack/plugins/ml/server/models/results_service/anomaly_charts.ts index 8b6f1d1fa0494..8d14417a1d383 100644 --- a/x-pack/plugins/ml/server/models/results_service/anomaly_charts.ts +++ b/x-pack/plugins/ml/server/models/results_service/anomaly_charts.ts @@ -227,7 +227,7 @@ export function anomalyChartsDataProvider(mlClient: MlClient, client: IScopedClu esSearchRequest.query!.bool!.minimum_should_match = shouldCriteria.length / 2; } - esSearchRequest.aggs!.byTime.aggs = {}; + esSearchRequest.aggs!.byTime.aggs = Object.create(null); if (metricFieldName !== undefined && metricFieldName !== '' && metricFunction) { const metricAgg: any = { @@ -258,7 +258,7 @@ export function anomalyChartsDataProvider(mlClient: MlClient, client: IScopedClu } esSearchRequest.aggs!.byTime.aggs = tempAggs; } else { - esSearchRequest.aggs!.byTime.aggs.metric = metricAgg; + esSearchRequest.aggs!.byTime.aggs!.metric = metricAgg; } } else { // if metricFieldName is not defined, it's probably a variation of the non zero count function @@ -465,9 +465,9 @@ export function anomalyChartsDataProvider(mlClient: MlClient, client: IScopedClu return { records: [], errors: undefined }; } // Aggregate by job, detector, and analysis fields (partition, by, over). - const aggregatedData: Record = {}; + const aggregatedData: Record = Object.create(null); - const jobsErrorMessage: Record = {}; + const jobsErrorMessage: Record = Object.create(null); each(anomalyRecords, (record) => { // Check if we can plot a chart for this record, depending on whether the source data // is chartable, and if model plot is enabled for the job. @@ -516,13 +516,13 @@ export function anomalyChartsDataProvider(mlClient: MlClient, client: IScopedClu } const jobId = record.job_id; if (aggregatedData[jobId] === undefined) { - aggregatedData[jobId] = {}; + aggregatedData[jobId] = Object.create(null); } const detectorsForJob = aggregatedData[jobId]; const detectorIndex = record.detector_index; if (detectorsForJob[detectorIndex] === undefined) { - detectorsForJob[detectorIndex] = {}; + detectorsForJob[detectorIndex] = Object.create(null); } // TODO - work out how best to display results from detectors with just an over field. @@ -534,11 +534,11 @@ export function anomalyChartsDataProvider(mlClient: MlClient, client: IScopedClu const groupsForDetector = detectorsForJob[detectorIndex]; if (groupsForDetector[firstFieldName] === undefined) { - groupsForDetector[firstFieldName] = {}; + groupsForDetector[firstFieldName] = Object.create(null); } const valuesForGroup: Record = groupsForDetector[firstFieldName]; if (valuesForGroup[firstFieldValue] === undefined) { - valuesForGroup[firstFieldValue] = {}; + valuesForGroup[firstFieldValue] = Object.create(null); } const dataForGroupValue = valuesForGroup[firstFieldValue]; @@ -568,12 +568,12 @@ export function anomalyChartsDataProvider(mlClient: MlClient, client: IScopedClu if (secondFieldName !== undefined && secondFieldValue !== undefined) { if (dataForGroupValue[secondFieldName] === undefined) { - dataForGroupValue[secondFieldName] = {}; + dataForGroupValue[secondFieldName] = Object.create(null); } const splitsForGroup = dataForGroupValue[secondFieldName]; if (splitsForGroup[secondFieldValue] === undefined) { - splitsForGroup[secondFieldValue] = {}; + splitsForGroup[secondFieldValue] = Object.create(null); } const dataForSplitValue = splitsForGroup[secondFieldValue]; @@ -604,7 +604,7 @@ export function anomalyChartsDataProvider(mlClient: MlClient, client: IScopedClu }); // Group job id by error message instead of by job: - const errorMessages: Record> | undefined = {}; + const errorMessages: Record> = Object.create(null); Object.keys(jobsErrorMessage).forEach((jobId) => { const msg = jobsErrorMessage[jobId]; if (errorMessages[msg] === undefined) { @@ -907,13 +907,13 @@ export function anomalyChartsDataProvider(mlClient: MlClient, client: IScopedClu handleError = (errorMsg: string, jobId: string) => { // Group the jobIds by the type of error message if (!errorMessages) { - errorMessages = {}; + errorMessages = Object.create(null); } - if (errorMessages[errorMsg]) { - errorMessages[errorMsg].add(jobId); + if (errorMessages![errorMsg]) { + errorMessages![errorMsg].add(jobId); } else { - errorMessages[errorMsg] = new Set([jobId]); + errorMessages![errorMsg] = new Set([jobId]); } }; } @@ -1408,7 +1408,7 @@ export function anomalyChartsDataProvider(mlClient: MlClient, client: IScopedClu const dataByJobId = get(resp, ['aggregations', 'jobs', 'buckets'], []); each(dataByJobId, (dataForJob: any) => { const jobId: string = dataForJob.key; - const resultsForTime: Record = {}; + const resultsForTime: Record = Object.create(null); const dataByTime = get(dataForJob, ['times', 'buckets'], []); each(dataByTime, (dataForTime: any) => { const time: string = dataForTime.key; @@ -1543,7 +1543,7 @@ export function anomalyChartsDataProvider(mlClient: MlClient, client: IScopedClu typeof metricFunction === 'string' ) { // @ts-ignore - body.aggs.sample.aggs.byTime.aggs.entities.aggs = {}; + body.aggs.sample.aggs.byTime.aggs.entities.aggs = Object.create(null); const metricAgg = { [metricFunction]: { diff --git a/x-pack/plugins/ml/server/models/results_service/results_service.ts b/x-pack/plugins/ml/server/models/results_service/results_service.ts index 0a732cf45a94c..bbf9c4def4722 100644 --- a/x-pack/plugins/ml/server/models/results_service/results_service.ts +++ b/x-pack/plugins/ml/server/models/results_service/results_service.ts @@ -54,7 +54,7 @@ interface Influencer { * @param source */ export function getTypicalAndActualValues(source: MlAnomalyRecordDoc) { - const result: { actual?: number[]; typical?: number[] } = {}; + const result: { actual?: number[]; typical?: number[] } = Object.create(null); const functionDescription = source.function_description || ''; const causes = source.causes || []; @@ -254,9 +254,9 @@ export function resultsServiceProvider(mlClient: MlClient, client?: IScopedClust (item: any) => item.entityName === 'mlcategory' ); if (categoryAnomalies.length > 0) { - tableData.examplesByJobId = {}; + tableData.examplesByJobId = Object.create(null); - const categoryIdsByJobId: { [key: string]: any } = {}; + const categoryIdsByJobId: { [key: string]: any } = Object.create(null); categoryAnomalies.forEach((anomaly) => { if (categoryIdsByJobId[anomaly.jobId] === undefined) { categoryIdsByJobId[anomaly.jobId] = []; @@ -420,7 +420,7 @@ export function resultsServiceProvider(mlClient: MlClient, client?: IScopedClust ['aggregations', 'byJobId', 'buckets'], [] ); - const timestampByJobId: { [key: string]: number | undefined } = {}; + const timestampByJobId: { [key: string]: number | undefined } = Object.create(null); bucketsByJobId.forEach((bucket) => { timestampByJobId[bucket.key] = bucket.maxTimestamp.value; }); @@ -446,7 +446,7 @@ export function resultsServiceProvider(mlClient: MlClient, client?: IScopedClust [jobId] ); - const examplesByCategoryId: { [key: string]: any } = {}; + const examplesByCategoryId: { [key: string]: any } = Object.create(null); // @ts-expect-error incorrect search response type if (body.hits.total.value > 0) { body.hits.hits.forEach((hit: any) => { diff --git a/x-pack/plugins/ml/server/routes/data_frame_analytics.ts b/x-pack/plugins/ml/server/routes/data_frame_analytics.ts index e408c2a719fbb..0229f9e9bba5b 100644 --- a/x-pack/plugins/ml/server/routes/data_frame_analytics.ts +++ b/x-pack/plugins/ml/server/routes/data_frame_analytics.ts @@ -668,7 +668,7 @@ export function dataFrameAnalyticsRoutes( routeGuard.fullLicenseAPIGuard(async ({ client, mlClient, request, response }) => { try { const { analyticsIds, allSpaces } = request.body; - const results: { [id: string]: { exists: boolean } } = {}; + const results: { [id: string]: { exists: boolean } } = Object.create(null); for (const id of analyticsIds) { try { const body = allSpaces diff --git a/x-pack/plugins/ml/server/routes/trained_models.ts b/x-pack/plugins/ml/server/routes/trained_models.ts index 2f3e402e05be3..b0197c19aa5f8 100644 --- a/x-pack/plugins/ml/server/routes/trained_models.ts +++ b/x-pack/plugins/ml/server/routes/trained_models.ts @@ -617,7 +617,8 @@ export function trainedModelsRoutes( try { const { deploymentId, modelId } = request.params; - const results: Record = {}; + const results: Record = + Object.create(null); for (const id of deploymentId.split(',')) { try { diff --git a/x-pack/plugins/ml/server/saved_objects/checks.ts b/x-pack/plugins/ml/server/saved_objects/checks.ts index 1985115d6ebf1..f8e1827c78a87 100644 --- a/x-pack/plugins/ml/server/saved_objects/checks.ts +++ b/x-pack/plugins/ml/server/saved_objects/checks.ts @@ -404,7 +404,7 @@ export function checksFactory( .reduce((acc, cur) => { const type = cur.type; if (acc[type] === undefined) { - acc[type] = {}; + acc[type] = Object.create(null); } acc[type][cur.jobId] = cur.namespaces; return acc; diff --git a/x-pack/plugins/ml/server/saved_objects/service.ts b/x-pack/plugins/ml/server/saved_objects/service.ts index eed08b2a74d63..e6c32f2bc6531 100644 --- a/x-pack/plugins/ml/server/saved_objects/service.ts +++ b/x-pack/plugins/ml/server/saved_objects/service.ts @@ -75,7 +75,7 @@ export function mlSavedObjectServiceFactory( currentSpaceOnly: boolean = true ) { await isMlReady(); - const filterObject: JobObjectFilter = {}; + const filterObject: JobObjectFilter = Object.create(null); if (jobType !== undefined) { filterObject.type = jobType; @@ -225,7 +225,7 @@ export function mlSavedObjectServiceFactory( async function getAllJobObjectsForAllSpaces(jobType?: JobType, jobId?: string) { await isMlReady(); - const filterObject: JobObjectFilter = {}; + const filterObject: JobObjectFilter = Object.create(null); if (jobType !== undefined) { filterObject.type = jobType; @@ -359,7 +359,7 @@ export function mlSavedObjectServiceFactory( return {}; } - const results: SavedObjectResult = {}; + const results: SavedObjectResult = Object.create(null); const jobs = await _getJobObjects(jobType); const jobObjectIdMap = new Map(); const jobObjectsToUpdate: Array<{ type: string; id: string }> = []; @@ -463,7 +463,7 @@ export function mlSavedObjectServiceFactory( async function _getTrainedModelObjects(modelId?: string, currentSpaceOnly: boolean = true) { await isMlReady(); - const filterObject: TrainedModelObjectFilter = {}; + const filterObject: TrainedModelObjectFilter = Object.create(null); if (modelId !== undefined) { filterObject.model_id = modelId; @@ -725,7 +725,7 @@ export function mlSavedObjectServiceFactory( if (modelIds.length === 0 || (spacesToAdd.length === 0 && spacesToRemove.length === 0)) { return {}; } - const results: SavedObjectResult = {}; + const results: SavedObjectResult = Object.create(null); const models = await _getTrainedModelObjects(); const trainedModelObjectIdMap = new Map(); const objectsToUpdate: Array<{ type: string; id: string }> = []; diff --git a/x-pack/plugins/ml/server/saved_objects/sync.ts b/x-pack/plugins/ml/server/saved_objects/sync.ts index cb8713f03acdf..f96233debf9a1 100644 --- a/x-pack/plugins/ml/server/saved_objects/sync.ts +++ b/x-pack/plugins/ml/server/saved_objects/sync.ts @@ -61,7 +61,7 @@ export function syncSavedObjectsFactory( if (job.checks.savedObjectExits === false) { const type = 'anomaly-detector'; if (results.savedObjectsCreated[type] === undefined) { - results.savedObjectsCreated[type] = {}; + results.savedObjectsCreated[type] = Object.create(null); } if (simulate === true) { results.savedObjectsCreated[type]![job.jobId] = { success: true }; @@ -88,7 +88,7 @@ export function syncSavedObjectsFactory( if (job.checks.savedObjectExits === false) { const type = 'data-frame-analytics'; if (results.savedObjectsCreated[type] === undefined) { - results.savedObjectsCreated[type] = {}; + results.savedObjectsCreated[type] = Object.create(null); } if (simulate === true) { results.savedObjectsCreated[type]![job.jobId] = { success: true }; @@ -119,7 +119,7 @@ export function syncSavedObjectsFactory( const { modelId } = model; const type = 'trained-model'; if (results.savedObjectsCreated[type] === undefined) { - results.savedObjectsCreated[type] = {}; + results.savedObjectsCreated[type] = Object.create(null); } if (simulate === true) { results.savedObjectsCreated[type]![modelId] = { success: true }; @@ -161,7 +161,7 @@ export function syncSavedObjectsFactory( if (job.checks.jobExists === false) { const type = 'anomaly-detector'; if (results.savedObjectsDeleted[type] === undefined) { - results.savedObjectsDeleted[type] = {}; + results.savedObjectsDeleted[type] = Object.create(null); } if (simulate === true) { results.savedObjectsDeleted[type]![job.jobId] = { success: true }; @@ -191,7 +191,7 @@ export function syncSavedObjectsFactory( if (job.checks.jobExists === false) { const type = 'data-frame-analytics'; if (results.savedObjectsDeleted[type] === undefined) { - results.savedObjectsDeleted[type] = {}; + results.savedObjectsDeleted[type] = Object.create(null); } if (simulate === true) { results.savedObjectsDeleted[type]![job.jobId] = { success: true }; @@ -225,7 +225,7 @@ export function syncSavedObjectsFactory( const { modelId, namespaces } = model; const type = 'trained-model'; if (results.savedObjectsDeleted[type] === undefined) { - results.savedObjectsDeleted[type] = {}; + results.savedObjectsDeleted[type] = Object.create(null); } if (simulate === true) { @@ -265,7 +265,7 @@ export function syncSavedObjectsFactory( adJobsById[job.jobId].datafeedId !== job.datafeedId) ) { if (results.datafeedsAdded[type] === undefined) { - results.datafeedsAdded[type] = {}; + results.datafeedsAdded[type] = Object.create(null); } // add datafeed id for jobs where the datafeed exists but the id is missing from the saved object // or if the datafeed id in the saved object is not the same as the one attached to the job in es @@ -298,7 +298,7 @@ export function syncSavedObjectsFactory( job.datafeedId !== undefined ) { if (results.datafeedsRemoved[type] === undefined) { - results.datafeedsRemoved[type] = {}; + results.datafeedsRemoved[type] = Object.create(null); } // remove datafeed id for jobs where the datafeed no longer exists but the id is populated in the saved object if (simulate === true) { diff --git a/x-pack/plugins/monitoring/public/application/hooks/use_table.ts b/x-pack/plugins/monitoring/public/application/hooks/use_table.ts index af1a71f95aa28..11f76bb577b11 100644 --- a/x-pack/plugins/monitoring/public/application/hooks/use_table.ts +++ b/x-pack/plugins/monitoring/public/application/hooks/use_table.ts @@ -72,7 +72,7 @@ export function useTable(storageKey: string) { ); const updateTotalItemCount = useCallback( - (num) => { + (num: any) => { // only update pagination state if different if (num === pagination.totalItemCount) return; setPagination({ diff --git a/x-pack/plugins/monitoring/public/application/pages/logstash/pipeline.tsx b/x-pack/plugins/monitoring/public/application/pages/logstash/pipeline.tsx index 206b43cad4578..b89bb112e56f5 100644 --- a/x-pack/plugins/monitoring/public/application/pages/logstash/pipeline.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/logstash/pipeline.tsx @@ -145,7 +145,7 @@ export const LogStashPipelinePage: React.FC = ({ clusters }) => }, [detailVertexId, getPageData]); const onChangePipelineHash = useCallback( - (hash) => { + (hash: any) => { window.location.hash = getSafeForExternalLink(`#/logstash/pipelines/${pipelineId}/${hash}`); }, [pipelineId] diff --git a/x-pack/plugins/monitoring/server/rules/base_rule.ts b/x-pack/plugins/monitoring/server/rules/base_rule.ts index f04ca15be27dd..cb8bfcf400d45 100644 --- a/x-pack/plugins/monitoring/server/rules/base_rule.ts +++ b/x-pack/plugins/monitoring/server/rules/base_rule.ts @@ -405,7 +405,7 @@ export class BaseRule { } protected createGlobalStateLink(link: string, clusterUuid: string, ccs?: string) { - const globalState = [`cluster_uuid:${clusterUuid}`]; + const globalState = [`cluster_uuid:'${clusterUuid}'`]; if (ccs) { globalState.push(`ccs:${ccs}`); } diff --git a/x-pack/plugins/monitoring/server/rules/ccr_read_exceptions_rule.test.ts b/x-pack/plugins/monitoring/server/rules/ccr_read_exceptions_rule.test.ts index 806c382cb3707..34f9c24b6d49b 100644 --- a/x-pack/plugins/monitoring/server/rules/ccr_read_exceptions_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/ccr_read_exceptions_rule.test.ts @@ -279,9 +279,9 @@ describe('CCRReadExceptionsRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'BcK-0pmsQniyPQfZuauuXw_remote_cluster_1:.follower_index_1', context: { - internalFullMessage: `CCR read exceptions alert is firing for the following remote cluster: ${remoteCluster}. Current 'follower_index' index affected: ${followerIndex}. [View CCR stats](http://localhost:5601/app/monitoring#/elasticsearch/ccr?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `CCR read exceptions alert is firing for the following remote cluster: ${remoteCluster}. Current 'follower_index' index affected: ${followerIndex}. [View CCR stats](http://localhost:5601/app/monitoring#/elasticsearch/ccr?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: `CCR read exceptions alert is firing for the following remote cluster: ${remoteCluster}. Verify follower and leader index relationships on the affected remote cluster.`, - action: `[View CCR stats](http://localhost:5601/app/monitoring#/elasticsearch/ccr?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View CCR stats](http://localhost:5601/app/monitoring#/elasticsearch/ccr?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Verify follower and leader index relationships on the affected remote cluster.', clusterName, @@ -452,9 +452,9 @@ describe('CCRReadExceptionsRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'BcK-0pmsQniyPQfZuauuXw_remote_cluster_1:.follower_index_1', context: { - internalFullMessage: `CCR read exceptions alert is firing for the following remote cluster: ${remoteCluster}. Current 'follower_index' index affected: ${followerIndex}. [View CCR stats](http://localhost:5601/app/monitoring#/elasticsearch/ccr?_g=(cluster_uuid:${clusterUuid},ccs:testCluster))`, + internalFullMessage: `CCR read exceptions alert is firing for the following remote cluster: ${remoteCluster}. Current 'follower_index' index affected: ${followerIndex}. [View CCR stats](http://localhost:5601/app/monitoring#/elasticsearch/ccr?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, internalShortMessage: `CCR read exceptions alert is firing for the following remote cluster: ${remoteCluster}. Verify follower and leader index relationships on the affected remote cluster.`, - action: `[View CCR stats](http://localhost:5601/app/monitoring#/elasticsearch/ccr?_g=(cluster_uuid:${clusterUuid},ccs:testCluster))`, + action: `[View CCR stats](http://localhost:5601/app/monitoring#/elasticsearch/ccr?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, actionPlain: 'Verify follower and leader index relationships on the affected remote cluster.', clusterName, diff --git a/x-pack/plugins/monitoring/server/rules/cpu_usage_rule.test.ts b/x-pack/plugins/monitoring/server/rules/cpu_usage_rule.test.ts index 1b107d4031981..0558c2cdf6d33 100644 --- a/x-pack/plugins/monitoring/server/rules/cpu_usage_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/cpu_usage_rule.test.ts @@ -185,9 +185,9 @@ describe('CpuUsageRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'myNodeId', context: { - internalFullMessage: `CPU usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `CPU usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: `CPU usage alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify CPU level of node.`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Verify CPU level of node.', clusterName, count, @@ -315,9 +315,9 @@ describe('CpuUsageRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'myNodeId', context: { - internalFullMessage: `CPU usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:${ccs}))`, + internalFullMessage: `CPU usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:${ccs}))`, internalShortMessage: `CPU usage alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify CPU level of node.`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:testCluster))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, actionPlain: 'Verify CPU level of node.', clusterName, count, diff --git a/x-pack/plugins/monitoring/server/rules/disk_usage_rule.test.ts b/x-pack/plugins/monitoring/server/rules/disk_usage_rule.test.ts index 5e1c30dce78f6..6e7f66b219e26 100644 --- a/x-pack/plugins/monitoring/server/rules/disk_usage_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/disk_usage_rule.test.ts @@ -232,9 +232,9 @@ describe('DiskUsageRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'myNodeId', context: { - internalFullMessage: `Disk usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `Disk usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: `Disk usage alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify disk usage level of node.`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Verify disk usage level of node.', clusterName, count, @@ -381,9 +381,9 @@ describe('DiskUsageRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'myNodeId', context: { - internalFullMessage: `Disk usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:${ccs}))`, + internalFullMessage: `Disk usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:${ccs}))`, internalShortMessage: `Disk usage alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify disk usage level of node.`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/myNodeId?_g=(cluster_uuid:abc123,ccs:testCluster))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/myNodeId?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, actionPlain: 'Verify disk usage level of node.', clusterName, count, diff --git a/x-pack/plugins/monitoring/server/rules/elasticsearch_version_mismatch_rule.test.ts b/x-pack/plugins/monitoring/server/rules/elasticsearch_version_mismatch_rule.test.ts index eafb51136fc73..4269c0d6b5a5e 100644 --- a/x-pack/plugins/monitoring/server/rules/elasticsearch_version_mismatch_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/elasticsearch_version_mismatch_rule.test.ts @@ -140,9 +140,9 @@ describe('ElasticsearchVersionMismatchAlert', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'abc123', context: { - action: `[View nodes](UNIT_TEST_URL/app/monitoring#/elasticsearch/nodes?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View nodes](UNIT_TEST_URL/app/monitoring#/elasticsearch/nodes?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Verify you have the same version across all nodes.', - internalFullMessage: `Elasticsearch version mismatch alert is firing for testCluster. Elasticsearch is running 8.0.0, 7.2.1. [View nodes](UNIT_TEST_URL/app/monitoring#/elasticsearch/nodes?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `Elasticsearch version mismatch alert is firing for testCluster. Elasticsearch is running 8.0.0, 7.2.1. [View nodes](UNIT_TEST_URL/app/monitoring#/elasticsearch/nodes?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: 'Elasticsearch version mismatch alert is firing for testCluster. Verify you have the same version across all nodes.', versionList: ['8.0.0', '7.2.1'], diff --git a/x-pack/plugins/monitoring/server/rules/kibana_version_mismatch_rule.test.ts b/x-pack/plugins/monitoring/server/rules/kibana_version_mismatch_rule.test.ts index 46b777dbee4a2..7a3370c4092a6 100644 --- a/x-pack/plugins/monitoring/server/rules/kibana_version_mismatch_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/kibana_version_mismatch_rule.test.ts @@ -143,9 +143,9 @@ describe('KibanaVersionMismatchRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'abc123', context: { - action: `[View instances](UNIT_TEST_URL/app/monitoring#/kibana/instances?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View instances](UNIT_TEST_URL/app/monitoring#/kibana/instances?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Verify you have the same version across all instances.', - internalFullMessage: `Kibana version mismatch alert is firing for testCluster. Kibana is running 8.0.0, 7.2.1. [View instances](UNIT_TEST_URL/app/monitoring#/kibana/instances?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `Kibana version mismatch alert is firing for testCluster. Kibana is running 8.0.0, 7.2.1. [View instances](UNIT_TEST_URL/app/monitoring#/kibana/instances?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: 'Kibana version mismatch alert is firing for testCluster. Verify you have the same version across all instances.', versionList: ['8.0.0', '7.2.1'], diff --git a/x-pack/plugins/monitoring/server/rules/large_shard_size_rule.test.ts b/x-pack/plugins/monitoring/server/rules/large_shard_size_rule.test.ts index 0ad6c7687c203..00272030ec4ab 100644 --- a/x-pack/plugins/monitoring/server/rules/large_shard_size_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/large_shard_size_rule.test.ts @@ -206,9 +206,9 @@ describe('LargeShardSizeRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'abc123:apm-8.0.0-onboarding-2021.06.30', context: { - internalFullMessage: `Large shard size alert is firing for the following index: ${shardIndex}. [View index shard size stats](http://localhost:5601/app/monitoring#/elasticsearch/indices/${shardIndex}?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `Large shard size alert is firing for the following index: ${shardIndex}. [View index shard size stats](http://localhost:5601/app/monitoring#/elasticsearch/indices/${shardIndex}?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: `Large shard size alert is firing for the following index: ${shardIndex}. Investigate indices with large shard sizes.`, - action: `[View index shard size stats](http://localhost:5601/app/monitoring#/elasticsearch/indices/${shardIndex}?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View index shard size stats](http://localhost:5601/app/monitoring#/elasticsearch/indices/${shardIndex}?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Investigate indices with large shard sizes.', clusterName, state: 'firing', @@ -327,9 +327,9 @@ describe('LargeShardSizeRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'abc123:apm-8.0.0-onboarding-2021.06.30', context: { - internalFullMessage: `Large shard size alert is firing for the following index: ${shardIndex}. [View index shard size stats](http://localhost:5601/app/monitoring#/elasticsearch/indices/${shardIndex}?_g=(cluster_uuid:${clusterUuid},ccs:testCluster))`, + internalFullMessage: `Large shard size alert is firing for the following index: ${shardIndex}. [View index shard size stats](http://localhost:5601/app/monitoring#/elasticsearch/indices/${shardIndex}?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, internalShortMessage: `Large shard size alert is firing for the following index: ${shardIndex}. Investigate indices with large shard sizes.`, - action: `[View index shard size stats](http://localhost:5601/app/monitoring#/elasticsearch/indices/${shardIndex}?_g=(cluster_uuid:${clusterUuid},ccs:testCluster))`, + action: `[View index shard size stats](http://localhost:5601/app/monitoring#/elasticsearch/indices/${shardIndex}?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, actionPlain: 'Investigate indices with large shard sizes.', clusterName, state: 'firing', diff --git a/x-pack/plugins/monitoring/server/rules/logstash_version_mismatch_rule.test.ts b/x-pack/plugins/monitoring/server/rules/logstash_version_mismatch_rule.test.ts index 97cbbd2c619a6..7944bd129f2f1 100644 --- a/x-pack/plugins/monitoring/server/rules/logstash_version_mismatch_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/logstash_version_mismatch_rule.test.ts @@ -141,9 +141,9 @@ describe('LogstashVersionMismatchRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'abc123', context: { - action: `[View nodes](UNIT_TEST_URL/app/monitoring#/logstash/nodes?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View nodes](UNIT_TEST_URL/app/monitoring#/logstash/nodes?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Verify you have the same version across all nodes.', - internalFullMessage: `Logstash version mismatch alert is firing for testCluster. Logstash is running 8.0.0, 7.2.1. [View nodes](UNIT_TEST_URL/app/monitoring#/logstash/nodes?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `Logstash version mismatch alert is firing for testCluster. Logstash is running 8.0.0, 7.2.1. [View nodes](UNIT_TEST_URL/app/monitoring#/logstash/nodes?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: 'Logstash version mismatch alert is firing for testCluster. Verify you have the same version across all nodes.', versionList: ['8.0.0', '7.2.1'], diff --git a/x-pack/plugins/monitoring/server/rules/memory_usage_rule.test.ts b/x-pack/plugins/monitoring/server/rules/memory_usage_rule.test.ts index c1a8836e293c1..6da0fb751c038 100644 --- a/x-pack/plugins/monitoring/server/rules/memory_usage_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/memory_usage_rule.test.ts @@ -216,9 +216,9 @@ describe('MemoryUsageRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'myNodeId', context: { - internalFullMessage: `Memory usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `Memory usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: `Memory usage alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify memory usage level of node.`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Verify memory usage level of node.', clusterName, count, @@ -380,9 +380,9 @@ describe('MemoryUsageRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'myNodeId', context: { - internalFullMessage: `Memory usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:${ccs}))`, + internalFullMessage: `Memory usage alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:${ccs}))`, internalShortMessage: `Memory usage alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify memory usage level of node.`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:testCluster))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, actionPlain: 'Verify memory usage level of node.', clusterName, count, diff --git a/x-pack/plugins/monitoring/server/rules/missing_monitoring_data_rule.test.ts b/x-pack/plugins/monitoring/server/rules/missing_monitoring_data_rule.test.ts index 8bf66a839d6dd..4dd7515e7e33e 100644 --- a/x-pack/plugins/monitoring/server/rules/missing_monitoring_data_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/missing_monitoring_data_rule.test.ts @@ -171,11 +171,11 @@ describe('MissingMonitoringDataRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'esNode1', context: { - internalFullMessage: `We have not detected any monitoring data for node ${nodeName} in cluster: ${clusterName}. [View what monitoring data we do have for this node.](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `We have not detected any monitoring data for node ${nodeName} in cluster: ${clusterName}. [View what monitoring data we do have for this node.](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: `We have not detected any monitoring data for node ${nodeName} in cluster: ${clusterName}. Verify the node is up and running, then double check the monitoring settings.`, nodes: `node: ${nodeName}`, node: `node: ${nodeName}`, - action: `[View what monitoring data we do have for this node.](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View what monitoring data we do have for this node.](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: 'Verify the node is up and running, then double check the monitoring settings.', clusterName, @@ -287,11 +287,11 @@ describe('MissingMonitoringDataRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'esNode1', context: { - internalFullMessage: `We have not detected any monitoring data for node ${nodeName} in cluster: ${clusterName}. [View what monitoring data we do have for this node.](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:${ccs}))`, + internalFullMessage: `We have not detected any monitoring data for node ${nodeName} in cluster: ${clusterName}. [View what monitoring data we do have for this node.](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:${ccs}))`, internalShortMessage: `We have not detected any monitoring data for node ${nodeName} in cluster: ${clusterName}. Verify the node is up and running, then double check the monitoring settings.`, nodes: `node: ${nodeName}`, node: `node: ${nodeName}`, - action: `[View what monitoring data we do have for this node.](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:${ccs}))`, + action: `[View what monitoring data we do have for this node.](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:${ccs}))`, actionPlain: 'Verify the node is up and running, then double check the monitoring settings.', clusterName, diff --git a/x-pack/plugins/monitoring/server/rules/thread_pool_search_rejections_rule.test.ts b/x-pack/plugins/monitoring/server/rules/thread_pool_search_rejections_rule.test.ts index c6602f536a83c..7f93f3cfe6f94 100644 --- a/x-pack/plugins/monitoring/server/rules/thread_pool_search_rejections_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/thread_pool_search_rejections_rule.test.ts @@ -223,10 +223,10 @@ describe('ThreadpoolSearchRejectionsRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'esNode1', context: { - internalFullMessage: `Thread pool search rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `Thread pool search rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: `Thread pool search rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify thread pool ${threadPoolType} rejections for the affected node.`, node: `${nodeName}`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: `Verify thread pool ${threadPoolType} rejections for the affected node.`, clusterName, count: 1, @@ -387,10 +387,10 @@ describe('ThreadpoolSearchRejectionsRule', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'esNode1', context: { - internalFullMessage: `Thread pool search rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:${ccs}))`, + internalFullMessage: `Thread pool search rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:${ccs}))`, internalShortMessage: `Thread pool search rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify thread pool ${threadPoolType} rejections for the affected node.`, node: `${nodeName}`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/esNode1?_g=(cluster_uuid:abc123,ccs:testCluster))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/esNode1?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, actionPlain: `Verify thread pool ${threadPoolType} rejections for the affected node.`, clusterName, count, diff --git a/x-pack/plugins/monitoring/server/rules/thread_pool_write_rejections_rule.test.ts b/x-pack/plugins/monitoring/server/rules/thread_pool_write_rejections_rule.test.ts index 163dc2b1a677b..71565b9e75c38 100644 --- a/x-pack/plugins/monitoring/server/rules/thread_pool_write_rejections_rule.test.ts +++ b/x-pack/plugins/monitoring/server/rules/thread_pool_write_rejections_rule.test.ts @@ -223,10 +223,10 @@ describe('ThreadpoolWriteRejectionsAlert', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'esNode1', context: { - internalFullMessage: `Thread pool ${threadPoolType} rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + internalFullMessage: `Thread pool ${threadPoolType} rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, internalShortMessage: `Thread pool ${threadPoolType} rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify thread pool ${threadPoolType} rejections for the affected node.`, node: `${nodeName}`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid}))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}'))`, actionPlain: `Verify thread pool ${threadPoolType} rejections for the affected node.`, clusterName, count: 1, @@ -387,10 +387,10 @@ describe('ThreadpoolWriteRejectionsAlert', () => { expect(services.alertsClient.setAlertData).toHaveBeenCalledWith({ id: 'esNode1', context: { - internalFullMessage: `Thread pool ${threadPoolType} rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:${clusterUuid},ccs:${ccs}))`, + internalFullMessage: `Thread pool ${threadPoolType} rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. [View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/${nodeId}?_g=(cluster_uuid:'${clusterUuid}',ccs:${ccs}))`, internalShortMessage: `Thread pool ${threadPoolType} rejections alert is firing for node ${nodeName} in cluster: ${clusterName}. Verify thread pool ${threadPoolType} rejections for the affected node.`, node: `${nodeName}`, - action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/esNode1?_g=(cluster_uuid:abc123,ccs:testCluster))`, + action: `[View node](http://localhost:5601/app/monitoring#/elasticsearch/nodes/esNode1?_g=(cluster_uuid:'${clusterUuid}',ccs:testCluster))`, actionPlain: `Verify thread pool ${threadPoolType} rejections for the affected node.`, clusterName, count, diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/alerts_overview/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/alerts_overview/index.tsx index e606c5c2e1632..a5d0df3b05538 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/alerts_overview/index.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/alerts_overview/index.tsx @@ -71,7 +71,7 @@ export function AlertsOverview() { }, [serviceName, environment]); const onKueryChange = useCallback( - (value) => push(history, { query: { kuery: value } }), + (value: any) => push(history, { query: { kuery: value } }), [history] ); diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/correlations/correlations_table.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/correlations/correlations_table.tsx index 670521bb6086c..ea79b1ef198bc 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/correlations/correlations_table.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/correlations/correlations_table.tsx @@ -69,7 +69,7 @@ export function CorrelationsTable({ }, [pageIndex, pageSize, significantTerms]); const onChange = useCallback( - (tableSettings) => { + (tableSettings: any) => { const { index, size } = tableSettings.page; setPageIndex(index); diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/correlations/failed_transactions_correlations.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/correlations/failed_transactions_correlations.tsx index 9149be49e2986..d02eed810acd0 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/correlations/failed_transactions_correlations.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/correlations/failed_transactions_correlations.tsx @@ -331,7 +331,7 @@ export function FailedTransactionsCorrelations({ onFilter }: { onFilter: () => v useState('normalizedScore'); const [sortDirection, setSortDirection] = useState('desc'); - const onTableChange = useCallback(({ sort }) => { + const onTableChange = useCallback(({ sort }: any) => { const { field: currentSortField, direction: currentSortDirection } = sort; setSortField(currentSortField); diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/correlations/latency_correlations.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/correlations/latency_correlations.tsx index 1183338b0f4bd..8144dbd548410 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/correlations/latency_correlations.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/correlations/latency_correlations.tsx @@ -249,7 +249,7 @@ export function LatencyCorrelations({ onFilter }: { onFilter: () => void }) { const [sortField, setSortField] = useState('correlation'); const [sortDirection, setSortDirection] = useState('desc'); - const onTableChange = useCallback(({ sort }) => { + const onTableChange = useCallback(({ sort }: any) => { const { field: currentSortField, direction: currentSortDirection } = sort; setSortField(currentSortField); diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/mobile/service_overview/stats/location_stats.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/mobile/service_overview/stats/location_stats.tsx index b59246cf27e1f..47451fac265c9 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/mobile/service_overview/stats/location_stats.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/mobile/service_overview/stats/location_stats.tsx @@ -88,7 +88,7 @@ export function MobileLocationStats({ const previousPeriod = locationStatsData?.previousPeriod; const getComparisonValueFormatter = useCallback( - ({ currentPeriodValue, previousPeriodValue }) => { + ({ currentPeriodValue, previousPeriodValue }: any) => { const comparisonDiffValue = calculateDiffPercentageAndFormat( currentPeriodValue, previousPeriodValue diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/mobile/service_overview/stats/stats.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/mobile/service_overview/stats/stats.tsx index f71da0cf8abd2..59f6020d61c33 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/mobile/service_overview/stats/stats.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/mobile/service_overview/stats/stats.tsx @@ -49,7 +49,7 @@ export function MobileStats({ start, end, kuery }: { start: string; end: string; ); const getComparisonValueFormatter = useCallback( - (value) => { + (value: any) => { return ( {value && comparisonEnabled diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_dashboards/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_dashboards/index.tsx index db8a2c1bac8cc..458a2e647cc2b 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/service_dashboards/index.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_dashboards/index.tsx @@ -124,7 +124,7 @@ export function ServiceDashboards({ checkForEntities = false }: { checkForEntiti }, [dataView, serviceName, environment, kuery, dashboard, rangeFrom, rangeTo, currentDashboard]); const getLocatorParams = useCallback( - (params) => { + (params: any) => { return { serviceName, dashboardId: params.dashboardId, diff --git a/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/get_log_categories/index.ts b/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/get_log_categories/index.ts index c55df1122a71e..41af9a4a0360d 100644 --- a/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/get_log_categories/index.ts +++ b/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/get_log_categories/index.ts @@ -14,6 +14,7 @@ import { APMEventClient } from '../../../lib/helpers/create_es_client/create_apm import { PROCESSOR_EVENT, TRACE_ID } from '../../../../common/es_fields/apm'; import { getTypedSearch } from '../../../utils/create_typed_es_client'; import { getDownstreamServiceResource } from '../get_observability_alert_details_context/get_downstream_dependency_name'; +import { getShouldMatchOrNotExistFilter } from '../utils/get_should_match_or_not_exist_filter'; export interface LogCategory { errorCategory: string; @@ -101,7 +102,7 @@ export async function getLogCategories({ categories: { categorize_text: { field: 'message', - size: 500, + size: 10, }, aggs: { sample: { @@ -147,37 +148,3 @@ export async function getLogCategories({ entities: flattenObject(sampleDoc), }; } - -// field/value pairs should match, or the field should not exist -export function getShouldMatchOrNotExistFilter( - keyValuePairs: Array<{ - field: string; - value?: string; - }> -) { - return keyValuePairs - .filter(({ value }) => value) - .map(({ field, value }) => { - return { - bool: { - should: [ - { - bool: { - filter: [{ term: { [field]: value } }], - }, - }, - { - bool: { - must_not: { - bool: { - filter: [{ exists: { field } }], - }, - }, - }, - }, - ], - minimum_should_match: 1, - }, - }; - }); -} diff --git a/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/get_log_rate_analysis_for_alert/index.ts b/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/get_log_rate_analysis_for_alert/index.ts new file mode 100644 index 0000000000000..097eff91ced14 --- /dev/null +++ b/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/get_log_rate_analysis_for_alert/index.ts @@ -0,0 +1,63 @@ +/* + * 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 { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { CoreRequestHandlerContext } from '@kbn/core/server'; +import { aiAssistantLogsIndexPattern } from '@kbn/observability-ai-assistant-plugin/server'; +import { fetchLogRateAnalysisForAlert } from '@kbn/aiops-log-rate-analysis/queries/fetch_log_rate_analysis_for_alert'; +import { PROCESSOR_EVENT } from '../../../../common/es_fields/apm'; +import { getShouldMatchOrNotExistFilter } from '../utils/get_should_match_or_not_exist_filter'; + +/** + * Runs log rate analysis data on an index given some alert metadata. + */ +export async function getLogRateAnalysisForAlert({ + esClient, + coreContext, + arguments: args, +}: { + esClient: ElasticsearchClient; + coreContext: Pick; + arguments: { + alertStartedAt: string; + alertRuleParameterTimeSize?: number; + alertRuleParameterTimeUnit?: string; + entities: { + 'service.name'?: string; + 'host.name'?: string; + 'container.id'?: string; + 'kubernetes.pod.name'?: string; + }; + }; +}): ReturnType { + const index = await coreContext.uiSettings.client.get(aiAssistantLogsIndexPattern); + + const keyValueFilters = getShouldMatchOrNotExistFilter( + Object.entries(args.entities).map(([key, value]) => ({ field: key, value })) + ); + + const searchQuery = { + bool: { + must_not: [ + // exclude APM errors + { term: { [PROCESSOR_EVENT]: 'error' } }, + ], + filter: [...keyValueFilters], + }, + }; + + return fetchLogRateAnalysisForAlert({ + esClient, + arguments: { + index, + alertStartedAt: args.alertStartedAt, + alertRuleParameterTimeSize: args.alertRuleParameterTimeSize, + alertRuleParameterTimeUnit: args.alertRuleParameterTimeUnit, + searchQuery, + }, + }); +} diff --git a/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/get_observability_alert_details_context/index.ts b/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/get_observability_alert_details_context/index.ts index 64141a7f533ee..e0f3f833a5ae2 100644 --- a/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/get_observability_alert_details_context/index.ts +++ b/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/get_observability_alert_details_context/index.ts @@ -22,6 +22,7 @@ import { APMDownstreamDependency, getAssistantDownstreamDependencies, } from '../get_apm_downstream_dependencies'; +import { getLogRateAnalysisForAlert } from '../get_log_rate_analysis_for_alert'; import { getLogCategories, LogCategory } from '../get_log_categories'; import { getAnomalies } from '../get_apm_service_summary/get_anomalies'; import { getServiceNameFromSignals } from './get_service_name_from_signals'; @@ -160,6 +161,42 @@ export const getAlertDetailsContextHandler = ( }); } + // log rate analysis + dataFetchers.push(async () => { + const { logRateAnalysisType, significantItems } = await getLogRateAnalysisForAlert({ + esClient, + coreContext, + arguments: { + alertStartedAt: moment(alertStartedAt).toISOString(), + alertRuleParameterTimeSize: query.alert_rule_parameter_time_size + ? parseInt(query.alert_rule_parameter_time_size, 10) + : undefined, + alertRuleParameterTimeUnit: query.alert_rule_parameter_time_unit, + entities: { + 'service.name': serviceName, + 'host.name': hostName, + 'container.id': containerId, + 'kubernetes.pod.name': kubernetesPodName, + }, + }, + }); + + if (logRateAnalysisType !== 'spike' || significantItems.length === 0) { + return { + key: 'logRateAnalysis', + description: + 'Log rate analysis did not identify any significant metadata or log patterns.', + data: [], + }; + } + + return { + key: 'logRateAnalysis', + description: `Statistically significant log metadata and log message patterns occurring in the lookback period before the alert was triggered.`, + data: significantItems, + }; + }); + // log categories dataFetchers.push(async () => { const downstreamDependencies = await downstreamDependenciesPromise; diff --git a/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/get_log_categories/index.test.ts b/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/utils/get_should_match_or_not_exist_filter.test.ts similarity index 96% rename from x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/get_log_categories/index.test.ts rename to x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/utils/get_should_match_or_not_exist_filter.test.ts index 3b4f2e58a5029..024c8ff6a9170 100644 --- a/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/get_log_categories/index.test.ts +++ b/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/utils/get_should_match_or_not_exist_filter.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { getShouldMatchOrNotExistFilter } from '.'; +import { getShouldMatchOrNotExistFilter } from './get_should_match_or_not_exist_filter'; describe('getShouldMatchOrNotExistFilter', () => { describe('when all fields are provided', () => { diff --git a/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/utils/get_should_match_or_not_exist_filter.ts b/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/utils/get_should_match_or_not_exist_filter.ts new file mode 100644 index 0000000000000..caf7bb4d5e820 --- /dev/null +++ b/x-pack/plugins/observability_solution/apm/server/routes/assistant_functions/utils/get_should_match_or_not_exist_filter.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +// field/value pairs should match, or the field should not exist +export function getShouldMatchOrNotExistFilter( + keyValuePairs: Array<{ + field: string; + value?: string; + }> +) { + return keyValuePairs + .filter(({ value }) => value) + .map(({ field, value }) => { + return { + bool: { + should: [ + { + bool: { + filter: [{ term: { [field]: value } }], + }, + }, + { + bool: { + must_not: { + bool: { + filter: [{ exists: { field } }], + }, + }, + }, + }, + ], + minimum_should_match: 1, + }, + }; + }); +} diff --git a/x-pack/plugins/observability_solution/apm/tsconfig.json b/x-pack/plugins/observability_solution/apm/tsconfig.json index b05447bc19e6c..7389566ed6a4c 100644 --- a/x-pack/plugins/observability_solution/apm/tsconfig.json +++ b/x-pack/plugins/observability_solution/apm/tsconfig.json @@ -127,7 +127,8 @@ "@kbn/server-route-repository-utils", "@kbn/core-analytics-browser", "@kbn/apm-types", - "@kbn/entities-schema" + "@kbn/entities-schema", + "@kbn/aiops-log-rate-analysis" ], "exclude": [ "target/**/*" diff --git a/x-pack/plugins/observability_solution/dataset_quality/common/constants.ts b/x-pack/plugins/observability_solution/dataset_quality/common/constants.ts index a6c6754befb8e..895381703742e 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/common/constants.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/common/constants.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { QualityIndicators } from './types'; +import { DataStreamType, QualityIndicators } from './types'; export const DATASET_QUALITY_APP_ID = 'dataset_quality'; -export const DEFAULT_DATASET_TYPE = 'logs'; +export const DEFAULT_DATASET_TYPE: DataStreamType = 'logs'; export const DEFAULT_LOGS_DATA_VIEW = 'logs-*-*'; export const POOR_QUALITY_MINIMUM_PERCENTAGE = 3; @@ -41,3 +41,5 @@ export const MAX_DEGRADED_FIELDS = 1000; export const MASKED_FIELD_PLACEHOLDER = ''; export const UNKOWN_FIELD_PLACEHOLDER = ''; + +export const KNOWN_TYPES: DataStreamType[] = ['logs', 'metrics', 'traces']; diff --git a/x-pack/plugins/observability_solution/dataset_quality/common/data_stream_details/types.ts b/x-pack/plugins/observability_solution/dataset_quality/common/data_stream_details/types.ts index 74f0653396447..82d6d2651be56 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/common/data_stream_details/types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/common/data_stream_details/types.ts @@ -5,9 +5,6 @@ * 2.0. */ -import { DataStreamType } from '../types'; - export interface GetDataStreamIntegrationParams { - type: DataStreamType; integrationName: string; } diff --git a/x-pack/plugins/observability_solution/dataset_quality/common/data_streams_stats/types.ts b/x-pack/plugins/observability_solution/dataset_quality/common/data_streams_stats/types.ts index 1963c73d263e7..79fdbfbd7dd96 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/common/data_streams_stats/types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/common/data_streams_stats/types.ts @@ -15,9 +15,6 @@ export type GetDataStreamsStatsResponse = export type DataStreamStatType = GetDataStreamsStatsResponse['dataStreamsStats'][0]; export type DataStreamStatServiceResponse = GetDataStreamsStatsResponse; -export type GetIntegrationsParams = - APIClientRequestParamsOf<`GET /internal/dataset_quality/integrations`>['params']; - export type GetDataStreamsDegradedDocsStatsParams = APIClientRequestParamsOf<`GET /internal/dataset_quality/data_streams/degraded_docs`>['params']; export type GetDataStreamsDegradedDocsStatsQuery = GetDataStreamsDegradedDocsStatsParams['query']; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/filters/filters.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/filters/filters.tsx index 8c247104415cd..4c63b8480d3b7 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/filters/filters.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/filters/filters.tsx @@ -10,12 +10,33 @@ import { EuiSuperDatePicker } from '@elastic/eui'; import { UI_SETTINGS } from '@kbn/data-service'; import { TimePickerQuickRange } from '@kbn/observability-shared-plugin/public/hooks/use_quick_time_ranges'; import React, { useMemo } from 'react'; +import { i18n } from '@kbn/i18n'; import { useDatasetQualityFilters } from '../../../hooks/use_dataset_quality_filters'; import { useKibanaContextForPlugin } from '../../../utils/use_kibana'; import { FilterBar } from './filter_bar'; import { IntegrationsSelector } from './integrations_selector'; import { NamespacesSelector } from './namespaces_selector'; import { QualitiesSelector } from './qualities_selector'; +import { Selector } from './selector'; + +const typesLabel = i18n.translate('xpack.datasetQuality.types.label', { + defaultMessage: 'Types', +}); + +const typesSearchPlaceholder = i18n.translate( + 'xpack.datasetQuality.selector.types.search.placeholder', + { + defaultMessage: 'Filter types', + } +); + +const typesNoneMatching = i18n.translate('xpack.datasetQuality.selector.types.noneMatching', { + defaultMessage: 'No types found', +}); + +const typesNoneAvailable = i18n.translate('xpack.datasetQuality.selector.types.noneAvailable', { + defaultMessage: 'No types available', +}); // Allow for lazy loading // eslint-disable-next-line import/no-default-export @@ -29,9 +50,11 @@ export default function Filters() { integrations, namespaces, qualities, + types, onIntegrationsChange, onNamespacesChange, onQualitiesChange, + onTypesChange, selectedQuery, onQueryChange, } = useDatasetQualityFilters(); @@ -65,6 +88,14 @@ export default function Filters() { integrations={integrations} onIntegrationsChange={onIntegrationsChange} /> + void; +} + +export interface Item { + label: string; + checked?: EuiSelectableOptionCheckedType; +} + +export function Selector({ + isLoading, + options, + loadingMessage, + label, + searchPlaceholder, + noneAvailableMessage, + noneMatchingMessage, + onOptionsChange, +}: SelectorProps) { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + const onButtonClick = () => { + setIsPopoverOpen(!isPopoverOpen); + }; + + const closePopover = () => { + setIsPopoverOpen(false); + }; + + const renderOption = (option: Item) => {option.label}; + + const button = ( + item.checked === 'on')} + numActiveFilters={options.filter((item) => item.checked === 'on').length} + > + {label} + + ); + + return ( + + renderOption(option)} + > + {(list, search) => ( +
+ {search} + {list} +
+ )} +
+
+ ); +} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/header.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/header.tsx index 4ec200b1b98c8..66e2cba5ed870 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/header.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/header.tsx @@ -10,7 +10,7 @@ import { EuiBetaBadge, EuiLink, EuiPageHeader, EuiCode } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { DEFAULT_LOGS_DATA_VIEW } from '../../../common/constants'; +import { KNOWN_TYPES } from '../../../common/constants'; import { datasetQualityAppTitle } from '../../../common/translations'; // Allow for lazy loading @@ -33,9 +33,16 @@ export default function Header() { description={ {DEFAULT_LOGS_DATA_VIEW}, + types: KNOWN_TYPES.map((type, index) => { + return ( + <> + {index > 0 && ', '} + {type} + + ); + }), dsNamingSchemeLink: ( void; isActiveDataset: (lastActivity: number) => boolean; timeRange: TimeRangeConfig; + urlService: BrowserUrlService; }): Array> => { return [ - { - name: '', - render: (dataStreamStat: DataStreamStat) => { - const isExpanded = dataStreamStat.rawName === selectedDataset?.rawName; - - return ( - openFlyout(dataStreamStat as FlyoutDataset)} - iconType={isExpanded ? 'minimize' : 'expand'} - title={!isExpanded ? expandDatasetAriaLabel : collapseDatasetAriaLabel} - aria-label={!isExpanded ? expandDatasetAriaLabel : collapseDatasetAriaLabel} - /> - ); - }, - width: '40px', - css: css` - &.euiTableCellContent { - padding: 0; - } - `, - }, { name: ( {nameColumnName} @@ -215,20 +185,22 @@ export const getDatasetQualityTableColumns = ({ field: 'title', sortable: true, render: (title: string, dataStreamStat: DataStreamStat) => { - const { integration, name } = dataStreamStat; + const { integration, name, rawName } = dataStreamStat; return ( - - - - - {title} - {showFullDatasetNames && ( - - {name} - - )} - + + + + + + {title} + {showFullDatasetNames && ( + + {name} + + )} + + ); }, }, @@ -245,6 +217,15 @@ export const getDatasetQualityTableColumns = ({ ), width: '160px', }, + { + name: typeColumnName, + field: 'type', + sortable: true, + render: (_, dataStreamStat: DataStreamStat) => ( + {dataStreamStat.type} + ), + width: '160px', + }, ...(isSizeStatsAvailable && canUserMonitorDataset && canUserMonitorAnyDataStream ? [ { @@ -382,9 +363,10 @@ const RedirectLink = ({ title: string; timeRange: TimeRangeConfig; }) => { + const { sendTelemetry } = useDatasetRedirectLinkTelemetry({ rawName: dataStreamStat.rawName }); const redirectLinkProps = useRedirectLink({ dataStreamStat, - telemetry: { page: 'main', navigationSource: NavigationSource.Table }, + sendTelemetry, timeRangeConfig: timeRange, }); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/dataset_quality_details_link.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/dataset_quality_details_link.tsx new file mode 100644 index 0000000000000..ac73f269d9f5a --- /dev/null +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/dataset_quality_details_link.tsx @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { BrowserUrlService } from '@kbn/share-plugin/public'; +import { + DATA_QUALITY_DETAILS_LOCATOR_ID, + DataQualityDetailsLocatorParams, +} from '@kbn/deeplinks-observability'; +import { getRouterLinkProps } from '@kbn/router-utils'; +import { EuiHeaderLink } from '@elastic/eui'; + +export const DatasetQualityDetailsLink = React.memo( + ({ + urlService, + dataStream, + children, + }: { + urlService: BrowserUrlService; + dataStream: string; + children: React.ReactNode; + }) => { + const locator = urlService.locators.get( + DATA_QUALITY_DETAILS_LOCATOR_ID + ); + const datasetQualityUrl = locator?.getRedirectUrl({ dataStream }); + const navigateToDatasetQuality = () => { + locator?.navigate({ dataStream }); + }; + + const datasetQualityLinkDetailsProps = getRouterLinkProps({ + href: datasetQualityUrl, + onClick: navigateToDatasetQuality, + }); + + return ( + + {children} + + ); + } +); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/degraded_docs_percentage_link.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/degraded_docs_percentage_link.tsx index 54c393323ccfd..9d32c84891a34 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/degraded_docs_percentage_link.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/degraded_docs_percentage_link.tsx @@ -8,8 +8,7 @@ import { EuiSkeletonRectangle, EuiFlexGroup, EuiLink } from '@elastic/eui'; import React from 'react'; import { _IGNORED } from '../../../../common/es_fields'; -import { NavigationSource } from '../../../services/telemetry'; -import { useRedirectLink } from '../../../hooks'; +import { useDatasetRedirectLinkTelemetry, useRedirectLink } from '../../../hooks'; import { QualityPercentageIndicator } from '../../quality_indicator'; import { DataStreamStat } from '../../../../common/data_streams_stats/data_stream_stat'; import { TimeRangeConfig } from '../../../../common/types'; @@ -27,13 +26,15 @@ export const DegradedDocsPercentageLink = ({ degradedDocs: { percentage, count }, } = dataStreamStat; + const { sendTelemetry } = useDatasetRedirectLinkTelemetry({ + rawName: dataStreamStat.rawName, + query: { language: 'kuery', query: `${_IGNORED}: *` }, + }); + const redirectLinkProps = useRedirectLink({ dataStreamStat, query: { language: 'kuery', query: `${_IGNORED}: *` }, - telemetry: { - page: 'main', - navigationSource: NavigationSource.Table, - }, + sendTelemetry, timeRangeConfig: timeRange, }); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/table.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/table.tsx index 5bd8783fd0684..a7524198aa24a 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/table.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/table.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import React from 'react'; import { EuiBasicTable, EuiEmptyPrompt, @@ -14,8 +15,6 @@ import { EuiText, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import { dynamic } from '@kbn/shared-ux-utility'; -import React from 'react'; import { fullDatasetNameDescription, fullDatasetNameLabel, @@ -27,8 +26,6 @@ import { import { useDatasetQualityTable } from '../../../hooks'; import { DescriptiveSwitch } from '../../common/descriptive_switch'; -const Flyout = dynamic(() => import('../../flyout/flyout')); - export const Table = () => { const { sort, @@ -38,8 +35,6 @@ export const Table = () => { columns, loading, resultsCount, - selectedDataset, - closeFlyout, showInactiveDatasets, showFullDatasetNames, canUserMonitorDataset, @@ -107,7 +102,6 @@ export const Table = () => { ) } /> - {selectedDataset && } ); }; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/dataset_quality_details.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/dataset_quality_details.tsx index 522ad22fae429..56632cdad8cfa 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/dataset_quality_details.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/dataset_quality_details.tsx @@ -4,9 +4,9 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React from 'react'; +import React, { useEffect } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui'; -import { useDatasetQualityDetailsState } from '../../hooks'; +import { useDatasetDetailsTelemetry, useDatasetQualityDetailsState } from '../../hooks'; import { DataStreamNotFoundPrompt } from './index_not_found_prompt'; import { Header } from './header'; import { Overview } from './overview'; @@ -16,10 +16,15 @@ import { Details } from './details'; // eslint-disable-next-line import/no-default-export export default function DatasetQualityDetails() { const { isIndexNotFoundError, dataStream } = useDatasetQualityDetailsState(); + const { startTracking } = useDatasetDetailsTelemetry(); + + useEffect(() => { + startTracking(); + }, [startTracking]); return isIndexNotFoundError ? ( ) : ( - +
diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/details/fields_list.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/details/fields_list.tsx index f48ad1d932357..f02b1720d9dfc 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/details/fields_list.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/details/fields_list.tsx @@ -32,7 +32,12 @@ export function FieldsList({ {fields.map(({ fieldTitle, fieldValue, isLoading: isFieldLoading, actionsMenu }, index) => ( - + {fieldTitle} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/header.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/header.tsx index 2a0e3e93e32ac..e45253b6405c8 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/header.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/header.tsx @@ -18,19 +18,30 @@ import { import { css } from '@emotion/react'; import React from 'react'; import { openInDiscoverText, openInLogsExplorerText } from '../../../common/translations'; -import { useDatasetQualityDetailsRedirectLink, useDatasetQualityDetailsState } from '../../hooks'; +import { + useDatasetDetailsRedirectLinkTelemetry, + useDatasetDetailsTelemetry, + useDatasetQualityDetailsState, + useRedirectLink, +} from '../../hooks'; import { IntegrationIcon } from '../common'; export function Header() { const { datasetDetails, timeRange, integrationDetails, loadingState } = useDatasetQualityDetailsState(); + const { navigationSources } = useDatasetDetailsTelemetry(); + const { rawName, name: title } = datasetDetails; const euiShadow = useEuiShadow('s'); const { euiTheme } = useEuiTheme(); - const redirectLinkProps = useDatasetQualityDetailsRedirectLink({ + const { sendTelemetry } = useDatasetDetailsRedirectLinkTelemetry({ + navigationSource: navigationSources.Header, + }); + const redirectLinkProps = useRedirectLink({ dataStreamStat: datasetDetails, timeRangeConfig: timeRange, + sendTelemetry, }); const pageTitle = integrationDetails?.integration?.datasets?.[datasetDetails.name] ?? title; @@ -38,15 +49,15 @@ export function Header() { return !loadingState.integrationDetailsLoaded ? ( ) : ( - +

{pageTitle}

export function DataStreamNotFoundPrompt({ dataStream }: { dataStream: string }) { const promptTitle =

{emptyPromptTitle}

; - const promptBody =

{emptyPromptBody(dataStream)}

; + const promptBody = ( + +

{emptyPromptBody(dataStream)}

+
+ ); - return ; + return ( + + ); } diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/degraded_docs_chart.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/degraded_docs_chart.tsx index ff311032fe69f..3040e81f0e587 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/degraded_docs_chart.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/degraded_docs_chart.tsx @@ -14,7 +14,7 @@ import { KibanaErrorBoundary } from '@kbn/shared-ux-error-boundary'; import { flyoutDegradedDocsTrendText } from '../../../../../../common/translations'; import { useKibanaContextForPlugin } from '../../../../../utils'; import { TimeRangeConfig } from '../../../../../../common/types'; -import { useDegradedDocs } from '../../../../../hooks/use_degraded_docs'; +import { useDegradedDocsChart } from '../../../../../hooks'; const CHART_HEIGHT = 180; const DISABLED_ACTIONS = [ @@ -26,7 +26,7 @@ const DISABLED_ACTIONS = [ interface DegradedDocsChartProps extends Pick< - ReturnType, + ReturnType, 'attributes' | 'isChartLoading' | 'onChartLoading' | 'extraActions' > { timeRange: TimeRangeConfig; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/index.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/index.tsx index 985a748e792b1..a0875f1367705 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/index.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality_details/overview/document_trends/degraded_docs/index.tsx @@ -6,6 +6,7 @@ */ import React, { useCallback, useEffect, useState } from 'react'; +import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiAccordion, @@ -29,13 +30,15 @@ import { openInLogsExplorerText, overviewDegradedDocsText, } from '../../../../../../common/translations'; -import { useDegradedDocs } from '../../../../../hooks/use_degraded_docs'; import { DegradedDocsChart } from './degraded_docs_chart'; import { - useDatasetQualityDetailsRedirectLink, + useDatasetDetailsRedirectLinkTelemetry, useDatasetQualityDetailsState, + useDegradedDocsChart, + useRedirectLink, } from '../../../../../hooks'; import { _IGNORED } from '../../../../../../common/es_fields'; +import { NavigationSource } from '../../../../../services/telemetry'; const degradedDocsTooltip = ( { @@ -125,7 +134,10 @@ export default function DegradedDocs({ lastReloadTime }: { lastReloadTime: numbe {userHasPrivilege && ( - -

{value}

+ +

{userHasPrivilege ? value : notAvailableLabel}

)} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/dataset_summary.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/dataset_summary.tsx deleted file mode 100644 index cb35e9c74d334..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/dataset_summary.tsx +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; -import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/field-types'; -import { DataStreamDetails, DataStreamSettings } from '../../../common/data_streams_stats'; -import { - datasetCreatedOnText, - flyoutDatasetDetailsText, - datasetLastActivityText, -} from '../../../common/translations'; -import { FieldsList, FieldsListLoading } from './fields_list'; - -interface DatasetSummaryProps { - fieldFormats: FieldFormatsStart; - dataStreamSettings?: DataStreamSettings; - dataStreamSettingsLoading: boolean; - dataStreamDetails?: DataStreamDetails; - dataStreamDetailsLoading: boolean; -} - -export function DatasetSummary({ - dataStreamSettings, - dataStreamSettingsLoading, - dataStreamDetails, - dataStreamDetailsLoading, - fieldFormats, -}: DatasetSummaryProps) { - const dataFormatter = fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.DATE, [ - ES_FIELD_TYPES.DATE, - ]); - const formattedLastActivity = dataStreamDetails?.lastActivity - ? dataFormatter.convert(dataStreamDetails?.lastActivity) - : '-'; - const formattedCreatedOn = dataStreamSettings?.createdOn - ? dataFormatter.convert(dataStreamSettings.createdOn) - : '-'; - - return ( - - ); -} - -export function DatasetSummaryLoading() { - return ; -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_docs_trend/degraded_docs.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_docs_trend/degraded_docs.tsx deleted file mode 100644 index 5335d5de8692d..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_docs_trend/degraded_docs.tsx +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useEffect, useState } from 'react'; -import { css } from '@emotion/react'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiPanel, - EuiSpacer, - EuiTitle, - EuiToolTip, - EuiIcon, - EuiCode, - OnTimeChangeProps, - EuiSkeletonRectangle, -} from '@elastic/eui'; -import { UnifiedBreakdownFieldSelector } from '@kbn/unified-histogram-plugin/public'; -import type { DataViewField } from '@kbn/data-views-plugin/common'; -import { useDegradedDocsChart } from '../../../hooks'; - -import { DEFAULT_TIME_RANGE, DEFAULT_DATEPICKER_REFRESH } from '../../../../common/constants'; -import { overviewDegradedDocsText } from '../../../../common/translations'; -import { DegradedDocsChart } from '../../dataset_quality_details/overview/document_trends/degraded_docs/degraded_docs_chart'; -import { TimeRangeConfig } from '../../../../common/types'; - -export function DegradedDocs({ - dataStream, - timeRange = { ...DEFAULT_TIME_RANGE, refresh: DEFAULT_DATEPICKER_REFRESH }, - lastReloadTime, - onTimeRangeChange, -}: { - dataStream?: string; - timeRange?: TimeRangeConfig; - lastReloadTime: number; - onTimeRangeChange: (props: Pick) => void; -}) { - const { dataView, breakdown, ...chartProps } = useDegradedDocsChart({ dataStream }); - - const [breakdownDataViewField, setBreakdownDataViewField] = useState( - undefined - ); - - useEffect(() => { - if (breakdown.dataViewField && breakdown.fieldSupportsBreakdown) { - setBreakdownDataViewField(breakdown.dataViewField); - } else { - setBreakdownDataViewField(undefined); - } - - if (breakdown.dataViewField && !breakdown.fieldSupportsBreakdown) { - // TODO: If needed, notify user that the field is not breakable - } - }, [setBreakdownDataViewField, breakdown]); - - return ( - - - - -
{overviewDegradedDocsText}
-
- - - -
- - - - -
- - - - -
- ); -} - -const degradedDocsTooltip = ( - - _ignored - - ), - }} - /> -); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/columns.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/columns.tsx deleted file mode 100644 index 1d7e79b3c0b36..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/columns.tsx +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiBasicTableColumn } from '@elastic/eui'; -import { FieldFormat } from '@kbn/field-formats-plugin/common'; -import { formatNumber } from '@elastic/eui'; - -import { DegradedField } from '../../../../common/api_types'; -import { SparkPlot } from './spark_plot'; -import { NUMBER_FORMAT } from '../../../../common/constants'; - -const fieldColumnName = i18n.translate('xpack.datasetQuality.flyout.degradedField.field', { - defaultMessage: 'Field', -}); - -const countColumnName = i18n.translate('xpack.datasetQuality.flyout.degradedField.count', { - defaultMessage: 'Docs count', -}); - -const lastOccurrenceColumnName = i18n.translate( - 'xpack.datasetQuality.flyout.degradedField.lastOccurrence', - { - defaultMessage: 'Last occurrence', - } -); - -export const getDegradedFieldsColumns = ({ - dateFormatter, - isLoading, -}: { - dateFormatter: FieldFormat; - isLoading: boolean; -}): Array> => [ - { - name: fieldColumnName, - field: 'name', - }, - { - name: countColumnName, - sortable: true, - field: 'count', - render: (_, { count, timeSeries }) => { - const countValue = formatNumber(count, NUMBER_FORMAT); - return ; - }, - }, - { - name: lastOccurrenceColumnName, - sortable: true, - field: 'lastOccurrence', - render: (lastOccurrence: number) => { - return dateFormatter.convert(lastOccurrence); - }, - }, -]; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/degraded_fields.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/degraded_fields.tsx deleted file mode 100644 index bd2c20b24171a..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/degraded_fields.tsx +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiFlexGroup, EuiPanel, EuiTitle, EuiIconTip } from '@elastic/eui'; -import { flyoutImprovementText, flyoutImprovementTooltip } from '../../../../common/translations'; -import { DegradedFieldTable } from './table'; - -export function DegradedFields() { - return ( - - - -
{flyoutImprovementText}
-
- -
- -
- ); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/spark_plot.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/spark_plot.tsx deleted file mode 100644 index 964c3ee434f45..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/spark_plot.tsx +++ /dev/null @@ -1,101 +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 { - EuiFlexGroup, - EuiFlexItem, - EuiIcon, - EuiLoadingChart, - euiPaletteColorBlind, - useEuiTheme, -} from '@elastic/eui'; -import React from 'react'; -import { ScaleType, Settings, Tooltip, Chart, BarSeries } from '@elastic/charts'; -import { i18n } from '@kbn/i18n'; -import { Coordinate } from '../../../../common/types'; - -export function SparkPlot({ - valueLabel, - isLoading, - series, -}: { - valueLabel: React.ReactNode; - isLoading: boolean; - series?: Coordinate[] | null; -}) { - return ( - - - - - {valueLabel} - - ); -} - -function SparkPlotItem({ - isLoading, - series, -}: { - isLoading: boolean; - series?: Coordinate[] | null; -}) { - const { euiTheme } = useEuiTheme(); - const chartSize = { - height: euiTheme.size.l, - width: '80px', - }; - - const commonStyle = { - ...chartSize, - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - }; - const palette = euiPaletteColorBlind({ rotations: 2 }); - - if (isLoading) { - return ( -
- -
- ); - } - - if (hasValidTimeSeries(series)) { - return ( -
- - - - - -
- ); - } - - return ( -
- -
- ); -} - -function hasValidTimeSeries(series?: Coordinate[] | null): series is Coordinate[] { - return !!series?.some((point) => point.y !== 0); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/table.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/table.tsx deleted file mode 100644 index 1a1baa8aae7cd..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/degraded_fields/table.tsx +++ /dev/null @@ -1,54 +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 { EuiBasicTable, EuiEmptyPrompt } from '@elastic/eui'; -import React from 'react'; -import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/field-types'; -import { useDatasetQualityDegradedField } from '../../../hooks'; -import { getDegradedFieldsColumns } from './columns'; -import { - overviewDegradedFieldsTableLoadingText, - overviewDegradedFieldsTableNoData, -} from '../../../../common/translations'; - -export const DegradedFieldTable = () => { - const { isLoading, pagination, renderedItems, onTableChange, sort, fieldFormats } = - useDatasetQualityDegradedField(); - const dateFormatter = fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.DATE, [ - ES_FIELD_TYPES.DATE, - ]); - const columns = getDegradedFieldsColumns({ dateFormatter, isLoading }); - - return ( - {overviewDegradedFieldsTableNoData}} - hasBorder={false} - titleSize="m" - /> - ) - } - /> - ); -}; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/fields_list.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/fields_list.tsx deleted file mode 100644 index 1861d23b69a45..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/fields_list.tsx +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { ReactNode, Fragment } from 'react'; -import { - EuiFlexGroup, - EuiPanel, - EuiFlexItem, - EuiSpacer, - EuiTitle, - EuiHorizontalRule, - EuiSkeletonTitle, - EuiSkeletonText, - EuiSkeletonRectangle, -} from '@elastic/eui'; - -export function FieldsList({ - title, - fields, - actionsMenu: ActionsMenu, - dataTestSubj = `datasetQualityFlyoutFieldsList-${title.toLowerCase().split(' ').join('_')}`, -}: { - title: string; - fields: Array<{ fieldTitle: string; fieldValue: ReactNode; isLoading: boolean }>; - actionsMenu?: ReactNode; - dataTestSubj?: string; -}) { - return ( - - - - {title} - - {ActionsMenu} - - - - {fields.map(({ fieldTitle, fieldValue, isLoading: isFieldLoading }, index) => ( - - - - - {fieldTitle} - - - - - {fieldValue} - - - - - {index < fields.length - 1 ? : null} - - ))} - - - ); -} - -export function FieldsListLoading() { - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout.tsx deleted file mode 100644 index cb6944057a2d6..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout.tsx +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { Fragment, useEffect } from 'react'; -import { css } from '@emotion/react'; -import { - EuiButtonEmpty, - EuiFlexGroup, - EuiFlexItem, - EuiFlyout, - EuiFlyoutBody, - EuiFlyoutFooter, - EuiSpacer, - EuiHorizontalRule, - EuiPanel, - EuiSkeletonRectangle, -} from '@elastic/eui'; -import { dynamic } from '@kbn/shared-ux-utility'; -import { flyoutCancelText } from '../../../common/translations'; -import { useDatasetQualityFlyout, useDatasetDetailsTelemetry } from '../../hooks'; -import { DatasetSummary, DatasetSummaryLoading } from './dataset_summary'; -import { Header } from './header'; -import { FlyoutProps } from './types'; -import { BasicDataStream } from '../../../common/types'; - -const FlyoutSummary = dynamic(() => import('./flyout_summary/flyout_summary')); -const IntegrationSummary = dynamic(() => import('./integration_summary')); - -// Allow for lazy loading -// eslint-disable-next-line import/no-default-export -export default function Flyout({ dataset, closeFlyout }: FlyoutProps) { - const { - dataStreamStat, - dataStreamSettings, - dataStreamDetails, - isNonAggregatable, - fieldFormats, - timeRange, - loadingState, - flyoutLoading, - integration, - } = useDatasetQualityFlyout(); - - const linkDetails: BasicDataStream = { - name: dataset.name, - rawName: dataset.rawName, - integration: integration?.integrationDetails, - type: dataset.type, - namespace: dataset.namespace, - }; - - const title = integration?.integrationDetails?.datasets?.[dataset.name] ?? dataset.name; - - const { startTracking } = useDatasetDetailsTelemetry(); - - useEffect(() => { - startTracking(); - }, [startTracking]); - - return ( - - {flyoutLoading ? ( - - ) : ( - <> -
- - - - - - - - - {loadingState.dataStreamDetailsLoading && loadingState.dataStreamSettingsLoading ? ( - - ) : dataStreamStat ? ( - - - - {integration?.integrationDetails && ( - <> - - - - )} - - ) : null} - - - - - - - - {flyoutCancelText} - - - - - - )} - - ); -} - -const flyoutBodyStyles = css` - .euiFlyoutBody__overflowContent { - padding: 0; - } -`; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary.tsx deleted file mode 100644 index 5b89c43ad92d1..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary.tsx +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useCallback, useState } from 'react'; -import { i18n } from '@kbn/i18n'; -import { - OnRefreshProps, - OnTimeChangeProps, - EuiSpacer, - EuiFlexGroup, - EuiFlexItem, - EuiCallOut, - EuiLink, - EuiCode, -} from '@elastic/eui'; - -import { FormattedMessage } from '@kbn/i18n-react'; -import { DegradedDocs } from '../degraded_docs_trend/degraded_docs'; -import { DataStreamDetails } from '../../../../common/api_types'; -import { DEFAULT_TIME_RANGE, DEFAULT_DATEPICKER_REFRESH } from '../../../../common/constants'; -import { useDatasetQualityContext } from '../../dataset_quality/context'; -import { FlyoutSummaryHeader } from './flyout_summary_header'; -import { FlyoutSummaryKpis, FlyoutSummaryKpisLoading } from './flyout_summary_kpis'; -import { DegradedFields } from '../degraded_fields/degraded_fields'; -import { TimeRangeConfig } from '../../../../common/types'; -import { FlyoutDataset } from '../../../state_machines/dataset_quality_controller'; - -const nonAggregatableWarningTitle = i18n.translate('xpack.datasetQuality.nonAggregatable.title', { - defaultMessage: 'Your request may take longer to complete', -}); - -const nonAggregatableWarningDescription = (dataset: string) => ( - - {dataset} - - ), - howToFixIt: ( - - {i18n.translate( - 'xpack.datasetQuality.flyout.nonAggregatableDatasets.link.title', - { - defaultMessage: 'rollover', - } - )} - - ), - }} - /> - ), - }} - /> - ), - }} - /> -); - -// Allow for lazy loading -// eslint-disable-next-line import/no-default-export -export default function FlyoutSummary({ - dataStream, - dataStreamStat, - dataStreamDetails, - isNonAggregatable, - dataStreamDetailsLoading, - timeRange = { ...DEFAULT_TIME_RANGE, refresh: DEFAULT_DATEPICKER_REFRESH }, -}: { - dataStream: string; - dataStreamStat?: FlyoutDataset; - dataStreamDetails?: DataStreamDetails; - dataStreamDetailsLoading: boolean; - timeRange?: TimeRangeConfig; - isNonAggregatable?: boolean; -}) { - const { service } = useDatasetQualityContext(); - const [lastReloadTime, setLastReloadTime] = useState(Date.now()); - - const updateTimeRange = useCallback( - ({ start, end, refreshInterval }: OnRefreshProps) => { - service.send({ - type: 'UPDATE_INSIGHTS_TIME_RANGE', - timeRange: { - from: start, - to: end, - refresh: { ...DEFAULT_DATEPICKER_REFRESH, value: refreshInterval }, - }, - }); - }, - [service] - ); - - const handleTimeChange = useCallback( - ({ isInvalid, ...timeRangeProps }: OnTimeChangeProps) => { - if (!isInvalid) { - updateTimeRange({ refreshInterval: timeRange.refresh.value, ...timeRangeProps }); - } - }, - [updateTimeRange, timeRange.refresh] - ); - - const handleTimeRangeChange = useCallback( - ({ start, end }: Pick) => { - updateTimeRange({ start, end, refreshInterval: timeRange.refresh.value }); - }, - [updateTimeRange, timeRange.refresh] - ); - - const handleRefresh = useCallback( - (refreshProps: OnRefreshProps) => { - updateTimeRange(refreshProps); - setLastReloadTime(Date.now()); - }, - [updateTimeRange] - ); - - return ( - <> - {isNonAggregatable && ( - - - -

{nonAggregatableWarningDescription(dataStream)}

-
-
-
- )} - - - - - {dataStreamStat ? ( - - ) : ( - - )} - - - - - - - - - - ); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_header.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_header.tsx deleted file mode 100644 index c0ee7303b51a5..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_header.tsx +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { css } from '@emotion/react'; -import { - EuiFlexGroup, - EuiIcon, - EuiSuperDatePicker, - EuiTitle, - EuiToolTip, - OnRefreshProps, - OnTimeChangeProps, -} from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; - -import { flyoutSummaryText } from '../../../../common/translations'; -import { TimeRangeConfig } from '../../../../common/types'; - -export function FlyoutSummaryHeader({ - timeRange, - onTimeChange, - onRefresh, -}: { - timeRange: TimeRangeConfig; - onTimeChange: (timeChangeProps: OnTimeChangeProps) => void; - onRefresh: (refreshProps: OnRefreshProps) => void; -}) { - return ( - - - - {flyoutSummaryText} - - - - - - - - - - - ); -} - -const flyoutSummaryTooltip = ( - -); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpi_item.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpi_item.tsx deleted file mode 100644 index 767cd8ec41f4f..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpi_item.tsx +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiPanel, - EuiTitle, - EuiText, - EuiLink, - useEuiTheme, - EuiSkeletonTitle, - EuiSkeletonRectangle, -} from '@elastic/eui'; - -import { PrivilegesWarningIconWrapper } from '../../common'; -import { notAvailableLabel } from '../../../../common/translations'; -import type { getSummaryKpis } from './get_summary_kpis'; - -export function FlyoutSummaryKpiItem({ - title, - value, - link, - isLoading, - userHasPrivilege, -}: ReturnType[number] & { isLoading: boolean }) { - const { euiTheme } = useEuiTheme(); - - return ( - - - - - -
{title}
-
- - - <> - -
- {link ? ( - - - {link.label} - - - ) : null} -
- - - -

{userHasPrivilege ? value : notAvailableLabel}

-
-
-
-
-
- ); -} - -export function FlyoutSummaryKpiItemLoading({ title }: { title: string }) { - return ( - - ); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpis.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpis.tsx deleted file mode 100644 index 47b41712dc7f5..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpis.tsx +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useMemo } from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; - -import { _IGNORED } from '../../../../common/es_fields'; - -import { DataStreamDetails } from '../../../../common/api_types'; -import { useKibanaContextForPlugin } from '../../../utils'; -import { NavigationSource } from '../../../services/telemetry'; -import { useDatasetDetailsTelemetry, useRedirectLink } from '../../../hooks'; -import { FlyoutDataset } from '../../../state_machines/dataset_quality_controller'; -import { FlyoutSummaryKpiItem, FlyoutSummaryKpiItemLoading } from './flyout_summary_kpi_item'; -import { getSummaryKpis } from './get_summary_kpis'; -import { TimeRangeConfig } from '../../../../common/types'; - -export function FlyoutSummaryKpis({ - dataStreamStat, - dataStreamDetails, - isLoading, - timeRange, -}: { - dataStreamStat: FlyoutDataset; - dataStreamDetails?: DataStreamDetails; - isLoading: boolean; - timeRange: TimeRangeConfig; -}) { - const { - services: { observabilityShared }, - } = useKibanaContextForPlugin(); - const telemetry = useDatasetDetailsTelemetry(); - const hostsLocator = observabilityShared.locators.infra.hostsLocator; - - const degradedDocsLinkProps = useRedirectLink({ - dataStreamStat, - query: { language: 'kuery', query: `${_IGNORED}: *` }, - timeRangeConfig: timeRange, - telemetry: { - page: 'details', - navigationSource: NavigationSource.Summary, - }, - }); - - const kpis = useMemo( - () => - getSummaryKpis({ - dataStreamDetails, - timeRange, - degradedDocsLinkProps, - hostsLocator, - telemetry, - }), - [dataStreamDetails, degradedDocsLinkProps, hostsLocator, telemetry, timeRange] - ); - - return ( - - - {kpis.map((kpi) => ( - - - - ))} - - - ); -} - -export function FlyoutSummaryKpisLoading() { - const telemetry = useDatasetDetailsTelemetry(); - - return ( - - - {getSummaryKpis({ telemetry }).map(({ title }) => ( - - - - ))} - - - ); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/get_summary_kpis.test.ts b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/get_summary_kpis.test.ts deleted file mode 100644 index 28f5334e2f199..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/get_summary_kpis.test.ts +++ /dev/null @@ -1,171 +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 { formatNumber } from '@elastic/eui'; -import type { useKibanaContextForPlugin } from '../../../utils'; -import type { useDatasetDetailsTelemetry } from '../../../hooks'; - -import { - BYTE_NUMBER_FORMAT, - DEFAULT_DATEPICKER_REFRESH, - DEFAULT_TIME_RANGE, - MAX_HOSTS_METRIC_VALUE, -} from '../../../../common/constants'; -import { - overviewDegradedDocsText, - flyoutDocsCountTotalText, - flyoutHostsText, - flyoutServicesText, - flyoutShowAllText, - flyoutSizeText, -} from '../../../../common/translations'; -import { getSummaryKpis } from './get_summary_kpis'; -import { TimeRangeConfig } from '../../../../common/types'; - -const dataStreamDetails = { - services: { - service1: ['service1Instance1', 'service1Instance2'], - service2: ['service2Instance1'], - }, - docsCount: 1000, - sizeBytes: 5000, - hosts: { - host1: ['host1Instance1', 'host1Instance2'], - host2: ['host2Instance1'], - }, - degradedDocsCount: 200, -}; - -const timeRange: TimeRangeConfig = { - ...DEFAULT_TIME_RANGE, - refresh: DEFAULT_DATEPICKER_REFRESH, - from: 'now-15m', - to: 'now', -}; - -const degradedDocsLinkProps = { - linkProps: { href: 'http://exploratory-view/degraded-docs', onClick: () => {} }, - navigate: () => {}, - isLogsExplorerAvailable: true, -}; -const hostsRedirectUrl = 'http://hosts/metric/'; - -const hostsLocator = { - getRedirectUrl: () => hostsRedirectUrl, -} as unknown as ReturnType< - typeof useKibanaContextForPlugin ->['services']['observabilityShared']['locators']['infra']['hostsLocator']; - -const telemetry = { - trackDetailsNavigated: () => {}, -} as unknown as ReturnType; - -describe('getSummaryKpis', () => { - it('should return the correct KPIs', () => { - const result = getSummaryKpis({ - dataStreamDetails, - timeRange, - degradedDocsLinkProps, - hostsLocator, - telemetry, - }); - - expect(result).toEqual([ - { - title: flyoutDocsCountTotalText, - value: '1,000', - userHasPrivilege: true, - }, - { - title: flyoutSizeText, - value: formatNumber(dataStreamDetails.sizeBytes ?? 0, BYTE_NUMBER_FORMAT), - userHasPrivilege: false, - }, - { - title: flyoutServicesText, - value: '3', - link: undefined, - userHasPrivilege: true, - }, - { - title: flyoutHostsText, - value: '3', - link: undefined, - userHasPrivilege: true, - }, - { - title: overviewDegradedDocsText, - value: '200', - link: { - label: flyoutShowAllText, - props: degradedDocsLinkProps.linkProps, - }, - userHasPrivilege: true, - }, - ]); - }); - - it('show X+ if number of hosts or services exceed MAX_HOSTS_METRIC_VALUE', () => { - const services = { - service1: new Array(MAX_HOSTS_METRIC_VALUE + 1) - .fill('service1Instance') - .map((_, i) => `service1Instance${i}`), - }; - - const host3 = new Array(MAX_HOSTS_METRIC_VALUE + 1) - .fill('host3Instance') - .map((_, i) => `host3Instance${i}`); - - const detailsWithMaxPlusHosts = { - ...dataStreamDetails, - services, - hosts: { ...dataStreamDetails.hosts, host3 }, - }; - - const result = getSummaryKpis({ - dataStreamDetails: detailsWithMaxPlusHosts, - timeRange, - degradedDocsLinkProps, - hostsLocator, - telemetry, - }); - - expect(result).toEqual([ - { - title: flyoutDocsCountTotalText, - value: '1,000', - userHasPrivilege: true, - }, - { - title: flyoutSizeText, - value: formatNumber(dataStreamDetails.sizeBytes ?? 0, BYTE_NUMBER_FORMAT), - userHasPrivilege: false, - }, - { - title: flyoutServicesText, - value: '50+', - link: undefined, - userHasPrivilege: true, - }, - { - title: flyoutHostsText, - value: '54+', - link: undefined, - userHasPrivilege: true, - }, - { - title: overviewDegradedDocsText, - value: '200', - link: { - label: flyoutShowAllText, - props: degradedDocsLinkProps.linkProps, - }, - userHasPrivilege: true, - }, - ]); - }); -}); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/get_summary_kpis.ts b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/get_summary_kpis.ts deleted file mode 100644 index b574e1e8a8160..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/get_summary_kpis.ts +++ /dev/null @@ -1,167 +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 { formatNumber } from '@elastic/eui'; -import { getRouterLinkProps, RouterLinkProps } from '@kbn/router-utils/src/get_router_link_props'; -import { - BYTE_NUMBER_FORMAT, - DEFAULT_DATEPICKER_REFRESH, - DEFAULT_TIME_RANGE, - MAX_HOSTS_METRIC_VALUE, - NUMBER_FORMAT, -} from '../../../../common/constants'; -import { - overviewDegradedDocsText, - flyoutDocsCountTotalText, - flyoutHostsText, - flyoutServicesText, - flyoutShowAllText, - flyoutSizeText, -} from '../../../../common/translations'; -import { DataStreamDetails } from '../../../../common/api_types'; -import { NavigationTarget, NavigationSource } from '../../../services/telemetry'; -import { useKibanaContextForPlugin } from '../../../utils'; -import type { useRedirectLink, useDatasetDetailsTelemetry } from '../../../hooks'; -import { TimeRangeConfig } from '../../../../common/types'; - -export function getSummaryKpis({ - dataStreamDetails, - timeRange = { ...DEFAULT_TIME_RANGE, refresh: DEFAULT_DATEPICKER_REFRESH }, - degradedDocsLinkProps, - hostsLocator, - telemetry, -}: { - dataStreamDetails?: DataStreamDetails; - timeRange?: TimeRangeConfig; - degradedDocsLinkProps?: ReturnType; - hostsLocator?: ReturnType< - typeof useKibanaContextForPlugin - >['services']['observabilityShared']['locators']['infra']['hostsLocator']; - telemetry: ReturnType; -}): Array<{ - title: string; - value: string; - link?: { label: string; props: RouterLinkProps }; - userHasPrivilege: boolean; -}> { - const services = dataStreamDetails?.services ?? {}; - const serviceKeys = Object.keys(services); - const countOfServices = serviceKeys - .map((key: string) => services[key].length) - .reduce((a, b) => a + b, 0); - - // @ts-ignore // TODO: Add link to APM services page when possible - https://github.com/elastic/kibana/issues/179904 - const servicesLink = { - label: flyoutShowAllText, - props: getRouterLinkProps({ - href: undefined, - onClick: () => { - telemetry.trackDetailsNavigated(NavigationTarget.Services, NavigationSource.Summary); - }, - }), - }; - - return [ - { - title: flyoutDocsCountTotalText, - value: formatNumber(dataStreamDetails?.docsCount ?? 0, NUMBER_FORMAT), - userHasPrivilege: true, - }, - // dataStreamDetails.sizeBytes = null indicates it's Serverless where `_stats` API isn't available - ...(dataStreamDetails?.sizeBytes !== null // Only show when not in Serverless - ? [ - { - title: flyoutSizeText, - value: formatNumber(dataStreamDetails?.sizeBytes ?? 0, BYTE_NUMBER_FORMAT), - userHasPrivilege: Boolean(dataStreamDetails?.userPrivileges?.canMonitor), - }, - ] - : []), - { - title: flyoutServicesText, - value: formatMetricValueForMax(countOfServices, MAX_HOSTS_METRIC_VALUE, NUMBER_FORMAT), - link: undefined, - userHasPrivilege: true, - }, - getHostsKpi(dataStreamDetails?.hosts, timeRange, telemetry, hostsLocator), - { - title: overviewDegradedDocsText, - value: formatNumber(dataStreamDetails?.degradedDocsCount ?? 0, NUMBER_FORMAT), - link: - degradedDocsLinkProps && degradedDocsLinkProps.linkProps.href - ? { - label: flyoutShowAllText, - props: degradedDocsLinkProps.linkProps, - } - : undefined, - userHasPrivilege: true, - }, - ]; -} - -function getHostsKpi( - dataStreamHosts: DataStreamDetails['hosts'], - timeRange: TimeRangeConfig, - telemetry: ReturnType, - hostsLocator?: ReturnType< - typeof useKibanaContextForPlugin - >['services']['observabilityShared']['locators']['infra']['hostsLocator'] -) { - const hosts = dataStreamHosts ?? {}; - const hostKeys = Object.keys(hosts); - const countOfHosts = hostKeys - .map((key: string) => hosts[key].length) - .reduce( - ({ count, anyHostExceedsMax }, hostCount) => ({ - count: count + hostCount, - anyHostExceedsMax: anyHostExceedsMax || hostCount > MAX_HOSTS_METRIC_VALUE, - }), - { count: 0, anyHostExceedsMax: false } - ); - - // Create a query so from hostKeys so that (key: value OR key: value2) - const hostsKuery = hostKeys - .filter((key) => hosts[key].length > 0) - .map((key) => hosts[key].map((value) => `${key}: "${value}"`).join(' OR ')) - .join(' OR '); - const hostsUrl = hostsLocator?.getRedirectUrl({ - query: { language: 'kuery', query: hostsKuery }, - dateRange: { from: timeRange.from, to: timeRange.to }, - limit: countOfHosts.count, - }); - - // @ts-ignore // TODO: Add link to Infra Hosts page when possible - const hostsLink = { - label: flyoutShowAllText, - props: getRouterLinkProps({ - href: hostsUrl, - onClick: () => { - telemetry.trackDetailsNavigated(NavigationTarget.Hosts, NavigationSource.Summary); - }, - }), - }; - - return { - title: flyoutHostsText, - value: formatMetricValueForMax( - countOfHosts.anyHostExceedsMax ? countOfHosts.count + 1 : countOfHosts.count, - countOfHosts.count, - NUMBER_FORMAT - ), - link: undefined, - userHasPrivilege: true, - }; -} - -/** - * Formats a metric value to show a '+' sign if it's above a max value e.g. 50+ - */ -function formatMetricValueForMax(value: number, max: number, numberFormat: string): string { - const exceedsMax = value > max; - const valueToShow = exceedsMax ? max : value; - return `${formatNumber(valueToShow, numberFormat)}${exceedsMax ? '+' : ''}`; -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/header.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/header.tsx deleted file mode 100644 index 1117c7da12a1b..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/header.tsx +++ /dev/null @@ -1,102 +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 { - EuiButton, - EuiFlexGroup, - EuiFlexItem, - EuiFlyoutHeader, - EuiSkeletonTitle, - EuiTitle, - useEuiShadow, - useEuiTheme, -} from '@elastic/eui'; -import { css } from '@emotion/react'; -import React from 'react'; -import { openInDiscoverText, openInLogsExplorerText } from '../../../common/translations'; -import { NavigationSource } from '../../services/telemetry'; -import { useRedirectLink } from '../../hooks'; -import { IntegrationIcon } from '../common'; -import { BasicDataStream, TimeRangeConfig } from '../../../common/types'; - -export function Header({ - linkDetails, - loading, - title, - timeRange, -}: { - linkDetails: BasicDataStream; - loading: boolean; - title: string; - timeRange: TimeRangeConfig; -}) { - const { integration } = linkDetails; - const euiShadow = useEuiShadow('s'); - const { euiTheme } = useEuiTheme(); - const redirectLinkProps = useRedirectLink({ - dataStreamStat: linkDetails, - telemetry: { - page: 'details', - navigationSource: NavigationSource.Header, - }, - timeRangeConfig: timeRange, - }); - - return ( - - {loading ? ( - - ) : ( - - - - -

{title}

-
-
- -
-
-
- - - - {redirectLinkProps.isLogsExplorerAvailable - ? openInLogsExplorerText - : openInDiscoverText} - - - -
- )} -
- ); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/integration_actions_menu.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/integration_actions_menu.tsx deleted file mode 100644 index 99afb7f269df5..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/integration_actions_menu.tsx +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useMemo } from 'react'; -import { i18n } from '@kbn/i18n'; -import { - EuiButtonEmpty, - EuiButtonIcon, - EuiContextMenu, - EuiContextMenuPanelDescriptor, - EuiContextMenuPanelItemDescriptor, - EuiPopover, - EuiSkeletonRectangle, -} from '@elastic/eui'; -import { css } from '@emotion/react'; -import { RouterLinkProps } from '@kbn/router-utils/src/get_router_link_props'; -import { useDatasetQualityFlyout } from '../../hooks'; -import { useFlyoutIntegrationActions } from '../../hooks/use_flyout_integration_actions'; -import { Integration } from '../../../common/data_streams_stats/integration'; -import { Dashboard } from '../../../common/api_types'; - -const integrationActionsText = i18n.translate('xpack.datasetQuality.flyoutIntegrationActionsText', { - defaultMessage: 'Integration actions', -}); - -const seeIntegrationText = i18n.translate('xpack.datasetQuality.flyoutSeeIntegrationActionText', { - defaultMessage: 'See integration', -}); - -const indexTemplateText = i18n.translate('xpack.datasetQuality.flyoutIndexTemplateActionText', { - defaultMessage: 'Index template', -}); - -const viewDashboardsText = i18n.translate('xpack.datasetQuality.flyoutViewDashboardsActionText', { - defaultMessage: 'View dashboards', -}); - -export function IntegrationActionsMenu({ - integration, - dashboards, - dashboardsLoading, -}: { - integration: Integration; - dashboards: Dashboard[]; - dashboardsLoading: boolean; -}) { - const { dataStreamStat, canUserAccessDashboards, canUserViewIntegrations } = - useDatasetQualityFlyout(); - const { version, name: integrationName } = integration; - const { type, name } = dataStreamStat!; - const { - isOpen, - handleCloseMenu, - handleToggleMenu, - getIntegrationOverviewLinkProps, - getIndexManagementLinkProps, - getDashboardLinkProps, - } = useFlyoutIntegrationActions(); - - const actionButton = ( - - ); - - const MenuActionItem = ({ - dataTestSubject, - buttonText, - routerLinkProps, - iconType, - disabled = false, - }: { - dataTestSubject: string; - buttonText: string | React.ReactNode; - routerLinkProps: RouterLinkProps; - iconType: string; - disabled?: boolean; - }) => ( - - {buttonText} - - ); - - const panelItems = useMemo(() => { - const firstLevelItems: EuiContextMenuPanelItemDescriptor[] = [ - ...(canUserViewIntegrations - ? [ - { - renderItem: () => ( - - ), - }, - ] - : []), - { - renderItem: () => ( - - ), - }, - { - isSeparator: true, - key: 'sep', - }, - ]; - - if (dashboards.length && canUserAccessDashboards) { - firstLevelItems.push({ - icon: 'dashboardApp', - panel: 1, - name: viewDashboardsText, - 'data-test-subj': 'datasetQualityFlyoutIntegrationActionViewDashboards', - disabled: false, - }); - } else if (dashboardsLoading) { - firstLevelItems.push({ - icon: 'dashboardApp', - name: , - 'data-test-subj': 'datasetQualityFlyoutIntegrationActionDashboardsLoading', - disabled: true, - }); - } - - const panel: EuiContextMenuPanelDescriptor[] = [ - { - id: 0, - items: firstLevelItems, - }, - { - id: 1, - title: viewDashboardsText, - items: dashboards.map((dashboard) => { - return { - renderItem: () => ( - - ), - }; - }), - }, - ]; - - return panel; - }, [ - dashboards, - getDashboardLinkProps, - getIndexManagementLinkProps, - getIntegrationOverviewLinkProps, - integrationName, - name, - type, - version, - dashboardsLoading, - canUserAccessDashboards, - canUserViewIntegrations, - ]); - - return ( - - - - ); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/integration_summary.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/integration_summary.tsx deleted file mode 100644 index 53262c7821ce7..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/integration_summary.tsx +++ /dev/null @@ -1,72 +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 { EuiFlexGroup, EuiBadge, EuiText } from '@elastic/eui'; -import React from 'react'; -import { css } from '@emotion/react'; -import { - flyoutIntegrationDetailsText, - flyoutIntegrationNameText, - integrationVersionText, -} from '../../../common/translations'; -import { IntegrationIcon } from '../common'; -import { FieldsList } from './fields_list'; -import { IntegrationActionsMenu } from './integration_actions_menu'; -import { Integration } from '../../../common/data_streams_stats/integration'; -import { Dashboard } from '../../../common/api_types'; - -// Allow for lazy loading -// eslint-disable-next-line import/no-default-export -export default function IntegrationSummary({ - integration, - dashboards, - dashboardsLoading, -}: { - integration: Integration; - dashboards: Dashboard[]; - dashboardsLoading: boolean; -}) { - const { name, version } = integration; - - const integrationActionsMenu = ( - - ); - return ( - - - - {name} - - - ), - isLoading: false, - }, - { - fieldTitle: integrationVersionText, - fieldValue: version, - isLoading: false, - }, - ]} - /> - ); -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/create_controller.ts b/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/create_controller.ts index 7424e13b0f93c..ea4443a61a8ff 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/create_controller.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/create_controller.ts @@ -11,12 +11,10 @@ import equal from 'fast-deep-equal'; import { distinctUntilChanged, from, map } from 'rxjs'; import { interpret } from 'xstate'; import { IDataStreamsStatsClient } from '../../services/data_streams_stats'; -import { IDataStreamDetailsClient } from '../../services/data_stream_details'; import { createDatasetQualityControllerStateMachine, DEFAULT_CONTEXT, } from '../../state_machines/dataset_quality_controller'; -import { DatasetQualityStartDeps } from '../../types'; import { getContextFromPublicState, getPublicStateFromContext } from './public_state'; import { DatasetQualityController, DatasetQualityPublicStateUpdate } from './types'; @@ -24,13 +22,11 @@ type InitialState = DatasetQualityPublicStateUpdate; interface Dependencies { core: CoreStart; - plugins: DatasetQualityStartDeps; dataStreamStatsClient: IDataStreamsStatsClient; - dataStreamDetailsClient: IDataStreamDetailsClient; } export const createDatasetQualityControllerFactory = - ({ core, plugins, dataStreamStatsClient, dataStreamDetailsClient }: Dependencies) => + ({ core, dataStreamStatsClient }: Dependencies) => async ({ initialState = DEFAULT_CONTEXT, }: { @@ -40,10 +36,8 @@ export const createDatasetQualityControllerFactory = const machine = createDatasetQualityControllerStateMachine({ initialContext, - plugins, toasts: core.notifications.toasts, dataStreamStatsClient, - dataStreamDetailsClient, }); const service = interpret(machine, { diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/public_state.ts b/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/public_state.ts index 1bf0088bc7a48..ea5ae63f97073 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/public_state.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/public_state.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { DatasetTableSortField, DegradedFieldSortField } from '../../hooks'; +import { DatasetTableSortField } from '../../hooks'; import { DatasetQualityControllerContext, DEFAULT_CONTEXT, @@ -17,7 +17,6 @@ export const getPublicStateFromContext = ( ): DatasetQualityPublicState => { return { table: context.table, - flyout: context.flyout, filters: context.filters, }; }; @@ -36,22 +35,6 @@ export const getContextFromPublicState = ( } : DEFAULT_CONTEXT.table.sort, }, - flyout: { - ...DEFAULT_CONTEXT.flyout, - ...publicState.flyout, - degradedFields: { - table: { - ...DEFAULT_CONTEXT.flyout.degradedFields.table, - ...publicState.flyout?.degradedFields?.table, - sort: publicState.flyout?.degradedFields?.table?.sort - ? { - ...publicState.flyout.degradedFields.table.sort, - field: publicState.flyout.degradedFields.table.sort.field as DegradedFieldSortField, - } - : DEFAULT_CONTEXT.flyout.degradedFields.table.sort, - }, - }, - }, filters: { ...DEFAULT_CONTEXT.filters, ...publicState.filters, diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/types.ts b/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/types.ts index decb7454bd193..81b2de0088a52 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality/types.ts @@ -9,9 +9,7 @@ import { Observable } from 'rxjs'; import { DatasetQualityControllerStateService, WithFilters, - WithFlyoutOptions, WithTableOptions, - DegradedFields, } from '../../state_machines/dataset_quality_controller'; export interface DatasetQualityController { @@ -25,25 +23,10 @@ export type DatasetQualityTableOptions = Partial< Omit & { sort: TableSortOptions } >; -type DegradedFieldSortOptions = Omit & { field: string }; - -export type DatasetQualityDegradedFieldTableOptions = Partial< - Omit & { - sort: DegradedFieldSortOptions; - } ->; - -export type DatasetQualityFlyoutOptions = Partial< - Omit & { - degradedFields: { table?: DatasetQualityDegradedFieldTableOptions }; - } ->; - export type DatasetQualityFilterOptions = Partial; export interface DatasetQualityPublicState { table: DatasetQualityTableOptions; - flyout: DatasetQualityFlyoutOptions; filters: DatasetQualityFilterOptions; } diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality_details/types.ts b/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality_details/types.ts index 65ca53c073d42..b5a295a897bd5 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality_details/types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/controller/dataset_quality_details/types.ts @@ -28,7 +28,7 @@ export type DatasetQualityDetailsPublicState = WithDefaultControllerState; // a must and everything else can be optional. The table inside the // degradedFields must accept field property as string export type DatasetQualityDetailsPublicStateUpdate = Partial< - Pick + Pick > & { dataStream: string; } & { diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/index.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/index.ts index 5c746e2f1177b..ad588fd0b673f 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/index.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/index.ts @@ -6,14 +6,13 @@ */ export * from './use_dataset_quality_table'; -export * from './use_dataset_quality_flyout'; export * from './use_degraded_docs_chart'; export * from './use_redirect_link'; export * from './use_summary_panel'; export * from './use_create_dataview'; -export * from './use_dataset_quality_degraded_field'; -export * from './use_telemetry'; +export * from './use_redirect_link_telemetry'; export * from './use_dataset_quality_details_state'; -export * from './use_dataset_quality_details_redirect_link'; export * from './use_degraded_fields'; export * from './use_integration_actions'; +export * from './use_dataset_telemetry'; +export * from './use_dataset_details_telemetry'; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_details_telemetry.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_details_telemetry.ts new file mode 100644 index 0000000000000..f613d3af7fdc4 --- /dev/null +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_details_telemetry.ts @@ -0,0 +1,200 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useCallback, useEffect, useMemo } from 'react'; +import { RouterLinkProps } from '@kbn/router-utils/src/get_router_link_props'; +import { getDateISORange } from '@kbn/timerange'; +import { useDatasetQualityDetailsState } from './use_dataset_quality_details_state'; +import { DatasetDetailsEbtProps, NavigationSource, NavigationTarget } from '../services/telemetry'; +import { BasicDataStream, TimeRangeConfig } from '../../common/types'; +import { DataStreamDetails } from '../../common/api_types'; +import { Integration } from '../../common/data_streams_stats/integration'; +import { mapPercentageToQuality } from '../../common/utils'; +import { MASKED_FIELD_PLACEHOLDER, UNKOWN_FIELD_PLACEHOLDER } from '../../common/constants'; + +export function useDatasetDetailsTelemetry() { + const { + telemetryClient, + datasetDetails, + dataStreamDetails, + timeRange, + canUserViewIntegrations, + canUserAccessDashboards, + breakdownField, + isNonAggregatable, + isBreakdownFieldEcs, + integrationDetails, + loadingState, + } = useDatasetQualityDetailsState(); + + const ebtProps = useMemo(() => { + if (dataStreamDetails && timeRange && !loadingState.dataStreamDetailsLoading) { + return getDatasetDetailsEbtProps({ + datasetDetails, + dataStreamDetails, + timeRange, + canUserViewIntegrations, + canUserAccessDashboards, + breakdownField, + isNonAggregatable, + isBreakdownFieldEcs, + integration: integrationDetails.integration, + }); + } + + return undefined; + }, [ + dataStreamDetails, + timeRange, + loadingState.dataStreamDetailsLoading, + datasetDetails, + canUserViewIntegrations, + canUserAccessDashboards, + breakdownField, + isNonAggregatable, + isBreakdownFieldEcs, + integrationDetails.integration, + ]); + + const startTracking = useCallback(() => { + telemetryClient.startDatasetDetailsTracking(); + }, [telemetryClient]); + + // Report opening dataset details + useEffect(() => { + const datasetDetailsTrackingState = telemetryClient.getDatasetDetailsTrackingState(); + if (datasetDetailsTrackingState === 'started' && ebtProps) { + telemetryClient.trackDatasetDetailsOpened(ebtProps); + } + }, [ebtProps, telemetryClient]); + + const trackDetailsNavigated = useCallback( + (target: NavigationTarget, source: NavigationSource, isDegraded = false) => { + const datasetDetailsTrackingState = telemetryClient.getDatasetDetailsTrackingState(); + if ( + (datasetDetailsTrackingState === 'opened' || datasetDetailsTrackingState === 'navigated') && + ebtProps + ) { + telemetryClient.trackDatasetDetailsNavigated({ + ...ebtProps, + filters: { + is_degraded: isDegraded, + }, + target, + source, + }); + } else { + throw new Error( + 'Cannot report dataset details navigation telemetry without required data and state' + ); + } + }, + [ebtProps, telemetryClient] + ); + + const trackDatasetDetailsBreakdownFieldChanged = useCallback(() => { + const datasetDetailsTrackingState = telemetryClient.getDatasetDetailsTrackingState(); + if ( + (datasetDetailsTrackingState === 'opened' || datasetDetailsTrackingState === 'navigated') && + ebtProps + ) { + telemetryClient.trackDatasetDetailsBreakdownFieldChanged({ + ...ebtProps, + breakdown_field: ebtProps.breakdown_field, + }); + } + }, [ebtProps, telemetryClient]); + + const wrapLinkPropsForTelemetry = useCallback( + ( + props: RouterLinkProps, + target: NavigationTarget, + source: NavigationSource, + isDegraded = false + ) => { + return { + ...props, + onClick: (event: Parameters[0]) => { + trackDetailsNavigated(target, source, isDegraded); + if (props.onClick) { + props.onClick(event); + } + }, + }; + }, + [trackDetailsNavigated] + ); + + return { + startTracking, + trackDetailsNavigated, + wrapLinkPropsForTelemetry, + navigationTargets: NavigationTarget, + navigationSources: NavigationSource, + trackDatasetDetailsBreakdownFieldChanged, + }; +} + +function getDatasetDetailsEbtProps({ + datasetDetails, + dataStreamDetails, + timeRange, + canUserViewIntegrations, + canUserAccessDashboards, + breakdownField, + isNonAggregatable, + isBreakdownFieldEcs, + integration, +}: { + datasetDetails: BasicDataStream; + dataStreamDetails: DataStreamDetails; + timeRange: TimeRangeConfig; + canUserViewIntegrations: boolean; + canUserAccessDashboards: boolean; + breakdownField?: string; + isNonAggregatable: boolean; + isBreakdownFieldEcs: boolean; + integration?: Integration; +}): DatasetDetailsEbtProps { + const indexName = datasetDetails.rawName; + const dataStream = { + dataset: datasetDetails.name, + namespace: datasetDetails.namespace, + type: datasetDetails.type, + }; + const degradedDocs = dataStreamDetails?.degradedDocsCount ?? 0; + const totalDocs = dataStreamDetails?.docsCount ?? 0; + const degradedPercentage = + totalDocs > 0 ? Number(((degradedDocs / totalDocs) * 100).toFixed(2)) : 0; + const health = mapPercentageToQuality(degradedPercentage); + const { startDate: from, endDate: to } = getDateISORange(timeRange); + + return { + index_name: indexName, + data_stream: dataStream, + privileges: { + can_monitor_data_stream: true, + can_view_integrations: canUserViewIntegrations, + can_view_dashboards: canUserAccessDashboards, + }, + data_stream_aggregatable: !isNonAggregatable, + data_stream_health: health, + from, + to, + degraded_percentage: degradedPercentage, + integration: integration?.name, + breakdown_field: breakdownField + ? isBreakdownFieldEcs === null + ? UNKOWN_FIELD_PLACEHOLDER + : getMaskedBreakdownField(breakdownField, isBreakdownFieldEcs) + : breakdownField, + }; +} + +function getMaskedBreakdownField(breakdownField: string, isBreakdownFieldEcs: boolean) { + return isBreakdownFieldEcs ? breakdownField : MASKED_FIELD_PLACEHOLDER; +} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_degraded_field.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_degraded_field.ts deleted file mode 100644 index d92aa5be153f6..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_degraded_field.ts +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { useSelector } from '@xstate/react'; -import { useCallback, useMemo } from 'react'; -import { orderBy } from 'lodash'; -import { useDatasetQualityContext } from '../components/dataset_quality/context'; -import { DegradedField } from '../../common/data_streams_stats'; -import { SortDirection } from '../../common/types'; -import { - DEFAULT_DEGRADED_FIELD_SORT_DIRECTION, - DEFAULT_DEGRADED_FIELD_SORT_FIELD, -} from '../../common/constants'; -import { useKibanaContextForPlugin } from '../utils'; - -type DegradedFieldSortField = keyof DegradedField; - -// TODO: DELETE this hook in favour of new hook post migration -export function useDatasetQualityDegradedField() { - const { service } = useDatasetQualityContext(); - const { - services: { fieldFormats }, - } = useKibanaContextForPlugin(); - - const degradedFields = useSelector(service, (state) => state.context.flyout.degradedFields) ?? {}; - const { data, table } = degradedFields; - const { page, rowsPerPage, sort } = table; - - const pagination = { - pageIndex: page, - pageSize: rowsPerPage, - totalItemCount: data?.length ?? 0, - hidePerPageOptions: true, - }; - - const onTableChange = useCallback( - (options: { - page: { index: number; size: number }; - sort?: { field: DegradedFieldSortField; direction: SortDirection }; - }) => { - service.send({ - type: 'UPDATE_DEGRADED_FIELDS_TABLE_CRITERIA', - degraded_field_criteria: { - page: options.page.index, - rowsPerPage: options.page.size, - sort: { - field: options.sort?.field || DEFAULT_DEGRADED_FIELD_SORT_FIELD, - direction: options.sort?.direction || DEFAULT_DEGRADED_FIELD_SORT_DIRECTION, - }, - }, - }); - }, - [service] - ); - - const renderedItems = useMemo(() => { - const sortedItems = orderBy(data, sort.field, sort.direction); - return sortedItems.slice(page * rowsPerPage, (page + 1) * rowsPerPage); - }, [data, sort.field, sort.direction, page, rowsPerPage]); - - const isLoading = useSelector(service, (state) => - state.matches('flyout.initializing.dataStreamDegradedFields.fetching') - ); - - return { - isLoading, - pagination, - onTableChange, - renderedItems, - sort: { sort }, - fieldFormats, - }; -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_details_redirect_link.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_details_redirect_link.ts deleted file mode 100644 index 3000d05aa34de..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_details_redirect_link.ts +++ /dev/null @@ -1,188 +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 { - SINGLE_DATASET_LOCATOR_ID, - type SingleDatasetLocatorParams, -} from '@kbn/deeplinks-observability'; -import { type DiscoverAppLocatorParams, DISCOVER_APP_LOCATOR } from '@kbn/discover-plugin/common'; -import { type Query, type AggregateQuery, buildPhraseFilter } from '@kbn/es-query'; -import { getRouterLinkProps } from '@kbn/router-utils'; -import type { RouterLinkProps } from '@kbn/router-utils/src/get_router_link_props'; -import type { LocatorPublic } from '@kbn/share-plugin/common'; -import type { LocatorClient } from '@kbn/shared-ux-prompt-no-data-views-types'; -import { useKibanaContextForPlugin } from '../utils'; -import { BasicDataStream, TimeRangeConfig } from '../../common/types'; - -export const useDatasetQualityDetailsRedirectLink = ({ - dataStreamStat, - query, - timeRangeConfig, - breakdownField, -}: { - dataStreamStat: T; - query?: Query | AggregateQuery; - timeRangeConfig: TimeRangeConfig; - breakdownField?: string; -}) => { - const { - services: { share }, - } = useKibanaContextForPlugin(); - - const { from, to } = timeRangeConfig; - - const logsExplorerLocator = - share.url.locators.get(SINGLE_DATASET_LOCATOR_ID); - - const config = logsExplorerLocator - ? buildLogsExplorerConfig({ - locator: logsExplorerLocator, - dataStreamStat, - query, - from, - to, - breakdownField, - }) - : buildDiscoverConfig({ - locatorClient: share.url.locators, - dataStreamStat, - query, - from, - to, - breakdownField, - }); - - return { - linkProps: { - ...config.routerLinkProps, - }, - navigate: config.navigate, - isLogsExplorerAvailable: !!logsExplorerLocator, - }; -}; - -const buildLogsExplorerConfig = ({ - locator, - dataStreamStat, - query, - from, - to, - breakdownField, -}: { - locator: LocatorPublic; - dataStreamStat: T; - query?: Query | AggregateQuery; - from: string; - to: string; - breakdownField?: string; -}): { - navigate: () => void; - routerLinkProps: RouterLinkProps; -} => { - const params: SingleDatasetLocatorParams = { - dataset: dataStreamStat.name, - timeRange: { - from, - to, - }, - integration: dataStreamStat.integration?.name, - query, - filterControls: { - namespace: { - mode: 'include', - values: [dataStreamStat.namespace], - }, - }, - breakdownField, - }; - - const urlToLogsExplorer = locator.getRedirectUrl(params); - - const navigateToLogsExplorer = () => { - locator.navigate(params) as Promise; - }; - - const logsExplorerLinkProps = getRouterLinkProps({ - href: urlToLogsExplorer, - onClick: navigateToLogsExplorer, - }); - - return { routerLinkProps: logsExplorerLinkProps, navigate: navigateToLogsExplorer }; -}; - -const buildDiscoverConfig = ({ - locatorClient, - dataStreamStat, - query, - from, - to, - breakdownField, -}: { - locatorClient: LocatorClient; - dataStreamStat: T; - query?: Query | AggregateQuery; - from: string; - to: string; - breakdownField?: string; -}): { - navigate: () => void; - routerLinkProps: RouterLinkProps; -} => { - const dataViewId = `${dataStreamStat.type}-${dataStreamStat.name}-*`; - const dataViewTitle = dataStreamStat.integration - ? `[${dataStreamStat.integration.title}] ${dataStreamStat.name}` - : `${dataViewId}`; - - const params: DiscoverAppLocatorParams = { - timeRange: { - from, - to, - }, - refreshInterval: { - pause: true, - value: 60000, - }, - dataViewId, - dataViewSpec: { - id: dataViewId, - title: dataViewTitle, - }, - query, - breakdownField, - columns: ['@timestamp', 'message'], - filters: [ - buildPhraseFilter( - { - name: 'data_stream.namespace', - type: 'string', - }, - dataStreamStat.namespace, - { - id: dataViewId, - title: dataViewTitle, - } - ), - ], - interval: 'auto', - sort: [['@timestamp', 'desc']], - }; - - const locator = locatorClient.get(DISCOVER_APP_LOCATOR); - - const urlToDiscover = locator?.getRedirectUrl(params); - - const navigateToDiscover = () => { - locator?.navigate(params) as Promise; - }; - - const discoverLinkProps = getRouterLinkProps({ - href: urlToDiscover, - onClick: navigateToDiscover, - }); - - return { routerLinkProps: discoverLinkProps, navigate: navigateToDiscover }; -}; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_details_state.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_details_state.ts index 4b0626f951580..146ff9e5aa413 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_details_state.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_details_state.ts @@ -15,7 +15,7 @@ import { BasicDataStream } from '../../common/types'; import { useKibanaContextForPlugin } from '../utils'; export const useDatasetQualityDetailsState = () => { - const { service } = useDatasetQualityDetailsContext(); + const { service, telemetryClient } = useDatasetQualityDetailsContext(); const { services: { fieldFormats }, @@ -36,6 +36,14 @@ export const useDatasetQualityDetailsState = () => { : false ); + const isBreakdownFieldAsserted = useSelector( + service, + (state) => + state.matches('initializing.checkBreakdownFieldIsEcs.done') && + breakdownField && + isBreakdownFieldEcs + ); + const dataStreamSettings = useSelector(service, (state) => state.matches('initializing.dataStreamSettings.initializeIntegrations') ? state.context.dataStreamSettings @@ -67,7 +75,9 @@ export const useDatasetQualityDetailsState = () => { ) ); - const canUserViewIntegrations = dataStreamSettings?.datasetUserPrivileges?.canViewIntegrations; + const canUserViewIntegrations = Boolean( + dataStreamSettings?.datasetUserPrivileges?.canViewIntegrations + ); const dataStreamDetails = useSelector(service, (state) => state.matches('initializing.dataStreamDetails.done') @@ -115,6 +125,7 @@ export const useDatasetQualityDetailsState = () => { return { service, + telemetryClient, fieldFormats, isIndexNotFoundError, dataStream, @@ -123,6 +134,7 @@ export const useDatasetQualityDetailsState = () => { dataStreamDetails, breakdownField, isBreakdownFieldEcs, + isBreakdownFieldAsserted, isNonAggregatable, timeRange, loadingState, diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_filters.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_filters.ts similarity index 86% rename from x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_filters.tsx rename to x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_filters.ts index a4d7be4fca46e..e370e7c22d469 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_filters.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_filters.ts @@ -8,12 +8,14 @@ import { OnRefreshChangeProps } from '@elastic/eui'; import { useSelector } from '@xstate/react'; import { useCallback, useMemo } from 'react'; -import { QualityIndicators } from '../../common/types'; +import { KNOWN_TYPES } from '../../common/constants'; +import { DataStreamType, QualityIndicators } from '../../common/types'; import { Integration } from '../../common/data_streams_stats/integration'; import { useDatasetQualityContext } from '../components/dataset_quality/context'; import { IntegrationItem } from '../components/dataset_quality/filters/integrations_selector'; import { NamespaceItem } from '../components/dataset_quality/filters/namespaces_selector'; import { QualityItem } from '../components/dataset_quality/filters/qualities_selector'; +import { Item } from '../components/dataset_quality/filters/selector'; export const useDatasetQualityFilters = () => { const { service } = useDatasetQualityContext(); @@ -22,13 +24,14 @@ export const useDatasetQualityFilters = () => { service, (state) => state.matches('integrations.fetching') && - (state.matches('datasets.fetching') || state.matches('degradedDocs.fetching')) + (state.matches('stats.datasets.fetching') || state.matches('stats.degradedDocs.fetching')) ); const { timeRange, integrations: selectedIntegrations, namespaces: selectedNamespaces, + types: selectedTypes, qualities: selectedQualities, query: selectedQuery, } = useSelector(service, (state) => state.context.filters); @@ -169,6 +172,25 @@ export const useDatasetQualityFilters = () => { [service] ); + const typeItems: Item[] = useMemo(() => { + return KNOWN_TYPES.map((type) => ({ + label: type, + checked: selectedTypes.includes(type) ? 'on' : undefined, + })); + }, [selectedTypes]); + + const onTypesChange = useCallback( + (newTypeItems: Item[]) => { + service.send({ + type: 'UPDATE_TYPES', + types: newTypeItems + .filter((quality) => quality.checked === 'on') + .map((type) => type.label as DataStreamType), + }); + }, + [service] + ); + const onQueryChange = useCallback( (query: string) => { service.send({ @@ -187,9 +209,11 @@ export const useDatasetQualityFilters = () => { integrations: integrationItems, namespaces: namespaceItems, qualities: qualityItems, + types: typeItems, onIntegrationsChange, onNamespacesChange, onQualitiesChange, + onTypesChange, isLoading, selectedQuery, onQueryChange, diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_flyout.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_flyout.tsx deleted file mode 100644 index 0f9d7981e619c..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_flyout.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useSelector } from '@xstate/react'; -import { useDatasetQualityContext } from '../components/dataset_quality/context'; -import { useKibanaContextForPlugin } from '../utils'; - -export const useDatasetQualityFlyout = () => { - const { - services: { fieldFormats }, - } = useKibanaContextForPlugin(); - - const { service } = useDatasetQualityContext(); - - const { - dataset: dataStreamStat, - dataStreamSettings, - datasetDetails: dataStreamDetails, - insightsTimeRange, - breakdownField, - isNonAggregatable, - integration, - } = useSelector(service, (state) => state.context.flyout) ?? {}; - - const { timeRange } = useSelector(service, (state) => state.context.filters); - - const loadingState = useSelector(service, (state) => ({ - dataStreamDetailsLoading: state.matches('flyout.initializing.dataStreamDetails.fetching'), - dataStreamSettingsLoading: state.matches('flyout.initializing.dataStreamSettings.fetching'), - datasetIntegrationDashboardLoading: state.matches( - 'flyout.initializing.dataStreamSettings.initializeIntegrations.integrationDashboards.fetching' - ), - datasetIntegrationDone: state.matches( - 'flyout.initializing.dataStreamSettings.initializeIntegrations.integrationDetails.done' - ), - })); - - const canUserAccessDashboards = useSelector( - service, - (state) => - !state.matches( - 'flyout.initializing.dataStreamSettings.initializeIntegrations.integrationDashboards.unauthorized' - ) - ); - - const canUserViewIntegrations = useSelector( - service, - (state) => state.context.datasetUserPrivileges.canViewIntegrations - ); - - return { - dataStreamStat, - dataStreamSettings, - dataStreamDetails, - isNonAggregatable, - integration, - fieldFormats, - timeRange: insightsTimeRange ?? timeRange, - breakdownField, - loadingState, - flyoutLoading: !dataStreamStat, - canUserAccessDashboards, - canUserViewIntegrations, - }; -}; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_table.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_table.tsx index b205a58dfb98f..77764acae1e1b 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_table.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_table.tsx @@ -14,7 +14,6 @@ import { DataStreamStat } from '../../common/data_streams_stats/data_stream_stat import { tableSummaryAllText, tableSummaryOfText } from '../../common/translations'; import { getDatasetQualityTableColumns } from '../components/dataset_quality/table/columns'; import { useDatasetQualityContext } from '../components/dataset_quality/context'; -import { FlyoutDataset } from '../state_machines/dataset_quality_controller'; import { useKibanaContextForPlugin } from '../utils'; import { filterInactiveDatasets, isActiveDataset } from '../utils/filter_inactive_datasets'; import { SortDirection } from '../../common/types'; @@ -30,7 +29,10 @@ const sortingOverrides: Partial<{ export const useDatasetQualityTable = () => { const { - services: { fieldFormats }, + services: { + fieldFormats, + share: { url }, + }, } = useKibanaContextForPlugin(); const { service } = useDatasetQualityContext(); @@ -46,8 +48,7 @@ export const useDatasetQualityTable = () => { service, (state) => !state.context.dataStreamStats || - !state.context.dataStreamStats.length || - state.context.dataStreamStats.some((s) => s.userPrivileges.canMonitor) + state.context.datasets.some((s) => s.userPrivileges?.canMonitor) ); const { @@ -61,20 +62,18 @@ export const useDatasetQualityTable = () => { } = useSelector(service, (state) => state.context.filters); const showInactiveDatasets = inactive || !canUserMonitorDataset; - const flyout = useSelector(service, (state) => state.context.flyout); - const loading = useSelector( service, (state) => - state.matches('datasets.fetching') || + state.matches('stats.datasets.fetching') || state.matches('integrations.fetching') || - state.matches('degradedDocs.fetching') + state.matches('stats.degradedDocs.fetching') ); const loadingDataStreamStats = useSelector(service, (state) => - state.matches('datasets.fetching') + state.matches('stats.datasets.fetching') ); const loadingDegradedStats = useSelector(service, (state) => - state.matches('degradedDocs.fetching') + state.matches('stats.degradedDocs.fetching') ); const datasets = useSelector(service, (state) => state.context.datasets); @@ -89,33 +88,6 @@ export const useDatasetQualityTable = () => { [service] ); - const closeFlyout = useCallback(() => service.send({ type: 'CLOSE_FLYOUT' }), [service]); - const openFlyout = useCallback( - (selectedDataset: FlyoutDataset) => { - if (flyout?.dataset?.rawName === selectedDataset.rawName) { - service.send({ - type: 'CLOSE_FLYOUT', - }); - - return; - } - - if (!flyout?.insightsTimeRange) { - service.send({ - type: 'OPEN_FLYOUT', - dataset: selectedDataset, - }); - return; - } - - service.send({ - type: 'SELECT_NEW_DATASET', - dataset: selectedDataset, - }); - }, - [flyout?.dataset?.rawName, flyout?.insightsTimeRange, service] - ); - const isActive = useCallback( (lastActivity: number) => isActiveDataset({ lastActivity, timeRange }), [timeRange] @@ -127,27 +99,25 @@ export const useDatasetQualityTable = () => { fieldFormats, canUserMonitorDataset, canUserMonitorAnyDataStream, - selectedDataset: flyout?.dataset, - openFlyout, loadingDataStreamStats, loadingDegradedStats, showFullDatasetNames, isSizeStatsAvailable, isActiveDataset: isActive, timeRange, + urlService: url, }), [ fieldFormats, canUserMonitorDataset, canUserMonitorAnyDataStream, - flyout?.dataset, - openFlyout, loadingDataStreamStats, loadingDegradedStats, showFullDatasetNames, isSizeStatsAvailable, isActive, timeRange, + url, ] ); @@ -235,8 +205,6 @@ export const useDatasetQualityTable = () => { columns, loading, resultsCount, - closeFlyout, - selectedDataset: flyout?.dataset, showInactiveDatasets, showFullDatasetNames, canUserMonitorDataset, diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_warnings.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_warnings.ts index ddb116dc48306..f5ba4d01f8983 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_warnings.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_quality_warnings.ts @@ -16,8 +16,11 @@ export function useDatasetQualityWarnings() { ); const isNonAggregatableDatasetsLoading = useSelector(service, (state) => - state.matches('nonAggregatableDatasets.fetching') + state.matches('stats.nonAggregatableDatasets.fetching') ); - return { loading: isNonAggregatableDatasetsLoading, nonAggregatableDatasets }; + return { + loading: isNonAggregatableDatasetsLoading, + nonAggregatableDatasets, + }; } diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_telemetry.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_telemetry.ts new file mode 100644 index 0000000000000..167ebd37fe81a --- /dev/null +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_dataset_telemetry.ts @@ -0,0 +1,119 @@ +/* + * 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 { useSelector } from '@xstate/react'; +import { useCallback } from 'react'; +import { getDateISORange } from '@kbn/timerange'; +import { useDatasetQualityContext } from '../components/dataset_quality/context'; +import { useDatasetQualityFilters } from './use_dataset_quality_filters'; +import { DataStreamStat } from '../../common/data_streams_stats'; +import { DatasetEbtProps, DatasetNavigatedEbtProps } from '../services/telemetry'; + +export function useDatasetTelemetry() { + const { service, telemetryClient } = useDatasetQualityContext(); + + // eslint-disable-next-line react-hooks/exhaustive-deps + const datasets = useSelector(service, (state) => state.context.datasets) ?? {}; + const nonAggregatableDatasets = useSelector( + service, + (state) => state.context.nonAggregatableDatasets + ); + const canUserViewIntegrations = useSelector( + service, + (state) => state.context.datasetUserPrivileges.canViewIntegrations + ); + const sort = useSelector(service, (state) => state.context.table.sort); + const appliedFilters = useDatasetQualityFilters(); + + const trackDatasetNavigated = useCallback<(rawName: string, isIgnoredFilter: boolean) => void>( + (rawName: string, isIgnoredFilter: boolean) => { + const foundDataset = datasets.find((dataset) => dataset.rawName === rawName); + if (foundDataset) { + const ebtProps = getDatasetEbtProps( + foundDataset, + sort, + appliedFilters, + nonAggregatableDatasets, + isIgnoredFilter, + canUserViewIntegrations + ); + telemetryClient.trackDatasetNavigated(ebtProps); + } else { + throw new Error( + `Cannot report dataset navigation telemetry for unknown dataset ${rawName}` + ); + } + }, + [ + sort, + appliedFilters, + canUserViewIntegrations, + datasets, + nonAggregatableDatasets, + telemetryClient, + ] + ); + + return { trackDatasetNavigated }; +} + +function getDatasetEbtProps( + dataset: DataStreamStat, + sort: { field: string; direction: 'asc' | 'desc' }, + filters: ReturnType, + nonAggregatableDatasets: string[], + isIgnoredFilter: boolean, + canUserViewIntegrations: boolean +): DatasetNavigatedEbtProps { + const { startDate: from, endDate: to } = getDateISORange(filters.timeRange); + const datasetEbtProps: DatasetEbtProps = { + index_name: dataset.rawName, + data_stream: { + dataset: dataset.name, + namespace: dataset.namespace, + type: dataset.type, + }, + data_stream_health: dataset.degradedDocs.quality, + data_stream_aggregatable: nonAggregatableDatasets.some( + (indexName) => indexName === dataset.rawName + ), + from, + to, + degraded_percentage: dataset.degradedDocs.percentage, + integration: dataset.integration?.name, + privileges: { + can_monitor_data_stream: dataset.userPrivileges?.canMonitor ?? true, + can_view_integrations: canUserViewIntegrations, + }, + }; + + const ebtFilters: DatasetNavigatedEbtProps['filters'] = { + is_degraded: isIgnoredFilter, + query_length: filters.selectedQuery?.length ?? 0, + integrations: { + total: filters.integrations.filter((item) => item.name !== 'none').length, + included: filters.integrations.filter((item) => item?.checked === 'on').length, + excluded: filters.integrations.filter((item) => item?.checked === 'off').length, + }, + namespaces: { + total: filters.namespaces.length, + included: filters.namespaces.filter((item) => item?.checked === 'on').length, + excluded: filters.namespaces.filter((item) => item?.checked === 'off').length, + }, + qualities: { + total: filters.qualities.length, + included: filters.qualities.filter((item) => item?.checked === 'on').length, + excluded: filters.qualities.filter((item) => item?.checked === 'off').length, + }, + }; + + return { + ...datasetEbtProps, + sort, + filters: ebtFilters, + }; +} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.ts similarity index 80% rename from x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs.ts rename to x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.ts index 7842fe81966f3..795700bfc9441 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { useCallback, useState, useMemo, useEffect } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import type { Action } from '@kbn/ui-actions-plugin/public'; import { fieldSupportsBreakdown } from '@kbn/unified-histogram-plugin/public'; import { i18n } from '@kbn/i18n'; @@ -16,7 +16,9 @@ import { useCreateDataView } from './use_create_dataview'; import { useKibanaContextForPlugin } from '../utils'; import { useDatasetQualityDetailsState } from './use_dataset_quality_details_state'; import { getLensAttributes } from '../components/dataset_quality_details/overview/document_trends/degraded_docs/lens_attributes'; -import { useDatasetQualityDetailsRedirectLink } from './use_dataset_quality_details_redirect_link'; +import { useRedirectLink } from './use_redirect_link'; +import { useDatasetDetailsTelemetry } from './use_dataset_details_telemetry'; +import { useDatasetDetailsRedirectLinkTelemetry } from './use_redirect_link_telemetry'; const exploreDataInLogsExplorerText = i18n.translate( 'xpack.datasetQuality.details.chartExploreDataInLogsExplorerText', @@ -39,13 +41,27 @@ const openInLensText = i18n.translate('xpack.datasetQuality.details.chartOpenInL const ACTION_EXPLORE_IN_LOGS_EXPLORER = 'ACTION_EXPLORE_IN_LOGS_EXPLORER'; const ACTION_OPEN_IN_LENS = 'ACTION_OPEN_IN_LENS'; -export const useDegradedDocs = () => { +export const useDegradedDocsChart = () => { const { euiTheme } = useEuiTheme(); const { services: { lens }, } = useKibanaContextForPlugin(); - const { service, dataStream, datasetDetails, timeRange, breakdownField, integrationDetails } = - useDatasetQualityDetailsState(); + const { + service, + dataStream, + datasetDetails, + timeRange, + breakdownField, + integrationDetails, + isBreakdownFieldAsserted, + } = useDatasetQualityDetailsState(); + + const { + trackDatasetDetailsBreakdownFieldChanged, + trackDetailsNavigated, + navigationTargets, + navigationSources, + } = useDatasetDetailsTelemetry(); const [isChartLoading, setIsChartLoading] = useState(undefined); const [attributes, setAttributes] = useState | undefined>( @@ -75,6 +91,10 @@ export const useDegradedDocs = () => { [service] ); + useEffect(() => { + if (isBreakdownFieldAsserted) trackDatasetDetailsBreakdownFieldChanged(); + }, [trackDatasetDetailsBreakdownFieldChanged, isBreakdownFieldAsserted]); + useEffect(() => { const dataStreamName = dataStream ?? DEFAULT_LOGS_DATA_VIEW; const datasetTitle = @@ -98,13 +118,21 @@ export const useDegradedDocs = () => { const openInLensCallback = useCallback(() => { if (attributes) { + trackDetailsNavigated(navigationTargets.Lens, navigationSources.Chart); lens.navigateToPrefilledEditor({ id: '', timeRange, attributes, }); } - }, [attributes, lens, timeRange]); + }, [ + attributes, + lens, + navigationSources.Chart, + navigationTargets.Lens, + timeRange, + trackDetailsNavigated, + ]); const getOpenInLensAction = useMemo(() => { return { @@ -126,11 +154,17 @@ export const useDegradedDocs = () => { }; }, [openInLensCallback]); - const redirectLinkProps = useDatasetQualityDetailsRedirectLink({ + const { sendTelemetry } = useDatasetDetailsRedirectLinkTelemetry({ + query: { language: 'kuery', query: '_ignored:*' }, + navigationSource: navigationSources.Chart, + }); + + const redirectLinkProps = useRedirectLink({ dataStreamStat: datasetDetails, query: { language: 'kuery', query: '_ignored:*' }, timeRangeConfig: timeRange, breakdownField: breakdownDataViewField?.name, + sendTelemetry, }); const getOpenInLogsExplorerAction = useMemo(() => { diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.tsx deleted file mode 100644 index 6840f2a4088a9..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.tsx +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useCallback, useState, useMemo, useEffect } from 'react'; -import { Action } from '@kbn/ui-actions-plugin/public'; -import { fieldSupportsBreakdown } from '@kbn/unified-histogram-plugin/public'; -import { useSelector } from '@xstate/react'; -import { i18n } from '@kbn/i18n'; -import { useEuiTheme } from '@elastic/eui'; -import { type DataView, DataViewField } from '@kbn/data-views-plugin/common'; -import { useDatasetQualityContext } from '../components/dataset_quality/context'; -import { DEFAULT_LOGS_DATA_VIEW } from '../../common/constants'; -import { useCreateDataView } from './use_create_dataview'; -import { useRedirectLink } from './use_redirect_link'; -import { useDatasetQualityFlyout } from './use_dataset_quality_flyout'; -import { useKibanaContextForPlugin } from '../utils'; -import { useDatasetDetailsTelemetry } from './use_telemetry'; -import { getLensAttributes } from '../components/dataset_quality_details/overview/document_trends/degraded_docs/lens_attributes'; - -const exploreDataInLogsExplorerText = i18n.translate( - 'xpack.datasetQuality.flyoutChartExploreDataInLogsExplorerText', - { - defaultMessage: 'Explore data in Logs Explorer', - } -); - -const exploreDataInDiscoverText = i18n.translate( - 'xpack.datasetQuality.flyoutChartExploreDataInDiscoverText', - { - defaultMessage: 'Explore data in Discover', - } -); - -const openInLensText = i18n.translate('xpack.datasetQuality.flyoutChartOpenInLensText', { - defaultMessage: 'Open in Lens', -}); - -const ACTION_EXPLORE_IN_LOGS_EXPLORER = 'ACTION_EXPLORE_IN_LOGS_EXPLORER'; -const ACTION_OPEN_IN_LENS = 'ACTION_OPEN_IN_LENS'; - -interface DegradedDocsChartDeps { - dataStream?: string; - breakdownField?: string; -} - -export const useDegradedDocsChart = ({ dataStream }: DegradedDocsChartDeps) => { - const { euiTheme } = useEuiTheme(); - const { - services: { lens }, - } = useKibanaContextForPlugin(); - const { service } = useDatasetQualityContext(); - - const { - trackDatasetDetailsBreakdownFieldChanged, - trackDetailsNavigated, - navigationTargets, - navigationSources, - } = useDatasetDetailsTelemetry(); - - const { dataStreamStat, timeRange, breakdownField } = useDatasetQualityFlyout(); - - const isBreakdownFieldEcs = useSelector( - service, - (state) => state.context.flyout.isBreakdownFieldEcs - ); - - const isBreakdownFieldEcsAsserted = useSelector(service, (state) => { - return ( - state.matches('flyout.initializing.assertBreakdownFieldIsEcs.done') && - state.history?.matches('flyout.initializing.assertBreakdownFieldIsEcs.fetching') && - isBreakdownFieldEcs !== null - ); - }); - - const [isChartLoading, setIsChartLoading] = useState(undefined); - const [attributes, setAttributes] = useState | undefined>( - undefined - ); - - const { dataView } = useCreateDataView({ - indexPatternString: getDataViewIndexPattern(dataStream), - }); - - const breakdownDataViewField = useMemo( - () => getDataViewField(dataView, breakdownField), - [breakdownField, dataView] - ); - - const handleChartLoading = (isLoading: boolean) => { - setIsChartLoading(isLoading); - }; - - const handleBreakdownFieldChange = useCallback( - (field: DataViewField | undefined) => { - service.send({ - type: 'BREAKDOWN_FIELD_CHANGE', - breakdownField: field?.name ?? null, - }); - }, - [service] - ); - - useEffect(() => { - if (isBreakdownFieldEcsAsserted) trackDatasetDetailsBreakdownFieldChanged(); - }, [trackDatasetDetailsBreakdownFieldChanged, isBreakdownFieldEcsAsserted]); - - useEffect(() => { - const dataStreamName = dataStream ?? DEFAULT_LOGS_DATA_VIEW; - - const lensAttributes = getLensAttributes({ - color: euiTheme.colors.danger, - dataStream: dataStreamName, - datasetTitle: dataStreamStat?.title ?? dataStreamName, - breakdownFieldName: breakdownDataViewField?.name, - }); - setAttributes(lensAttributes); - }, [ - breakdownDataViewField?.name, - euiTheme.colors.danger, - setAttributes, - dataStream, - dataStreamStat?.title, - ]); - - const openInLensCallback = useCallback(() => { - if (attributes) { - trackDetailsNavigated(navigationTargets.Lens, navigationSources.Chart); - lens.navigateToPrefilledEditor({ - id: '', - timeRange, - attributes, - }); - } - }, [attributes, trackDetailsNavigated, navigationTargets, navigationSources, lens, timeRange]); - - const getOpenInLensAction = useMemo(() => { - return { - id: ACTION_OPEN_IN_LENS, - type: 'link', - order: 17, - getDisplayName(): string { - return openInLensText; - }, - getIconType(): string { - return 'visArea'; - }, - async isCompatible(): Promise { - return true; - }, - async execute(): Promise { - return openInLensCallback(); - }, - }; - }, [openInLensCallback]); - - const redirectLinkProps = useRedirectLink({ - dataStreamStat: dataStreamStat!, - query: { language: 'kuery', query: '_ignored:*' }, - timeRangeConfig: timeRange, - breakdownField: breakdownDataViewField?.name, - telemetry: { - page: 'details', - navigationSource: navigationSources.Chart, - }, - }); - - const getOpenInLogsExplorerAction = useMemo(() => { - return { - id: ACTION_EXPLORE_IN_LOGS_EXPLORER, - type: 'link', - getDisplayName(): string { - return redirectLinkProps?.isLogsExplorerAvailable - ? exploreDataInLogsExplorerText - : exploreDataInDiscoverText; - }, - getHref: async () => { - return redirectLinkProps.linkProps.href; - }, - getIconType(): string | undefined { - return 'visTable'; - }, - async isCompatible(): Promise { - return true; - }, - async execute(): Promise { - return redirectLinkProps.navigate(); - }, - order: 18, - }; - }, [redirectLinkProps]); - - const extraActions: Action[] = [getOpenInLensAction, getOpenInLogsExplorerAction]; - - return { - attributes, - dataView, - breakdown: { - dataViewField: breakdownDataViewField, - fieldSupportsBreakdown: breakdownDataViewField - ? fieldSupportsBreakdown(breakdownDataViewField) - : true, - onChange: handleBreakdownFieldChange, - }, - extraActions, - isChartLoading, - onChartLoading: handleChartLoading, - setAttributes, - setIsChartLoading, - }; -}; - -function getDataViewIndexPattern(dataStream: string | undefined) { - return dataStream ?? DEFAULT_LOGS_DATA_VIEW; -} - -function getDataViewField(dataView: DataView | undefined, fieldName: string | undefined) { - return fieldName && dataView - ? dataView.fields.find((field) => field.name === fieldName) - : undefined; -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_empty_state.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_empty_state.ts index a7de315a35895..f60a7914275be 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_empty_state.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_empty_state.ts @@ -18,9 +18,9 @@ export function useEmptyState() { const isDatasetEmpty = useSelector( service, (state) => - !state.matches('datasets.fetching') && + !state.matches('stats.datasets.fetching') && !state.matches('integrations.fetching') && - !state.matches('degradedDocs.fetching') && + !state.matches('stats.degradedDocs.fetching') && (state.context.datasets?.length ?? 0) === 0 ); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_flyout_integration_actions.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_flyout_integration_actions.tsx deleted file mode 100644 index b0f47716100b4..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_flyout_integration_actions.tsx +++ /dev/null @@ -1,104 +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 { getRouterLinkProps } from '@kbn/router-utils'; -import { useMemo, useCallback } from 'react'; -import useToggle from 'react-use/lib/useToggle'; -import { MANAGEMENT_APP_LOCATOR } from '@kbn/deeplinks-management/constants'; -import { DASHBOARD_APP_LOCATOR } from '@kbn/deeplinks-analytics'; -import { useKibanaContextForPlugin } from '../utils'; -import { Dashboard } from '../../common/api_types'; -import { useDatasetDetailsTelemetry } from './use_telemetry'; - -export const useFlyoutIntegrationActions = () => { - const { - services: { - application: { navigateToUrl }, - http: { basePath }, - share, - }, - } = useKibanaContextForPlugin(); - const { wrapLinkPropsForTelemetry, navigationSources, navigationTargets } = - useDatasetDetailsTelemetry(); - - const [isOpen, toggleIsOpen] = useToggle(false); - - const dashboardLocator = useMemo( - () => share.url.locators.get(DASHBOARD_APP_LOCATOR), - [share.url.locators] - ); - const indexManagementLocator = useMemo( - () => share.url.locators.get(MANAGEMENT_APP_LOCATOR), - [share.url.locators] - ); - - const handleCloseMenu = useCallback(() => { - toggleIsOpen(); - }, [toggleIsOpen]); - const handleToggleMenu = useCallback(() => { - toggleIsOpen(); - }, [toggleIsOpen]); - - const getIntegrationOverviewLinkProps = useCallback( - (name: string, version: string) => { - const href = basePath.prepend(`/app/integrations/detail/${name}-${version}/overview`); - return wrapLinkPropsForTelemetry( - getRouterLinkProps({ - href, - onClick: () => { - return navigateToUrl(href); - }, - }), - navigationTargets.Integration, - navigationSources.ActionMenu - ); - }, - [basePath, navigateToUrl, navigationSources, navigationTargets, wrapLinkPropsForTelemetry] - ); - const getIndexManagementLinkProps = useCallback( - (params: { sectionId: string; appId: string }) => - wrapLinkPropsForTelemetry( - getRouterLinkProps({ - href: indexManagementLocator?.getRedirectUrl(params), - onClick: () => { - return indexManagementLocator?.navigate(params); - }, - }), - navigationTargets.IndexTemplate, - navigationSources.ActionMenu - ), - [ - indexManagementLocator, - navigationSources.ActionMenu, - navigationTargets.IndexTemplate, - wrapLinkPropsForTelemetry, - ] - ); - const getDashboardLinkProps = useCallback( - (dashboard: Dashboard) => - wrapLinkPropsForTelemetry( - getRouterLinkProps({ - href: dashboardLocator?.getRedirectUrl({ dashboardId: dashboard?.id } || ''), - onClick: () => { - return dashboardLocator?.navigate({ dashboardId: dashboard?.id } || ''); - }, - }), - navigationTargets.Dashboard, - navigationSources.ActionMenu - ), - [dashboardLocator, navigationSources, navigationTargets, wrapLinkPropsForTelemetry] - ); - - return { - isOpen, - handleCloseMenu, - handleToggleMenu, - getIntegrationOverviewLinkProps, - getIndexManagementLinkProps, - getDashboardLinkProps, - }; -}; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_integration_actions.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_integration_actions.ts index 0fce743875a60..165ac2a651809 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_integration_actions.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_integration_actions.ts @@ -12,6 +12,7 @@ import { MANAGEMENT_APP_LOCATOR } from '@kbn/deeplinks-management/constants'; import { DASHBOARD_APP_LOCATOR } from '@kbn/deeplinks-analytics'; import { useKibanaContextForPlugin } from '../utils'; import { Dashboard } from '../../common/api_types'; +import { useDatasetDetailsTelemetry } from './use_dataset_details_telemetry'; export const useIntegrationActions = () => { const { @@ -21,6 +22,8 @@ export const useIntegrationActions = () => { share, }, } = useKibanaContextForPlugin(); + const { wrapLinkPropsForTelemetry, navigationSources, navigationTargets } = + useDatasetDetailsTelemetry(); const [isOpen, toggleIsOpen] = useToggle(false); @@ -43,34 +46,51 @@ export const useIntegrationActions = () => { const getIntegrationOverviewLinkProps = useCallback( (name: string, version: string) => { const href = basePath.prepend(`/app/integrations/detail/${name}-${version}/overview`); - return getRouterLinkProps({ - href, - onClick: () => { - return navigateToUrl(href); - }, - }); + return wrapLinkPropsForTelemetry( + getRouterLinkProps({ + href, + onClick: () => { + return navigateToUrl(href); + }, + }), + navigationTargets.Integration, + navigationSources.ActionMenu + ); }, - [basePath, navigateToUrl] + [basePath, navigateToUrl, navigationSources, navigationTargets, wrapLinkPropsForTelemetry] ); const getIndexManagementLinkProps = useCallback( (params: { sectionId: string; appId: string }) => - getRouterLinkProps({ - href: indexManagementLocator?.getRedirectUrl(params), - onClick: () => { - return indexManagementLocator?.navigate(params); - }, - }), - [indexManagementLocator] + wrapLinkPropsForTelemetry( + getRouterLinkProps({ + href: indexManagementLocator?.getRedirectUrl(params), + onClick: () => { + return indexManagementLocator?.navigate(params); + }, + }), + navigationTargets.IndexTemplate, + navigationSources.ActionMenu + ), + [ + indexManagementLocator, + navigationSources.ActionMenu, + navigationTargets.IndexTemplate, + wrapLinkPropsForTelemetry, + ] ); const getDashboardLinkProps = useCallback( (dashboard: Dashboard) => - getRouterLinkProps({ - href: dashboardLocator?.getRedirectUrl({ dashboardId: dashboard?.id } || ''), - onClick: () => { - return dashboardLocator?.navigate({ dashboardId: dashboard?.id } || ''); - }, - }), - [dashboardLocator] + wrapLinkPropsForTelemetry( + getRouterLinkProps({ + href: dashboardLocator?.getRedirectUrl({ dashboardId: dashboard?.id } || ''), + onClick: () => { + return dashboardLocator?.navigate({ dashboardId: dashboard?.id } || ''); + }, + }), + navigationTargets.Dashboard, + navigationSources.ActionMenu + ), + [dashboardLocator, navigationSources, navigationTargets, wrapLinkPropsForTelemetry] ); return { diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link.ts index e4fbf0771ee1f..b015d2335d625 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link.ts @@ -18,20 +18,20 @@ import { LocatorPublic } from '@kbn/share-plugin/common'; import { LocatorClient } from '@kbn/shared-ux-prompt-no-data-views-types'; import { useKibanaContextForPlugin } from '../utils'; import { BasicDataStream, TimeRangeConfig } from '../../common/types'; -import { useRedirectLinkTelemetry } from './use_telemetry'; +import { SendTelemetryFn } from './use_redirect_link_telemetry'; export const useRedirectLink = ({ dataStreamStat, query, timeRangeConfig, breakdownField, - telemetry, + sendTelemetry, }: { dataStreamStat: T; query?: Query | AggregateQuery; timeRangeConfig: TimeRangeConfig; breakdownField?: string; - telemetry?: Parameters[0]['telemetry']; + sendTelemetry: SendTelemetryFn; }) => { const { services: { share }, @@ -42,19 +42,13 @@ export const useRedirectLink = ({ const logsExplorerLocator = share.url.locators.get(SINGLE_DATASET_LOCATOR_ID); - const { sendTelemetry } = useRedirectLinkTelemetry({ - rawName: dataStreamStat.rawName, - isLogsExplorer: !!logsExplorerLocator, - telemetry, - query, - }); - return useMemo<{ linkProps: RouterLinkProps; navigate: () => void; isLogsExplorerAvailable: boolean; }>(() => { - const config = logsExplorerLocator + const isLogsExplorerAvailable = !!logsExplorerLocator && dataStreamStat.type === 'logs'; + const config = isLogsExplorerAvailable ? buildLogsExplorerConfig({ locator: logsExplorerLocator, dataStreamStat, @@ -90,7 +84,7 @@ export const useRedirectLink = ({ onClick: onClickWithTelemetry, }, navigate: navigateWithTelemetry, - isLogsExplorerAvailable: !!logsExplorerLocator, + isLogsExplorerAvailable, }; }, [ breakdownField, @@ -188,7 +182,7 @@ const buildDiscoverConfig = ({ dataViewId, dataViewSpec: { id: dataViewId, - title: dataViewTitle, + title: dataViewId, }, query, breakdownField, diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link_telemetry.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link_telemetry.ts new file mode 100644 index 0000000000000..a70de0bd20295 --- /dev/null +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link_telemetry.ts @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useCallback } from 'react'; +import { AggregateQuery, Query } from '@kbn/es-query'; +import { + SINGLE_DATASET_LOCATOR_ID, + SingleDatasetLocatorParams, +} from '@kbn/deeplinks-observability'; +import { NavigationSource } from '../services/telemetry'; +import { useDatasetTelemetry } from './use_dataset_telemetry'; +import { useDatasetDetailsTelemetry } from './use_dataset_details_telemetry'; +import { useKibanaContextForPlugin } from '../utils'; + +export type SendTelemetryFn = + | ReturnType['sendTelemetry'] + | ReturnType['sendTelemetry']; + +export const useDatasetRedirectLinkTelemetry = ({ + rawName, + query, +}: { + rawName: string; + query?: Query | AggregateQuery; +}) => { + const { trackDatasetNavigated } = useDatasetTelemetry(); + + const sendTelemetry = useCallback(() => { + const isIgnoredFilter = query ? JSON.stringify(query).includes('_ignored') : false; + + trackDatasetNavigated(rawName, isIgnoredFilter); + }, [query, rawName, trackDatasetNavigated]); + + return { + sendTelemetry, + }; +}; + +export const useDatasetDetailsRedirectLinkTelemetry = ({ + query, + navigationSource, +}: { + navigationSource: NavigationSource; + query?: Query | AggregateQuery; +}) => { + const { + services: { share }, + } = useKibanaContextForPlugin(); + const logsExplorerLocator = + share.url.locators.get(SINGLE_DATASET_LOCATOR_ID); + const isLogsExplorer = !!logsExplorerLocator; + const { trackDetailsNavigated, navigationTargets } = useDatasetDetailsTelemetry(); + + const sendTelemetry = useCallback(() => { + const isIgnoredFilter = query ? JSON.stringify(query).includes('_ignored') : false; + const target = isLogsExplorer ? navigationTargets.LogsExplorer : navigationTargets.Discover; + + trackDetailsNavigated(target, navigationSource, isIgnoredFilter); + }, [ + query, + isLogsExplorer, + navigationTargets.LogsExplorer, + navigationTargets.Discover, + trackDetailsNavigated, + navigationSource, + ]); + + return { + sendTelemetry, + }; +}; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_summary_panel.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_summary_panel.ts similarity index 86% rename from x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_summary_panel.tsx rename to x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_summary_panel.ts index 622f495fc4774..ce8acd58b7507 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_summary_panel.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_summary_panel.ts @@ -19,6 +19,7 @@ const useSummaryPanel = () => { isSizeStatsAvailable, canUserMonitorDataset, canUserMonitorAnyDataStream, + loading, } = useDatasetQualityTable(); const { timeRange } = useSelector(service, (state) => state.context.filters); @@ -32,7 +33,7 @@ const useSummaryPanel = () => { }; const isDatasetsQualityLoading = useSelector(service, (state) => - state.matches('degradedDocs.fetching') + state.matches('stats.degradedDocs.fetching') ); /* @@ -42,8 +43,9 @@ const useSummaryPanel = () => { (item) => item.userPrivileges?.canMonitor ?? true ); - const isUserAuthorizedForDataset = - canUserMonitorDataset && canUserMonitorAnyDataStream && canUserMonitorAllFilteredDataStreams; + const isUserAuthorizedForDataset = !loading + ? canUserMonitorDataset && canUserMonitorAnyDataStream && canUserMonitorAllFilteredDataStreams + : true; /* Datasets Activity @@ -57,7 +59,7 @@ const useSummaryPanel = () => { }; const isDatasetsActivityLoading = useSelector(service, (state) => - state.matches('datasets.fetching') + state.matches('stats.datasets.fetching') ); /* @@ -70,7 +72,8 @@ const useSummaryPanel = () => { const isEstimatedDataLoading = useSelector( service, - (state) => state.matches('datasets.fetching') || state.matches('degradedDocs.fetching') + (state) => + state.matches('stats.datasets.fetching') || state.matches('stats.degradedDocs.fetching') ); return { diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_telemetry.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_telemetry.tsx deleted file mode 100644 index c473495c0a661..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_telemetry.tsx +++ /dev/null @@ -1,382 +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 { RouterLinkProps } from '@kbn/router-utils/src/get_router_link_props'; -import { useCallback, useEffect, useMemo } from 'react'; -import { useSelector } from '@xstate/react'; -import { getDateISORange } from '@kbn/timerange'; -import { AggregateQuery, Query } from '@kbn/es-query'; - -import { MASKED_FIELD_PLACEHOLDER, UNKOWN_FIELD_PLACEHOLDER } from '../../common/constants'; -import { DataStreamStat } from '../../common/data_streams_stats'; -import { DataStreamDetails } from '../../common/api_types'; -import { mapPercentageToQuality } from '../../common/utils'; -import { - NavigationTarget, - NavigationSource, - DatasetDetailsEbtProps, - DatasetNavigatedEbtProps, - DatasetEbtProps, -} from '../services/telemetry'; -import { FlyoutDataset } from '../state_machines/dataset_quality_controller'; -import { useDatasetQualityContext } from '../components/dataset_quality/context'; -import { useDatasetQualityFilters } from './use_dataset_quality_filters'; -import { TimeRangeConfig } from '../../common/types'; - -export const useRedirectLinkTelemetry = ({ - rawName, - isLogsExplorer, - telemetry, - query, -}: { - rawName: string; - isLogsExplorer: boolean; - telemetry?: { - page: 'main' | 'details'; - navigationSource: NavigationSource; - }; - query?: Query | AggregateQuery; -}) => { - const { trackDatasetNavigated } = useDatasetTelemetry(); - const { trackDetailsNavigated, navigationTargets } = useDatasetDetailsTelemetry(); - - const sendTelemetry = useCallback(() => { - if (telemetry) { - const isIgnoredFilter = query ? JSON.stringify(query).includes('_ignored') : false; - if (telemetry.page === 'main') { - trackDatasetNavigated(rawName, isIgnoredFilter); - } else { - trackDetailsNavigated( - isLogsExplorer ? navigationTargets.LogsExplorer : navigationTargets.Discover, - telemetry.navigationSource, - isIgnoredFilter - ); - } - } - }, [ - isLogsExplorer, - trackDetailsNavigated, - navigationTargets, - query, - rawName, - telemetry, - trackDatasetNavigated, - ]); - - const wrapLinkPropsForTelemetry = useCallback( - (props: RouterLinkProps) => { - return { - ...props, - onClick: (event: Parameters[0]) => { - sendTelemetry(); - if (props.onClick) { - props.onClick(event); - } - }, - }; - }, - [sendTelemetry] - ); - - return { - wrapLinkPropsForTelemetry, - sendTelemetry, - }; -}; - -export const useDatasetTelemetry = () => { - const { service, telemetryClient } = useDatasetQualityContext(); - - // eslint-disable-next-line react-hooks/exhaustive-deps - const datasets = useSelector(service, (state) => state.context.datasets) ?? {}; - const nonAggregatableDatasets = useSelector( - service, - (state) => state.context.nonAggregatableDatasets - ); - const canUserViewIntegrations = useSelector( - service, - (state) => state.context.datasetUserPrivileges.canViewIntegrations - ); - const sort = useSelector(service, (state) => state.context.table.sort); - const appliedFilters = useDatasetQualityFilters(); - - const trackDatasetNavigated = useCallback<(rawName: string, isIgnoredFilter: boolean) => void>( - (rawName: string, isIgnoredFilter: boolean) => { - const foundDataset = datasets.find((dataset) => dataset.rawName === rawName); - if (foundDataset) { - const ebtProps = getDatasetEbtProps( - foundDataset, - sort, - appliedFilters, - nonAggregatableDatasets, - isIgnoredFilter, - canUserViewIntegrations - ); - telemetryClient.trackDatasetNavigated(ebtProps); - } else { - throw new Error( - `Cannot report dataset navigation telemetry for unknown dataset ${rawName}` - ); - } - }, - [ - sort, - appliedFilters, - canUserViewIntegrations, - datasets, - nonAggregatableDatasets, - telemetryClient, - ] - ); - - return { trackDatasetNavigated }; -}; - -export const useDatasetDetailsTelemetry = () => { - const { service, telemetryClient } = useDatasetQualityContext(); - - const { - dataset: dataStreamStat, - datasetDetails: dataStreamDetails, - insightsTimeRange, - breakdownField, - isNonAggregatable, - isBreakdownFieldEcs, - } = useSelector(service, (state) => state.context.flyout) ?? {}; - - const loadingState = useSelector(service, (state) => ({ - dataStreamDetailsLoading: - state.matches('flyout.initializing.dataStreamDetails.fetching') || - state.matches('flyout.initializing.assertBreakdownFieldIsEcs.fetching'), - })); - - const canUserAccessDashboards = useSelector( - service, - (state) => !state.matches('flyout.initializing.integrationDashboards.unauthorized') - ); - - const canUserViewIntegrations = useSelector( - service, - (state) => state.context.datasetUserPrivileges.canViewIntegrations - ); - - const ebtProps = useMemo(() => { - if ( - dataStreamDetails && - insightsTimeRange && - dataStreamStat && - !loadingState.dataStreamDetailsLoading - ) { - return getDatasetDetailsEbtProps( - insightsTimeRange, - dataStreamStat, - dataStreamDetails, - isNonAggregatable ?? false, - canUserViewIntegrations, - canUserAccessDashboards, - isBreakdownFieldEcs, - breakdownField - ); - } - - return undefined; - }, [ - insightsTimeRange, - dataStreamStat, - dataStreamDetails, - loadingState.dataStreamDetailsLoading, - isNonAggregatable, - canUserViewIntegrations, - canUserAccessDashboards, - isBreakdownFieldEcs, - breakdownField, - ]); - - const startTracking = useCallback(() => { - telemetryClient.startDatasetDetailsTracking(); - }, [telemetryClient]); - - // Report opening dataset details - useEffect(() => { - const datasetDetailsTrackingState = telemetryClient.getDatasetDetailsTrackingState(); - if (datasetDetailsTrackingState === 'started' && ebtProps) { - telemetryClient.trackDatasetDetailsOpened(ebtProps); - } - }, [ebtProps, telemetryClient]); - - const trackDetailsNavigated = useCallback( - (target: NavigationTarget, source: NavigationSource, isDegraded = false) => { - const datasetDetailsTrackingState = telemetryClient.getDatasetDetailsTrackingState(); - if ( - (datasetDetailsTrackingState === 'opened' || datasetDetailsTrackingState === 'navigated') && - ebtProps - ) { - telemetryClient.trackDatasetDetailsNavigated({ - ...ebtProps, - filters: { - is_degraded: isDegraded, - }, - target, - source, - }); - } else { - throw new Error( - 'Cannot report dataset details navigation telemetry without required data and state' - ); - } - }, - [ebtProps, telemetryClient] - ); - - const trackDatasetDetailsBreakdownFieldChanged = useCallback(() => { - const datasetDetailsTrackingState = telemetryClient.getDatasetDetailsTrackingState(); - if ( - (datasetDetailsTrackingState === 'opened' || datasetDetailsTrackingState === 'navigated') && - ebtProps - ) { - telemetryClient.trackDatasetDetailsBreakdownFieldChanged({ - ...ebtProps, - breakdown_field: ebtProps.breakdown_field, - }); - } - }, [ebtProps, telemetryClient]); - - const wrapLinkPropsForTelemetry = useCallback( - ( - props: RouterLinkProps, - target: NavigationTarget, - source: NavigationSource, - isDegraded = false - ) => { - return { - ...props, - onClick: (event: Parameters[0]) => { - trackDetailsNavigated(target, source, isDegraded); - if (props.onClick) { - props.onClick(event); - } - }, - }; - }, - [trackDetailsNavigated] - ); - - return { - startTracking, - trackDetailsNavigated, - wrapLinkPropsForTelemetry, - navigationTargets: NavigationTarget, - navigationSources: NavigationSource, - trackDatasetDetailsBreakdownFieldChanged, - }; -}; - -function getDatasetEbtProps( - dataset: DataStreamStat, - sort: { field: string; direction: 'asc' | 'desc' }, - filters: ReturnType, - nonAggregatableDatasets: string[], - isIgnoredFilter: boolean, - canUserViewIntegrations: boolean -): DatasetNavigatedEbtProps { - const { startDate: from, endDate: to } = getDateISORange(filters.timeRange); - const datasetEbtProps: DatasetEbtProps = { - index_name: dataset.rawName, - data_stream: { - dataset: dataset.name, - namespace: dataset.namespace, - type: dataset.type, - }, - data_stream_health: dataset.degradedDocs.quality, - data_stream_aggregatable: nonAggregatableDatasets.some( - (indexName) => indexName === dataset.rawName - ), - from, - to, - degraded_percentage: dataset.degradedDocs.percentage, - integration: dataset.integration?.name, - privileges: { - can_monitor_data_stream: dataset.userPrivileges?.canMonitor ?? true, - can_view_integrations: canUserViewIntegrations, - }, - }; - - const ebtFilters: DatasetNavigatedEbtProps['filters'] = { - is_degraded: isIgnoredFilter, - query_length: filters.selectedQuery?.length ?? 0, - integrations: { - total: filters.integrations.filter((item) => item.name !== 'none').length, - included: filters.integrations.filter((item) => item?.checked === 'on').length, - excluded: filters.integrations.filter((item) => item?.checked === 'off').length, - }, - namespaces: { - total: filters.namespaces.length, - included: filters.namespaces.filter((item) => item?.checked === 'on').length, - excluded: filters.namespaces.filter((item) => item?.checked === 'off').length, - }, - qualities: { - total: filters.qualities.length, - included: filters.qualities.filter((item) => item?.checked === 'on').length, - excluded: filters.qualities.filter((item) => item?.checked === 'off').length, - }, - }; - - return { - ...datasetEbtProps, - sort, - filters: ebtFilters, - }; -} - -function getDatasetDetailsEbtProps( - insightsTimeRange: TimeRangeConfig, - flyoutDataset: FlyoutDataset, - details: DataStreamDetails, - isNonAggregatable: boolean, - canUserViewIntegrations: boolean, - canUserAccessDashboards: boolean, - isBreakdownFieldEcs: boolean | null, - breakdownField?: string -): DatasetDetailsEbtProps { - const indexName = flyoutDataset.rawName; - const dataStream = { - dataset: flyoutDataset.name, - namespace: flyoutDataset.namespace, - type: flyoutDataset.type, - }; - const degradedDocs = details?.degradedDocsCount ?? 0; - const totalDocs = details?.docsCount ?? 0; - const degradedPercentage = - totalDocs > 0 ? Number(((degradedDocs / totalDocs) * 100).toFixed(2)) : 0; - const health = mapPercentageToQuality(degradedPercentage); - const { startDate: from, endDate: to } = getDateISORange(insightsTimeRange); - - return { - index_name: indexName, - data_stream: dataStream, - privileges: { - can_monitor_data_stream: true, - can_view_integrations: canUserViewIntegrations, - can_view_dashboards: canUserAccessDashboards, - }, - data_stream_aggregatable: !isNonAggregatable, - data_stream_health: health, - from, - to, - degraded_percentage: degradedPercentage, - integration: flyoutDataset.integration?.name, - breakdown_field: breakdownField - ? isBreakdownFieldEcs === null - ? UNKOWN_FIELD_PLACEHOLDER - : getMaskedBreakdownField(breakdownField, isBreakdownFieldEcs) - : breakdownField, - }; -} - -function getMaskedBreakdownField(breakdownField: string, isBreakdownFieldEcs: boolean) { - return isBreakdownFieldEcs ? breakdownField : MASKED_FIELD_PLACEHOLDER; -} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/plugin.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/plugin.tsx index 6cb4c12975412..84dbabe1d2540 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/plugin.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/plugin.tsx @@ -52,9 +52,7 @@ export class DatasetQualityPlugin const createDatasetQualityController = createDatasetQualityControllerLazyFactory({ core, - plugins, dataStreamStatsClient, - dataStreamDetailsClient, }); const DatasetQualityDetails = createDatasetQualityDetails({ diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/services/data_stream_details/data_stream_details_client.ts b/x-pack/plugins/observability_solution/dataset_quality/public/services/data_stream_details/data_stream_details_client.ts index 55d21286d7f60..5f944bd3fcde7 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/services/data_stream_details/data_stream_details_client.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/services/data_stream_details/data_stream_details_client.ts @@ -123,11 +123,9 @@ export class DataStreamDetailsClient implements IDataStreamDetailsClient { public async getDataStreamIntegration( params: GetDataStreamIntegrationParams ): Promise { - const { type, integrationName } = params; + const { integrationName } = params; const response = await this.http - .get('/internal/dataset_quality/integrations', { - query: { type }, - }) + .get('/internal/dataset_quality/integrations') .catch((error) => { throw new DatasetQualityError(`Failed to fetch integrations: ${error}`, error); }); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/services/data_streams_stats/data_streams_stats_client.ts b/x-pack/plugins/observability_solution/dataset_quality/public/services/data_streams_stats/data_streams_stats_client.ts index 35cd67a1724f9..1e75088853d33 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/services/data_streams_stats/data_streams_stats_client.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/services/data_streams_stats/data_streams_stats_client.ts @@ -7,6 +7,8 @@ import { HttpStart } from '@kbn/core/public'; import { decodeOrThrow } from '@kbn/io-ts-utils'; +import rison from '@kbn/rison'; +import { KNOWN_TYPES } from '../../../common/constants'; import { getDataStreamsDegradedDocsStatsResponseRt, getDataStreamsStatsResponseRt, @@ -15,14 +17,12 @@ import { IntegrationResponse, NonAggregatableDatasets, } from '../../../common/api_types'; -import { DEFAULT_DATASET_TYPE } from '../../../common/constants'; import { DataStreamStatServiceResponse, GetDataStreamsDegradedDocsStatsQuery, GetDataStreamsDegradedDocsStatsResponse, GetDataStreamsStatsQuery, GetDataStreamsStatsResponse, - GetIntegrationsParams, GetNonAggregatableDataStreamsParams, } from '../../../common/data_streams_stats'; import { Integration } from '../../../common/data_streams_stats/integration'; @@ -33,11 +33,15 @@ export class DataStreamsStatsClient implements IDataStreamsStatsClient { constructor(private readonly http: HttpStart) {} public async getDataStreamsStats( - params: GetDataStreamsStatsQuery = { type: DEFAULT_DATASET_TYPE } + params: GetDataStreamsStatsQuery ): Promise { + const types = params.types.length === 0 ? KNOWN_TYPES : params.types; const response = await this.http .get('/internal/dataset_quality/data_streams/stats', { - query: params, + query: { + ...params, + types: rison.encodeArray(types), + }, }) .catch((error) => { throw new DatasetQualityError(`Failed to fetch data streams stats: ${error}`, error); @@ -59,7 +63,6 @@ export class DataStreamsStatsClient implements IDataStreamsStatsClient { { query: { ...params, - type: DEFAULT_DATASET_TYPE, }, } ) @@ -86,7 +89,7 @@ export class DataStreamsStatsClient implements IDataStreamsStatsClient { .get('/internal/dataset_quality/data_streams/non_aggregatable', { query: { ...params, - type: DEFAULT_DATASET_TYPE, + types: rison.encodeArray(params.types), }, }) .catch((error) => { @@ -102,13 +105,9 @@ export class DataStreamsStatsClient implements IDataStreamsStatsClient { return nonAggregatableDatasets; } - public async getIntegrations( - params: GetIntegrationsParams['query'] = { type: DEFAULT_DATASET_TYPE } - ): Promise { + public async getIntegrations(): Promise { const response = await this.http - .get('/internal/dataset_quality/integrations', { - query: params, - }) + .get('/internal/dataset_quality/integrations') .catch((error) => { throw new DatasetQualityError(`Failed to fetch integrations: ${error}`, error); }); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/services/data_streams_stats/types.ts b/x-pack/plugins/observability_solution/dataset_quality/public/services/data_streams_stats/types.ts index 785cdb4a88ccc..ae1c72c23df0e 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/services/data_streams_stats/types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/services/data_streams_stats/types.ts @@ -11,7 +11,6 @@ import { DataStreamStatServiceResponse, GetDataStreamsDegradedDocsStatsQuery, GetDataStreamsStatsQuery, - GetIntegrationsParams, GetNonAggregatableDataStreamsParams, } from '../../../common/data_streams_stats'; import { Integration } from '../../../common/data_streams_stats/integration'; @@ -32,7 +31,7 @@ export interface IDataStreamsStatsClient { getDataStreamsDegradedStats( params?: GetDataStreamsDegradedDocsStatsQuery ): Promise; - getIntegrations(params: GetIntegrationsParams['query']): Promise; + getIntegrations(): Promise; getNonAggregatableDatasets( params: GetNonAggregatableDataStreamsParams ): Promise; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/services/telemetry/types.ts b/x-pack/plugins/observability_solution/dataset_quality/public/services/telemetry/types.ts index e4b5e07c8df92..f1a41ffc666cc 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/services/telemetry/types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/services/telemetry/types.ts @@ -34,6 +34,7 @@ export enum NavigationSource { Footer = 'footer', Summary = 'summary', Chart = 'chart', + Trend = 'trend', Table = 'table', ActionMenu = 'action_menu', } diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/defaults.ts b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/defaults.ts index 62ec47632c242..d0b2b9978080a 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/defaults.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/defaults.ts @@ -7,8 +7,6 @@ import { DEFAULT_DATASET_TYPE, - DEFAULT_DEGRADED_FIELD_SORT_DIRECTION, - DEFAULT_DEGRADED_FIELD_SORT_FIELD, DEFAULT_SORT_DIRECTION, DEFAULT_SORT_FIELD, } from '../../../../common/constants'; @@ -16,8 +14,15 @@ import { DefaultDatasetQualityControllerState } from './types'; const ONE_MINUTE_IN_MS = 60000; +export const DEFAULT_DICTIONARY_TYPE = { + logs: [], + metrics: [], + traces: [], + synthetics: [], + profiling: [], +}; + export const DEFAULT_CONTEXT: DefaultDatasetQualityControllerState = { - type: DEFAULT_DATASET_TYPE, table: { page: 0, rowsPerPage: 10, @@ -32,6 +37,7 @@ export const DEFAULT_CONTEXT: DefaultDatasetQualityControllerState = { canViewIntegrations: true, }, dataStreamStats: [], + degradedDocStats: DEFAULT_DICTIONARY_TYPE, filters: { inactive: true, fullNames: false, @@ -46,19 +52,7 @@ export const DEFAULT_CONTEXT: DefaultDatasetQualityControllerState = { integrations: [], namespaces: [], qualities: [], - }, - flyout: { - degradedFields: { - table: { - page: 0, - rowsPerPage: 10, - sort: { - field: DEFAULT_DEGRADED_FIELD_SORT_FIELD, - direction: DEFAULT_DEGRADED_FIELD_SORT_DIRECTION, - }, - }, - }, - isBreakdownFieldEcs: null, + types: [DEFAULT_DATASET_TYPE], }, datasets: [], isSizeStatsAvailable: true, diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/notifications.ts b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/notifications.ts index f10ea32da3af6..a21cc85aac449 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/notifications.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/notifications.ts @@ -17,15 +17,6 @@ export const fetchDatasetStatsFailedNotifier = (toasts: IToasts, error: Error) = }); }; -export const fetchDatasetDetailsFailedNotifier = (toasts: IToasts, error: Error) => { - toasts.addDanger({ - title: i18n.translate('xpack.datasetQuality.fetchDatasetDetailsFailed', { - defaultMessage: "We couldn't get your data set details.", - }), - text: error.message, - }); -}; - export const fetchDegradedStatsFailedNotifier = (toasts: IToasts, error: Error) => { toasts.addDanger({ title: i18n.translate('xpack.datasetQuality.fetchDegradedStatsFailed', { @@ -35,15 +26,6 @@ export const fetchDegradedStatsFailedNotifier = (toasts: IToasts, error: Error) }); }; -export const fetchNonAggregatableDatasetsFailedNotifier = (toasts: IToasts, error: Error) => { - toasts.addDanger({ - title: i18n.translate('xpack.datasetQuality.fetchNonAggregatableDatasetsFailed', { - defaultMessage: "We couldn't get non aggregatable datasets information.", - }), - text: error.message, - }); -}; - export const fetchIntegrationsFailedNotifier = (toasts: IToasts, error: Error) => { toasts.addDanger({ title: i18n.translate('xpack.datasetQuality.fetchIntegrationsFailed', { @@ -52,19 +34,3 @@ export const fetchIntegrationsFailedNotifier = (toasts: IToasts, error: Error) = text: error.message, }); }; - -export const noDatasetSelected = i18n.translate( - 'xpack.datasetQuality.fetchDatasetDetailsFailed.noDatasetSelected', - { - defaultMessage: 'No data set have been selected', - } -); - -export const assertBreakdownFieldEcsFailedNotifier = (toasts: IToasts, error: Error) => { - toasts.addDanger({ - title: i18n.translate('xpack.datasetQuality.assertBreakdownFieldEcsFailed', { - defaultMessage: "We couldn't retrieve breakdown field metadata.", - }), - text: error.message, - }); -}; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/state_machine.ts b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/state_machine.ts index fb6c03fae153a..127e56a755c86 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/state_machine.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/state_machine.ts @@ -8,55 +8,44 @@ import { IToasts } from '@kbn/core/public'; import { getDateISORange } from '@kbn/timerange'; import { assign, createMachine, DoneInvokeEvent, InterpreterFrom } from 'xstate'; -import { DatasetQualityStartDeps } from '../../../types'; +import { DataStreamStat, NonAggregatableDatasets } from '../../../../common/api_types'; +import { KNOWN_TYPES } from '../../../../common/constants'; import { - Dashboard, - DataStreamStat, - DegradedFieldResponse, - NonAggregatableDatasets, -} from '../../../../common/api_types'; -import { Integration } from '../../../../common/data_streams_stats/integration'; -import { IDataStreamDetailsClient } from '../../../services/data_stream_details'; -import { - DataStreamSettings, - DataStreamDetails, - GetDataStreamsStatsQuery, - GetIntegrationsParams, - GetNonAggregatableDataStreamsParams, + DataStreamDegradedDocsStatServiceResponse, DataStreamStatServiceResponse, } from '../../../../common/data_streams_stats'; -import { DegradedDocsStat } from '../../../../common/data_streams_stats/malformed_docs_stat'; +import { Integration } from '../../../../common/data_streams_stats/integration'; import { DataStreamType } from '../../../../common/types'; -import { dataStreamPartsToIndexName } from '../../../../common/utils'; import { IDataStreamsStatsClient } from '../../../services/data_streams_stats'; import { generateDatasets } from '../../../utils'; +import { fetchNonAggregatableDatasetsFailedNotifier } from '../../common/notifications'; import { DEFAULT_CONTEXT } from './defaults'; import { - fetchDatasetDetailsFailedNotifier, fetchDatasetStatsFailedNotifier, fetchDegradedStatsFailedNotifier, fetchIntegrationsFailedNotifier, - noDatasetSelected, - assertBreakdownFieldEcsFailedNotifier, } from './notifications'; -import { fetchNonAggregatableDatasetsFailedNotifier } from '../../common/notifications'; import { DatasetQualityControllerContext, DatasetQualityControllerEvent, DatasetQualityControllerTypeState, - DefaultDatasetQualityControllerState, - FlyoutDataset, } from './types'; -import { - fetchDataStreamSettingsFailedNotifier, - fetchIntegrationDashboardsFailedNotifier, - fetchDataStreamIntegrationFailedNotifier, -} from '../../dataset_quality_details_controller/notifications'; + +const generateInvokePerType = ({ src }: { src: string }) => ({ + invoke: KNOWN_TYPES.map((type) => ({ + id: `${type}`, + src, + data: { type }, + })), +}); + +const isTypeSelected = (type: DataStreamType, context: DatasetQualityControllerContext) => + context.filters.types.length === 0 || context.filters.types.includes(type); export const createPureDatasetQualityControllerStateMachine = ( initialContext: DatasetQualityControllerContext ) => - /** @xstate-layout N4IgpgJg5mDOIC5QBECGAXVszoIoFdUAbAS3QE8BhAewDt0AnaoosBgOggyx1gGIAqgAVkAQQAqAUQD64gJIBZGQCVRAOQDikgNoAGALqJQAB2qwyJOkZAAPRAFZ77AEwAWAGwAOXfc+f39u7uAIwBADQg5IieAMwAnOwA7PbOujHucTHpzs72AL55EWiY2HiEpBQ09EwsbJzcpfzKkgBizQDKABLSYuKieoZIIKbm6Ja01nYIzu4xLv4ZMcGJwZ7OiXERUQieronsurtxibquufYrMQVFDTgExGRUdIzMrBxcJbzsAGY4AMYACxItCgfAgdDA7GBADdqABrSHFHhlB6VZ41N71T7oWA-f5AkEIGHUP4YcYDAbWEYWKxDKbpJwxNJZHIxHK6DKJLaIYI+fauTzBeyuOLOOKuGKxK6FEBI0r3CpPaqvOofZG437oQHA0FsJgcYxEDDfagMAC27Dld3KjyqL1q71uOLxWoJUCJtFhpLGdApBipZhpEzpiD2nhccVWx2CwVch1W9m5Owy7HciT89klIr2rnyMqtKMVdoxqrAUAYqAgkGQJP4wl6MnkSmkqk0On9Q2pPuDoCm3nc7F26aynLOIqTsQSyVS6Uy2Tc11lToVtvRKveZYrVYgNb+TVaHW6vX6HZMge7kx5umWB3WYaynkSMWFE-czlTrj2s2C6yf9mCi4FiuaLKg6nCbpW1a1i62ogmCEJQp68KIsuNogfamJVuWkE7tBmqwe6xLeuSBiUp257jJeCAxiE7AeOmJzPokzF7EmvIXHRgrCqK4qSlkgGoaiSoYaW2HbruGr4jqfB6qa7CGsapoWkBaHCSWG5iVBe4wW6HpemSvqkaewwUbSvY8ss+zXnEsShB49iRlykSIHEhzzMxKQ-s4ni+HmNzYsBanroh6AQd2dYiBIjaKCo6haGRZ6jJRIYIMKqarMsbIhB5QqJs5CCfq4g4xs+nkhDEEruAJAWqcWwXAqF2HhXwzRtJIXQ9BIJ6DIlQZUTkRWZisiQij5qzuBySbOEK7AXCNwTHLxqQpNVyKBXVYENWF4wRQ20hyGoUgaKo8gAPJqO0CUmUlZm2A4HGxJ+Sz+CsDl5dsoRON4mRxvYPgcuKq3yrVa6bfQ210LtUXSGoohKO0QiiJQ7VXV2yXmalngJEyMTDXEKQCksU1pi4cZY2moRzq4QPWkJG2YltTU7YIkVSNIuACJIygAJqo6ZPZ3dRqxFRkszJFluPLGxGzsDZv7pCscbrH5S41XToMM+DTOQzp0ngrQkLEgilqCUWGt1IzFbhbrhJEQZtB+j1119Slua6IOzE+VmPhvm4Sa44yey6AxyzTb4NOFquoGa41Vs7TbuoMPq8lGugJrmibatm9HFta3HOv4bpdvdo7AY3QL9K8rNcTuAK3ixgKyRJoE7t7AHkZxKKDlVfmptRyJHCW-buJENQOEs3tfQAEIADIyJQyhyFIi-dWXLsY2m4a8Y+-7LJvSYTYNWQ1xkFyPjMEfrebg958P7Cj+P4inRoGhz-tsOUPIABqMjHu0kjiEusZNGt0+wzHYBlUUWNj4XFcEmCU+w2Q-lnP4T8mRL4gxzjfWOd8H7bj4E-F+b8WgCBnjPTqfR-7iBhnDFGwD+ZUUFPsea14BS6EyFGf26ROKhw5FjDwAoVYqXVlgn4RByDUHwOgPg-856fxhpIAA6hQ0QVC+blyoimdhvgTiZmcFkBBbEKpFSfN5ZIwQ2S42pr3LO-d1JiIkVIvglAZ6nX-tIFoM9uanQEOIdR69Bb-icJ+RwARYysifEY0IsssZ+A2KcCqmYMEiIHg4yR6BEIWAeAALz1ghWAmBQqZzWpg1J3xxHpMyWMHJOp-EXhSryGacZEj6O8p3XGxw2L4zmMkGywpprDXWMk7OZSKlSKqSQGpIIsSoHaIwMAqAzTIBwKgEgRBJKujyQbRCsJjbCJGfY8pjiMnAiyaQXJ0y1RzIYAspZKy1kbIInpEk9tS7kQ0a7fRqYVhYwWv+XMViuluHYLjYx6xBTsk8MMuxwUjmVNOdU85OoZnXNucszADyE4ySTnJBSaclLFOBikw5YyTm0DOSQC5UAUXzMWei1Z6yE7POIoZfQdT0aCzOMEJI2jryxiCaKJyH10xTl4r4fwPhhSJGhehElxyJlTOpUPbsaBYAAgAEZjwYBAR5bp4LbKNihWxsrYWkoVUi6Zyrxiqo1VqnVTLi4kTZfQj5GM0EuCWN5NY1k1h+3yjkRwEDQ4BAmiOR8MqgpgTheMhFkyLVKtviqrAtrUDat1dJWSBpU7p2Un3E1UazWxsVSFCGtAbWatTfawuOpmWvKMk7EBFdQwig9T+PwqQFq+rgf60I74rEXF0OsTIpwI30zqNGjJeDIDONce4zx3jfHstAYgEaCQT6jWWjmZwbE9hODFKHY4iwghQpsSU4lpr5VTogBPaGB12hyA0J0QBsgYotjiu2BtDCGmdoOEybR4TDjMTYrA1MQRUjBxrrkLwo7r5pPGX8Ue2Br2nSEJINQHivE+L8S6gJUxwUQIqsxNMMxEi13SDumuBx-D40fKcE4J6ZS0GoFWeAQx9kwodGvepGMAC0rhuWSlWCRyUA1djvUQDxre00cwZE-LoYO-gYOiLVI0LjHKpj7DcF4HwfgQ0hHCPlacIKFhiiyJKR81j-JnoOcFFTXxq0gjU8uoW4Z5O7DSIKSUswBRJnFAOLIvhPwzElhkJTqS7POivU5ptqVwFCksSJiU-Hgi+Z8rNGYf0mR-XWOkML9isJbi0qx3q3HBbJHDEOKUo43CbEMykYzYG5zmZGnl2zEFxJ4Sko595uHoiRlmvxxwrkuInBS-lY4744n+FCN4Ea6ZWtgQKzhCS98x7bmi1RCxaW1h6Nco4CqaQ2LXjmMRxw15DhsmFAtmOpbivO1K1MAcIQmFZUskE8TCB0x0QlJkMUPgDFLGu7nHB1sHNQA2w08USRYi128Bmc+7gppQ8Ysgi434fJCLzZGm72taAjzW5ACHG8zgQN8KESUwdgtCocDkA4AQRTsLo14OIQOOATqJ2Vun9FZwnDTHNtiOQEhvk-N4JkHheTOFZ3BslFKqUc6mIGjk3POQcg8mxEITgOQVUFIzrMlnVbWY45iCd5rKXIqubSu5GL1ny6vHMJYsxIyEfxtNRH+VliDrol63TrkYz4ylybot8aaU3LpfcxlYPbfUX-CC8nTu9gu9CGxXYRVTiOVmFxbykvT1EpswW+VQezeXO4KisP1vcT6zAFH0+ECctCkjOcIIyeHLfN5LsGM00KrZ6s7no347C3ksRUXhNIPrXJorWmqPvI5hK7TDz1XTd-XB01+w1YLT4isIDwP2XyKrV0HLXa9N3WSvqZ5DH2fT4Vd84+wMkxPFO4zjTD3HvtM8-G+30PqlJbccH8rRXiEUepG7sYGmYFiwoSCMQU0C0rcsYrkiwZwawW+l6BOEAU+wc3KHCjEaOYoQG7ugQCQ-gHawW-GsQ3eBuve+a7+8qCGZghOPWD290A44oLSg66+2YkB7uEo742iTIywvgg6K0BQeQQAA */ + /** @xstate-layout N4IgpgJg5mDOIC5QBECGAXVszoIoFdUAbAS3QE8BhAewDt0AnaoosBgOlk3VnYgyw5YAYgDKAQQBqAUQD6ycQBVxoxQCVp4gLKzVS0QG0ADAF1EoAA7VYZEnXMgAHogCMANgDMAdnYAONwBMbgAsAKxh3kYAnL4ANCDkiMHBHsHsRgG+vh4xIb6hLgC+hfFomNh4hKQUNPRMLGyc3Lz85ULCAHIA8ooAkgBiAJrySirqmjp6iqKy-eK9ADLSyMZmSCBWNuh2tA7OCO7efoEh4aGRMfGJCCkevunBLsmBOQEeHsWlAhUExGRUdEYzFYHC4GBa33aAFUAAoKRRyPpaORqcQdADi0lWDk2tns632hx8-iCYQiXmicQSSQCwQC6XCRlCQRcHjcLlCnxAZUElT+NUB9RBTXBfEhPGEGn6GlEAAkRspsetcdt8aBCZ5iScyecKZdqTcXFEXOwvC5zXcjMEvMFfEUStzxb9qgC6sDGmCeHwwFAGKgIJBkNQAMYiCQyeTSdGo5DLeRdSgzKaGUw46x43YE1ya46ks4XKnXYJRUJRdieKJ0sJRY0FLk8n5Vf61IENUHNb2+-2BkMibp9IaR6PiWPIeOJ3TKaazeZLFap5Xp1WZ9XZo4k07kylXJJuPfsKJeLLsm1eUJW+tOpsCt1tkVegNdgMQIOhzo9AbDWPD0fjpNTmY5kWZYDBcNZLCXHY9jXLU8y3fUi38Dxy2ZIwPGiLwPHOD4HQbHBnWbQV3XbUVHz9Z9XxEWF4URXpkVkVEMSxBcIK2KCswOHMNx1AsdxuLw3B8Pdgk1VIvFrS82j5F0WyFD0OzI7sX17SVpGlaQ5QVcQlVYjNoM49dtXzPVCySM0fA8AIXC8AIAiPay7Uk3kCJvVthU9XhaDocQoF9H0BAAI1YPCJXDORug6WRxHRaMo1GAAhJYtNEaRph0jZILVJwYNzTddW3A0cn8dgglCUJskPDIjScxt+VdNz5NFLzaB8vyoEC4LxT7D9BwiqKYo0dEEqS+EVFSwDZxAliMrYrKNUMuD8oQxBvByErizcNDfCiTbMhq-Dr3quSSK9ZrWoYfzMCCsAQu6gdhj66LYqG5RErkUaUunIC51A8CZr0jiiVyniTL4u4oiMEr7Ih1IRKMIwvH26TCNvdyOzO3yLvaq7Oqkqi4SUWj6MYzF0pVdjVwM2C8t4wqKoPLDvErHaUn8JGXKO4j7087zMcu1Brtu1T1M00aycyldsqp4HjIK65vG29hS1pEIonQ9DOVwq86tkrmSHoH0-WXfGaNkJEUTRUnpvJubEEPPiRJs9gIjso1fAyNwonZw7dbvfX0ENjAdhEKUZXlMXrYl-T7YNETbPYc00NCG0nlZNxvZ1oi-YNrtjeEajCdkXoOgRYc+i6DoUz+m3Jf2GOiyNE0Nb3EI2RtAIM5krPhX9wO84LhFZA6bQNJhcRKA08XZtru2vAdzIfACNWjE2le3nTrWpI532e5zo3g-zgnB9wKFxAWXo+knyPp+jufY7uZDMitc43F8cTxM7lGGo4Xvc4PgfESDBhFfauUdAYuDtM7ZIh5X7WXcA7SyyFHi0m2mhJeWRP6uWOuwX++86Am0LifaQahBhTwBpTKI8dKzRAyDtSyKcHYZFCMcKqm0vA2gKB3Tezkfbd0aLgoO+D2AADMcDBgABb6ygMICAdAwA4NoAAN2oAAa3kSFbefCf570EbQXgoj0ASKkQgfWyjgy6NWGQ5c+lQivz8FkCB8MV55DvkWZkbhTQp3POeBGGDuG1S7qjfhOjjYiLEZI2g0i2BMA4BYIgGBhHUAYAAW3YBo3hQTtEBz-kIgxRjIkmKUSGCxpgrEUylrY+4WQ7Tu3hsJN+DsQgeOSC4IwRoFbMi9v4g6mdMkKOyXgvR7AiDUCUofU2r0kqUDUBfYhvRtLX3IVLfwZZbRGF8LaM0ENHhRAduVNIZU1ZL09hkFImDObZwGbo3gIyxmKC6DFJKxdx59AjB9caZTbYIHyCacIFJrSVjPN4FwDsRImm2lhcS1pU6ay+FvDJ39+l92DsM0Zz5hD3MeXIfoUIFgLGSqlIeI8q5phvhxDZyFWnMzXm-CBrikhsmYRDdk+QNnJ0POcnejRhFEHINQfA6AxDSCWJQRQQ9pAAHUCWKE+TPBANkwYligTWVkNY7R2Q3nCnhvTEU8r5QK4QlAFhdBSrMBYgwuhQhlYs6xHEFUGlpMhN+ORwiPAVncWFjp4U6uwXq-l6AFG2D+AALykTIuR951Ha0Cbq3l-rA3bBDVI2V+lWS0gPBA4IGRLLlTcOVPitI0KmnXiWV+JZHLdORlgrmfqBUJpIEmyJ7AMZtQ6jdcUYTDEROkbI2g8jTGqKjd6mNvq411v1kG0goam0tqxm2kKnb8lQEKWYkpJgU0cQ2ukM0WQSwFCwpkPiTxKwlVsUedeAkbI4S1QEr+o79UBonYmqdUjm281bTjdtUlF3duENEpJ7A4kJKSak9JPqa1jsfbQSdJBp1QDfS1Pm2MBa415D+4xA7zHLksTa8p+wt0IwgdtMqrJmSmQOOVReYQjR0nEoeIInKtEiMg-Wxt8HZ380Fh23tYBxmF2LqIXo6JZTTnNgxS2zFQFkspsyZhZ5X6+CXmmtW9LOLuxKu8Ta7JKF2XeIxvptaoMwbgwh86nHUMVD4HIoVIqxXvOtVJpZ+xPBpCtBDCkR4UiljcEeoqJVPZ0prGeSs9ob09JHRBh9rGX1NtaKgUQjAwCoGSaIHA2xIn6PCWGnjCjlFqLSdGu9kX41PobTF+DcWEsXWS6l9A6WoCZa7RhopWGdg4cc7aymdJ7gcmqW07wbDggFreCaMIngl42jQp5-TsaoulbY2KTAVWkspbS1IxrS6-0MBiYB+J6BEkpIK8Oord5DPRdg6+yriWatrYy+hgpmG10bq65kBO5Usj9YEgjIbDrLJpGSNaR4eaggf0rZogzLH5vlcW-F67q26vrfO8GsAvQQkooEcuZAOBUAkCIBt39OWB35bAxF07kPoPPou7FgQy2bsI7u1D2DKO0dCIxzsLHmBcf4+a6u7DpTcNfLIweEITi0KCSyKEAttL2DvBsoJR4GzFczfvSVinZWqcVZp3D2r9XeCM+R6jq5oS2d0A5zjvH92onbYA0B-bIGjvatJ8KM7+vLta+q-D3XSPmdG-Ryz2gZuueW5XcUvn66BdyqFyzUXbcJcFvYfcVIEuyor0zcr4r461cLaux7nXiP9c++Raz-3aBYDiICqMhgEBueRPDX23Lg6He3urWTubWfoc55W3nhn7emeG6L0Mk3AesDl8r9X4Pj2w-PYqVmhOGzX6e2LLkVTHh3AePYW8MqyCKQr3T631Xxm3dLe17dhr3v+85MHyXkfFfUBV5r1bnbtuDugcKy3535PD-U+P7n0-eve8G7+7-6+6m435j4P4h6tZ0DtakpOaICMhz4iQrJL7+Ar4BClimibQHoRDmiIxg4Ioq6Z5f6a4-5d5-7n5AFIqX6l6j537j55K-r-qxJ7Yv5N7hYnYf5t7EEw606e754AGF6X7AED40G3734T4tZPZgSwGdYz6QyZoL7MzL5gwIzIRHg5BebwxZoIx76cEH6U4mad7JaB4W4MHZYRpE5DqO4cHcqf4GFH6w4e4mEQGT5tb84dZ4YMppBsgQzZABArwryVgeBHpGjMKKZLxvAtKKbRC6G2FcH2Hf6OErbOGW5bZP4sH24k42EcAu4AEOG8EpFmEPaSFT4R76QpDeEnJ+EBGL7BEGiJz0jZDUYchLyoShZerWHv5xH6Hq6GHu7JHY5B48Z8aDwCZCYiYzBiYkySYyGeE3CpAy5VGWQ1FBFHp1J+DQrWQwwQxcJhZVoXJ6FEEJEkFJHGGDEW7DHxQaDiAADSyAXQEqkU-QvQwqY4lAsoEm0++wJISs9G9C7Ir85wIRRa2QnCKQvhiCsRORdhvR+RcOWOT4kA-QJAYARA9BWWtehORSxOb+Bx3RRxsJiRBRgcz4yJqJ6JTWxRvObh4eHhgu0QwupY1CWQ7CLg6BR6MQJoLcea0QVkIQZy+B4G++BJ2e-RZxiJEAZJaJD+aRNuGRh2WRXR0J8RhJJxxJEpUpFJS6kBT2ZRHE54ZYO0TJWaLJZo7JDq32KEIkAKgQqeUJzGKpoppB4p5ESJKJ0pVmfaIxcgYxwmomdEFsTEXx8B7wCcERbSdIh4O0qmRGzCgkEMtiJGiZeBex4Os2PRTppxySCJrpkp7p4+wxACQ4MYcYzxrxkx4gb0sg0ysyMyCydJcq2QkMX2rSym6ynsHJDJ7CycqhlYSB16HRzeeJypGZ0OWA2ADA6A8U1WKisiAA7rQJqb0LANIKGKkViXllYUOVyiOSKWObABOVOTOfOYufmcuauS4SUTScGTcIJP5naJhGVJkAUGeGDH4X4DulaO4AUHWIKU7viUZscewOOWwEeUlrOdQAuUuSuWuUUY-nKcBgqbiTuQ6aORrsBQeaBdOeBSedBReRIdSdAe4bMV8o7PedZFhGRi+ZLoVJhGWFkO8DplRe0YqcOahXWrcuikaiatiuapag5iRXKpQnxDZP9qtAjC8BwimYOewUqexQGsGCMtgBAMIF0MAk8XxVajeT4QePDGaSDqgjRdcOgSaKWlZDuucBAqkMUA6F5AGPAOsKxTuYJfpAALS2J8R2IljsLeC2Tz7hC+D2keQuWAzhDgpGTwTkZYSeBKyEY7TOoAmepOVMYeQw4VAOW6SyGEjlT0URVLTkaPBWinoTbBblSMpBUKRdSW4hWUxGhHglSKaJnuzWi0hGVJBGhlh3DQr0auosXIUpWVV4yopKQ1VSx1X3CZDoF5rNWiVtXzF2K6gg7PBqxhAVWkQkk9ihijXZWKzcSyzLQ3DJz3CL6ljwzZCvxrUPgbXKSwUYlQDbWIC2RtKmhvzxUcjwzGiqbWjZDlgnDuBZriS7EyX7EoWpWKQUS9jDXPgPUIBPUmhHjiSwI+KfUOwxD3AwLlShHJzsiXUtDXWUTsD4C0CoACriJJJM4QAw1w0vWI12jI3WSNL7gtFNIPmMy42mZIbzpdQw29a5WLS0zyw8mMnoFsgIxLzs0cbIZcZDVwVU3oGGmHLeJHjnABBvmhnmitKCTuCslJX9V9KpWS1c1DWcWQBy0YF7olhMjK2WSMIZD+bRXqwZCRES3vpzqfq3SE3E2k3k3I6U2LjSZSy2Tm2K1W35A220V3DOyRFPBMgQrWj2lD4ZX-RZVJC7KxytJOrWibSVToSewJ2UGy3+1wEICy7lgli2RL6eCr4-ZFh5o+BPAbSZDbQ1hA3JV9KJ1Q2m1F0p0IDUJKzlTnDwxnAQqNL5BKyOxvCr65ocj2mGYw2uXkYcjNK80CTuwNGt163pl7ka4w1Zp8TZCmWr5aEpB5oBWz0wkLaG3u3igw01i+atJ+AWiMxhV8nn2OnQ5X0oZfpoaF2ZVzFPAxl0iUpXraYxBGlv1oUmaf3S1oY8Yw3ZCJ5vw2SULuw2TsJHrMhNwvxZpNIFB7gQPb19HOl8EZbwPkZWQpAHgxDWh6gnKarA1pmEGAWqk8En705n6-3J3-3WjDaUM7QAm+XeCbIEPMOZm8Hd5n4F4X6DJJ01yppsgFpYHOz0J3CezoQljBAiNI5wm-7sP-7GaCEyNUGDLOE80bKKMQx+DGjwyZCBBmgz1-nZHyXaNElsNe5SOUFD6FF3VU3h3GXiSQysqKYJ5tKKZaOu6uO6PuMCHSPXLGO6IpFwPd1zGKbIRWiFr0ab5S4rxKwWhPCK2sgDlt1b2iMd5ikkOSMxOePX5l5iHV5mM12PW5Ay5TXiTvC+IiThN5GRNkF6MUEgFX4DOiHgHVXJNfJvCq2FTRBIJPBvxWgCTgOONyW5HcFGEVP6MGGGNxNeNgF0EtByI81nUy5hBWSZAljoS0hgytkHjWlMKLUlhdOrPlMSMbO9FbPG41O0HiFE0k3oBk0MAU2HPrLHOYNnOD2XOFToE+AVFNItzoSYSPNAVrMvOelgA82BBgwKxR1o2YSnhmiIssNrOmNjNCVp3XDGidWoLsjWRO1hNLNsUrNIvlPeOUn3Ukupo8P1EezFpnia3JArwbIEtiPwnnH7N9ow2YQeI1g1i2KMUpAM31Fsk+DrL+GWS7pbSaP0soWMuEvMvXWamyNgIUJkuuDiQTX+GA13A0YcpatMY6vCtOH6v5kP482cvXBGhMj93eXWg9lGj0PFNMMuNqkisanOuou32QLGgpDvx03z4FptLNlV1tICRkjSUBsZ6lPoUgWTnYWoAQVQVnkwWGsB2EhGhgzA5R2cLux+FYRCv7mHm5v5unnknnm3Wsvosr5nj0g5CWRBDry2R9XHbLMX31tYXHmQXNtomttitovst2ohCmizPUuoRRWr0fnRmshMKr5pub2Bsm1+1-1fJPBrR0jYSK6UI5CqZvCHjpDCQjatKYSDudEMssaKXWBd2Htyp9vljWmNzIOWQliKP13+EkjGhuz8M2WFBAA */ createMachine< DatasetQualityControllerContext, DatasetQualityControllerEvent, @@ -68,66 +57,105 @@ export const createPureDatasetQualityControllerStateMachine = ( id: 'DatasetQualityController', type: 'parallel', states: { - datasets: { - initial: 'fetching', + stats: { + type: 'parallel', states: { - fetching: { - invoke: { - src: 'loadDataStreamStats', - onDone: { - target: 'loaded', - actions: ['storeDataStreamStats', 'storeDatasets'], + datasets: { + initial: 'fetching', + states: { + fetching: { + invoke: { + src: 'loadDataStreamStats', + onDone: { + target: 'loaded', + actions: ['storeDataStreamStats', 'storeDatasets'], + }, + onError: { + target: 'loaded', + actions: ['notifyFetchDatasetStatsFailed'], + }, + }, }, - onError: { - target: 'loaded', - actions: ['notifyFetchDatasetStatsFailed'], + loaded: {}, + }, + on: { + UPDATE_TIME_RANGE: { + target: 'datasets.fetching', + actions: ['storeTimeRange'], + }, + REFRESH_DATA: { + target: 'datasets.fetching', }, }, }, - loaded: {}, - }, - on: { - UPDATE_TIME_RANGE: { - target: 'datasets.fetching', - actions: ['storeTimeRange'], - }, - REFRESH_DATA: { - target: 'datasets.fetching', - }, - }, - }, - degradedDocs: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'loadDegradedDocs', - onDone: { - target: 'loaded', + degradedDocs: { + initial: 'fetching', + states: { + fetching: { + ...generateInvokePerType({ + src: 'loadDegradedDocs', + }), + }, + loaded: {}, + unauthorized: { type: 'final' }, + }, + on: { + SAVE_DEGRADED_DOCS_STATS: { + target: 'degradedDocs.loaded', actions: ['storeDegradedDocStats', 'storeDatasets'], }, - onError: [ + NOTIFY_DEGRADED_DOCS_STATS_FAILED: [ { - target: 'unauthorized', + target: 'degradedDocs.unauthorized', cond: 'checkIfActionForbidden', }, { - target: 'loaded', + target: 'degradedDocs.loaded', actions: ['notifyFetchDegradedStatsFailed'], }, ], + UPDATE_TIME_RANGE: { + target: 'degradedDocs.fetching', + actions: ['storeTimeRange'], + }, + REFRESH_DATA: { + target: 'degradedDocs.fetching', + }, }, }, - loaded: {}, - unauthorized: { type: 'final' }, - }, - on: { - UPDATE_TIME_RANGE: { - target: 'degradedDocs.fetching', - actions: ['storeTimeRange'], - }, - REFRESH_DATA: { - target: 'degradedDocs.fetching', + nonAggregatableDatasets: { + initial: 'fetching', + states: { + fetching: { + invoke: { + src: 'loadNonAggregatableDatasets', + onDone: { + target: 'loaded', + actions: ['storeNonAggregatableDatasets'], + }, + onError: [ + { + target: 'unauthorized', + cond: 'checkIfActionForbidden', + }, + { + target: 'loaded', + actions: ['notifyFetchNonAggregatableDatasetsFailed'], + }, + ], + }, + }, + loaded: {}, + unauthorized: { type: 'final' }, + }, + on: { + UPDATE_TIME_RANGE: { + target: 'nonAggregatableDatasets.fetching', + }, + REFRESH_DATA: { + target: 'nonAggregatableDatasets.fetching', + }, + }, }, }, }, @@ -188,270 +216,15 @@ export const createPureDatasetQualityControllerStateMachine = ( target: 'integrations.loaded', actions: ['storeQualities'], }, + UPDATE_TYPES: { + target: '#DatasetQualityController.stats', + actions: ['storeTypes'], + }, UPDATE_QUERY: { actions: ['storeQuery'], }, }, }, - nonAggregatableDatasets: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'loadNonAggregatableDatasets', - onDone: { - target: 'loaded', - actions: ['storeNonAggregatableDatasets'], - }, - onError: [ - { - target: 'unauthorized', - cond: 'checkIfActionForbidden', - }, - { - target: 'loaded', - actions: ['notifyFetchNonAggregatableDatasetsFailed'], - }, - ], - }, - }, - loaded: {}, - unauthorized: { type: 'final' }, - }, - on: { - UPDATE_TIME_RANGE: { - target: 'nonAggregatableDatasets.fetching', - }, - REFRESH_DATA: { - target: 'nonAggregatableDatasets.fetching', - }, - }, - }, - flyout: { - initial: 'closed', - states: { - initializing: { - type: 'parallel', - states: { - nonAggregatableDataset: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'loadDatasetIsNonAggregatable', - onDone: { - target: 'done', - actions: ['storeDatasetIsNonAggregatable'], - }, - onError: { - target: 'done', - actions: ['notifyFetchNonAggregatableDatasetsFailed'], - }, - }, - }, - done: { - on: { - UPDATE_INSIGHTS_TIME_RANGE: { - target: 'fetching', - actions: ['storeFlyoutOptions'], - }, - SELECT_DATASET: { - target: 'fetching', - actions: ['storeFlyoutOptions'], - }, - }, - }, - }, - }, - dataStreamSettings: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'loadDataStreamSettings', - onDone: { - target: 'initializeIntegrations', - actions: ['storeDataStreamSettings'], - }, - onError: { - target: 'done', - actions: ['notifyFetchDataStreamSettingsFailed'], - }, - }, - }, - initializeIntegrations: { - type: 'parallel', - states: { - integrationDetails: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'loadDataStreamIntegration', - onDone: { - target: 'done', - actions: ['storeDataStreamIntegration'], - }, - onError: { - target: 'done', - actions: ['notifyFetchDatasetIntegrationsFailed'], - }, - }, - }, - done: { - type: 'final', - }, - }, - }, - integrationDashboards: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'loadIntegrationDashboards', - onDone: { - target: 'done', - actions: ['storeIntegrationDashboards'], - }, - onError: [ - { - target: 'unauthorized', - cond: 'checkIfActionForbidden', - }, - { - target: 'done', - actions: ['notifyFetchIntegrationDashboardsFailed'], - }, - ], - }, - }, - done: { - type: 'final', - }, - unauthorized: { - type: 'final', - }, - }, - }, - }, - }, - done: { - type: 'final', - }, - }, - }, - dataStreamDetails: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'loadDataStreamDetails', - onDone: { - target: 'done', - actions: ['storeDatasetDetails'], - }, - onError: { - target: 'done', - actions: ['notifyFetchDatasetDetailsFailed'], - }, - }, - }, - done: { - on: { - UPDATE_INSIGHTS_TIME_RANGE: { - target: 'fetching', - actions: ['storeFlyoutOptions'], - }, - BREAKDOWN_FIELD_CHANGE: { - target: - '#DatasetQualityController.flyout.initializing.assertBreakdownFieldIsEcs.fetching', - actions: ['storeFlyoutOptions'], - }, - }, - }, - }, - }, - dataStreamDegradedFields: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'loadDegradedFieldsPerDataStream', - onDone: { - target: 'done', - actions: ['storeDegradedFields'], - }, - onError: { - target: 'done', - }, - }, - }, - done: { - on: { - UPDATE_INSIGHTS_TIME_RANGE: { - target: 'fetching', - actions: ['resetDegradedFieldPage'], - }, - UPDATE_DEGRADED_FIELDS_TABLE_CRITERIA: { - target: 'done', - actions: ['storeDegradedFieldTableOptions'], - }, - }, - }, - }, - }, - assertBreakdownFieldIsEcs: { - initial: 'fetching', - states: { - fetching: { - invoke: { - src: 'assertBreakdownFieldIsEcs', - onDone: { - target: 'done', - actions: ['storeBreakdownFieldIsEcs'], - }, - onError: { - target: 'done', - actions: ['notifyAssertBreakdownFieldEcsFailed'], - }, - }, - }, - done: {}, - }, - }, - }, - onDone: { - target: '#DatasetQualityController.flyout.loaded', - }, - }, - loaded: { - on: { - CLOSE_FLYOUT: { - target: 'closed', - actions: ['resetFlyoutOptions'], - }, - }, - }, - closed: { - on: { - OPEN_FLYOUT: { - target: '#DatasetQualityController.flyout.initializing', - actions: ['storeFlyoutOptions'], - }, - }, - }, - }, - on: { - SELECT_NEW_DATASET: { - target: '#DatasetQualityController.flyout.initializing', - actions: ['storeFlyoutOptions'], - }, - CLOSE_FLYOUT: { - target: '#DatasetQualityController.flyout.closed', - actions: ['resetFlyoutOptions'], - }, - }, - }, }, }, { @@ -463,38 +236,12 @@ export const createPureDatasetQualityControllerStateMachine = ( } : {}; }), - storeDegradedFieldTableOptions: assign((context, event) => { - return 'degraded_field_criteria' in event - ? { - flyout: { - ...context.flyout, - degradedFields: { - ...context.flyout.degradedFields, - table: event.degraded_field_criteria, - }, - }, - } - : {}; - }), resetPage: assign((context, _event) => ({ table: { ...context.table, page: 0, }, })), - resetDegradedFieldPage: assign((context, _event) => ({ - flyout: { - ...context.flyout, - degradedFields: { - ...context.flyout.degradedFields, - table: { - ...context.flyout.degradedFields.table, - page: 0, - rowsPerPage: 10, - }, - }, - }, - })), storeInactiveDatasetsVisibility: assign((context, _event) => { return { filters: { @@ -551,6 +298,16 @@ export const createPureDatasetQualityControllerStateMachine = ( } : {}; }), + storeTypes: assign((context, event) => { + return 'types' in event + ? { + filters: { + ...context.filters, + types: event.types, + }, + } + : {}; + }), storeQuery: assign((context, event) => { return 'query' in event ? { @@ -561,122 +318,38 @@ export const createPureDatasetQualityControllerStateMachine = ( } : {}; }), - storeFlyoutOptions: assign((context, event) => { - const insightsTimeRange = - 'timeRange' in event - ? event.timeRange - : context.flyout?.insightsTimeRange ?? context.filters?.timeRange; - const dataset = - 'dataset' in event ? (event.dataset as FlyoutDataset) : context.flyout?.dataset; - const breakdownField = - 'breakdownField' in event - ? event.breakdownField ?? undefined - : context.flyout?.breakdownField; - - return { - flyout: { - ...context.flyout, - dataset, - insightsTimeRange, - breakdownField, - }, - }; - }), - storeBreakdownFieldIsEcs: assign((context, event: DoneInvokeEvent) => { - return { - flyout: { - ...context.flyout, - isBreakdownFieldEcs: - 'data' in event && typeof event.data === 'boolean' ? event.data : null, - }, - }; - }), - resetFlyoutOptions: assign((_context, _event) => ({ flyout: DEFAULT_CONTEXT.flyout })), storeDataStreamStats: assign( (_context, event: DoneInvokeEvent) => { - if ('data' in event && 'dataStreamsStats' in event.data) { - const dataStreamStats = event.data.dataStreamsStats as DataStreamStat[]; - const datasetUserPrivileges = event.data.datasetUserPrivileges; + const dataStreamStats = event.data.dataStreamsStats as DataStreamStat[]; + const datasetUserPrivileges = event.data.datasetUserPrivileges; - // Check if any DataStreamStat has null; to check for serverless - const isSizeStatsAvailable = - !dataStreamStats.length || dataStreamStats.some((stat) => stat.totalDocs !== null); + // Check if any DataStreamStat has null; to check for serverless + const isSizeStatsAvailable = + !dataStreamStats.length || dataStreamStats.some((stat) => stat.totalDocs !== null); - return { - dataStreamStats, - isSizeStatsAvailable, - datasetUserPrivileges, - }; - } - return {}; + return { + dataStreamStats, + isSizeStatsAvailable, + datasetUserPrivileges, + }; } ), - storeDegradedDocStats: assign((_context, event) => { - return 'data' in event - ? { - degradedDocStats: event.data as DegradedDocsStat[], - } - : {}; - }), - storeDegradedFields: assign((context, event: DoneInvokeEvent) => { - return 'data' in event - ? { - flyout: { - ...context.flyout, - degradedFields: { - ...context.flyout.degradedFields, - data: event.data.degradedFields, - }, - }, - } - : {}; - }), - storeNonAggregatableDatasets: assign( - ( - _context: DefaultDatasetQualityControllerState, - event: DoneInvokeEvent - ) => { - return 'data' in event - ? { - nonAggregatableDatasets: event.data.datasets, - } - : {}; + storeDegradedDocStats: assign( + (context, event: DoneInvokeEvent, meta) => { + const type = meta._event.origin as DataStreamType; + + return { + degradedDocStats: { + ...context.degradedDocStats, + [type]: event.data, + }, + }; } ), - storeDataStreamSettings: assign((context, event) => { - return 'data' in event - ? { - flyout: { - ...context.flyout, - dataStreamSettings: (event.data ?? {}) as DataStreamSettings, - }, - } - : {}; - }), - storeDatasetDetails: assign((context, event) => { - return 'data' in event - ? { - flyout: { - ...context.flyout, - datasetDetails: event.data as DataStreamDetails, - }, - } - : {}; - }), - storeDatasetIsNonAggregatable: assign( - ( - context: DefaultDatasetQualityControllerState, - event: DoneInvokeEvent - ) => { - return 'data' in event - ? { - flyout: { - ...context.flyout, - isNonAggregatable: !event.data.aggregatable, - }, - } - : {}; - } + storeNonAggregatableDatasets: assign( + (_context, event: DoneInvokeEvent) => ({ + nonAggregatableDatasets: event.data.datasets, + }) ), storeIntegrations: assign((_context, event) => { return 'data' in event @@ -690,34 +363,8 @@ export const createPureDatasetQualityControllerStateMachine = ( integrations: [], }; }), - storeDataStreamIntegration: assign((context, event: DoneInvokeEvent) => { - return 'data' in event - ? { - flyout: { - ...context.flyout, - integration: { - ...context.flyout.integration, - integrationDetails: event.data, - }, - }, - } - : {}; - }), - storeIntegrationDashboards: assign((context, event: DoneInvokeEvent) => { - return 'data' in event - ? { - flyout: { - ...context.flyout, - integration: { - ...context.flyout.integration, - dashboards: event.data, - }, - }, - } - : {}; - }), storeDatasets: assign((context, _event) => { - return context.integrations && (context.dataStreamStats || context.degradedDocStats) + return context.integrations ? { datasets: generateDatasets( context.dataStreamStats, @@ -743,18 +390,14 @@ export const createPureDatasetQualityControllerStateMachine = ( export interface DatasetQualityControllerStateMachineDependencies { initialContext?: DatasetQualityControllerContext; - plugins: DatasetQualityStartDeps; toasts: IToasts; dataStreamStatsClient: IDataStreamsStatsClient; - dataStreamDetailsClient: IDataStreamDetailsClient; } export const createDatasetQualityControllerStateMachine = ({ initialContext = DEFAULT_CONTEXT, - plugins, toasts, dataStreamStatsClient, - dataStreamDetailsClient, }: DatasetQualityControllerStateMachineDependencies) => createPureDatasetQualityControllerStateMachine(initialContext).withConfig({ actions: { @@ -764,173 +407,52 @@ export const createDatasetQualityControllerStateMachine = ({ fetchDegradedStatsFailedNotifier(toasts, event.data), notifyFetchNonAggregatableDatasetsFailed: (_context, event: DoneInvokeEvent) => fetchNonAggregatableDatasetsFailedNotifier(toasts, event.data), - notifyFetchDataStreamSettingsFailed: (_context, event: DoneInvokeEvent) => - fetchDataStreamSettingsFailedNotifier(toasts, event.data), - notifyFetchDatasetDetailsFailed: (_context, event: DoneInvokeEvent) => - fetchDatasetDetailsFailedNotifier(toasts, event.data), - notifyFetchIntegrationDashboardsFailed: (_context, event: DoneInvokeEvent) => - fetchIntegrationDashboardsFailedNotifier(toasts, event.data), notifyFetchIntegrationsFailed: (_context, event: DoneInvokeEvent) => fetchIntegrationsFailedNotifier(toasts, event.data), - notifyFetchDatasetIntegrationsFailed: (context, event: DoneInvokeEvent) => { - const integrationName = context.flyout.dataStreamSettings?.integration; - return fetchDataStreamIntegrationFailedNotifier(toasts, event.data, integrationName); - }, - notifyAssertBreakdownFieldEcsFailed: (_context, event: DoneInvokeEvent) => - assertBreakdownFieldEcsFailedNotifier(toasts, event.data), }, services: { - loadDataStreamStats: (context) => + loadDataStreamStats: (context, _event) => dataStreamStatsClient.getDataStreamsStats({ - type: context.type as GetDataStreamsStatsQuery['type'], + types: context.filters.types as DataStreamType[], datasetQuery: context.filters.query, }), - loadDegradedDocs: (context) => { - const { startDate: start, endDate: end } = getDateISORange(context.filters.timeRange); + loadDegradedDocs: + (context, _event, { data: { type } }) => + async (send) => { + try { + const { startDate: start, endDate: end } = getDateISORange(context.filters.timeRange); - return dataStreamStatsClient.getDataStreamsDegradedStats({ - type: context.type as GetDataStreamsStatsQuery['type'], - datasetQuery: context.filters.query, - start, - end, - }); - }, + const degradedDocsStats = await (isTypeSelected(type, context) + ? dataStreamStatsClient.getDataStreamsDegradedStats({ + type, + datasetQuery: context.filters.query, + start, + end, + }) + : Promise.resolve([])); - loadDegradedFieldsPerDataStream: (context) => { - if (!context.flyout.dataset || !context.flyout.insightsTimeRange) { - return Promise.resolve({}); - } - - const { startDate: start, endDate: end } = getDateISORange( - context.flyout.insightsTimeRange - ); - const { type, name: dataset, namespace } = context.flyout.dataset; - - return dataStreamDetailsClient.getDataStreamDegradedFields({ - dataStream: dataStreamPartsToIndexName({ - type: type as DataStreamType, - dataset, - namespace, - }), - start, - end, - }); - }, - loadIntegrations: (context) => { - return dataStreamStatsClient.getIntegrations({ - type: context.type as GetIntegrationsParams['query']['type'], - }); - }, + send({ + type: 'SAVE_DEGRADED_DOCS_STATS', + data: degradedDocsStats, + }); + } catch (e) { + send({ + type: 'NOTIFY_DEGRADED_DOCS_STATS_FAILED', + data: e, + }); + } + }, loadNonAggregatableDatasets: (context) => { const { startDate: start, endDate: end } = getDateISORange(context.filters.timeRange); return dataStreamStatsClient.getNonAggregatableDatasets({ - type: context.type as GetNonAggregatableDataStreamsParams['type'], - start, - end, - }); - }, - loadDataStreamSettings: (context) => { - if (!context.flyout.dataset) { - fetchDataStreamSettingsFailedNotifier(toasts, new Error(noDatasetSelected)); - - return Promise.resolve({}); - } - - const { type, name: dataset, namespace } = context.flyout.dataset; - - return dataStreamDetailsClient.getDataStreamSettings({ - dataStream: dataStreamPartsToIndexName({ - type: type as DataStreamType, - dataset, - namespace, - }), - }); - }, - loadDataStreamIntegration: (context) => { - if (context.flyout.dataStreamSettings?.integration && context.flyout.dataset) { - const { type } = context.flyout.dataset; - return dataStreamDetailsClient.getDataStreamIntegration({ - type: type as DataStreamType, - integrationName: context.flyout.dataStreamSettings.integration, - }); - } - return Promise.resolve(); - }, - loadDataStreamDetails: (context) => { - if (!context.flyout.dataset || !context.flyout.insightsTimeRange) { - fetchDatasetDetailsFailedNotifier(toasts, new Error(noDatasetSelected)); - - return Promise.resolve({}); - } - - const { type, name: dataset, namespace } = context.flyout.dataset; - const { startDate: start, endDate: end } = getDateISORange( - context.flyout.insightsTimeRange - ); - - return dataStreamDetailsClient.getDataStreamDetails({ - dataStream: dataStreamPartsToIndexName({ - type: type as DataStreamType, - dataset, - namespace, - }), + types: context.filters.types as DataStreamType[], start, end, }); }, - loadIntegrationDashboards: (context) => { - if (context.flyout.dataStreamSettings?.integration) { - return dataStreamDetailsClient.getIntegrationDashboards({ - integration: context.flyout.dataStreamSettings.integration, - }); - } - - return Promise.resolve(); - }, - loadDatasetIsNonAggregatable: async (context) => { - if (!context.flyout.dataset || !context.flyout.insightsTimeRange) { - fetchDatasetDetailsFailedNotifier(toasts, new Error(noDatasetSelected)); - - return Promise.resolve({}); - } - - const { type, name: dataset, namespace } = context.flyout.dataset; - const { startDate: start, endDate: end } = getDateISORange( - context.flyout.insightsTimeRange - ); - - return dataStreamStatsClient.getNonAggregatableDatasets({ - type: context.type as GetNonAggregatableDataStreamsParams['type'], - start, - end, - dataStream: dataStreamPartsToIndexName({ - type: type as DataStreamType, - dataset, - namespace, - }), - }); - }, - assertBreakdownFieldIsEcs: async (context) => { - if (context.flyout.breakdownField) { - const allowedFieldSources = ['ecs', 'metadata']; - - // This timeout is to avoid a runtime error that randomly happens on breakdown field change - // TypeError: Cannot read properties of undefined (reading 'timeFieldName') - await new Promise((res) => setTimeout(res, 300)); - - const client = await plugins.fieldsMetadata.getClient(); - const { fields } = await client.find({ - attributes: ['source'], - fieldNames: [context.flyout.breakdownField], - }); - - const breakdownFieldSource = fields[context.flyout.breakdownField]?.source; - - return !!(breakdownFieldSource && allowedFieldSources.includes(breakdownFieldSource)); - } - - return null; + loadIntegrations: () => { + return dataStreamStatsClient.getIntegrations(); }, }, }); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/types.ts b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/types.ts index d6bfaaad216b9..624fef066afcb 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_controller/src/types.ts @@ -6,35 +6,23 @@ */ import { DoneInvokeEvent } from 'xstate'; -import { QualityIndicators, TableCriteria, TimeRangeConfig } from '../../../../common/types'; -import { - Dashboard, - DatasetUserPrivileges, - NonAggregatableDatasets, -} from '../../../../common/api_types'; -import { Integration } from '../../../../common/data_streams_stats/integration'; -import { DatasetTableSortField, DegradedFieldSortField } from '../../../hooks'; -import { DegradedDocsStat } from '../../../../common/data_streams_stats/malformed_docs_stat'; +import { DatasetUserPrivileges, NonAggregatableDatasets } from '../../../../common/api_types'; import { DataStreamDegradedDocsStatServiceResponse, - DataStreamSettings, DataStreamDetails, - DataStreamStatServiceResponse, DataStreamStat, + DataStreamStatServiceResponse, DataStreamStatType, - DegradedField, - DegradedFieldResponse, } from '../../../../common/data_streams_stats'; - -export type FlyoutDataset = Omit< - DataStreamStat, - 'type' | 'size' | 'sizeBytes' | 'lastActivity' | 'degradedDocs' -> & { type: string }; - -export interface DegradedFields { - table: TableCriteria; - data?: DegradedField[]; -} +import { Integration } from '../../../../common/data_streams_stats/integration'; +import { DegradedDocsStat } from '../../../../common/data_streams_stats/malformed_docs_stat'; +import { + DataStreamType, + QualityIndicators, + TableCriteria, + TimeRangeConfig, +} from '../../../../common/types'; +import { DatasetTableSortField } from '../../../hooks'; interface FiltersCriteria { inactive: boolean; @@ -43,43 +31,27 @@ interface FiltersCriteria { integrations: string[]; namespaces: string[]; qualities: QualityIndicators[]; + types: string[]; query?: string; } -export interface DataStreamIntegrations { - integrationDetails?: Integration; - dashboards?: Dashboard[]; -} - export interface WithTableOptions { table: TableCriteria; } -export interface WithFlyoutOptions { - flyout: { - dataset?: FlyoutDataset; - dataStreamSettings?: DataStreamSettings; - datasetDetails?: DataStreamDetails; - insightsTimeRange?: TimeRangeConfig; - breakdownField?: string; - degradedFields: DegradedFields; - isNonAggregatable?: boolean; - integration?: DataStreamIntegrations; - isBreakdownFieldEcs: boolean | null; - }; -} - export interface WithFilters { filters: FiltersCriteria; } +export type DictionaryType = Record; + export interface WithDataStreamStats { datasetUserPrivileges: DatasetUserPrivileges; dataStreamStats: DataStreamStatType[]; } export interface WithDegradedDocs { - degradedDocStats: DegradedDocsStat[]; + degradedDocStats: DictionaryType; } export interface WithNonAggregatableDatasets { @@ -95,33 +67,31 @@ export interface WithIntegrations { integrations: Integration[]; } -export type DefaultDatasetQualityControllerState = { type: string } & WithTableOptions & +export type DefaultDatasetQualityControllerState = WithTableOptions & WithDataStreamStats & - Partial & - WithFlyoutOptions & + WithDegradedDocs & WithDatasets & WithFilters & WithNonAggregatableDatasets & Partial; -type DefaultDatasetQualityStateContext = DefaultDatasetQualityControllerState & - Partial; +type DefaultDatasetQualityStateContext = DefaultDatasetQualityControllerState; export type DatasetQualityControllerTypeState = | { - value: 'datasets.fetching'; + value: 'stats.datasets.fetching'; context: DefaultDatasetQualityStateContext; } | { - value: 'datasets.loaded'; + value: 'stats.datasets.loaded'; context: DefaultDatasetQualityStateContext; } | { - value: 'datasets.loaded.idle'; + value: 'stats.degradedDocs.fetching'; context: DefaultDatasetQualityStateContext; } | { - value: 'degradedDocs.fetching'; + value: 'stats.nonAggregatableDatasets.fetching'; context: DefaultDatasetQualityStateContext; } | { @@ -131,48 +101,6 @@ export type DatasetQualityControllerTypeState = | { value: 'nonAggregatableDatasets.fetching'; context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.dataStreamSettings.fetching'; - context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.dataStreamSettings.initializeIntegrations.integrationDashboards.fetching'; - context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.dataStreamSettings.initializeIntegrations.integrationDashboards.unauthorized'; - context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.dataStreamSettings.initializeIntegrations.integrationDetails.done'; - context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.dataStreamDetails.fetching'; - context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.dataStreamDetails.done'; - context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.assertBreakdownFieldIsEcs.fetching'; - context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.assertBreakdownFieldIsEcs.done'; - context: DefaultDatasetQualityStateContext; - } - | { - value: 'flyout.initializing.dataStreamDegradedFields.fetching'; - context: DefaultDatasetQualityStateContext; - } - | { - value: - | 'flyout.initializing.integrationDashboards.fetching' - | 'flyout.initializing.integrationDashboards.unauthorized'; - context: DefaultDatasetQualityStateContext; }; export type DatasetQualityControllerContext = DatasetQualityControllerTypeState['context']; @@ -182,29 +110,10 @@ export type DatasetQualityControllerEvent = type: 'UPDATE_TABLE_CRITERIA'; dataset_criteria: TableCriteria; } - | { - type: 'UPDATE_DEGRADED_FIELDS_TABLE_CRITERIA'; - degraded_field_criteria: TableCriteria; - } - | { - type: 'OPEN_FLYOUT'; - dataset: FlyoutDataset; - } - | { - type: 'SELECT_NEW_DATASET'; - dataset: FlyoutDataset; - } | { type: 'UPDATE_INSIGHTS_TIME_RANGE'; timeRange: TimeRangeConfig; } - | { - type: 'BREAKDOWN_FIELD_CHANGE'; - breakdownField: string | null; - } - | { - type: 'CLOSE_FLYOUT'; - } | { type: 'TOGGLE_INACTIVE_DATASETS'; } @@ -234,12 +143,13 @@ export type DatasetQualityControllerEvent = type: 'UPDATE_QUERY'; query: string; } + | { + type: 'UPDATE_TYPES'; + types: DataStreamType[]; + } | DoneInvokeEvent | DoneInvokeEvent - | DoneInvokeEvent | DoneInvokeEvent - | DoneInvokeEvent - | DoneInvokeEvent | DoneInvokeEvent | DoneInvokeEvent | DoneInvokeEvent diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_details_controller/state_machine.ts b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_details_controller/state_machine.ts index 74dca94990190..c18f3d479ee95 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_details_controller/state_machine.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/state_machines/dataset_quality_details_controller/state_machine.ts @@ -427,7 +427,7 @@ export const createDatasetQualityDetailsControllerStateMachine = ({ const { startDate: start, endDate: end } = getDateISORange(context.timeRange); return dataStreamStatsClient.getNonAggregatableDatasets({ - type, + types: [type], start, end, dataStream: context.dataStream, @@ -479,9 +479,7 @@ export const createDatasetQualityDetailsControllerStateMachine = ({ }, loadDataStreamIntegration: (context) => { if ('dataStreamSettings' in context && context.dataStreamSettings?.integration) { - const { type } = indexNameToDataStreamParts(context.dataStream); return dataStreamDetailsClient.getDataStreamIntegration({ - type, integrationName: context.dataStreamSettings.integration, }); } diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/utils/flatten_stats.ts b/x-pack/plugins/observability_solution/dataset_quality/public/utils/flatten_stats.ts new file mode 100644 index 0000000000000..70a861191ba9f --- /dev/null +++ b/x-pack/plugins/observability_solution/dataset_quality/public/utils/flatten_stats.ts @@ -0,0 +1,16 @@ +/* + * 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 { DataStreamType } from '../../common/types'; + +export function flattenStats( + stats: Record +): Array { + return Object.entries(stats).flatMap(([type, dataStreams]) => + dataStreams.map((dataStream) => ({ ...dataStream, type: type as DataStreamType })) + ); +} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/utils/generate_datasets.test.ts b/x-pack/plugins/observability_solution/dataset_quality/public/utils/generate_datasets.test.ts index b6ce00628dd51..6f2e46baacf8c 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/utils/generate_datasets.test.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/utils/generate_datasets.test.ts @@ -8,7 +8,8 @@ import { indexNameToDataStreamParts } from '../../common/utils'; import { Integration } from '../../common/data_streams_stats/integration'; import { generateDatasets } from './generate_datasets'; -import { DataStreamStatType } from '../../common/data_streams_stats/types'; +import { DataStreamStatType } from '../../common/data_streams_stats'; +import { DEFAULT_DICTIONARY_TYPE } from '../state_machines/dataset_quality_controller'; describe('generateDatasets', () => { const integrations: Integration[] = [ @@ -56,25 +57,28 @@ describe('generateDatasets', () => { }, ]; - const degradedDocs = [ - { - dataset: 'logs-system.application-default', - percentage: 0, - count: 0, - docsCount: 0, - quality: 'good' as const, - }, - { - dataset: 'logs-synth-default', - percentage: 11.320754716981131, - count: 6, - docsCount: 0, - quality: 'poor' as const, - }, - ]; + const degradedDocs = { + ...DEFAULT_DICTIONARY_TYPE, + logs: [ + { + dataset: 'logs-system.application-default', + percentage: 0, + count: 0, + docsCount: 0, + quality: 'good' as const, + }, + { + dataset: 'logs-synth-default', + percentage: 11.320754716981131, + count: 6, + docsCount: 0, + quality: 'poor' as const, + }, + ], + }; it('merges integrations information with dataStreamStats', () => { - const datasets = generateDatasets(dataStreamStats, undefined, integrations); + const datasets = generateDatasets(dataStreamStats, DEFAULT_DICTIONARY_TYPE, integrations); expect(datasets).toEqual([ { @@ -87,10 +91,10 @@ describe('generateDatasets', () => { rawName: dataStreamStats[0].name, integration: integrations[0], degradedDocs: { - percentage: degradedDocs[0].percentage, - count: degradedDocs[0].count, - docsCount: degradedDocs[0].docsCount, - quality: degradedDocs[0].quality, + percentage: degradedDocs.logs[0].percentage, + count: degradedDocs.logs[0].count, + docsCount: degradedDocs.logs[0].docsCount, + quality: degradedDocs.logs[0].quality, }, }, { @@ -115,40 +119,42 @@ describe('generateDatasets', () => { expect(datasets).toEqual([ { - rawName: degradedDocs[0].dataset, - name: indexNameToDataStreamParts(degradedDocs[0].dataset).dataset, - type: indexNameToDataStreamParts(degradedDocs[0].dataset).type, + rawName: degradedDocs.logs[0].dataset, + name: indexNameToDataStreamParts(degradedDocs.logs[0].dataset).dataset, + type: indexNameToDataStreamParts(degradedDocs.logs[0].dataset).type, lastActivity: undefined, size: undefined, sizeBytes: undefined, userPrivileges: undefined, - namespace: indexNameToDataStreamParts(degradedDocs[0].dataset).namespace, + namespace: indexNameToDataStreamParts(degradedDocs.logs[0].dataset).namespace, title: - integrations[0].datasets[indexNameToDataStreamParts(degradedDocs[0].dataset).dataset], + integrations[0].datasets[ + indexNameToDataStreamParts(degradedDocs.logs[0].dataset).dataset + ], integration: integrations[0], degradedDocs: { - percentage: degradedDocs[0].percentage, - count: degradedDocs[0].count, - docsCount: degradedDocs[0].docsCount, - quality: degradedDocs[0].quality, + percentage: degradedDocs.logs[0].percentage, + count: degradedDocs.logs[0].count, + docsCount: degradedDocs.logs[0].docsCount, + quality: degradedDocs.logs[0].quality, }, }, { - rawName: degradedDocs[1].dataset, - name: indexNameToDataStreamParts(degradedDocs[1].dataset).dataset, - type: indexNameToDataStreamParts(degradedDocs[1].dataset).type, + rawName: degradedDocs.logs[1].dataset, + name: indexNameToDataStreamParts(degradedDocs.logs[1].dataset).dataset, + type: indexNameToDataStreamParts(degradedDocs.logs[1].dataset).type, lastActivity: undefined, size: undefined, sizeBytes: undefined, userPrivileges: undefined, - namespace: indexNameToDataStreamParts(degradedDocs[1].dataset).namespace, - title: indexNameToDataStreamParts(degradedDocs[1].dataset).dataset, + namespace: indexNameToDataStreamParts(degradedDocs.logs[1].dataset).namespace, + title: indexNameToDataStreamParts(degradedDocs.logs[1].dataset).dataset, integration: undefined, degradedDocs: { - percentage: degradedDocs[1].percentage, - count: degradedDocs[1].count, - docsCount: degradedDocs[1].docsCount, - quality: degradedDocs[1].quality, + percentage: degradedDocs.logs[1].percentage, + count: degradedDocs.logs[1].count, + docsCount: degradedDocs.logs[1].docsCount, + quality: degradedDocs.logs[1].quality, }, }, ]); @@ -168,10 +174,10 @@ describe('generateDatasets', () => { rawName: dataStreamStats[0].name, integration: integrations[0], degradedDocs: { - percentage: degradedDocs[0].percentage, - count: degradedDocs[0].count, - docsCount: degradedDocs[0].docsCount, - quality: degradedDocs[0].quality, + percentage: degradedDocs.logs[0].percentage, + count: degradedDocs.logs[0].count, + docsCount: degradedDocs.logs[0].docsCount, + quality: degradedDocs.logs[0].quality, }, }, { @@ -182,10 +188,10 @@ describe('generateDatasets', () => { type: indexNameToDataStreamParts(dataStreamStats[1].name).type, rawName: dataStreamStats[1].name, degradedDocs: { - percentage: degradedDocs[1].percentage, - count: degradedDocs[1].count, - docsCount: degradedDocs[1].docsCount, - quality: degradedDocs[1].quality, + percentage: degradedDocs.logs[1].percentage, + count: degradedDocs.logs[1].count, + docsCount: degradedDocs.logs[1].docsCount, + quality: degradedDocs.logs[1].quality, }, }, ]); @@ -205,7 +211,7 @@ describe('generateDatasets', () => { }, }; - const datasets = generateDatasets([nonDefaultDataset], undefined, integrations); + const datasets = generateDatasets([nonDefaultDataset], DEFAULT_DICTIONARY_TYPE, integrations); expect(datasets).toEqual([ { @@ -225,8 +231,4 @@ describe('generateDatasets', () => { }, ]); }); - - it('returns an empty array if no valid object is provided', () => { - expect(generateDatasets(undefined, undefined, integrations)).toEqual([]); - }); }); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/utils/generate_datasets.ts b/x-pack/plugins/observability_solution/dataset_quality/public/utils/generate_datasets.ts index ca6dc793d35e5..fb479198bbac3 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/utils/generate_datasets.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/utils/generate_datasets.ts @@ -10,10 +10,12 @@ import { mapPercentageToQuality } from '../../common/utils'; import { Integration } from '../../common/data_streams_stats/integration'; import { DataStreamStat } from '../../common/data_streams_stats/data_stream_stat'; import { DegradedDocsStat } from '../../common/data_streams_stats/malformed_docs_stat'; +import { DictionaryType } from '../state_machines/dataset_quality_controller/src/types'; +import { flattenStats } from './flatten_stats'; export function generateDatasets( dataStreamStats: DataStreamStatType[] = [], - degradedDocStats: DegradedDocsStat[] = [], + degradedDocStats: DictionaryType, integrations: Integration[] ): DataStreamStat[] { if (!dataStreamStats.length && !integrations.length) { @@ -48,8 +50,10 @@ export function generateDatasets( { datasetIntegrationMap: {}, integrationsMap: {} } ); + const degradedDocs = flattenStats(degradedDocStats); + if (!dataStreamStats.length) { - return degradedDocStats.map((degradedDocStat) => + return degradedDocs.map((degradedDocStat) => DataStreamStat.fromDegradedDocStat({ degradedDocStat, datasetIntegrationMap }) ); } @@ -62,8 +66,8 @@ export function generateDatasets( docsCount: DegradedDocsStat['docsCount']; quality: DegradedDocsStat['quality']; } - > = degradedDocStats.reduce( - (degradedMapAcc, { dataset, percentage, count, docsCount, quality }) => + > = degradedDocs.reduce( + (degradedMapAcc, { dataset, percentage, count, docsCount }) => Object.assign(degradedMapAcc, { [dataset]: { percentage, diff --git a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_data_streams/get_data_streams.test.ts b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_data_streams/get_data_streams.test.ts index ae28384e7a160..907c0c0fdc05c 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_data_streams/get_data_streams.test.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_data_streams/get_data_streams.test.ts @@ -40,13 +40,13 @@ describe('getDataStreams', () => { const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); const result = await getDataStreams({ esClient: esClientMock, - type: 'logs', - datasetQuery: 'nginx', + types: ['logs'], + datasetQuery: 'nginx-*', uncategorisedOnly: true, }); expect(dataStreamService.getMatchingDataStreams).toHaveBeenCalledWith( expect.anything(), - 'logs-*nginx*' + 'logs-nginx-*' ); expect(result.datasetUserPrivileges.canMonitor).toBe(true); @@ -57,8 +57,8 @@ describe('getDataStreams', () => { const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); const results = await getDataStreams({ esClient: esClientMock, - type: 'logs', - datasetQuery: 'nginx', + types: ['logs'], + datasetQuery: 'nginx-*', uncategorisedOnly: true, }); expect(results.items.length).toBe(1); @@ -67,8 +67,8 @@ describe('getDataStreams', () => { const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); const results = await getDataStreams({ esClient: esClientMock, - type: 'logs', - datasetQuery: 'nginx', + types: ['logs'], + datasetQuery: 'nginx-*', uncategorisedOnly: false, }); expect(results.items.length).toBe(5); diff --git a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_data_streams/index.ts b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_data_streams/index.ts index 346946d8bed5c..853a0cf208b42 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_data_streams/index.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_data_streams/index.ts @@ -6,27 +6,28 @@ */ import type { ElasticsearchClient } from '@kbn/core/server'; -import { DEFAULT_DATASET_TYPE } from '../../../../common/constants'; import { streamPartsToIndexPattern } from '../../../../common/utils'; import { DataStreamType } from '../../../../common/types'; import { dataStreamService, datasetQualityPrivileges } from '../../../services'; export async function getDataStreams(options: { esClient: ElasticsearchClient; - type?: DataStreamType; + types: DataStreamType[]; datasetQuery?: string; uncategorisedOnly: boolean; }) { - const { esClient, type = DEFAULT_DATASET_TYPE, datasetQuery, uncategorisedOnly } = options; + const { esClient, types, datasetQuery, uncategorisedOnly } = options; - const datasetName = streamPartsToIndexPattern({ - typePattern: type, - datasetPattern: datasetQuery ? `*${datasetQuery}*` : '*-*', - }); + const datasetNames = types.map((type) => + streamPartsToIndexPattern({ + typePattern: type, + datasetPattern: datasetQuery ? `${datasetQuery}` : '*-*', + }) + ); const datasetUserPrivileges = await datasetQualityPrivileges.getDatasetPrivileges( esClient, - datasetName + datasetNames.join(',') ); if (!datasetUserPrivileges.canMonitor) { @@ -36,7 +37,10 @@ export async function getDataStreams(options: { }; } - const allDataStreams = await dataStreamService.getMatchingDataStreams(esClient, datasetName); + const allDataStreams = await dataStreamService.getMatchingDataStreams( + esClient, + datasetNames.join(',') + ); const filteredDataStreams = uncategorisedOnly ? allDataStreams.filter((stream) => { diff --git a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_non_aggregatable_data_streams.ts b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_non_aggregatable_data_streams.ts index b59999d0c3c2e..6137bc5426f86 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_non_aggregatable_data_streams.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/get_non_aggregatable_data_streams.ts @@ -8,28 +8,29 @@ import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { rangeQuery } from '@kbn/observability-plugin/server/utils/queries'; import { extractIndexNameFromBackingIndex } from '../../../common/utils'; -import { DEFAULT_DATASET_TYPE } from '../../../common/constants'; import { _IGNORED } from '../../../common/es_fields'; import { DataStreamType } from '../../../common/types'; import { createDatasetQualityESClient } from '../../utils'; export async function getNonAggregatableDataStreams({ esClient, - type = DEFAULT_DATASET_TYPE, + types, start, end, dataStream, }: { esClient: ElasticsearchClient; - type?: DataStreamType; + types: DataStreamType[]; start: number; end: number; dataStream?: string; }) { const datasetQualityESClient = createDatasetQualityESClient(esClient); + const dataStreamTypes = types.map((type) => `${type}-*-*`).join(','); + const response = await datasetQualityESClient.fieldCaps({ - index: dataStream ?? `${type}-*-*`, + index: dataStream ?? dataStreamTypes, fields: [_IGNORED], index_filter: { ...rangeQuery(start, end)[0], diff --git a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/routes.ts b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/routes.ts index 9862b11cf16e0..54a229cb790e7 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/routes.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/server/routes/data_streams/routes.ts @@ -16,7 +16,7 @@ import { DegradedFieldResponse, DatasetUserPrivileges, } from '../../../common/api_types'; -import { rangeRt, typeRt } from '../../types/default_api_types'; +import { rangeRt, typeRt, typesRt } from '../../types/default_api_types'; import { createDatasetQualityServerRoute } from '../create_datasets_quality_server_route'; import { datasetQualityPrivileges } from '../../services'; import { getDataStreamDetails, getDataStreamSettings } from './get_data_stream_details'; @@ -30,7 +30,7 @@ const statsRoute = createDatasetQualityServerRoute({ endpoint: 'GET /internal/dataset_quality/data_streams/stats', params: t.type({ query: t.intersection([ - typeRt, + t.type({ types: typesRt }), t.partial({ datasetQuery: t.string, }), @@ -59,6 +59,7 @@ const statsRoute = createDatasetQualityServerRoute({ const privilegedDataStreams = items.filter((stream) => { return stream.userPrivileges.canMonitor; }); + const dataStreamsStats = await getDataStreamsStats({ esClient, dataStreams: privilegedDataStreams.map((stream) => stream.name), @@ -116,7 +117,7 @@ const nonAggregatableDatasetsRoute = createDatasetQualityServerRoute({ params: t.type({ query: t.intersection([ rangeRt, - typeRt, + t.type({ types: typesRt }), t.partial({ dataStream: t.string, }), @@ -131,11 +132,36 @@ const nonAggregatableDatasetsRoute = createDatasetQualityServerRoute({ const esClient = coreContext.elasticsearch.client.asCurrentUser; + return await getNonAggregatableDataStreams({ + esClient, + ...params.query, + }); + }, +}); + +const nonAggregatableDatasetRoute = createDatasetQualityServerRoute({ + endpoint: 'GET /internal/dataset_quality/data_streams/{dataStream}/non_aggregatable', + params: t.type({ + path: t.type({ + dataStream: t.string, + }), + query: t.intersection([rangeRt, typeRt]), + }), + options: { + tags: [], + }, + async handler(resources): Promise { + const { context, params } = resources; + const coreContext = await context.core; + + const esClient = coreContext.elasticsearch.client.asCurrentUser; + await datasetQualityPrivileges.throwIfCannotReadDataset(esClient, params.query.type); return await getNonAggregatableDataStreams({ esClient, ...params.query, + types: [params.query.type], }); }, }); @@ -230,6 +256,7 @@ export const dataStreamsRouteRepository = { ...statsRoute, ...degradedDocsRoute, ...nonAggregatableDatasetsRoute, + ...nonAggregatableDatasetRoute, ...degradedFieldsRoute, ...dataStreamDetailsRoute, ...dataStreamSettingsRoute, diff --git a/x-pack/plugins/observability_solution/dataset_quality/server/routes/integrations/get_integrations.ts b/x-pack/plugins/observability_solution/dataset_quality/server/routes/integrations/get_integrations.ts index 208ed7e70ab32..10e89db800a20 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/server/routes/integrations/get_integrations.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/server/routes/integrations/get_integrations.ts @@ -9,16 +9,13 @@ import { Logger } from '@kbn/core/server'; import { PackageClient } from '@kbn/fleet-plugin/server'; import { PackageNotFoundError } from '@kbn/fleet-plugin/server/errors'; import { PackageListItem, RegistryDataStream } from '@kbn/fleet-plugin/common'; -import { DEFAULT_DATASET_TYPE } from '../../../common/constants'; -import { DataStreamType } from '../../../common/types'; import { IntegrationType } from '../../../common/api_types'; export async function getIntegrations(options: { packageClient: PackageClient; logger: Logger; - type?: DataStreamType; }): Promise { - const { packageClient, logger, type = DEFAULT_DATASET_TYPE } = options; + const { packageClient, logger } = options; const packages = await packageClient.getPackages(); const installedPackages = packages.filter((p) => p.status === 'installed'); @@ -29,7 +26,7 @@ export async function getIntegrations(options: { title: p.title, version: p.version, icons: p.icons, - datasets: await getDatasets({ packageClient, logger, pkg: p, type }), + datasets: await getDatasets({ packageClient, logger, pkg: p }), })) ); @@ -40,9 +37,8 @@ const getDatasets = async (options: { packageClient: PackageClient; logger: Logger; pkg: PackageListItem; - type: DataStreamType; }) => { - const { packageClient, logger, pkg, type } = options; + const { packageClient, logger, pkg } = options; return ( (await fetchDatasets({ @@ -50,7 +46,6 @@ const getDatasets = async (options: { logger, name: pkg.name, version: pkg.version, - type, })) ?? getDatasetsReadableName(pkg.data_streams ?? []) ); }; @@ -60,16 +55,13 @@ const fetchDatasets = async (options: { logger: Logger; name: string; version: string; - type: DataStreamType; }) => { try { - const { packageClient, name, version, type } = options; + const { packageClient, name, version } = options; const pkg = await packageClient.getPackage(name, version); - return getDatasetsReadableName( - (pkg.packageInfo.data_streams ?? []).filter((ds) => ds.type === type) - ); + return getDatasetsReadableName(pkg.packageInfo.data_streams ?? []); } catch (error) { // Custom integration if (error instanceof PackageNotFoundError) { diff --git a/x-pack/plugins/observability_solution/dataset_quality/server/routes/integrations/routes.ts b/x-pack/plugins/observability_solution/dataset_quality/server/routes/integrations/routes.ts index 1a21d7e1a14c4..dfeb2f3329bae 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/server/routes/integrations/routes.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/server/routes/integrations/routes.ts @@ -7,28 +7,24 @@ import * as t from 'io-ts'; import { IntegrationType, IntegrationDashboardsResponse } from '../../../common/api_types'; -import { typeRt } from '../../types/default_api_types'; import { createDatasetQualityServerRoute } from '../create_datasets_quality_server_route'; import { getIntegrations } from './get_integrations'; import { getIntegrationDashboards } from './get_integration_dashboards'; const integrationsRoute = createDatasetQualityServerRoute({ endpoint: 'GET /internal/dataset_quality/integrations', - params: t.type({ - query: typeRt, - }), options: { tags: [], }, async handler(resources): Promise<{ integrations: IntegrationType[]; }> { - const { params, plugins, logger } = resources; + const { plugins, logger } = resources; const fleetPluginStart = await plugins.fleet.start(); const packageClient = fleetPluginStart.packageService.asInternalUser; - const integrations = await getIntegrations({ packageClient, logger, ...params.query }); + const integrations = await getIntegrations({ packageClient, logger }); return { integrations }; }, diff --git a/x-pack/plugins/observability_solution/dataset_quality/server/types/default_api_types.ts b/x-pack/plugins/observability_solution/dataset_quality/server/types/default_api_types.ts index 91eb8698dfcac..c2b746e655280 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/server/types/default_api_types.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/server/types/default_api_types.ts @@ -7,12 +7,24 @@ import { isoToEpochRt } from '@kbn/io-ts-utils'; import * as t from 'io-ts'; -import { dataStreamTypesRt } from '../../common/types'; +import { DataStreamType, dataStreamTypesRt } from '../../common/types'; -export const typeRt = t.partial({ +export const typeRt = t.type({ type: dataStreamTypesRt, }); +export const typesRt = new t.Type( + 'typesRt', + (input: unknown): input is DataStreamType[] => + (typeof input === 'string' && input.split(',').every((value) => dataStreamTypesRt.is(value))) || + (Array.isArray(input) && input.every((value) => dataStreamTypesRt.is(value))), + (input, context) => + typeof input === 'string' && input.split(',').every((value) => dataStreamTypesRt.is(value)) + ? t.success(input.split(',') as DataStreamType[]) + : t.failure(input, context), + t.identity +); + export const rangeRt = t.type({ start: isoToEpochRt, end: isoToEpochRt, diff --git a/x-pack/plugins/observability_solution/dataset_quality/tsconfig.json b/x-pack/plugins/observability_solution/dataset_quality/tsconfig.json index 04d5362bb9861..8bec2d8cb1a63 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/tsconfig.json +++ b/x-pack/plugins/observability_solution/dataset_quality/tsconfig.json @@ -55,7 +55,8 @@ "@kbn/server-route-repository-utils", "@kbn/core-analytics-browser", "@kbn/core-lifecycle-browser", - "@kbn/core-notifications-browser" + "@kbn/core-notifications-browser", + "@kbn/rison" ], "exclude": [ "target/**/*" diff --git a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/helpers/calculate_offset.ts b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/helpers/calculate_offset.ts new file mode 100644 index 0000000000000..3eba710561abf --- /dev/null +++ b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/helpers/calculate_offset.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EntityDefinition } from '@kbn/entities-schema'; +import moment from 'moment'; +import { + ENTITY_DEFAULT_HISTORY_FREQUENCY, + ENTITY_DEFAULT_HISTORY_SYNC_DELAY, +} from '../../../../common/constants_entities'; + +const durationToSeconds = (dateMath: string) => { + const parts = dateMath.match(/(\d+)([m|s|h|d])/); + if (!parts) { + throw new Error(`Invalid date math supplied: ${dateMath}`); + } + const value = parseInt(parts[1], 10); + const unit = parts[2] as 'm' | 's' | 'h' | 'd'; + return moment.duration(value, unit).asSeconds(); +}; + +export function calculateOffset(definition: EntityDefinition) { + const syncDelay = durationToSeconds( + definition.history.settings.syncDelay || ENTITY_DEFAULT_HISTORY_SYNC_DELAY + ); + const frequency = + durationToSeconds(definition.history.settings.frequency || ENTITY_DEFAULT_HISTORY_FREQUENCY) * + 2; + + return syncDelay + frequency; +} diff --git a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/helpers/fixtures/entity_definition.ts b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/helpers/fixtures/entity_definition.ts index 727f73a044c4f..940e209260c54 100644 --- a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/helpers/fixtures/entity_definition.ts +++ b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/helpers/fixtures/entity_definition.ts @@ -15,6 +15,11 @@ export const rawEntityDefinition = { history: { timestampField: '@timestamp', interval: '1m', + settings: { + lookbackPeriod: '10m', + frequency: '2m', + syncDelay: '2m', + }, }, identityFields: ['log.logger', { field: 'event.category', optional: true }], displayNameTemplate: '{{log.logger}}{{#event.category}}:{{.}}{{/event.category}}', diff --git a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/transform/__snapshots__/generate_history_transform.test.ts.snap b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/transform/__snapshots__/generate_history_transform.test.ts.snap index 93c440038c3e6..b19a805b24b12 100644 --- a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/transform/__snapshots__/generate_history_transform.test.ts.snap +++ b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/transform/__snapshots__/generate_history_transform.test.ts.snap @@ -163,7 +163,7 @@ Object { "index": ".entities.v1.history.noop", "pipeline": "entities-v1-history-admin-console-services", }, - "frequency": "1m", + "frequency": "2m", "pivot": Object { "aggs": Object { "_errorRate_A": Object { @@ -286,7 +286,7 @@ Object { Object { "range": Object { "@timestamp": Object { - "gte": "now-1h", + "gte": "now-10m", }, }, }, @@ -296,7 +296,7 @@ Object { }, "sync": Object { "time": Object { - "delay": "60s", + "delay": "2m", "field": "@timestamp", }, }, diff --git a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/transform/__snapshots__/generate_latest_transform.test.ts.snap b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/transform/__snapshots__/generate_latest_transform.test.ts.snap index ca4cda934328e..ab1224525f4d7 100644 --- a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/transform/__snapshots__/generate_latest_transform.test.ts.snap +++ b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/transform/__snapshots__/generate_latest_transform.test.ts.snap @@ -98,7 +98,7 @@ Object { "filter": Object { "range": Object { "@timestamp": Object { - "gte": "now-1m", + "gte": "now-360s", }, }, }, @@ -115,7 +115,7 @@ Object { "filter": Object { "range": Object { "@timestamp": Object { - "gte": "now-1m", + "gte": "now-360s", }, }, }, @@ -132,7 +132,7 @@ Object { "filter": Object { "range": Object { "@timestamp": Object { - "gte": "now-1m", + "gte": "now-360s", }, }, }, @@ -149,7 +149,7 @@ Object { "filter": Object { "range": Object { "@timestamp": Object { - "gte": "now-1m", + "gte": "now-360s", }, }, }, diff --git a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/transform/generate_metadata_aggregations.test.ts b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/transform/generate_metadata_aggregations.test.ts index ef54abe305a69..69f6d4f071696 100644 --- a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/transform/generate_metadata_aggregations.test.ts +++ b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/transform/generate_metadata_aggregations.test.ts @@ -86,7 +86,7 @@ describe('Generate Metadata Aggregations for history and latest', () => { filter: { range: { '@timestamp': { - gte: 'now-1m', + gte: 'now-360s', }, }, }, @@ -112,7 +112,7 @@ describe('Generate Metadata Aggregations for history and latest', () => { filter: { range: { '@timestamp': { - gte: 'now-1m', + gte: 'now-360s', }, }, }, @@ -138,7 +138,7 @@ describe('Generate Metadata Aggregations for history and latest', () => { filter: { range: { '@timestamp': { - gte: 'now-1m', + gte: 'now-360s', }, }, }, @@ -164,7 +164,7 @@ describe('Generate Metadata Aggregations for history and latest', () => { filter: { range: { '@timestamp': { - gte: 'now-1m', + gte: 'now-360s', }, }, }, diff --git a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/transform/generate_metadata_aggregations.ts b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/transform/generate_metadata_aggregations.ts index 79aa4312c2955..1da8988209db6 100644 --- a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/transform/generate_metadata_aggregations.ts +++ b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/transform/generate_metadata_aggregations.ts @@ -7,6 +7,7 @@ import { EntityDefinition } from '@kbn/entities-schema'; import { ENTITY_DEFAULT_METADATA_LIMIT } from '../../../../common/constants_entities'; +import { calculateOffset } from '../helpers/calculate_offset'; export function generateHistoryMetadataAggregations(definition: EntityDefinition) { if (!definition.metadata) { @@ -31,6 +32,8 @@ export function generateLatestMetadataAggregations(definition: EntityDefinition) return {}; } + const offsetInSeconds = calculateOffset(definition); + return definition.metadata.reduce( (aggs, metadata) => ({ ...aggs, @@ -38,7 +41,7 @@ export function generateLatestMetadataAggregations(definition: EntityDefinition) filter: { range: { '@timestamp': { - gte: `now-${definition.history.interval}`, + gte: `now-${offsetInSeconds}s`, }, }, }, diff --git a/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/header/add_to_case_action.tsx b/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/header/add_to_case_action.tsx index 8f91ee3c87cd6..4a3693de8265e 100644 --- a/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/header/add_to_case_action.tsx +++ b/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/header/add_to_case_action.tsx @@ -45,7 +45,7 @@ export function AddToCaseAction({ } = kServices; const getToastText = useCallback( - (theCase) => + (theCase: any) => toMountPoint( { + (isLoading: any) => { const timeLoaded = Date.now(); setChartTimeRangeContext?.({ diff --git a/x-pack/plugins/observability_solution/exploratory_view/public/context/date_picker_context.tsx b/x-pack/plugins/observability_solution/exploratory_view/public/context/date_picker_context.tsx index 33d57611d1399..598cb9f956f1b 100644 --- a/x-pack/plugins/observability_solution/exploratory_view/public/context/date_picker_context.tsx +++ b/x-pack/plugins/observability_solution/exploratory_view/public/context/date_picker_context.tsx @@ -108,7 +108,7 @@ export function DatePickerContextProvider({ children }: { children: React.ReactE ); const updateRefreshInterval = useCallback( - ({ interval, isPaused }) => { + ({ interval, isPaused }: any) => { updateUrl({ refreshInterval: interval, refreshPaused: isPaused }); data.query.timefilter.timefilter.setRefreshInterval({ value: interval, pause: isPaused }); setLastUpdated(Date.now()); diff --git a/x-pack/plugins/observability_solution/infra/public/alerting/inventory/components/expression.tsx b/x-pack/plugins/observability_solution/infra/public/alerting/inventory/components/expression.tsx index f89cd7e778763..89579ac74a326 100644 --- a/x-pack/plugins/observability_solution/infra/public/alerting/inventory/components/expression.tsx +++ b/x-pack/plugins/observability_solution/infra/public/alerting/inventory/components/expression.tsx @@ -128,7 +128,7 @@ export const Expressions: React.FC = (props) => { const { metricsView } = useMetricsDataViewContext(); const updateParams = useCallback( - (id, e: InventoryMetricConditions) => { + (id: any, e: InventoryMetricConditions) => { const exp = ruleParams.criteria ? ruleParams.criteria.slice() : []; exp[id] = e; setRuleParams('criteria', exp); @@ -492,7 +492,7 @@ export const ExpressionRow: FC> = (props) ); const updateThreshold = useCallback( - (t) => { + (t: any) => { if (t.join() !== expression.threshold.join()) { setRuleParams(expressionId, { ...expression, threshold: t }); } @@ -501,7 +501,7 @@ export const ExpressionRow: FC> = (props) ); const updateWarningThreshold = useCallback( - (t) => { + (t: any) => { if (t.join() !== expression.warningThreshold?.join()) { setRuleParams(expressionId, { ...expression, warningThreshold: t }); } diff --git a/x-pack/plugins/observability_solution/infra/public/alerting/log_threshold/components/expression_editor/criteria.tsx b/x-pack/plugins/observability_solution/infra/public/alerting/log_threshold/components/expression_editor/criteria.tsx index 33f63fe6a49c3..f821d7510b3bf 100644 --- a/x-pack/plugins/observability_solution/infra/public/alerting/log_threshold/components/expression_editor/criteria.tsx +++ b/x-pack/plugins/observability_solution/infra/public/alerting/log_threshold/components/expression_editor/criteria.tsx @@ -218,7 +218,7 @@ const useCriteriaState = ( onUpdateCriteria: (criteria: PartialCountCriteriaType) => void ) => { const updateCriterion = useCallback( - (idx, criterionParams) => { + (idx: any, criterionParams: any) => { const nextCriteria = criteria.map((criterion, index) => { return idx === index ? { ...criterion, ...criterionParams } : criterion; }); @@ -233,7 +233,7 @@ const useCriteriaState = ( }, [criteria, defaultCriterion, onUpdateCriteria]); const removeCriterion = useCallback( - (idx) => { + (idx: any) => { const nextCriteria = criteria.filter((_criterion, index) => { return index !== idx; }); diff --git a/x-pack/plugins/observability_solution/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx b/x-pack/plugins/observability_solution/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx index a38eed49ee82b..85935143da399 100644 --- a/x-pack/plugins/observability_solution/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx +++ b/x-pack/plugins/observability_solution/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx @@ -193,7 +193,7 @@ export const Editor: React.FC { + (thresholdParams: any) => { const nextThresholdParams = { ...ruleParams.count, ...thresholdParams }; setRuleParams('count', nextThresholdParams); }, diff --git a/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/expression.tsx b/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/expression.tsx index 4855d71274e96..42eb0daa7806d 100644 --- a/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/expression.tsx +++ b/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/expression.tsx @@ -81,7 +81,7 @@ export const Expressions: React.FC = (props) => { }, [metadata]); const updateParams = useCallback( - (id, e: MetricExpression) => { + (id: any, e: MetricExpression) => { const exp = ruleParams.criteria ? ruleParams.criteria.slice() : []; exp[id] = e; setRuleParams('criteria', exp); diff --git a/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/expression_row.tsx b/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/expression_row.tsx index cca94d10e9539..48371bebb2569 100644 --- a/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/expression_row.tsx +++ b/x-pack/plugins/observability_solution/infra/public/alerting/metric_threshold/components/expression_row.tsx @@ -118,13 +118,13 @@ export const ExpressionRow = ({ ); const convertThreshold = useCallback( - (enteredThreshold) => + (enteredThreshold: any) => isMetricPct ? enteredThreshold.map((v: number) => pctToDecimal(v)) : enteredThreshold, [isMetricPct] ); const updateThreshold = useCallback( - (enteredThreshold) => { + (enteredThreshold: any) => { const t = convertThreshold(enteredThreshold); if (t.join() !== expression.threshold.join()) { setRuleParams(expressionId, { ...expression, threshold: t }); @@ -134,7 +134,7 @@ export const ExpressionRow = ({ ); const updateWarningThreshold = useCallback( - (enteredThreshold) => { + (enteredThreshold: any) => { const t = convertThreshold(enteredThreshold); if (t.join() !== expression.warningThreshold?.join()) { setRuleParams(expressionId, { ...expression, warningThreshold: t }); @@ -165,7 +165,7 @@ export const ExpressionRow = ({ ]); const handleCustomMetricChange = useCallback( - (exp) => { + (exp: any) => { setRuleParams(expressionId, exp); }, [expressionId, setRuleParams] diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/dashboards/actions/save_dashboard_modal.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/dashboards/actions/save_dashboard_modal.tsx index cda931e81a3fa..87ff45ef2173c 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/dashboards/actions/save_dashboard_modal.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/dashboards/actions/save_dashboard_modal.tsx @@ -91,7 +91,7 @@ export function SaveDashboardModal({ () => setAssetNameFiltersEnabled(!assetNameEnabled), [assetNameEnabled] ); - const onSelect = useCallback((newSelection) => setSelectedDashboard(newSelection), []); + const onSelect = useCallback((newSelection: any) => setSelectedDashboard(newSelection), []); const onClickSave = useCallback( async function () { diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/dashboards/dashboards.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/dashboards/dashboards.tsx index 2c7aaeafa6878..0178d478a85b3 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/dashboards/dashboards.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/dashboards/dashboards.tsx @@ -165,7 +165,7 @@ export function Dashboards() { ]); const getLocatorParams = useCallback( - (params, isFlyoutView) => { + (params: any, isFlyoutView: any) => { const searchParams = new URLSearchParams(location.search); const tableProperties = searchParams.get('tableProperties'); const flyoutParams = diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/metadata/table.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/metadata/table.tsx index 4d4d2e4c05588..fedf54a2d10a0 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/metadata/table.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/metadata/table.tsx @@ -126,7 +126,7 @@ export const Table = ({ loading, rows, onSearchChange, search, showActionsColumn ); const searchBarOnChange = useCallback( - ({ queryText, error }) => { + ({ queryText, error }: any) => { if (error) { setSearchError(error); } else { diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/processes/processes.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/processes/processes.tsx index d11aab9307ab5..e7666a7f4191e 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/processes/processes.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/processes/processes.tsx @@ -110,7 +110,7 @@ export const Processes = () => { }, []); const searchBarOnChange = useCallback( - ({ query, queryText, error: queryError }) => { + ({ query, queryText, error: queryError }: any) => { if (queryError) { setSearchQueryError(queryError); } else { diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/processes/processes_table.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/processes/processes_table.tsx index 87d4d7d9b5aa7..6d432910c20b3 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/processes/processes_table.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/processes/processes_table.tsx @@ -66,7 +66,7 @@ function useSortableProperties( return { updateSortableProperties: useCallback( - (property) => { + (property: any) => { sortableProperties.sortOn(property); callback(omit(sortableProperties.getSortedProperty(), 'getValue')); }, diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/profiling/profiling.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/profiling/profiling.tsx index c31c79f024635..709d249616f29 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/profiling/profiling.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/profiling/profiling.tsx @@ -49,7 +49,7 @@ export function Profiling() { ); const onSearchSubmit = useCallback( - ({ dateRange: range, query }) => { + ({ dateRange: range, query }: any) => { setDateRange(range); setCustomKuery(query); }, diff --git a/x-pack/plugins/observability_solution/infra/public/components/logging/log_analysis_results/analyze_in_ml_button.tsx b/x-pack/plugins/observability_solution/infra/public/components/logging/log_analysis_results/analyze_in_ml_button.tsx index 7550f81112c02..0751ad3b897fb 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/logging/log_analysis_results/analyze_in_ml_button.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/logging/log_analysis_results/analyze_in_ml_button.tsx @@ -19,7 +19,7 @@ export const AnalyzeInMlButton: React.FunctionComponent<{ } = useKibanaContextForPlugin(); const handleClick = useCallback( - (e) => { + (e: React.MouseEvent) => { if (!href || !shouldHandleLinkEvent(e)) return; application.navigateToUrl(href); }, diff --git a/x-pack/plugins/observability_solution/infra/public/components/logging/log_datepicker.tsx b/x-pack/plugins/observability_solution/infra/public/components/logging/log_datepicker.tsx index db2f90fc52dfc..097f2fbf755d7 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/logging/log_datepicker.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/logging/log_datepicker.tsx @@ -6,7 +6,13 @@ */ import React, { useCallback } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiSuperDatePicker, EuiButton } from '@elastic/eui'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiSuperDatePicker, + EuiButton, + OnTimeChangeProps, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; interface LogDatepickerProps { @@ -27,7 +33,7 @@ export const LogDatepicker: React.FC = ({ onStopStreaming, }) => { const handleTimeChange = useCallback( - ({ start, end, isInvalid }) => { + ({ start, end, isInvalid }: OnTimeChangeProps) => { if (onUpdateDateRange && !isInvalid) { onUpdateDateRange({ startDateExpression: start, endDateExpression: end }); } diff --git a/x-pack/plugins/observability_solution/infra/public/components/ml/anomaly_detection/anomalies_table/anomalies_table.tsx b/x-pack/plugins/observability_solution/infra/public/components/ml/anomaly_detection/anomalies_table/anomalies_table.tsx index 4e344808c04ef..fca61d349ce35 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/ml/anomaly_detection/anomalies_table/anomalies_table.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/ml/anomaly_detection/anomalies_table/anomalies_table.tsx @@ -357,7 +357,7 @@ export const AnomaliesTable = ({ setSearch(e.target.value); }, []); - const changeJobType = useCallback((selectedOptions) => { + const changeJobType = useCallback((selectedOptions: any) => { setSelectedJobType(selectedOptions); setJobType(selectedOptions[0].id); }, []); diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/sections/top_categories/analyze_dataset_in_ml_action.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/sections/top_categories/analyze_dataset_in_ml_action.tsx index a0ee944e5efb5..088f54a149974 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/sections/top_categories/analyze_dataset_in_ml_action.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/sections/top_categories/analyze_dataset_in_ml_action.tsx @@ -47,7 +47,7 @@ export const AnalyzeCategoryDatasetInMlAction: React.FunctionComponent<{ ); const handleClick = useCallback( - (e) => { + (e: React.MouseEvent) => { if (!viewAnomalyInMachineLearningLink || !shouldHandleLinkEvent(e)) return; application.navigateToUrl(viewAnomalyInMachineLearningLink); }, diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/sections/top_categories/top_categories_table.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/sections/top_categories/top_categories_table.tsx index f119a08cbd10a..7848672391315 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/sections/top_categories/top_categories_table.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/sections/top_categories/top_categories_table.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui'; +import { Criteria, EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui'; import numeral from '@elastic/numeral'; import { i18n } from '@kbn/i18n'; import React, { useMemo, useCallback } from 'react'; @@ -14,6 +14,7 @@ import useSet from 'react-use/lib/useSet'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { PersistedLogViewReference } from '@kbn/logs-shared-plugin/common'; import { + categoriesSortRT, LogEntryCategory, LogEntryCategoryDataset, LogEntryCategoryHistogram, @@ -51,8 +52,10 @@ export const TopCategoriesTable = euiStyled( }, [sortOptions]); const handleTableChange = useCallback( - ({ sort = {} }) => { - changeSortOptions(sort); + ({ sort }: Criteria) => { + if (categoriesSortRT.is(sort)) { + changeSortOptions(sort); + } }, [changeSortOptions] ); diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_rate/sections/anomalies/log_entry_example.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_rate/sections/anomalies/log_entry_example.tsx index ad5601846f339..6c545beb4b9cd 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_rate/sections/anomalies/log_entry_example.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_rate/sections/anomalies/log_entry_example.tsx @@ -139,7 +139,7 @@ export const LogEntryExampleMessage: React.FunctionComponent = ({ }); const handleMlLinkClick = useCallback( - (e) => { + (e: React.MouseEvent) => { if (!viewAnomalyInMachineLearningLink || !shouldHandleLinkEvent(e)) return; application.navigateToUrl(viewAnomalyInMachineLearningLink); }, diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_rate/sections/anomalies/table.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_rate/sections/anomalies/table.tsx index e3f7767662a09..a0c8eb762e9f1 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_rate/sections/anomalies/table.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_rate/sections/anomalies/table.tsx @@ -6,42 +6,44 @@ */ import { + Criteria, EuiBasicTable, EuiBasicTableColumn, - EuiIcon, + EuiButtonIcon, EuiFlexGroup, EuiFlexItem, - EuiButtonIcon, + EuiIcon, EuiSpacer, RIGHT_ALIGNMENT, } from '@elastic/eui'; -import moment from 'moment'; import { i18n } from '@kbn/i18n'; +import moment from 'moment'; import React, { useCallback, useMemo } from 'react'; import useSet from 'react-use/lib/useSet'; -import { TimeRange } from '../../../../../../common/time/time_range'; import { + anomaliesSortRT, AnomalyType, - getFriendlyNameForPartitionId, formatOneDecimalPlace, + getFriendlyNameForPartitionId, isCategoryAnomaly, } from '../../../../../../common/log_analysis'; +import { TimeRange } from '../../../../../../common/time/time_range'; import { RowExpansionButton } from '../../../../../components/basic_table'; -import { AnomaliesTableExpandedRow } from './expanded_row'; +import { LoadingOverlayWrapper } from '../../../../../components/loading_overlay_wrapper'; import { AnomalySeverityIndicator } from '../../../../../components/logging/log_analysis_results/anomaly_severity_indicator'; import { RegularExpressionRepresentation } from '../../../../../components/logging/log_analysis_results/category_expression'; import { useKibanaUiSetting } from '../../../../../hooks/use_kibana_ui_setting'; import { - Page, + ChangePaginationOptions, + ChangeSortOptions, FetchNextPage, FetchPreviousPage, - ChangeSortOptions, - ChangePaginationOptions, - SortOptions, - PaginationOptions, LogEntryAnomalies, + Page, + PaginationOptions, + SortOptions, } from '../../use_log_entry_anomalies_results'; -import { LoadingOverlayWrapper } from '../../../../../components/loading_overlay_wrapper'; +import { AnomaliesTableExpandedRow } from './expanded_row'; interface TableItem { id: string; @@ -146,8 +148,10 @@ export const AnomaliesTable: React.FunctionComponent<{ ); const handleTableChange = useCallback( - ({ sort = {} }) => { - changeSortOptions(sort); + ({ sort }: Criteria) => { + if (anomaliesSortRT.is(sort)) { + changeSortOptions(sort); + } }, [changeSortOptions] ); diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/log_columns_configuration_panel.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/log_columns_configuration_panel.tsx index 97fd485fac24c..931219dc0bce4 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/log_columns_configuration_panel.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/log_columns_configuration_panel.tsx @@ -57,7 +57,7 @@ export const LogColumnsConfigurationPanel = React.memo<{ ); const moveLogColumn = useCallback( - (sourceIndex, destinationIndex) => { + (sourceIndex: number, destinationIndex: number) => { logColumnsFormElement.updateValue((logColumns) => { if (destinationIndex >= 0 && sourceIndex <= logColumnsFormElement.value.length - 1) { const newLogColumns = [...logColumnsFormElement.value]; @@ -189,6 +189,8 @@ const TimestampLogColumnConfigurationPanel: React.FunctionComponent< id="xpack.infra.sourceConfiguration.timestampLogColumnDescription" defaultMessage="This system field shows the log entry's time as determined by the {timestampSetting} field setting." values={{ + // this is a settings key and should not be translated + // eslint-disable-next-line @kbn/i18n/strings_should_be_translated_with_i18n timestampSetting: timestamp, }} /> diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/stream/page_logs_content.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/stream/page_logs_content.tsx index 7184b0c9ecf37..d40014ed4468b 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/stream/page_logs_content.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/stream/page_logs_content.tsx @@ -13,10 +13,12 @@ import { LogEntryFlyout, LogEntryStreamItem, ScrollableLogTextStreamView, + UpdatedDateRange, useLogHighlightsStateContext, useLogPositionStateContext, useLogStreamContext, useLogViewContext, + VisibleInterval, WithSummary, WithSummaryProps, } from '@kbn/logs-shared-plugin/public'; @@ -173,11 +175,11 @@ export const StreamPageLogsContent = React.memo<{ const [, { setContextEntry }] = useViewLogInProviderContext(); const handleDateRangeExtension = useCallback( - (newDateRange) => { + (newDateRange: UpdatedDateRange) => { updateDateRange(newDateRange); if ( - 'startDateExpression' in newDateRange && + newDateRange.startDateExpression != null && isValidDatemath(newDateRange.startDateExpression) ) { fetchPreviousEntries({ @@ -185,7 +187,10 @@ export const StreamPageLogsContent = React.memo<{ extendTo: datemathToEpochMillis(newDateRange.startDateExpression)!, }); } - if ('endDateExpression' in newDateRange && isValidDatemath(newDateRange.endDateExpression)) { + if ( + newDateRange.endDateExpression != null && + isValidDatemath(newDateRange.endDateExpression) + ) { fetchNextEntries({ force: true, extendTo: datemathToEpochMillis(newDateRange.endDateExpression)!, @@ -196,7 +201,7 @@ export const StreamPageLogsContent = React.memo<{ ); const handlePagination = useCallback( - (params) => { + (params: VisibleInterval) => { reportVisiblePositions(params); if (!params.fromScroll) { return; diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/table/add_data_troubleshooting_popover.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/table/add_data_troubleshooting_popover.tsx new file mode 100644 index 0000000000000..419f78a892352 --- /dev/null +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/table/add_data_troubleshooting_popover.tsx @@ -0,0 +1,111 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { + EuiBadge, + EuiButton, + EuiFlexGroup, + EuiFlexItem, + EuiLink, + EuiPopover, + EuiPopoverFooter, + EuiPopoverTitle, + EuiText, +} from '@elastic/eui'; + +import { + ObservabilityOnboardingLocatorParams, + OBSERVABILITY_ONBOARDING_LOCATOR, +} from '@kbn/deeplinks-observability'; +import { i18n } from '@kbn/i18n'; +import { useBoolean } from '@kbn/react-hooks'; + +import { useKibanaContextForPlugin } from '../../../../../hooks/use_kibana'; +import { APM_HOST_TROUBLESHOOTING_LINK } from '../../../../../components/asset_details/constants'; + +const popoverContent = { + title: i18n.translate('xpack.infra.addDataPopover.wantToSeeMorePopoverTitleLabel', { + defaultMessage: 'Want to see more?', + }), + content: i18n.translate('xpack.infra.addDataPopover.understandHostPerformanceByTextLabel', { + defaultMessage: 'Understand host performance by collecting more metrics.', + }), + button: i18n.translate('xpack.infra.addDataPopover.understandHostPerformanceByTextLabel', { + defaultMessage: 'Add data', + }), + link: i18n.translate('xpack.infra.addDataPopover.troubleshootingLinkLabel', { + defaultMessage: 'Troubleshooting', + }), +}; + +const badgeContent = i18n.translate('xpack.infra.addDataPopover.naBadgeLabel', { + defaultMessage: 'N/A', +}); + +export const AddDataTroubleshootingPopover = () => { + const [isPopoverOpen, { off: closePopover, toggle: togglePopover }] = useBoolean(false); + + const { + services: { share }, + } = useKibanaContextForPlugin(); + const addDataLinkHref = share.url.locators + .get(OBSERVABILITY_ONBOARDING_LOCATOR) + ?.getRedirectUrl({ category: 'logs' }); + + const onButtonClick = () => togglePopover(); + + return ( + + {badgeContent} + + } + isOpen={isPopoverOpen} + closePopover={closePopover} + > + {popoverContent.title} + + {popoverContent.content} + + + + + + {popoverContent.button} + + + + + + {popoverContent.link} + + + + + + + ); +}; diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.test.ts b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.test.ts index 965f6acd24c93..a0ebb20184912 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.test.ts +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { useHostsTable } from './use_hosts_table'; +import { type HostNodeRow, useHostsTable } from './use_hosts_table'; import { renderHook } from '@testing-library/react-hooks'; import { InfraAssetMetricsItem } from '../../../../../common/http_api'; import * as useUnifiedSearchHooks from './use_unified_search'; @@ -158,7 +158,7 @@ describe('useHostTable hook', () => { } as unknown as ReturnType); }); it('it should map the nodes returned from the snapshot api to a format matching eui table items', () => { - const expected = [ + const expected: Array> = [ { name: 'host-0', os: '-', diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx index 4bdb72e625a89..dece3437e3e1d 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx @@ -40,6 +40,7 @@ import { ColumnHeader } from '../components/table/column_header'; import { TABLE_COLUMN_LABEL, TABLE_CONTENT_LABEL } from '../translations'; import { METRICS_TOOLTIP } from '../../../../common/visualizations'; import { buildCombinedAssetFilter } from '../../../../utils/filters/build'; +import { AddDataTroubleshootingPopover } from '../components/table/add_data_troubleshooting_popover'; /** * Columns and items types @@ -64,7 +65,20 @@ export type HostNodeRow = HostMetadata & * Helper functions */ const formatMetric = (type: InfraAssetMetricType, value: number | undefined | null) => { - return value || value === 0 ? createInventoryMetricFormatter({ type })(value) : 'N/A'; + const defaultValue = value ?? 0; + return createInventoryMetricFormatter({ type })(defaultValue); +}; + +const buildMetricCell = ( + value: number | null, + formatType: InfraAssetMetricType, + hasSystemMetrics?: boolean +) => { + if (!hasSystemMetrics && value === null) { + return ; + } + + return formatMetric(formatType, value); }; const buildItemsList = (nodes: InfraAssetMetricsItem[]): HostNodeRow[] => { @@ -89,7 +103,7 @@ const buildItemsList = (nodes: InfraAssetMetricsItem[]): HostNodeRow[] => { ...metrics.reduce( (acc, curr) => ({ ...acc, - [curr.name]: curr.value ?? 0, + [curr.name]: curr.value, }), {} as HostMetrics ), @@ -104,12 +118,15 @@ const isTitleColumn = (cell: HostNodeRow[keyof HostNodeRow]): cell is HostNodeRo }; const sortValues = (aValue: any, bValue: any, { direction }: Sorting) => { - if (typeof aValue === 'string' && typeof bValue === 'string') { - return direction === 'desc' ? bValue.localeCompare(aValue) : aValue.localeCompare(bValue); + const a = aValue ?? -1; + const b = bValue ?? -1; + + if (typeof a === 'string' && typeof b === 'string') { + return direction === 'desc' ? b.localeCompare(a) : a.localeCompare(b); } - if (isNumber(aValue) && isNumber(bValue)) { - return direction === 'desc' ? bValue - aValue : aValue - bValue; + if (isNumber(a) && isNumber(b)) { + return direction === 'desc' ? b - a : a - b; } return 1; @@ -358,7 +375,8 @@ export const useHostsTable = () => { field: 'cpuV2', sortable: true, 'data-test-subj': 'hostsView-tableRow-cpuUsage', - render: (avg: number) => formatMetric('cpuV2', avg), + render: (avg: number, { hasSystemMetrics }: HostNodeRow) => + buildMetricCell(avg, 'cpuV2', hasSystemMetrics), align: 'right', }, { @@ -373,7 +391,8 @@ export const useHostsTable = () => { field: 'normalizedLoad1m', sortable: true, 'data-test-subj': 'hostsView-tableRow-normalizedLoad1m', - render: (avg: number) => formatMetric('normalizedLoad1m', avg), + render: (avg: number, { hasSystemMetrics }: HostNodeRow) => + buildMetricCell(avg, 'normalizedLoad1m', hasSystemMetrics), align: 'right', }, { @@ -388,7 +407,8 @@ export const useHostsTable = () => { field: 'memory', sortable: true, 'data-test-subj': 'hostsView-tableRow-memoryUsage', - render: (avg: number) => formatMetric('memory', avg), + render: (avg: number, { hasSystemMetrics }: HostNodeRow) => + buildMetricCell(avg, 'memory', hasSystemMetrics), align: 'right', }, { @@ -403,7 +423,8 @@ export const useHostsTable = () => { field: 'memoryFree', sortable: true, 'data-test-subj': 'hostsView-tableRow-memoryFree', - render: (avg: number) => formatMetric('memoryFree', avg), + render: (avg: number, { hasSystemMetrics }: HostNodeRow) => + buildMetricCell(avg, 'memoryFree', hasSystemMetrics), align: 'right', }, { @@ -418,7 +439,8 @@ export const useHostsTable = () => { field: 'diskSpaceUsage', sortable: true, 'data-test-subj': 'hostsView-tableRow-diskSpaceUsage', - render: (max: number) => formatMetric('diskSpaceUsage', max), + render: (max: number, { hasSystemMetrics }: HostNodeRow) => + buildMetricCell(max, 'diskSpaceUsage', hasSystemMetrics), align: 'right', }, { @@ -433,7 +455,8 @@ export const useHostsTable = () => { field: 'rxV2', sortable: true, 'data-test-subj': 'hostsView-tableRow-rx', - render: (avg: number) => formatMetric('rx', avg), + render: (avg: number, { hasSystemMetrics }: HostNodeRow) => + buildMetricCell(avg, 'rx', hasSystemMetrics), align: 'right', }, { @@ -448,7 +471,8 @@ export const useHostsTable = () => { field: 'txV2', sortable: true, 'data-test-subj': 'hostsView-tableRow-tx', - render: (avg: number) => formatMetric('tx', avg), + render: (avg: number, { hasSystemMetrics }: HostNodeRow) => + buildMetricCell(avg, 'tx', hasSystemMetrics), align: 'right', }, ], diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/inventory_view/components/waffle/legend_controls.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/inventory_view/components/waffle/legend_controls.tsx index 92c57e9459916..7b81056b32b8f 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/inventory_view/components/waffle/legend_controls.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/inventory_view/components/waffle/legend_controls.tsx @@ -27,6 +27,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import React, { SyntheticEvent, useState, useCallback, useEffect } from 'react'; import { first, last } from 'lodash'; +import { EuiRangeProps, EuiSelectProps } from '@elastic/eui'; import type { WaffleLegendOptions } from '../../hooks/use_waffle_options'; import { type InfraWaffleMapBounds, @@ -148,17 +149,17 @@ export const LegendControls = ({ setPopoverState(false); }, [autoBounds, boundsOverride, options]); - const handleStepsChange = useCallback( + const handleStepsChange = useCallback>( (e) => { - const steps = parseInt(e.target.value, 10); + const steps = parseInt((e.target as HTMLInputElement).value, 10); setLegendOptions((previous) => ({ ...previous, steps })); }, [setLegendOptions] ); - const handlePaletteChange = useCallback( + const handlePaletteChange = useCallback>( (e) => { - const palette = e.target.value; + const palette = e.target.value as WaffleLegendOptions['palette']; setLegendOptions((previous) => ({ ...previous, palette })); }, [setLegendOptions] diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/components/aggregation.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/components/aggregation.tsx index 582c52a969ac3..9a24e0b0cd0e6 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/components/aggregation.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/components/aggregation.tsx @@ -10,6 +10,7 @@ import { i18n } from '@kbn/i18n'; import React, { useCallback } from 'react'; import { xor } from 'lodash'; +import { EuiSelectProps } from '@elastic/eui'; import { MetricsExplorerAggregation } from '../../../../../common/http_api/metrics_explorer'; import { MetricsExplorerOptions } from '../hooks/use_metrics_explorer_options'; import { @@ -56,7 +57,7 @@ export const MetricsExplorerAggregationPicker = ({ options, onChange }: Props) = }), }; - const handleChange = useCallback( + const handleChange = useCallback>( (e) => { const aggregation = (metricsExplorerAggregationRT.is(e.target.value) && e.target.value) || 'avg'; diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/components/chart_options.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/components/chart_options.tsx index abd82b4e74a90..01471fab526ae 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/components/chart_options.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/components/chart_options.tsx @@ -15,6 +15,7 @@ import { EuiForm, EuiFormRow, EuiSwitch, + EuiSwitchProps, } from '@elastic/eui'; import { MetricsExplorerChartOptions as ChartOptions, @@ -111,7 +112,7 @@ export const MetricsExplorerChartOptions = ({ chartOptions, onChange }: Props) = [chartOptions, onChange] ); - const handleStackChange = useCallback( + const handleStackChange = useCallback( (e) => { onChange({ ...chartOptions, diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/components/metrics.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/components/metrics.tsx index 4e2764d9222e0..c493d2922359b 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/components/metrics.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/components/metrics.tsx @@ -60,7 +60,7 @@ export const MetricsExplorerMetrics = ({ options, onChange, autoFocus = false }: ); const handleChange = useCallback( - (selectedOptions) => { + (selectedOptions: any) => { onChange( selectedOptions.map((opt: SelectedOption, index: number) => ({ aggregation: options.aggregation, diff --git a/x-pack/plugins/observability_solution/investigate/common/index.ts b/x-pack/plugins/observability_solution/investigate/common/index.ts index 541e2d7206bf3..47b5ad6ed2318 100644 --- a/x-pack/plugins/observability_solution/investigate/common/index.ts +++ b/x-pack/plugins/observability_solution/investigate/common/index.ts @@ -4,11 +4,5 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -export type { - Investigation, - InvestigateWidget, - InvestigateWidgetCreate, - InvestigationNote, -} from './types'; export { mergePlainObjects } from './utils/merge_plain_objects'; diff --git a/x-pack/plugins/observability_solution/investigate/common/types.ts b/x-pack/plugins/observability_solution/investigate/common/types.ts index 8a2bba966ed7e..55eab5836ce5b 100644 --- a/x-pack/plugins/observability_solution/investigate/common/types.ts +++ b/x-pack/plugins/observability_solution/investigate/common/types.ts @@ -5,47 +5,9 @@ * 2.0. */ -import type { DeepPartial } from 'utility-types'; - export interface GlobalWidgetParameters { timeRange: { from: string; to: string; }; } - -export interface Investigation { - id: string; - createdAt: number; - title: string; - items: InvestigateWidget[]; - notes: InvestigationNote[]; - parameters: GlobalWidgetParameters; -} - -export interface InvestigationNote { - id: string; - createdAt: number; - createdBy: string; - content: string; -} - -export interface InvestigateWidget< - TParameters extends Record = {}, - TData extends Record = {} -> { - id: string; - createdAt: number; - createdBy: string; - title: string; - type: string; - parameters: GlobalWidgetParameters & TParameters; - data: TData; -} - -export type InvestigateWidgetCreate = {}> = Pick< - InvestigateWidget, - 'title' | 'type' -> & { - parameters: DeepPartial & TParameters; -}; diff --git a/x-pack/plugins/observability_solution/investigate/public/create_widget.ts b/x-pack/plugins/observability_solution/investigate/public/create_widget.ts deleted file mode 100644 index 697202ac42d2b..0000000000000 --- a/x-pack/plugins/observability_solution/investigate/public/create_widget.ts +++ /dev/null @@ -1,35 +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 { DeepPartial } from 'utility-types'; -import { InvestigateWidgetCreate } from '../common'; -import { GlobalWidgetParameters } from '../common/types'; - -type MakePartial, K extends keyof T> = Omit & - DeepPartial>; - -type PredefinedKeys = 'type'; - -export type WidgetFactory> = < - T extends MakePartial, PredefinedKeys> ->( - widgetCreate: T -) => Pick, PredefinedKeys> & - Omit & { parameters: T['parameters'] & DeepPartial }; - -export function createWidgetFactory>( - type: string -): WidgetFactory { - const createWidget: WidgetFactory = (widgetCreate) => { - return { - type, - ...widgetCreate, - }; - }; - - return createWidget; -} diff --git a/x-pack/plugins/observability_solution/investigate/public/esql_widget/create_esql_widget.ts b/x-pack/plugins/observability_solution/investigate/public/esql_widget/create_esql_widget.ts deleted file mode 100644 index f3226afd14198..0000000000000 --- a/x-pack/plugins/observability_solution/investigate/public/esql_widget/create_esql_widget.ts +++ /dev/null @@ -1,12 +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 { createWidgetFactory } from '../create_widget'; -import { ESQL_WIDGET_NAME } from './constants'; -import type { EsqlWidgetParameters } from './types'; - -export const createEsqlWidget = createWidgetFactory(ESQL_WIDGET_NAME); diff --git a/x-pack/plugins/observability_solution/investigate/public/esql_widget/types.ts b/x-pack/plugins/observability_solution/investigate/public/esql_widget/types.ts deleted file mode 100644 index 764daedc9c5ed..0000000000000 --- a/x-pack/plugins/observability_solution/investigate/public/esql_widget/types.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 type { IconType } from '@elastic/eui'; -import type { Ast } from '@kbn/interpreter'; - -// copied over from the Lens plugin to prevent dependency hell -type TableChangeType = 'initial' | 'unchanged' | 'reduced' | 'extended' | 'reorder' | 'layers'; - -interface Suggestion { - visualizationId: string; - datasourceState?: V; - datasourceId?: string; - columns: number; - score: number; - title: string; - visualizationState: T; - previewExpression?: Ast | string; - previewIcon: IconType; - hide?: boolean; - // flag to indicate if the visualization is incomplete - incomplete?: boolean; - changeType: TableChangeType; - keptLayerIds: string[]; -} - -export interface EsqlWidgetParameters { - esql: string; - suggestion?: Suggestion; -} diff --git a/x-pack/plugins/observability_solution/investigate/public/hooks/use_investigation/create_new_investigation.ts b/x-pack/plugins/observability_solution/investigate/public/hooks/use_investigation/create_new_investigation.ts deleted file mode 100644 index af6227e552115..0000000000000 --- a/x-pack/plugins/observability_solution/investigate/public/hooks/use_investigation/create_new_investigation.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; -import { GetInvestigationResponse } from '@kbn/investigation-shared'; -import { v4 } from 'uuid'; -import type { Investigation } from '../../../common'; - -export function createNewInvestigation(): Investigation { - return { - id: v4(), - createdAt: new Date().getTime(), - title: i18n.translate('xpack.investigate.newInvestigationTitle', { - defaultMessage: 'New investigation', - }), - items: [], - notes: [], - parameters: { - timeRange: { - from: new Date(Date.now() - 15 * 60 * 1000).toISOString(), - to: new Date().toISOString(), - }, - }, - }; -} - -export function fromInvestigationResponse( - investigationData: GetInvestigationResponse -): Investigation { - return { - id: investigationData.id, - createdAt: investigationData.createdAt, - title: investigationData.title, - items: [], - notes: investigationData.notes, - parameters: { - timeRange: { - from: new Date(investigationData.params.timeRange.from).toISOString(), - to: new Date(investigationData.params.timeRange.to).toISOString(), - }, - }, - }; -} diff --git a/x-pack/plugins/observability_solution/investigate/public/hooks/use_investigation/index.tsx b/x-pack/plugins/observability_solution/investigate/public/hooks/use_investigation/index.tsx deleted file mode 100644 index fd3c50cdb80ac..0000000000000 --- a/x-pack/plugins/observability_solution/investigate/public/hooks/use_investigation/index.tsx +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import type { AuthenticatedUser, NotificationsStart } from '@kbn/core/public'; -import { i18n } from '@kbn/i18n'; -import { GetInvestigationResponse } from '@kbn/investigation-shared'; -import { pull } from 'lodash'; -import React, { useMemo, useRef, useState } from 'react'; -import useObservable from 'react-use/lib/useObservable'; -import { v4 } from 'uuid'; -import type { GlobalWidgetParameters } from '../..'; -import type { InvestigateWidget, InvestigateWidgetCreate } from '../../../common'; -import type { WidgetDefinition } from '../../types'; -import { createNewInvestigation, fromInvestigationResponse } from './create_new_investigation'; -import { StatefulInvestigation, createInvestigationStore } from './investigation_store'; - -export type RenderableInvestigateWidget = InvestigateWidget & { - loading: boolean; - element: React.ReactNode; -}; - -export type RenderableInvestigation = Omit & { - items: RenderableInvestigateWidget[]; -}; - -export interface UseInvestigationApi { - investigation?: StatefulInvestigation; - renderableInvestigation?: RenderableInvestigation; - copyItem: (id: string) => Promise; - deleteItem: (id: string) => Promise; - addItem: (options: InvestigateWidgetCreate) => Promise; - setGlobalParameters: (parameters: GlobalWidgetParameters) => Promise; - setTitle: (title: string) => Promise; -} - -function useInvestigationWithoutContext({ - user, - notifications, - widgetDefinitions, - investigationData, -}: { - user: AuthenticatedUser; - notifications: NotificationsStart; - widgetDefinitions: WidgetDefinition[]; - investigationData?: GetInvestigationResponse; -}): UseInvestigationApi { - const [investigationStore, _] = useState(() => - createInvestigationStore({ - user, - widgetDefinitions, - investigation: investigationData - ? fromInvestigationResponse(investigationData) - : createNewInvestigation(), - }) - ); - - const investigation$ = investigationStore.asObservable(); - const investigation = useObservable(investigation$)?.investigation; - - const addItem = async (widget: InvestigateWidgetCreate) => { - try { - const id = v4(); - await investigationStore.addItem(id, widget); - } catch (error) { - notifications.showErrorDialog({ - title: i18n.translate('xpack.investigate.failedToAddWidget', { - defaultMessage: 'Failed to add widget', - }), - error, - }); - } - }; - - const deleteItem = async (id: string) => { - return investigationStore.deleteItem(id); - }; - - const widgetComponentsById = useRef< - Record> - >({}); - - const itemsWithContext = useMemo(() => { - const unusedComponentIds = Object.keys(widgetComponentsById); - - const nextItemsWithContext = - investigation?.items.map((item) => { - let Component = widgetComponentsById.current[item.id]; - if (!Component) { - const id = item.id; - const widgetDefinition = widgetDefinitions.find( - (definition) => definition.type === item.type - )!; - - Component = widgetComponentsById.current[id] = (props) => { - return <>{widgetDefinition?.render({ widget: props.widget })}; - }; - } - - pull(unusedComponentIds, item.id); - - return { - ...item, - Component, - }; - }) ?? []; - - unusedComponentIds.forEach((id) => { - delete widgetComponentsById.current[id]; - }); - - return nextItemsWithContext; - }, [investigation?.items, widgetDefinitions]); - - const renderableInvestigation = useMemo(() => { - return investigation - ? { - ...investigation, - items: itemsWithContext.map((item) => { - const { Component, ...rest } = item; - return { - ...rest, - element: , - }; - }), - } - : undefined; - }, [investigation, itemsWithContext]); - - const { copyItem, setGlobalParameters, setTitle } = investigationStore; - - return { - addItem, - copyItem, - deleteItem, - investigation, - renderableInvestigation, - setGlobalParameters, - setTitle, - }; -} - -export function createUseInvestigation({ - notifications, - widgetDefinitions, -}: { - notifications: NotificationsStart; - widgetDefinitions: WidgetDefinition[]; -}) { - return ({ - user, - investigationData, - }: { - user: AuthenticatedUser; - investigationData?: GetInvestigationResponse; - }) => { - return useInvestigationWithoutContext({ - user, - notifications, - widgetDefinitions, - investigationData, - }); - }; -} diff --git a/x-pack/plugins/observability_solution/investigate/public/hooks/use_investigation/investigation_store.ts b/x-pack/plugins/observability_solution/investigate/public/hooks/use_investigation/investigation_store.ts deleted file mode 100644 index be2da347f995a..0000000000000 --- a/x-pack/plugins/observability_solution/investigate/public/hooks/use_investigation/investigation_store.ts +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { AuthenticatedUser } from '@kbn/security-plugin/common'; -import { MaybePromise } from '@kbn/utility-types'; -import { BehaviorSubject, Observable } from 'rxjs'; -import { v4 } from 'uuid'; -import { InvestigateWidget } from '../../../common'; -import { - GlobalWidgetParameters, - InvestigateWidgetCreate, - Investigation, -} from '../../../common/types'; -import { WidgetDefinition } from '../../types'; -import { regenerateItem } from './regenerate_item'; - -export type StatefulInvestigateWidget = InvestigateWidget & { - loading: boolean; -}; - -export type StatefulInvestigation = Omit & { - items: StatefulInvestigateWidget[]; -}; - -interface InvestigationStore { - copyItem: (id: string) => Promise; - deleteItem: (id: string) => Promise; - addItem: (id: string, item: InvestigateWidgetCreate) => Promise; - asObservable: () => Observable<{ - investigation: StatefulInvestigation; - }>; - setGlobalParameters: (globalWidgetParameters: GlobalWidgetParameters) => Promise; - setTitle: (title: string) => Promise; - destroy: () => void; -} - -export function createInvestigationStore({ - investigation, - user, - widgetDefinitions, -}: { - investigation: Investigation; - user: AuthenticatedUser; - widgetDefinitions: WidgetDefinition[]; -}): InvestigationStore { - const controller = new AbortController(); - - const observable$ = new BehaviorSubject<{ investigation: StatefulInvestigation }>({ - investigation: { - ...investigation, - items: investigation.items.map((item) => ({ ...item, loading: false })), - }, - }); - - async function updateInvestigationInPlace( - cb: (prevInvestigation: StatefulInvestigation) => MaybePromise - ) { - observable$.next({ investigation: await cb(observable$.value.investigation) }); - } - - const asObservable = observable$.asObservable(); - - return { - addItem: (itemId, item) => { - return updateInvestigationInPlace(async (prevInvestigation) => { - return { - ...prevInvestigation, - items: prevInvestigation.items.concat({ - ...(await regenerateItem({ - user, - widgetDefinitions, - signal: controller.signal, - widget: { - ...item, - id: itemId, - }, - globalWidgetParameters: prevInvestigation.parameters, - })), - loading: false, - }), - }; - }); - }, - copyItem: (itemId) => { - return updateInvestigationInPlace((prevInvestigation) => { - const itemToCopy = prevInvestigation.items.find((item) => item.id === itemId); - if (!itemToCopy) { - throw new Error('Cannot find item for id ' + itemId); - } - return { - ...prevInvestigation, - items: prevInvestigation.items.concat({ - ...itemToCopy, - id: v4(), - }), - }; - }); - }, - deleteItem: (itemId) => { - return updateInvestigationInPlace((prevInvestigation) => { - return { - ...prevInvestigation, - items: prevInvestigation.items.filter((item) => item.id !== itemId), - }; - }); - }, - asObservable: () => asObservable, - destroy: () => { - return controller.abort(); - }, - setGlobalParameters: async (parameters) => { - await updateInvestigationInPlace((prevInvestigation) => { - return { - ...prevInvestigation, - items: prevInvestigation.items.map((item) => { - return { ...item, loading: true }; - }), - }; - }); - - await updateInvestigationInPlace(async (prevInvestigation) => { - return { - ...prevInvestigation, - parameters, - items: await Promise.all( - prevInvestigation.items.map(async (item) => { - return { - ...(await regenerateItem({ - widget: item, - globalWidgetParameters: parameters, - signal: controller.signal, - user, - widgetDefinitions, - })), - loading: false, - }; - }) - ), - }; - }); - }, - setTitle: async (title: string) => { - return updateInvestigationInPlace((prevInvestigation) => { - return { ...prevInvestigation, title }; - }); - }, - }; -} diff --git a/x-pack/plugins/observability_solution/investigate/public/hooks/use_investigation/regenerate_item.ts b/x-pack/plugins/observability_solution/investigate/public/hooks/use_investigation/regenerate_item.ts deleted file mode 100644 index 7f7d6208ed9eb..0000000000000 --- a/x-pack/plugins/observability_solution/investigate/public/hooks/use_investigation/regenerate_item.ts +++ /dev/null @@ -1,52 +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 { AuthenticatedUser } from '@kbn/core-security-common'; -import { v4 } from 'uuid'; -import { InvestigateWidget, InvestigateWidgetCreate, mergePlainObjects } from '../../../common'; -import { GlobalWidgetParameters } from '../../../common/types'; -import { WidgetDefinition } from '../../types'; - -export async function regenerateItem({ - user, - widgetDefinitions, - signal, - widget, - globalWidgetParameters, -}: { - user: AuthenticatedUser; - widgetDefinitions: WidgetDefinition[]; - widget: InvestigateWidgetCreate | InvestigateWidget; - signal: AbortSignal; - globalWidgetParameters: GlobalWidgetParameters; -}): Promise { - const now = Date.now(); - - const definition = widgetDefinitions.find( - (currentDefinition) => currentDefinition.type === widget.type - ); - - if (!definition) { - throw new Error(`Definition for widget ${widget.type} not found`); - } - - const nextParameters = mergePlainObjects(widget.parameters, globalWidgetParameters); - - const widgetData = await definition.generate({ - parameters: nextParameters, - signal, - }); - - return { - createdAt: now, - id: v4(), - ...widget, - parameters: nextParameters, - data: widgetData, - createdBy: user.username, - }; -} diff --git a/x-pack/plugins/observability_solution/investigate/public/index.ts b/x-pack/plugins/observability_solution/investigate/public/index.ts index 2f55a27ef1c27..07493d8360552 100644 --- a/x-pack/plugins/observability_solution/investigate/public/index.ts +++ b/x-pack/plugins/observability_solution/investigate/public/index.ts @@ -13,27 +13,16 @@ import type { InvestigateSetupDependencies, InvestigateStartDependencies, ConfigSchema, - OnWidgetAdd, } from './types'; -export type { InvestigatePublicSetup, InvestigatePublicStart, OnWidgetAdd }; +export type { InvestigatePublicSetup, InvestigatePublicStart }; -export { - type Investigation, - type InvestigateWidget, - type InvestigateWidgetCreate, - type GlobalWidgetParameters, -} from '../common/types'; +export { type GlobalWidgetParameters } from '../common/types'; export { mergePlainObjects } from '../common/utils/merge_plain_objects'; -export { createWidgetFactory } from './create_widget'; export { getEsFilterFromGlobalParameters } from './util/get_es_filters_from_global_parameters'; -export { ESQL_WIDGET_NAME } from './esql_widget/constants'; -export { createEsqlWidget } from './esql_widget/create_esql_widget'; -export type { EsqlWidgetParameters } from './esql_widget/types'; - export const plugin: PluginInitializer< InvestigatePublicSetup, InvestigatePublicStart, diff --git a/x-pack/plugins/observability_solution/investigate/public/investigation/item_definition_registry.ts b/x-pack/plugins/observability_solution/investigate/public/investigation/item_definition_registry.ts new file mode 100644 index 0000000000000..6fcb8308e7161 --- /dev/null +++ b/x-pack/plugins/observability_solution/investigate/public/investigation/item_definition_registry.ts @@ -0,0 +1,45 @@ +/* + * 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 { GlobalWidgetParameters } from '../../common/types'; + +export type ItemDefinitionData = Record; +export type ItemDefinitionParams = Record; + +export interface ItemDefinition< + Params extends ItemDefinitionParams = {}, + Data extends ItemDefinitionData = {} +> { + type: string; + generate: (option: { itemParams: Params; globalParams: GlobalWidgetParameters }) => Promise; + render: (option: { + data: Data; + itemParams: Params; + globalParams: GlobalWidgetParameters; + }) => React.ReactNode; +} + +export class ItemDefinitionRegistry { + private readonly definitions: ItemDefinition[] = []; + + constructor() {} + + public registerItem( + definition: ItemDefinition + ) { + // @ts-ignore TODO fix this type issue with generics + this.definitions.push(definition); + } + + public getItemDefinitions(): ItemDefinition[] { + return this.definitions; + } + + public getItemDefinitionByType(type: string): ItemDefinition | undefined { + return this.definitions.find((definition) => definition.type === type); + } +} diff --git a/x-pack/plugins/observability_solution/investigate/public/plugin.tsx b/x-pack/plugins/observability_solution/investigate/public/plugin.tsx index 887753446c4a9..9429383d851a8 100644 --- a/x-pack/plugins/observability_solution/investigate/public/plugin.tsx +++ b/x-pack/plugins/observability_solution/investigate/public/plugin.tsx @@ -4,17 +4,13 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { - AuthenticatedUser, - CoreSetup, - CoreStart, - Plugin, - PluginInitializerContext, -} from '@kbn/core/public'; -import { GetInvestigationResponse } from '@kbn/investigation-shared'; -import type { Logger } from '@kbn/logging'; -import { useMemo } from 'react'; -import { createUseInvestigation } from './hooks/use_investigation'; +import type { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from '@kbn/core/public'; +import { + ItemDefinition, + ItemDefinitionData, + ItemDefinitionParams, + ItemDefinitionRegistry, +} from './investigation/item_definition_registry'; import type { ConfigSchema, InvestigatePublicSetup, @@ -22,7 +18,6 @@ import type { InvestigateSetupDependencies, InvestigateStartDependencies, } from './types'; -import { WidgetRegistry } from './widget_registry'; export class InvestigatePlugin implements @@ -33,57 +28,28 @@ export class InvestigatePlugin InvestigateStartDependencies > { - logger: Logger; - - widgetRegistry: WidgetRegistry = new WidgetRegistry(); + private itemDefinitionRegistry: ItemDefinitionRegistry = new ItemDefinitionRegistry(); - registrationPromises: Array> = []; + constructor(context: PluginInitializerContext) {} - constructor(context: PluginInitializerContext) { - this.logger = context.logger.get(); - } setup(coreSetup: CoreSetup, pluginsSetup: InvestigateSetupDependencies): InvestigatePublicSetup { return { - register: (callback) => { - const registrationPromise = Promise.race([ - callback(this.widgetRegistry.registerWidget), - new Promise((resolve, reject) => { - setTimeout(() => { - reject(new Error('Timed out running registration function')); - }, 30000); - }), - ]).catch((error) => { - this.logger.error( - new Error('Encountered an error during widget registration', { cause: error }) - ); - return Promise.resolve(); - }); - - this.registrationPromises.push(registrationPromise); + registerItemDefinition: < + Params extends ItemDefinitionParams, + Data extends ItemDefinitionData + >( + definition: ItemDefinition + ) => { + this.itemDefinitionRegistry.registerItem(definition); }, }; } start(coreStart: CoreStart, pluginsStart: InvestigateStartDependencies): InvestigatePublicStart { return { - getWidgetDefinitions: this.widgetRegistry.getWidgetDefinitions, - useInvestigation: ({ - user, - investigationData, - }: { - user: AuthenticatedUser; - investigationData?: GetInvestigationResponse; - }) => { - const widgetDefinitions = useMemo(() => this.widgetRegistry.getWidgetDefinitions(), []); - - return createUseInvestigation({ - notifications: coreStart.notifications, - widgetDefinitions, - })({ - user, - investigationData, - }); - }, + getItemDefinitions: () => this.itemDefinitionRegistry.getItemDefinitions(), + getItemDefinitionByType: (type: string) => + this.itemDefinitionRegistry.getItemDefinitionByType(type), }; } } diff --git a/x-pack/plugins/observability_solution/investigate/public/types.ts b/x-pack/plugins/observability_solution/investigate/public/types.ts index dc6eb8b62021d..36a87759c2711 100644 --- a/x-pack/plugins/observability_solution/investigate/public/types.ts +++ b/x-pack/plugins/observability_solution/investigate/public/types.ts @@ -6,54 +6,11 @@ */ /* eslint-disable @typescript-eslint/no-empty-interface*/ -import type { AuthenticatedUser } from '@kbn/core/public'; -import type { CompatibleJSONSchema } from '@kbn/observability-ai-assistant-plugin/public'; -import type { GetInvestigationResponse } from '@kbn/investigation-shared'; -import type { FromSchema } from 'json-schema-to-ts'; -import type { InvestigateWidget } from '../common'; -import type { GlobalWidgetParameters, InvestigateWidgetCreate } from '../common/types'; -import type { UseInvestigationApi } from './hooks/use_investigation'; - -export type OnWidgetAdd = (create: InvestigateWidgetCreate) => Promise; - -interface WidgetRenderOptions { - widget: TInvestigateWidget; -} - -export interface WidgetDefinition { - type: string; - description: string; - schema: CompatibleJSONSchema; - generate: (options: { - parameters: GlobalWidgetParameters; - signal: AbortSignal; - }) => Promise>; - render: (options: WidgetRenderOptions) => React.ReactNode; -} - -type RegisterWidgetOptions = Omit; - -type MaybeSchemaFrom = - {} & (TSchema extends CompatibleJSONSchema ? FromSchema : {}); - -type GenerateCallback< - TSchema extends CompatibleJSONSchema | undefined, - TData extends Record | undefined -> = (options: { - parameters: MaybeSchemaFrom & GlobalWidgetParameters; - signal: AbortSignal; -}) => Promise; - -export type RegisterWidget = < - TSchema extends CompatibleJSONSchema, - TData extends Record ->( - definition: Omit & { schema: TSchema }, - generateCallback: GenerateCallback, - renderCallback: ( - options: WidgetRenderOptions, TData>> - ) => React.ReactNode -) => void; +import { + ItemDefinition, + ItemDefinitionData, + ItemDefinitionParams, +} from './investigation/item_definition_registry'; export interface ConfigSchema {} @@ -62,13 +19,15 @@ export interface InvestigateSetupDependencies {} export interface InvestigateStartDependencies {} export interface InvestigatePublicSetup { - register: (callback: (registerWidget: RegisterWidget) => Promise) => void; + registerItemDefinition: < + Params extends ItemDefinitionParams = {}, + Data extends ItemDefinitionData = {} + >( + itemDefinition: ItemDefinition + ) => void; } export interface InvestigatePublicStart { - getWidgetDefinitions: () => WidgetDefinition[]; - useInvestigation: ({}: { - user: AuthenticatedUser; - investigationData?: GetInvestigationResponse; - }) => UseInvestigationApi; + getItemDefinitions: () => ItemDefinition[]; + getItemDefinitionByType: (type: string) => ItemDefinition | undefined; } diff --git a/x-pack/plugins/observability_solution/investigate/public/widget_registry.ts b/x-pack/plugins/observability_solution/investigate/public/widget_registry.ts deleted file mode 100644 index f76adf5a72506..0000000000000 --- a/x-pack/plugins/observability_solution/investigate/public/widget_registry.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { RegisterWidget, WidgetDefinition } from './types'; - -export class WidgetRegistry { - private readonly definitions: WidgetDefinition[] = []; - - constructor() {} - - registerWidget: RegisterWidget = (definition, generateCallback, renderCallback) => { - this.definitions.push({ - ...definition, - generate: generateCallback as WidgetDefinition['generate'], - render: renderCallback as WidgetDefinition['render'], - }); - }; - - getWidgetDefinitions = (): WidgetDefinition[] => { - return this.definitions; - }; -} diff --git a/x-pack/plugins/observability_solution/investigate/tsconfig.json b/x-pack/plugins/observability_solution/investigate/tsconfig.json index d48acf4a215ad..e2e39f527c2e1 100644 --- a/x-pack/plugins/observability_solution/investigate/tsconfig.json +++ b/x-pack/plugins/observability_solution/investigate/tsconfig.json @@ -14,14 +14,7 @@ "@kbn/core", "@kbn/logging", "@kbn/config-schema", - "@kbn/observability-ai-assistant-plugin", "@kbn/es-query", - "@kbn/interpreter", - "@kbn/security-plugin", - "@kbn/i18n", - "@kbn/utility-types", - "@kbn/core-security-common", - "@kbn/investigation-shared", ], "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/observability_solution/investigate_app/kibana.jsonc b/x-pack/plugins/observability_solution/investigate_app/kibana.jsonc index 5b31cbc3973a2..c7e860a047366 100644 --- a/x-pack/plugins/observability_solution/investigate_app/kibana.jsonc +++ b/x-pack/plugins/observability_solution/investigate_app/kibana.jsonc @@ -21,9 +21,9 @@ "security", ], "requiredBundles": [ + "esql", "kibanaReact", "kibanaUtils", - "esql", "esqlDataGrid", ], "optionalPlugins": [], diff --git a/x-pack/plugins/observability_solution/investigate_app/public/components/investigate_widget_grid/index.stories.tsx b/x-pack/plugins/observability_solution/investigate_app/public/components/investigate_widget_grid/index.stories.tsx deleted file mode 100644 index 072d25b1e5526..0000000000000 --- a/x-pack/plugins/observability_solution/investigate_app/public/components/investigate_widget_grid/index.stories.tsx +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { ComponentMeta, ComponentStoryObj } from '@storybook/react'; -import React, { useState } from 'react'; -import { v4 } from 'uuid'; -import { InvestigateWidgetGrid as Component, InvestigateWidgetGridItem } from '.'; -import { KibanaReactStorybookDecorator } from '../../../.storybook/storybook_decorator'; - -const meta: ComponentMeta = { - component: Component, - title: 'app/Organisms/InvestigateWidgetGrid', - decorators: [KibanaReactStorybookDecorator], -}; - -export default meta; - -function WithPersistedChanges(props: React.ComponentProps) { - const [items, setItems] = useState(props.items); - - return ( - { - setItems((prevItems) => - prevItems.concat({ - ...item, - id: v4(), - }) - ); - }} - onItemDelete={async (item) => { - setItems((prevItems) => prevItems.filter((currentItem) => currentItem.id !== item.id)); - }} - items={items} - /> - ); -} - -const defaultProps: ComponentStoryObj = { - args: {}, - render: (props) => ( -
- -
- ), -}; - -function createItem>(overrides: T) { - return { - ...overrides, - id: v4(), - columns: 4, - rows: 2, - description: '', - loading: false, - overrides: [], - }; -} - -export const InvestigateWidgetGridStory: ComponentStoryObj = { - ...defaultProps, - args: { - ...defaultProps.args, - items: [ - createItem({ - title: '1', - element: ( -
- This should not overflow -
- ), - columns: 4, - rows: 12, - }), - - createItem({ - title: '2', - element: <>TODO, - columns: 2, - rows: 3, - overrides: [ - { - id: v4(), - label: '4 hours earlier', - }, - { - id: v4(), - label: 'service.name:opbeans-java AND service.enviroment:(production OR development)', - }, - ], - }), - createItem({ - title: '3', - element: <>TODO, - columns: 2, - rows: 3, - }), - createItem({ - title: '4', - element: <>TODO, - columns: 4, - rows: 3, - }), - ], - }, - name: 'default', -}; diff --git a/x-pack/plugins/observability_solution/investigate_app/public/components/investigate_widget_grid/styles.scss b/x-pack/plugins/observability_solution/investigate_app/public/components/investigate_widget_grid/styles.scss deleted file mode 100644 index 5528e053f84aa..0000000000000 --- a/x-pack/plugins/observability_solution/investigate_app/public/components/investigate_widget_grid/styles.scss +++ /dev/null @@ -1 +0,0 @@ -@import '../../../../../../../src/plugins/dashboard/public/dashboard_container/dashboard_container'; diff --git a/x-pack/plugins/observability_solution/investigate_app/public/hooks/query_key_factory.ts b/x-pack/plugins/observability_solution/investigate_app/public/hooks/query_key_factory.ts index d2f6bc9060e43..62078d7d55bca 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/hooks/query_key_factory.ts +++ b/x-pack/plugins/observability_solution/investigate_app/public/hooks/query_key_factory.ts @@ -13,6 +13,9 @@ export const investigationKeys = { notes: ['investigation', 'notes'] as const, fetchNotes: (params: { investigationId: string }) => [...investigationKeys.notes, 'fetch', params] as const, + items: ['investigation', 'items'] as const, + fetchItems: (params: { investigationId: string }) => + [...investigationKeys.items, 'fetch', params] as const, }; export type InvestigationKeys = typeof investigationKeys; diff --git a/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_add_investigation_item.ts b/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_add_investigation_item.ts new file mode 100644 index 0000000000000..a11b5d976fe00 --- /dev/null +++ b/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_add_investigation_item.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public'; +import { + CreateInvestigationItemParams, + CreateInvestigationItemResponse, +} from '@kbn/investigation-shared'; +import { useMutation } from '@tanstack/react-query'; +import { useKibana } from './use_kibana'; + +type ServerError = IHttpFetchError; + +export function useAddInvestigationItem() { + const { + core: { + http, + notifications: { toasts }, + }, + } = useKibana(); + + return useMutation< + CreateInvestigationItemResponse, + ServerError, + { investigationId: string; item: CreateInvestigationItemParams }, + { investigationId: string } + >( + ['addInvestigationItem'], + ({ investigationId, item }) => { + const body = JSON.stringify(item); + return http.post( + `/api/observability/investigations/${investigationId}/items`, + { body, version: '2023-10-31' } + ); + }, + { + onSuccess: (response, {}) => { + toasts.addSuccess('Item saved'); + }, + onError: (error, {}, context) => { + toasts.addError(new Error(error.body?.message ?? 'An error occurred'), { title: 'Error' }); + }, + } + ); +} diff --git a/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_delete_investigation_item.ts b/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_delete_investigation_item.ts new file mode 100644 index 0000000000000..41c19013e6b2d --- /dev/null +++ b/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_delete_investigation_item.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public'; +import { useMutation } from '@tanstack/react-query'; +import { useKibana } from './use_kibana'; + +type ServerError = IHttpFetchError; + +export function useDeleteInvestigationItem() { + const { + core: { + http, + notifications: { toasts }, + }, + } = useKibana(); + + return useMutation< + void, + ServerError, + { investigationId: string; itemId: string }, + { investigationId: string } + >( + ['deleteInvestigationItem'], + ({ investigationId, itemId }) => { + return http.delete( + `/api/observability/investigations/${investigationId}/items/${itemId}`, + { version: '2023-10-31' } + ); + }, + { + onSuccess: (response, {}) => { + toasts.addSuccess('Item deleted'); + }, + onError: (error, {}, context) => { + toasts.addError(new Error(error.body?.message ?? 'An error occurred'), { title: 'Error' }); + }, + } + ); +} diff --git a/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_delete_investigation_note.ts b/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_delete_investigation_note.ts index 136387372c581..aed3cc571ec92 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_delete_investigation_note.ts +++ b/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_delete_investigation_note.ts @@ -25,7 +25,7 @@ export function useDeleteInvestigationNote() { { investigationId: string; noteId: string }, { investigationId: string } >( - ['addInvestigationNote'], + ['deleteInvestigationNote'], ({ investigationId, noteId }) => { return http.delete( `/api/observability/investigations/${investigationId}/notes/${noteId}`, diff --git a/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_fetch_investigation_items.ts b/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_fetch_investigation_items.ts new file mode 100644 index 0000000000000..5cc253fc6c44d --- /dev/null +++ b/x-pack/plugins/observability_solution/investigate_app/public/hooks/use_fetch_investigation_items.ts @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + GetInvestigationItemsResponse, + InvestigationItemResponse, +} from '@kbn/investigation-shared'; +import { + QueryObserverResult, + RefetchOptions, + RefetchQueryFilters, + useQuery, +} from '@tanstack/react-query'; +import { investigationKeys } from './query_key_factory'; +import { useKibana } from './use_kibana'; + +export interface Params { + investigationId: string; + initialItems?: InvestigationItemResponse[]; +} + +export interface Response { + isInitialLoading: boolean; + isLoading: boolean; + isRefetching: boolean; + isSuccess: boolean; + isError: boolean; + refetch: ( + options?: (RefetchOptions & RefetchQueryFilters) | undefined + ) => Promise>; + data: GetInvestigationItemsResponse | undefined; +} + +export function useFetchInvestigationItems({ investigationId, initialItems }: Params): Response { + const { + core: { + http, + notifications: { toasts }, + }, + } = useKibana(); + + const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data, refetch } = useQuery( + { + queryKey: investigationKeys.fetchItems({ investigationId }), + queryFn: async ({ signal }) => { + return await http.get( + `/api/observability/investigations/${investigationId}/items`, + { version: '2023-10-31', signal } + ); + }, + initialData: initialItems, + refetchOnWindowFocus: false, + refetchInterval: 10 * 1000, + refetchIntervalInBackground: true, + onError: (error: Error) => { + toasts.addError(error, { + title: 'Something went wrong while fetching investigation items', + }); + }, + } + ); + + return { + data, + isInitialLoading, + isLoading, + isRefetching, + isSuccess, + isError, + refetch, + }; +} diff --git a/x-pack/plugins/observability_solution/investigate_app/public/items/README.md b/x-pack/plugins/observability_solution/investigate_app/public/items/README.md new file mode 100644 index 0000000000000..710c9fd3624ec --- /dev/null +++ b/x-pack/plugins/observability_solution/investigate_app/public/items/README.md @@ -0,0 +1 @@ +This folder replaces widgets/ diff --git a/x-pack/plugins/observability_solution/investigate_app/public/widgets/embeddable_widget/register_embeddable_widget.tsx b/x-pack/plugins/observability_solution/investigate_app/public/items/embeddable_item/register_embeddable_item.tsx similarity index 79% rename from x-pack/plugins/observability_solution/investigate_app/public/widgets/embeddable_widget/register_embeddable_widget.tsx rename to x-pack/plugins/observability_solution/investigate_app/public/items/embeddable_item/register_embeddable_item.tsx index 779fb9c5301b9..e07c940c8ca5f 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/widgets/embeddable_widget/register_embeddable_widget.tsx +++ b/x-pack/plugins/observability_solution/investigate_app/public/items/embeddable_item/register_embeddable_item.tsx @@ -6,16 +6,14 @@ */ import { EuiLoadingSpinner } from '@elastic/eui'; import { css } from '@emotion/css'; +import { ReactEmbeddableRenderer } from '@kbn/embeddable-plugin/public'; import type { GlobalWidgetParameters } from '@kbn/investigate-plugin/public'; import { useAbortableAsync } from '@kbn/observability-ai-assistant-plugin/public'; import React, { useEffect, useMemo, useRef, useState } from 'react'; import { v4 } from 'uuid'; -import { ReactEmbeddableRenderer } from '@kbn/embeddable-plugin/public'; -import { EMBEDDABLE_WIDGET_NAME } from '../../constants'; -import { useKibana } from '../../hooks/use_kibana'; -import { RegisterWidgetOptions } from '../register_widgets'; -import { EmbeddableWidgetParameters } from './types'; import { ErrorMessage } from '../../components/error_message'; +import { useKibana } from '../../hooks/use_kibana'; +import { Options } from '../register_items'; const embeddableClassName = css` height: 100%; @@ -24,7 +22,7 @@ const embeddableClassName = css` } `; -type Props = EmbeddableWidgetParameters & GlobalWidgetParameters; +type Props = EmbeddableItemParams & GlobalWidgetParameters; type ParentApi = ReturnType['getParentApi']>; @@ -155,40 +153,38 @@ function EmbeddableWidget(props: Props) { return ; } -export function registerEmbeddableWidget({ registerWidget }: RegisterWidgetOptions) { - registerWidget( - { - type: EMBEDDABLE_WIDGET_NAME, - description: 'Display a saved embeddable', - schema: { - type: 'object', - properties: { - type: { - type: 'string', - }, - config: { - type: 'object', - }, - savedObjectId: { - type: 'string', - }, - }, - required: ['type', 'config'], - } as const, - }, - async ({ parameters, signal }) => { +interface EmbeddableItemParams { + type: string; + config: Record; + savedObjectId?: string; +} + +export function registerEmbeddableItem({ + dependencies: { + setup: { investigate }, + }, + services, +}: Options) { + investigate.registerItemDefinition({ + type: 'esql', + generate: async (option: { + itemParams: EmbeddableItemParams; + globalParams: GlobalWidgetParameters; + }) => { return {}; }, - ({ widget }) => { + render: (option: { + itemParams: EmbeddableItemParams; + globalParams: GlobalWidgetParameters; + }) => { const parameters = { - type: widget.parameters.type, - config: widget.parameters.config, - savedObjectId: widget.parameters.savedObjectId, - timeRange: widget.parameters.timeRange, - query: widget.parameters.query, + type: option.itemParams.type, + config: option.itemParams.config, + savedObjectId: option.itemParams.savedObjectId, + timeRange: option.globalParams.timeRange, }; return ; - } - ); + }, + }); } diff --git a/x-pack/plugins/observability_solution/investigate_app/public/widgets/esql_widget/get_date_histogram_results.ts b/x-pack/plugins/observability_solution/investigate_app/public/items/esql_item/get_date_histogram_results.ts similarity index 100% rename from x-pack/plugins/observability_solution/investigate_app/public/widgets/esql_widget/get_date_histogram_results.ts rename to x-pack/plugins/observability_solution/investigate_app/public/items/esql_item/get_date_histogram_results.ts diff --git a/x-pack/plugins/observability_solution/investigate_app/public/widgets/esql_widget/register_esql_widget.tsx b/x-pack/plugins/observability_solution/investigate_app/public/items/esql_item/register_esql_item.tsx similarity index 80% rename from x-pack/plugins/observability_solution/investigate_app/public/widgets/esql_widget/register_esql_widget.tsx rename to x-pack/plugins/observability_solution/investigate_app/public/items/esql_item/register_esql_item.tsx index 84818c758ffe1..1b62b5476f021 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/widgets/esql_widget/register_esql_widget.tsx +++ b/x-pack/plugins/observability_solution/investigate_app/public/items/esql_item/register_esql_item.tsx @@ -10,20 +10,16 @@ import type { DataView } from '@kbn/data-views-plugin/common'; import type { ESQLSearchResponse } from '@kbn/es-types'; import { ESQLDataGrid } from '@kbn/esql-datagrid/public'; import { i18n } from '@kbn/i18n'; -import { - type EsqlWidgetParameters, - type GlobalWidgetParameters, -} from '@kbn/investigate-plugin/public'; +import { type GlobalWidgetParameters } from '@kbn/investigate-plugin/public'; import type { Suggestion } from '@kbn/lens-plugin/public'; import { useAbortableAsync } from '@kbn/observability-ai-assistant-plugin/public'; import React, { useMemo } from 'react'; import { ErrorMessage } from '../../components/error_message'; -import { ESQL_WIDGET_NAME } from '../../constants'; import { useKibana } from '../../hooks/use_kibana'; import { getDatatableFromEsqlResponse } from '../../utils/get_data_table_from_esql_response'; import { getEsFilterFromOverrides } from '../../utils/get_es_filter_from_overrides'; import { getLensAttrsForSuggestion } from '../../utils/get_lens_attrs_for_suggestion'; -import type { RegisterWidgetOptions } from '../register_widgets'; +import type { Options } from '../register_items'; import { getDateHistogramResults } from './get_date_histogram_results'; const lensClassName = css` @@ -45,6 +41,24 @@ interface Props { }; } +interface EsqlItemParams { + esql: string; + suggestion?: Suggestion; +} + +interface EsqlItemData { + dataView: DataView; + columns: ESQLSearchResponse['columns']; + values: ESQLSearchResponse['values']; + suggestion: Suggestion; + dateHistoResponse?: { + query: string; + columns: ESQLSearchResponse['columns']; + values: ESQLSearchResponse['values']; + groupingExpression: string; + }; +} + export function EsqlWidget({ suggestion, dataView, @@ -207,34 +221,21 @@ export function EsqlWidget({ ); } -export function registerEsqlWidget({ +export function registerEsqlItem({ dependencies: { setup: { investigate }, }, services, - registerWidget, -}: RegisterWidgetOptions) { - registerWidget( - { - type: ESQL_WIDGET_NAME, - description: 'Visualize an ES|QL query', - schema: { - type: 'object', - properties: { - esql: { - description: 'The ES|QL query', - type: 'string', - }, - }, - required: ['esql'], - } as const, - }, - async ({ parameters, signal }) => { - const { - esql: esqlQuery, - timeRange, - suggestion: suggestionFromParameters, - } = parameters as EsqlWidgetParameters & GlobalWidgetParameters; +}: Options) { + investigate.registerItemDefinition({ + type: 'esql', + generate: async (option: { + itemParams: EsqlItemParams; + globalParams: GlobalWidgetParameters; + }) => { + const controller = new AbortController(); + const { esql: esqlQuery, suggestion: suggestionFromParameters } = option.itemParams; + const { timeRange } = option.globalParams; const esql = await services.esql; @@ -252,7 +253,7 @@ export function registerEsqlWidget({ const mainResponse = await esql.queryWithMeta({ query: esqlQuery, - signal, + signal: controller.signal, filter: getFilter(), }); @@ -263,37 +264,36 @@ export function registerEsqlWidget({ columns: mainResponse.query.columns, esql, filter: getFilter(), - signal, + signal: controller.signal, suggestion, timeRange, }); return { - main: { - columns: mainResponse.query.columns, - values: mainResponse.query.values, - suggestion, - dataView: mainResponse.meta.dataView, - }, - dateHistogram: dateHistoResponse, + dataView: mainResponse.meta.dataView, + columns: mainResponse.query.columns, + values: mainResponse.query.values, + suggestion, + dateHistoResponse, }; }, - ({ widget }) => { - const { - main: { dataView, columns, values, suggestion }, - dateHistogram, - } = widget.data; + render: (option: { + itemParams: EsqlItemParams; + globalParams: GlobalWidgetParameters; + data: EsqlItemData; + }) => { + const { itemParams, data } = option; return ( ); - } - ); + }, + }); } diff --git a/x-pack/plugins/observability_solution/investigate_app/public/widgets/register_widgets.ts b/x-pack/plugins/observability_solution/investigate_app/public/items/register_items.ts similarity index 55% rename from x-pack/plugins/observability_solution/investigate_app/public/widgets/register_widgets.ts rename to x-pack/plugins/observability_solution/investigate_app/public/items/register_items.ts index fd2e2b9728176..ff0304105a0b0 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/widgets/register_widgets.ts +++ b/x-pack/plugins/observability_solution/investigate_app/public/items/register_items.ts @@ -5,22 +5,20 @@ * 2.0. */ -import type { RegisterWidget } from '@kbn/investigate-plugin/public/types'; import type { InvestigateAppServices } from '../services/types'; import type { InvestigateAppSetupDependencies, InvestigateAppStartDependencies } from '../types'; -import { registerEmbeddableWidget } from './embeddable_widget/register_embeddable_widget'; -import { registerEsqlWidget } from './esql_widget/register_esql_widget'; +import { registerEmbeddableItem } from './embeddable_item/register_embeddable_item'; +import { registerEsqlItem } from './esql_item/register_esql_item'; -export interface RegisterWidgetOptions { +export interface Options { dependencies: { setup: InvestigateAppSetupDependencies; start: InvestigateAppStartDependencies; }; services: InvestigateAppServices; - registerWidget: RegisterWidget; } -export function registerWidgets(options: RegisterWidgetOptions) { - registerEsqlWidget(options); - registerEmbeddableWidget(options); +export function registerItems(options: Options) { + registerEsqlItem(options); + registerEmbeddableItem(options); } diff --git a/x-pack/plugins/observability_solution/investigate_app/public/components/add_observation_ui/index.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/add_investigation_item/add_investigation_item.tsx similarity index 93% rename from x-pack/plugins/observability_solution/investigate_app/public/components/add_observation_ui/index.tsx rename to x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/add_investigation_item/add_investigation_item.tsx index 69f43ef515146..e4dcd2fe2000d 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/components/add_observation_ui/index.tsx +++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/add_investigation_item/add_investigation_item.tsx @@ -9,19 +9,20 @@ import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiIcon, EuiPanel, EuiTitle } fro import { css } from '@emotion/css'; import { TextBasedLangEditor } from '@kbn/esql/public'; import { i18n } from '@kbn/i18n'; -import { GlobalWidgetParameters, OnWidgetAdd } from '@kbn/investigate-plugin/public'; +import { GlobalWidgetParameters } from '@kbn/investigate-plugin/public'; +import { Item } from '@kbn/investigation-shared'; import React from 'react'; import { EsqlWidgetPreview } from './esql_widget_preview'; type Props = { - onWidgetAdd: OnWidgetAdd; + onItemAdd: (item: Item) => void; } & GlobalWidgetParameters; const emptyPreview = css` padding: 36px 0px 36px 0px; `; -export function AddObservationUI({ onWidgetAdd, timeRange }: Props) { +export function AddInvestigationItem({ onItemAdd: onItemAdd, timeRange }: Props) { const [isOpen, setIsOpen] = React.useState(false); const [query, setQuery] = React.useState({ esql: '' }); @@ -113,9 +114,9 @@ export function AddObservationUI({ onWidgetAdd, timeRange }: Props) { { + onItemAdd={(item) => { resetState(); - return onWidgetAdd(widget); + return onItemAdd(item); }} /> )} diff --git a/x-pack/plugins/observability_solution/investigate_app/public/components/add_observation_ui/esql_widget_preview.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/add_investigation_item/esql_widget_preview.tsx similarity index 85% rename from x-pack/plugins/observability_solution/investigate_app/public/components/add_observation_ui/esql_widget_preview.tsx rename to x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/add_investigation_item/esql_widget_preview.tsx index 2d1e1f1506797..c865dfcf91826 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/components/add_observation_ui/esql_widget_preview.tsx +++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/add_investigation_item/esql_widget_preview.tsx @@ -8,38 +8,33 @@ import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui'; import { css } from '@emotion/css'; import type { DataView } from '@kbn/data-views-plugin/common'; import type { ESQLColumn, ESQLRow } from '@kbn/es-types'; -import { - ESQL_WIDGET_NAME, - GlobalWidgetParameters, - InvestigateWidgetCreate, - OnWidgetAdd, - createEsqlWidget, -} from '@kbn/investigate-plugin/public'; +import { GlobalWidgetParameters } from '@kbn/investigate-plugin/public'; +import { Item } from '@kbn/investigation-shared'; import type { Suggestion } from '@kbn/lens-plugin/public'; import { useAbortableAsync } from '@kbn/observability-ai-assistant-plugin/public'; import React, { useEffect, useMemo, useState } from 'react'; -import { useKibana } from '../../hooks/use_kibana'; -import { getEsFilterFromOverrides } from '../../utils/get_es_filter_from_overrides'; -import { getDateHistogramResults } from '../../widgets/esql_widget/get_date_histogram_results'; -import { EsqlWidget } from '../../widgets/esql_widget/register_esql_widget'; -import { ErrorMessage } from '../error_message'; -import { SuggestVisualizationList } from '../suggest_visualization_list'; +import { ErrorMessage } from '../../../../components/error_message'; +import { SuggestVisualizationList } from '../../../../components/suggest_visualization_list'; +import { useKibana } from '../../../../hooks/use_kibana'; +import { getDateHistogramResults } from '../../../../items/esql_item/get_date_histogram_results'; +import { EsqlWidget } from '../../../../items/esql_item/register_esql_item'; +import { getEsFilterFromOverrides } from '../../../../utils/get_es_filter_from_overrides'; -function getWidgetFromSuggestion({ +function getItemFromSuggestion({ query, suggestion, }: { query: string; suggestion: Suggestion; -}): InvestigateWidgetCreate { - return createEsqlWidget({ +}): Item { + return { title: suggestion.title, - type: ESQL_WIDGET_NAME, - parameters: { + type: 'esql', + params: { esql: query, suggestion, }, - }); + }; } function PreviewContainer({ children }: { children: React.ReactNode }) { @@ -64,11 +59,11 @@ function PreviewContainer({ children }: { children: React.ReactNode }) { export function EsqlWidgetPreview({ esqlQuery, - onWidgetAdd, + onItemAdd, timeRange, }: { esqlQuery: string; - onWidgetAdd: OnWidgetAdd; + onItemAdd: (item: Item) => void; } & GlobalWidgetParameters) { const { services: { esql }, @@ -199,7 +194,7 @@ export function EsqlWidgetPreview({ { - onWidgetAdd(getWidgetFromSuggestion({ query: esqlQuery, suggestion })); + onItemAdd(getItemFromSuggestion({ query: esqlQuery, suggestion })); }} loading={queryResult.loading} onMouseLeave={() => {}} diff --git a/x-pack/plugins/observability_solution/investigate_app/public/components/grid_item/index.stories.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/grid_item/index.stories.tsx similarity index 90% rename from x-pack/plugins/observability_solution/investigate_app/public/components/grid_item/index.stories.tsx rename to x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/grid_item/index.stories.tsx index 6111d0181ccbb..54b13f1eea29d 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/components/grid_item/index.stories.tsx +++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/grid_item/index.stories.tsx @@ -9,8 +9,8 @@ import { Meta, StoryObj } from '@storybook/react'; import React from 'react'; import { v4 } from 'uuid'; import { GridItem as Component } from '.'; -import { extendProps } from '../../../.storybook/extend_props'; -import { KibanaReactStorybookDecorator } from '../../../.storybook/storybook_decorator'; +import { extendProps } from '../../../../../.storybook/extend_props'; +import { KibanaReactStorybookDecorator } from '../../../../../.storybook/storybook_decorator'; type Props = React.ComponentProps; diff --git a/x-pack/plugins/observability_solution/investigate_app/public/components/grid_item/index.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/grid_item/index.tsx similarity index 95% rename from x-pack/plugins/observability_solution/investigate_app/public/components/grid_item/index.tsx rename to x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/grid_item/index.tsx index 465f6f803edd9..91f7a58b43b5e 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/components/grid_item/index.tsx +++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/grid_item/index.tsx @@ -7,8 +7,8 @@ import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui'; import { css } from '@emotion/css'; import React from 'react'; -import { useTheme } from '../../hooks/use_theme'; -import { InvestigateTextButton } from '../investigate_text_button'; +import { useTheme } from '../../../../hooks/use_theme'; +import { InvestigateTextButton } from '../../../../components/investigate_text_button'; export const GRID_ITEM_HEADER_HEIGHT = 40; diff --git a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_details/index.stories.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_details/index.stories.tsx index 8dfb18a753ac2..83b61c331843f 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_details/index.stories.tsx +++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_details/index.stories.tsx @@ -5,10 +5,11 @@ * 2.0. */ +import { mockAuthenticatedUser } from '@kbn/core-security-common/mocks'; import { ComponentMeta, ComponentStoryObj } from '@storybook/react'; import React from 'react'; -import { InvestigationDetails as Component } from '.'; import { KibanaReactStorybookDecorator } from '../../../../../.storybook/storybook_decorator'; +import { InvestigationDetails as Component } from './investigation_details'; const meta: ComponentMeta = { component: Component, @@ -20,7 +21,7 @@ export default meta; const defaultProps: ComponentStoryObj = { args: {}, - render: (props) => , + render: (props) => , }; export const InvestigateViewStory: ComponentStoryObj = { diff --git a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_details/index.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_details/index.tsx deleted file mode 100644 index c1c77ef564545..0000000000000 --- a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_details/index.tsx +++ /dev/null @@ -1,121 +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 datemath from '@elastic/datemath'; -import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui'; -import { AuthenticatedUser } from '@kbn/security-plugin/common'; -import React from 'react'; -import useAsync from 'react-use/lib/useAsync'; -import { AddObservationUI } from '../../../../components/add_observation_ui'; -import { InvestigateSearchBar } from '../../../../components/investigate_search_bar'; -import { InvestigateWidgetGrid } from '../../../../components/investigate_widget_grid'; -import { useFetchInvestigation } from '../../../../hooks/use_fetch_investigation'; -import { useKibana } from '../../../../hooks/use_kibana'; -import { InvestigationNotes } from '../investigation_notes/investigation_notes'; - -function InvestigationDetailsWithUser({ - user, - investigationId, -}: { - user: AuthenticatedUser; - investigationId: string; -}) { - const { - dependencies: { - start: { investigate }, - }, - } = useKibana(); - // const widgetDefinitions = investigate.getWidgetDefinitions(); - const { data: investigationData } = useFetchInvestigation({ id: investigationId }); - - const { - addItem, - copyItem, - deleteItem, - investigation, - setGlobalParameters, - renderableInvestigation, - } = investigate.useInvestigation({ - user, - investigationData, - }); - - if (!investigation || !renderableInvestigation || !investigationData) { - return ; - } - - return ( - - - - - - { - const nextDateRange = { - from: datemath.parse(dateRange.from)!.toISOString(), - to: datemath.parse(dateRange.to)!.toISOString(), - }; - await setGlobalParameters({ - ...renderableInvestigation.parameters, - timeRange: nextDateRange, - }); - }} - /> - - - - { - return copyItem(copiedItem.id); - }} - onItemDelete={async (deletedItem) => { - return deleteItem(deletedItem.id); - }} - /> - - - - { - return addItem(widget); - }} - /> - - - - - - - - ); -} - -export function InvestigationDetails({ investigationId }: { investigationId: string }) { - const { - core: { security }, - } = useKibana(); - - const user = useAsync(() => { - return security.authc.getCurrentUser(); - }, [security]); - - return user.value ? ( - - ) : null; -} diff --git a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_details/investigation_details.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_details/investigation_details.tsx new file mode 100644 index 0000000000000..5f6e1ca4515d3 --- /dev/null +++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_details/investigation_details.tsx @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui'; +import { AuthenticatedUser } from '@kbn/security-plugin/common'; +import React from 'react'; +import { useFetchInvestigation } from '../../../../hooks/use_fetch_investigation'; +import { InvestigationItems } from '../investigation_items/investigation_items'; +import { InvestigationNotes } from '../investigation_notes/investigation_notes'; + +interface Props { + user: AuthenticatedUser; + investigationId: string; +} + +export function InvestigationDetails({ user, investigationId }: Props) { + const { data: investigation, isLoading } = useFetchInvestigation({ id: investigationId }); + + if (isLoading || !investigation) { + return ; + } + + return ( + + + + + + + + + + ); +} diff --git a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_items/investigation_items.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_items/investigation_items.tsx new file mode 100644 index 0000000000000..dcc83eb968344 --- /dev/null +++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_items/investigation_items.tsx @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { GetInvestigationResponse, Item } from '@kbn/investigation-shared'; +import { pick } from 'lodash'; +import React from 'react'; +import { useAddInvestigationItem } from '../../../../hooks/use_add_investigation_item'; +import { useDeleteInvestigationItem } from '../../../../hooks/use_delete_investigation_item'; +import { useFetchInvestigationItems } from '../../../../hooks/use_fetch_investigation_items'; +import { useRenderItems } from '../../hooks/use_render_items'; +import { AddInvestigationItem } from '../add_investigation_item/add_investigation_item'; +import { InvestigationItemsList } from '../investigation_items_list/investigation_items_list'; +import { InvestigationSearchBar } from '../investigation_search_bar/investigation_search_bar'; + +export interface Props { + investigationId: string; + investigation: GetInvestigationResponse; +} + +export function InvestigationItems({ investigationId, investigation }: Props) { + const { data: items, refetch } = useFetchInvestigationItems({ + investigationId, + initialItems: investigation.items, + }); + const renderableItems = useRenderItems({ items, params: investigation.params }); + + const { mutateAsync: addInvestigationItem, isLoading: isAdding } = useAddInvestigationItem(); + const { mutateAsync: deleteInvestigationItem, isLoading: isDeleting } = + useDeleteInvestigationItem(); + + const onAddItem = async (item: Item) => { + await addInvestigationItem({ investigationId, item }); + refetch(); + }; + + const onDeleteItem = async (itemId: string) => { + await deleteInvestigationItem({ investigationId, itemId }); + refetch(); + }; + + return ( + + + { + // const nextDateRange = { + // from: datemath.parse(dateRange.from)!.toISOString(), + // to: datemath.parse(dateRange.to)!.toISOString(), + // }; + // await setGlobalParameters({ + // ...renderableInvestigation.parameters, + // timeRange: nextDateRange, + // }); + }} + /> + + + { + await onAddItem(pick(copiedItem, ['title', 'type', 'params'])); + }} + onItemDelete={async (deletedItem) => { + await onDeleteItem(deletedItem.id); + }} + /> + + + + + + ); +} diff --git a/x-pack/plugins/observability_solution/investigate_app/public/components/investigate_widget_grid/index.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_items_list/investigation_items_list.tsx similarity index 75% rename from x-pack/plugins/observability_solution/investigate_app/public/components/investigate_widget_grid/index.tsx rename to x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_items_list/investigation_items_list.tsx index 41c3b3a3e8b66..8ec5bf3ffef98 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/components/investigate_widget_grid/index.tsx +++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_items_list/investigation_items_list.tsx @@ -8,24 +8,19 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React from 'react'; import 'react-grid-layout/css/styles.css'; import 'react-resizable/css/styles.css'; +import { RenderedInvestigationItem } from '../../hooks/use_render_items'; import { GridItem } from '../grid_item'; -import './styles.scss'; - -export interface InvestigateWidgetGridItem { - id: string; - title: string; - element: React.ReactNode; - loading: boolean; -} interface InvestigateWidgetGridProps { - items: InvestigateWidgetGridItem[]; - onItemCopy: (item: InvestigateWidgetGridItem) => Promise; - onItemDelete: (item: InvestigateWidgetGridItem) => Promise; + items: RenderedInvestigationItem[]; + isLoading: boolean; + onItemCopy: (item: RenderedInvestigationItem) => Promise; + onItemDelete: (item: RenderedInvestigationItem) => Promise; } -export function InvestigateWidgetGrid({ +export function InvestigationItemsList({ items, + isLoading, onItemDelete, onItemCopy, }: InvestigateWidgetGridProps) { @@ -41,7 +36,7 @@ export function InvestigateWidgetGrid({ { return onItemCopy(item); }} diff --git a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_notes/investigation_notes.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_notes/investigation_notes.tsx index 0f03a9f374ac3..8406ba8fe3f03 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_notes/investigation_notes.tsx +++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_notes/investigation_notes.tsx @@ -16,7 +16,7 @@ import { } from '@elastic/eui'; import { css } from '@emotion/css'; import { i18n } from '@kbn/i18n'; -import { InvestigationNote } from '@kbn/investigate-plugin/common'; +import { InvestigationNoteResponse, GetInvestigationResponse } from '@kbn/investigation-shared'; import React, { useState } from 'react'; import { useAddInvestigationNote } from '../../../../hooks/use_add_investigation_note'; import { useDeleteInvestigationNote } from '../../../../hooks/use_delete_investigation_note'; @@ -27,16 +27,16 @@ import { TimelineMessage } from './timeline_message'; export interface Props { investigationId: string; - initialNotes: InvestigationNote[]; + investigation: GetInvestigationResponse; } -export function InvestigationNotes({ investigationId, initialNotes }: Props) { +export function InvestigationNotes({ investigationId, investigation }: Props) { const theme = useTheme(); const [noteInput, setNoteInput] = useState(''); const { data: notes, refetch } = useFetchInvestigationNotes({ investigationId, - initialNotes, + initialNotes: investigation.notes, }); const { mutateAsync: addInvestigationNote, isLoading: isAdding } = useAddInvestigationNote(); const { mutateAsync: deleteInvestigationNote, isLoading: isDeleting } = @@ -70,7 +70,7 @@ export function InvestigationNotes({ investigationId, initialNotes }: Props) { - {notes?.map((currNote: InvestigationNote) => { + {notes?.map((currNote: InvestigationNoteResponse) => { return ( void; isDeleting: boolean; }) { diff --git a/x-pack/plugins/observability_solution/investigate_app/public/components/investigate_search_bar/index.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_search_bar/investigation_search_bar.tsx similarity index 93% rename from x-pack/plugins/observability_solution/investigate_app/public/components/investigate_search_bar/index.tsx rename to x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_search_bar/investigation_search_bar.tsx index 45519f2e799be..a6ad73bc67d0d 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/components/investigate_search_bar/index.tsx +++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_search_bar/investigation_search_bar.tsx @@ -8,7 +8,7 @@ import { css } from '@emotion/css'; import type { TimeRange } from '@kbn/es-query'; import { SearchBar } from '@kbn/unified-search-plugin/public'; import React from 'react'; -import { useKibana } from '../../hooks/use_kibana'; +import { useKibana } from '../../../../hooks/use_kibana'; const parentClassName = css` width: 100%; @@ -21,7 +21,7 @@ interface Props { onRefresh?: Required>['onRefresh']; } -export function InvestigateSearchBar({ +export function InvestigationSearchBar({ dateRangeFrom, dateRangeTo, onQuerySubmit, diff --git a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/hooks/use_render_items.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/hooks/use_render_items.tsx new file mode 100644 index 0000000000000..dc2c1c029bccd --- /dev/null +++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/hooks/use_render_items.tsx @@ -0,0 +1,84 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; +import { GetInvestigationResponse, InvestigationItem } from '@kbn/investigation-shared'; +import React, { useEffect, useState } from 'react'; +import { useKibana } from '../../../hooks/use_kibana'; + +export type RenderedInvestigationItem = InvestigationItem & { + loading: boolean; + element: React.ReactNode; +}; + +export function useRenderItems({ + items, + params, +}: { + items?: InvestigationItem[]; + params: GetInvestigationResponse['params']; +}) { + const { + dependencies: { + start: { investigate }, + }, + } = useKibana(); + + const [renderableItems, setRenderableItems] = useState([]); + + useEffect(() => { + async function renderItems(currItems: InvestigationItem[]) { + return await Promise.all( + currItems.map(async (item) => { + const itemDefinition = investigate.getItemDefinitionByType(item.type); + if (!itemDefinition) { + return Promise.resolve({ + ...item, + loading: false, + element: ( +
+ {i18n.translate('xpack.investigateApp.renderableItems.div.notFoundLabel', { + defaultMessage: 'Not found for type {type}', + values: { type: item.type }, + })} +
+ ), + }); + } + + const globalParams = { + timeRange: { + from: new Date(params.timeRange.from).toISOString(), + to: new Date(params.timeRange.to).toISOString(), + }, + }; + + const data = await itemDefinition.generate({ + itemParams: item.params, + globalParams, + }); + + return Promise.resolve({ + ...item, + loading: false, + element: itemDefinition.render({ + data, + globalParams, + itemParams: item.params, + }), + }); + }) + ); + } + + if (items) { + renderItems(items).then((nextRenderableItems) => setRenderableItems(nextRenderableItems)); + } + }, [items, investigate, params]); + + return renderableItems; +} diff --git a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/investigation_details_page.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/investigation_details_page.tsx index 90af6b4591c69..8bce69ea125af 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/investigation_details_page.tsx +++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/investigation_details_page.tsx @@ -11,23 +11,29 @@ import { alertOriginSchema } from '@kbn/investigation-shared'; import { ALERT_RULE_CATEGORY } from '@kbn/rule-data-utils/src/default_alerts_as_data'; import React from 'react'; import { useParams } from 'react-router-dom'; +import useAsync from 'react-use/lib/useAsync'; import { paths } from '../../../common/paths'; import { useFetchAlert } from '../../hooks/use_get_alert_details'; import { useFetchInvestigation } from '../../hooks/use_get_investigation_details'; import { useKibana } from '../../hooks/use_kibana'; -import { InvestigationDetails } from './components/investigation_details'; +import { InvestigationDetails } from './components/investigation_details/investigation_details'; import { InvestigationDetailsPathParams } from './types'; export function InvestigationDetailsPage() { const { core: { http: { basePath }, + security, }, dependencies: { start: { observabilityShared }, }, } = useKibana(); + const user = useAsync(() => { + return security.authc.getCurrentUser(); + }, [security]); + const { investigationId } = useParams(); const ObservabilityPageTemplate = observabilityShared.navigation.PageTemplate; @@ -44,6 +50,10 @@ export function InvestigationDetailsPage() { const { data: alertDetails } = useFetchAlert({ id: alertId }); + if (!user.value) { + return null; + } + if (isFetchInvestigationLoading) { return (

@@ -106,7 +116,7 @@ export function InvestigationDetailsPage() { ], }} > - + ); } diff --git a/x-pack/plugins/observability_solution/investigate_app/public/plugin.tsx b/x-pack/plugins/observability_solution/investigate_app/public/plugin.tsx index 75b07099cbb62..abbe762562541 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/plugin.tsx +++ b/x-pack/plugins/observability_solution/investigate_app/public/plugin.tsx @@ -125,28 +125,26 @@ export class InvestigateAppPlugin .getStartServices() .then(([, pluginsStart]) => pluginsStart); - pluginsSetup.investigate.register((registerWidget) => - Promise.all([ - pluginsStartPromise, - import('./widgets/register_widgets').then((m) => m.registerWidgets), - getCreateEsqlService(), - ]).then(([pluginsStart, registerWidgets, createEsqlService]) => { - registerWidgets({ - dependencies: { - setup: pluginsSetup, - start: pluginsStart, - }, - services: { - esql: createEsqlService({ - data: pluginsStart.data, - dataViews: pluginsStart.dataViews, - lens: pluginsStart.lens, - }), - }, - registerWidget, - }); - }) - ); + // new + Promise.all([ + pluginsStartPromise, + import('./items/register_items').then((m) => m.registerItems), + getCreateEsqlService(), + ]).then(([pluginsStart, registerItems, createEsqlService]) => { + registerItems({ + dependencies: { + setup: pluginsSetup, + start: pluginsStart, + }, + services: { + esql: createEsqlService({ + data: pluginsStart.data, + dataViews: pluginsStart.dataViews, + lens: pluginsStart.lens, + }), + }, + }); + }); return {}; } diff --git a/x-pack/plugins/observability_solution/investigate_app/public/widgets/embeddable_widget/create_embeddable_widget.ts b/x-pack/plugins/observability_solution/investigate_app/public/widgets/embeddable_widget/create_embeddable_widget.ts deleted file mode 100644 index 61e99df8b28b2..0000000000000 --- a/x-pack/plugins/observability_solution/investigate_app/public/widgets/embeddable_widget/create_embeddable_widget.ts +++ /dev/null @@ -1,13 +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 { createWidgetFactory } from '@kbn/investigate-plugin/public'; -import { EMBEDDABLE_WIDGET_NAME } from '../../constants'; -import { EmbeddableWidgetParameters } from './types'; - -export const createEmbeddableWidget = - createWidgetFactory(EMBEDDABLE_WIDGET_NAME); diff --git a/x-pack/plugins/observability_solution/investigate_app/public/widgets/embeddable_widget/types.ts b/x-pack/plugins/observability_solution/investigate_app/public/widgets/embeddable_widget/types.ts deleted file mode 100644 index d3ecd0379c716..0000000000000 --- a/x-pack/plugins/observability_solution/investigate_app/public/widgets/embeddable_widget/types.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { InvestigateWidget, InvestigateWidgetCreate } from '@kbn/investigate-plugin/common'; - -export interface EmbeddableWidgetParameters { - type: string; - savedObjectId?: string; - config: Record; -} - -export type EmbeddableWidgetCreate = InvestigateWidgetCreate; - -export type EmbeddableWidget = InvestigateWidget; diff --git a/x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_entry_flyout/log_entry_flyout.tsx b/x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_entry_flyout/log_entry_flyout.tsx index ffb1881122540..952ee959e4a72 100644 --- a/x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_entry_flyout/log_entry_flyout.tsx +++ b/x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_entry_flyout/log_entry_flyout.tsx @@ -51,7 +51,7 @@ export const useLogEntryFlyout = (logViewReference: LogViewReference) => { }, []); const openLogEntryFlyout = useCallback( - (logEntryId) => { + (logEntryId: string | null | undefined) => { const { Provider: KibanaReactContextProvider } = createKibanaReactContext({ http, data, diff --git a/x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/index.ts b/x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/index.ts index c4507a2b4ebc5..6468ea3d94d22 100644 --- a/x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/index.ts +++ b/x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/index.ts @@ -17,3 +17,4 @@ export { LogEntryMessageColumn } from './log_entry_message_column'; export { LogEntryRowWrapper } from './log_entry_row_wrapper'; export { LogEntryTimestampColumn } from './log_entry_timestamp_column'; export { ScrollableLogTextStreamView } from './scrollable_log_text_stream_view'; +export type { UpdatedDateRange, VisibleInterval } from './scrollable_log_text_stream_view'; diff --git a/x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx b/x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx index fdb0d6a88f8a5..6fe7260e8c7e2 100644 --- a/x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx +++ b/x-pack/plugins/observability_solution/logs_shared/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx @@ -28,6 +28,20 @@ import { LogDateRow } from './log_date_row'; import { LogEntry } from '../../../../common/log_entry'; import { LogColumnRenderConfiguration } from '../../../utils/log_column_render_configuration'; +export interface VisibleInterval { + pagesBeforeStart: number; + pagesAfterEnd: number; + startKey: TimeKey | null; + middleKey: TimeKey | null; + endKey: TimeKey | null; + fromScroll: boolean; +} + +export interface UpdatedDateRange { + startDateExpression?: string; + endDateExpression?: string; +} + export interface ScrollableLogTextStreamViewProps { columnConfigurations: LogColumnRenderConfiguration[]; items: StreamItem[]; @@ -41,14 +55,7 @@ export interface ScrollableLogTextStreamViewProps { lastLoadedTime?: Date; target: TimeKey | null; jumpToTarget: (target: TimeKey) => any; - reportVisibleInterval: (params: { - pagesBeforeStart: number; - pagesAfterEnd: number; - startKey: TimeKey | null; - middleKey: TimeKey | null; - endKey: TimeKey | null; - fromScroll: boolean; - }) => any; + reportVisibleInterval: (params: VisibleInterval) => any; reloadItems: () => void; onOpenLogEntryFlyout?: (logEntryId?: string) => void; setContextEntry?: (entry: LogEntry) => void; @@ -56,7 +63,7 @@ export interface ScrollableLogTextStreamViewProps { currentHighlightKey: UniqueTimeKey | null; startDateExpression: string; endDateExpression: string; - updateDateRange: (range: { startDateExpression?: string; endDateExpression?: string }) => void; + updateDateRange: (range: UpdatedDateRange) => void; startLiveStreaming: () => void; hideScrollbar?: boolean; } diff --git a/x-pack/plugins/observability_solution/logs_shared/public/index.ts b/x-pack/plugins/observability_solution/logs_shared/public/index.ts index 80b8dd3638924..7a0f731b4a93b 100644 --- a/x-pack/plugins/observability_solution/logs_shared/public/index.ts +++ b/x-pack/plugins/observability_solution/logs_shared/public/index.ts @@ -46,6 +46,10 @@ export { } from './components/logging/log_text_stream/log_entry_column'; export type { LogAIAssistantProps } from './components/log_ai_assistant/log_ai_assistant'; export type { LogStreamProps } from './components/log_stream/log_stream'; +export type { + UpdatedDateRange, + VisibleInterval, +} from './components/logging/log_text_stream/scrollable_log_text_stream_view'; export const WithSummary = dynamic(() => import('./containers/logs/log_summary/with_summary')); export const LogEntryFlyout = dynamic( diff --git a/x-pack/plugins/observability_solution/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/metrics_node_details_link.tsx b/x-pack/plugins/observability_solution/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/metrics_node_details_link.tsx index 10ecf3dc42626..e683d1708907b 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/metrics_node_details_link.tsx +++ b/x-pack/plugins/observability_solution/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/metrics_node_details_link.tsx @@ -8,7 +8,6 @@ import { parse } from '@kbn/datemath'; import { EuiLink } from '@elastic/eui'; import React from 'react'; -import { useLinkProps } from '@kbn/observability-shared-plugin/public'; import type { InventoryItemType } from '../../../../../common/inventory_models/types'; import { useNodeDetailsRedirect } from '../../../../pages/link_to/use_node_details_redirect'; @@ -28,16 +27,14 @@ export const MetricsNodeDetailsLink = ({ timerange, }: MetricsNodeDetailsLinkProps) => { const { getNodeDetailUrl } = useNodeDetailsRedirect(); - const linkProps = useLinkProps( - getNodeDetailUrl({ - nodeType, - nodeId: id, - search: { - from: parse(timerange.from)?.valueOf(), - to: parse(timerange.to)?.valueOf(), - }, - }) - ); + const linkProps = getNodeDetailUrl({ + nodeType, + nodeId: id, + search: { + from: parse(timerange.from)?.valueOf(), + to: parse(timerange.to)?.valueOf(), + }, + }); return ( diff --git a/x-pack/plugins/observability_solution/metrics_data_access/public/hooks/use_kibana.tsx b/x-pack/plugins/observability_solution/metrics_data_access/public/hooks/use_kibana.tsx index c99caa3f4c266..423460b383549 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/public/hooks/use_kibana.tsx +++ b/x-pack/plugins/observability_solution/metrics_data_access/public/hooks/use_kibana.tsx @@ -12,12 +12,14 @@ import { KibanaReactContextValue, useKibana, } from '@kbn/kibana-react-plugin/public'; +import type { SharePluginStart } from '@kbn/share-plugin/public'; -export type PluginKibanaContextValue = CoreStart; +export type PluginKibanaContextValue = CoreStart & { share?: SharePluginStart }; export const createKibanaContextForPlugin = (core: CoreStart) => createKibanaReactContext({ ...core, + share: {} as SharePluginStart, }); export const useKibanaContextForPlugin = diff --git a/x-pack/plugins/observability_solution/metrics_data_access/public/pages/link_to/use_node_details_redirect.ts b/x-pack/plugins/observability_solution/metrics_data_access/public/pages/link_to/use_node_details_redirect.ts index 7d9c813f97479..aea3042d79ae2 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/public/pages/link_to/use_node_details_redirect.ts +++ b/x-pack/plugins/observability_solution/metrics_data_access/public/pages/link_to/use_node_details_redirect.ts @@ -7,8 +7,13 @@ import { useCallback } from 'react'; import { useLocation } from 'react-router-dom'; -import type { LinkDescriptor } from '@kbn/observability-shared-plugin/public'; import useObservable from 'react-use/lib/useObservable'; +import { RouterLinkProps, getRouterLinkProps } from '@kbn/router-utils/src/get_router_link_props'; +import { Search } from 'history'; +import { + type AssetDetailsLocatorParams, + ASSET_DETAILS_LOCATOR_ID, +} from '@kbn/observability-shared-plugin/common'; import type { InventoryItemType } from '../../../common/inventory_models/types'; import { useKibanaContextForPlugin } from '../../hooks/use_kibana'; @@ -18,15 +23,24 @@ interface QueryParams { assetName?: string; } +export interface RouteState { + originAppId: string; + originPathname: string; + originSearch?: Search; +} + export const useNodeDetailsRedirect = () => { const location = useLocation(); const { services: { application: { currentAppId$ }, + share, }, } = useKibanaContextForPlugin(); const appId = useObservable(currentAppId$); + const locator = share?.url.locators.get(ASSET_DETAILS_LOCATOR_ID); + const getNodeDetailUrl = useCallback( ({ nodeType, @@ -36,34 +50,54 @@ export const useNodeDetailsRedirect = () => { nodeType: InventoryItemType; nodeId: string; search: QueryParams; - }): LinkDescriptor => { + }): RouterLinkProps => { const { to, from, ...rest } = search; - - return { - app: 'metrics', - pathname: `link-to/${nodeType}-detail/${nodeId}`, - search: { - ...rest, - ...(to && from - ? { - to: `${to}`, - from: `${from}`, - } - : undefined), - // While we don't have a shared state between all page in infra, this makes it possible to restore a page state when returning to the previous route - ...(location.search || location.pathname + const queryParams = { + nodeDetails: + Object.keys(rest).length > 0 ? { - state: JSON.stringify({ - originAppId: appId, - originSearch: location.search, - originPathname: location.pathname, - }), + ...rest, + dateRange: { + from: from ? new Date(from).toISOString() : undefined, + to: to ? new Date(to).toISOString() : undefined, + }, } - : undefined), + : {}, + _a: { + time: { + ...(from ? { from: new Date(from).toISOString() } : undefined), + ...(to ? { to: new Date(to).toISOString() } : undefined), + interval: '>=1m', + }, }, }; + + const nodeDetailsLocatorParams = { + ...queryParams, + assetType: nodeType, + assetId: nodeId, + state: { + ...(location.state ?? {}), + ...(location.key + ? ({ + originAppId: appId, + originSearch: location.search, + originPathname: location.pathname, + } as RouteState) + : {}), + }, + }; + + const nodeDetailsLinkProps = getRouterLinkProps({ + href: locator?.getRedirectUrl(nodeDetailsLocatorParams), + onClick: () => { + locator?.navigate(nodeDetailsLocatorParams, { replace: false }); + }, + }); + + return nodeDetailsLinkProps; }, - [location.pathname, appId, location.search] + [appId, location.key, location.pathname, location.search, location.state, locator] ); return { getNodeDetailUrl }; diff --git a/x-pack/plugins/observability_solution/metrics_data_access/tsconfig.json b/x-pack/plugins/observability_solution/metrics_data_access/tsconfig.json index 39ca16361f6cd..0c2c471a6bf77 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/tsconfig.json +++ b/x-pack/plugins/observability_solution/metrics_data_access/tsconfig.json @@ -35,6 +35,7 @@ "@kbn/core-http-request-handler-context-server", "@kbn/lens-embeddable-utils", "@kbn/react-kibana-context-render", - "@kbn/react-kibana-context-theme" + "@kbn/react-kibana-context-theme", + "@kbn/router-utils" ] } diff --git a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/expression_row.tsx b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/expression_row.tsx index ffeaf3aef61cb..d98b0a69d984f 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/expression_row.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/expression_row.tsx @@ -73,13 +73,13 @@ export const ExpressionRow: React.FC = (props) => { ); const convertThreshold = useCallback( - (enteredThreshold) => + (enteredThreshold: any) => isMetricPct ? enteredThreshold.map((v: number) => pctToDecimal(v)) : enteredThreshold, [isMetricPct] ); const updateThreshold = useCallback( - (enteredThreshold) => { + (enteredThreshold: any) => { const t = convertThreshold(enteredThreshold); if (t.join() !== expression.threshold.join()) { setRuleParams(expressionId, { ...expression, threshold: t }); @@ -89,7 +89,7 @@ export const ExpressionRow: React.FC = (props) => { ); const handleCustomMetricChange = useCallback( - (exp) => { + (exp: any) => { setRuleParams(expressionId, exp); }, [expressionId, setRuleParams] diff --git a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/custom_threshold_rule_expression.tsx b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/custom_threshold_rule_expression.tsx index bbbcb59057824..747abedfc0f35 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/custom_threshold_rule_expression.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/custom_threshold_rule_expression.tsx @@ -219,7 +219,7 @@ export default function Expressions(props: Props) { ); const updateParams = useCallback( - (id, e: MetricExpression) => { + (id: any, e: MetricExpression) => { const ruleCriteria = ruleParams.criteria ? ruleParams.criteria.slice() : []; ruleCriteria[id] = e; setRuleParams('criteria', ruleCriteria); diff --git a/x-pack/plugins/observability_solution/observability/public/context/date_picker_context/date_picker_context.tsx b/x-pack/plugins/observability_solution/observability/public/context/date_picker_context/date_picker_context.tsx index b31b48456a564..3a7b3ed89b212 100644 --- a/x-pack/plugins/observability_solution/observability/public/context/date_picker_context/date_picker_context.tsx +++ b/x-pack/plugins/observability_solution/observability/public/context/date_picker_context/date_picker_context.tsx @@ -108,7 +108,7 @@ export function DatePickerContextProvider({ children }: { children: React.ReactE ); const updateRefreshInterval = useCallback( - ({ interval, isPaused }) => { + ({ interval, isPaused }: any) => { updateUrl({ refreshInterval: interval, refreshPaused: isPaused }); data.query.timefilter.timefilter.setRefreshInterval({ value: interval, pause: isPaused }); setLastUpdated(Date.now()); diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details_contextual_insights.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details_contextual_insights.tsx index 2f6fed0013102..cf42243b1e1da 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details_contextual_insights.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/alert_details_contextual_insights.tsx @@ -9,6 +9,7 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; +import { ALERT_RULE_PARAMETERS } from '@kbn/rule-data-utils'; import dedent from 'dedent'; import { type AlertDetailsContextualInsight } from '../../../server/services'; import { useKibana } from '../../utils/kibana_react'; @@ -35,6 +36,12 @@ export function AlertDetailContextualInsights({ alert }: { alert: AlertData | nu query: { alert_started_at: new Date(alert.formatted.start).toISOString(), + // alert fields used for log rate analysis + alert_rule_parameter_time_size: alert.formatted.fields[ALERT_RULE_PARAMETERS] + ?.timeSize as string | undefined, + alert_rule_parameter_time_unit: alert.formatted.fields[ALERT_RULE_PARAMETERS] + ?.timeUnit as string | undefined, + // service fields 'service.name': fields['service.name'], 'service.environment': fields['service.environment'], diff --git a/x-pack/plugins/observability_solution/observability/server/services/index.ts b/x-pack/plugins/observability_solution/observability/server/services/index.ts index 3325a9d1dbfea..1e19f1cbbbb77 100644 --- a/x-pack/plugins/observability_solution/observability/server/services/index.ts +++ b/x-pack/plugins/observability_solution/observability/server/services/index.ts @@ -20,6 +20,10 @@ export const alertDetailsContextRt = t.intersection([ alert_started_at: t.string, }), t.partial({ + // alert fields used for log rate analysis + alert_rule_parameter_time_size: t.string, + alert_rule_parameter_time_unit: t.string, + // apm fields 'service.name': t.string, 'service.environment': t.string, diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/common/index.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/common/index.ts index 81b8a6ac56292..78c3d55e706e3 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/common/index.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/common/index.ts @@ -38,7 +38,6 @@ export { } from './conversation_complete'; export { - aiAssistantResponseLanguage, aiAssistantLogsIndexPattern, aiAssistantSimulatedFunctionCalling, aiAssistantSearchConnectorIndexPattern, @@ -46,8 +45,6 @@ export { export { concatenateChatCompletionChunks } from './utils/concatenate_chat_completion_chunks'; -export { DEFAULT_LANGUAGE_OPTION, LANGUAGE_OPTIONS } from './ui_settings/language_options'; - export { isSupportedConnectorType } from './connectors'; export { ShortIdTable } from './utils/short_id_table'; diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/common/ui_settings/language_options.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/common/ui_settings/language_options.ts deleted file mode 100644 index b4f89d512cd95..0000000000000 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/common/ui_settings/language_options.ts +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -/* eslint-disable @typescript-eslint/naming-convention */ -// Data taken from https://github.com/L-P/native-language-list/blob/master/data/langs.json -export const languages: { [key: string]: string } = { - af: 'Afrikaans', - ak: 'Akan', - am: '\u12a0\u121b\u122d\u129b', - ar: '\u0627\u0644\u0639\u0631\u0628\u064a\u0629', - as: '\u0985\u09b8\u09ae\u09c0\u09af\u09bc\u09be', - az: 'az\u0259rbaycan', - be: '\u0431\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f', - bg: '\u0431\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438', - bm: 'bamanakan', - bn: '\u09ac\u09be\u0982\u09b2\u09be', - bo: '\u0f56\u0f7c\u0f51\u0f0b\u0f66\u0f90\u0f51\u0f0b', - br: 'brezhoneg', - bs: 'bosanski', - ca: 'catal\u00e0', - cs: '\u010de\u0161tina', - cy: 'Cymraeg', - da: 'dansk', - de: 'Deutsch', - de_AT: '\u00d6sterreichisches Deutsch', - de_CH: 'Schweizer Hochdeutsch', - dz: '\u0f62\u0fab\u0f7c\u0f44\u0f0b\u0f41', - ee: 'e\u028begbe', - el: '\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac', - en: 'English', - en_AU: 'Australian English', - en_CA: 'Canadian English', - en_GB: 'British English', - en_US: 'American English', - eo: 'esperanto', - es: 'espa\u00f1ol', - es_ES: 'espa\u00f1ol de Espa\u00f1a', - es_MX: 'espa\u00f1ol de M\u00e9xico', - et: 'eesti', - eu: 'euskara', - fa: '\u0641\u0627\u0631\u0633\u06cc', - ff: 'Pulaar', - fi: 'suomi', - fo: 'f\u00f8royskt', - fr: 'fran\u00e7ais', - fr_CA: 'fran\u00e7ais canadien', - fr_CH: 'fran\u00e7ais suisse', - fy: 'West-Frysk', - ga: 'Gaeilge', - gd: 'G\u00e0idhlig', - gl: 'galego', - gu: '\u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0', - gv: 'Gaelg', - ha: 'Hausa', - he: '\u05e2\u05d1\u05e8\u05d9\u05ea', - hi: '\u0939\u093f\u0902\u0926\u0940', - hr: 'hrvatski', - hu: 'magyar', - hy: '\u0570\u0561\u0575\u0565\u0580\u0565\u0576', - id: 'Bahasa Indonesia', - ig: 'Igbo', - ii: '\ua188\ua320\ua259', - is: '\u00edslenska', - it: 'italiano', - ja: '\u65e5\u672c\u8a9e', - ka: '\u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8', - ki: 'Gikuyu', - kk: '\u049b\u0430\u0437\u0430\u049b \u0442\u0456\u043b\u0456', - kl: 'kalaallisut', - km: '\u1781\u17d2\u1798\u17c2\u179a', - kn: '\u0c95\u0ca8\u0ccd\u0ca8\u0ca1', - ko: '\ud55c\uad6d\uc5b4', - ks: '\u06a9\u0672\u0634\u064f\u0631', - kw: 'kernewek', - ky: '\u043a\u044b\u0440\u0433\u044b\u0437\u0447\u0430', - lb: 'L\u00ebtzebuergesch', - lg: 'Luganda', - ln: 'ling\u00e1la', - lo: '\u0ea5\u0eb2\u0ea7', - lt: 'lietuvi\u0173', - lu: 'Tshiluba', - lv: 'latvie\u0161u', - mg: 'Malagasy', - mk: '\u043c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438', - ml: '\u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02', - mn: '\u043c\u043e\u043d\u0433\u043e\u043b', - mr: '\u092e\u0930\u093e\u0920\u0940', - ms: 'Bahasa Melayu', - mt: 'Malti', - my: '\u1017\u1019\u102c', - nb: 'norsk bokm\u00e5l', - nd: 'isiNdebele', - ne: '\u0928\u0947\u092a\u093e\u0932\u0940', - nl: 'Nederlands', - nl_BE: 'Vlaams', - nn: 'nynorsk', - no: 'norsk', - om: 'Oromoo', - or: '\u0b13\u0b21\u0b3c\u0b3f\u0b06', - os: '\u0438\u0440\u043e\u043d', - pa: '\u0a2a\u0a70\u0a1c\u0a3e\u0a2c\u0a40', - pl: 'polski', - ps: '\u067e\u069a\u062a\u0648', - pt: 'portugu\u00eas', - pt_BR: 'portugu\u00eas do Brasil', - pt_PT: 'portugu\u00eas europeu', - qu: 'Runasimi', - rm: 'rumantsch', - rn: 'Ikirundi', - ro: 'rom\u00e2n\u0103', - ro_MD: 'moldoveneasc\u0103', - ru: '\u0440\u0443\u0441\u0441\u043a\u0438\u0439', - rw: 'Kinyarwanda', - se: 'davvis\u00e1megiella', - sg: 'S\u00e4ng\u00f6', - sh: 'Srpskohrvatski', - si: '\u0dc3\u0dd2\u0d82\u0dc4\u0dbd', - sk: 'sloven\u010dina', - sl: 'sloven\u0161\u010dina', - sn: 'chiShona', - so: 'Soomaali', - sq: 'shqip', - sr: '\u0441\u0440\u043f\u0441\u043a\u0438', - sv: 'svenska', - sw: 'Kiswahili', - ta: '\u0ba4\u0bae\u0bbf\u0bb4\u0bcd', - te: '\u0c24\u0c46\u0c32\u0c41\u0c17\u0c41', - th: '\u0e44\u0e17\u0e22', - ti: '\u1275\u130d\u122d\u129b', - tl: 'Tagalog', - to: 'lea fakatonga', - tr: 'T\u00fcrk\u00e7e', - ug: '\u0626\u06c7\u064a\u063a\u06c7\u0631\u0686\u06d5', - uk: '\u0443\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430', - ur: '\u0627\u0631\u062f\u0648', - uz: 'o\u02bbzbekcha', - vi: 'Ti\u1ebfng Vi\u1ec7t', - yi: '\u05d9\u05d9\u05b4\u05d3\u05d9\u05e9', - yo: '\u00c8d\u00e8 Yor\u00f9b\u00e1', - zh: '\u4e2d\u6587', - zh_Hans: '\u7b80\u4f53\u4e2d\u6587', - zh_Hant: '\u7e41\u9ad4\u4e2d\u6587', - zu: 'isiZulu', -}; - -export const KIBANA_LOCALE_SETTING = { - value: 'locale_setting', - label: 'Kibana locale setting', -}; - -export const BROWSER_LANGUAGE_SETTING = { - value: 'browser_setting', - label: 'Browser language setting', -}; - -export const DEFAULT_LANGUAGE_OPTION = KIBANA_LOCALE_SETTING; -export const LANGUAGE_OPTIONS = [ - KIBANA_LOCALE_SETTING, - BROWSER_LANGUAGE_SETTING, - ...Object.entries(languages).map(([value, label]) => ({ value, label })), -]; diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/common/ui_settings/settings_keys.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/common/ui_settings/settings_keys.ts index 1f6d4d173cfa8..eae50d1116a8f 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/common/ui_settings/settings_keys.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/common/ui_settings/settings_keys.ts @@ -7,8 +7,8 @@ // AI Assistant export const aiAssistantLogsIndexPattern = 'observability:aiAssistantLogsIndexPattern'; -export const aiAssistantResponseLanguage = 'observability:aiAssistantResponseLanguage'; export const aiAssistantSimulatedFunctionCalling = 'observability:aiAssistantSimulatedFunctionCalling'; export const aiAssistantSearchConnectorIndexPattern = 'observability:aiAssistantSearchConnectorIndexPattern'; +export const aiAssistantPreferredAIAssistantType = 'aiAssistant:preferredAIAssistantType'; diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/public/hooks/use_chat.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/public/hooks/use_chat.ts index 4d850118bb736..712b102c36f85 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/public/hooks/use_chat.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/public/hooks/use_chat.ts @@ -21,7 +21,6 @@ import { import type { ObservabilityAIAssistantChatService, ObservabilityAIAssistantService } from '..'; import { useKibana } from './use_kibana'; import { useOnce } from './use_once'; -import { useUserPreferredLanguage } from './use_user_preferred_language'; export enum ChatState { Ready = 'ready', @@ -88,8 +87,6 @@ function useChatWithoutContext({ const abortControllerRef = useRef(new AbortController()); - const { getPreferredLanguage } = useUserPreferredLanguage(); - const onChatCompleteRef = useRef(onChatComplete); onChatCompleteRef.current = onChatComplete; @@ -164,7 +161,6 @@ function useChatWithoutContext({ disableFunctions: disableFunctions ?? false, signal: abortControllerRef.current.signal, conversationId, - responseLanguage: getPreferredLanguage(), }); function getPendingMessages() { @@ -263,7 +259,6 @@ function useChatWithoutContext({ disableFunctions, service, systemMessage, - getPreferredLanguage, ] ); diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/public/hooks/use_user_preferred_language.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/public/hooks/use_user_preferred_language.ts deleted file mode 100644 index 16e4edbf8ceb7..0000000000000 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/public/hooks/use_user_preferred_language.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; -import { useCallback } from 'react'; -import { - DEFAULT_LANGUAGE_OPTION, - KIBANA_LOCALE_SETTING, - BROWSER_LANGUAGE_SETTING, - languages, -} from '../../common/ui_settings/language_options'; -import { aiAssistantResponseLanguage } from '../../common'; - -import { useKibana } from './use_kibana'; - -export type UseUserPreferredLanguageResult = ReturnType; - -export function useUserPreferredLanguage() { - const { - services: { uiSettings }, - } = useKibana(); - - const selectedLanguage = uiSettings.get( - aiAssistantResponseLanguage, - DEFAULT_LANGUAGE_OPTION.value - ); - - const getPreferredLanguage = useCallback(() => { - if (selectedLanguage === KIBANA_LOCALE_SETTING.value) { - return getLanguageFromKibanaSettings(); - } else if (selectedLanguage === BROWSER_LANGUAGE_SETTING.value) { - return getLanguageFromBrowserSetting(); - } else { - return languages[selectedLanguage] || 'English'; - } - }, [selectedLanguage]); - - return { selectedLanguage, getPreferredLanguage }; -} - -function getLanguageFromKibanaSettings() { - switch (i18n.getLocale()) { - case 'en': - return 'English'; - case 'zh-cn': - return '简体中文'; - case 'ja-jp': - return '日本語'; - case 'fr-fr': - return 'français'; - default: - return 'English'; - } -} - -function getLanguageFromBrowserSetting() { - return languages[navigator.language] || 'English'; -} diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/public/index.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/public/index.ts index 7e7ed20de18e3..ab2dea089dcf1 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/public/index.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/public/index.ts @@ -93,13 +93,12 @@ export type { } from './api'; export type { UseChatResult } from './hooks/use_chat'; -export { LANGUAGE_OPTIONS, DEFAULT_LANGUAGE_OPTION } from '../common/ui_settings/language_options'; export { - aiAssistantResponseLanguage, aiAssistantLogsIndexPattern, aiAssistantSimulatedFunctionCalling, aiAssistantSearchConnectorIndexPattern, + aiAssistantPreferredAIAssistantType, } from '../common/ui_settings/settings_keys'; export const plugin: PluginInitializer< diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/public/mock.tsx b/x-pack/plugins/observability_solution/observability_ai_assistant/public/mock.tsx index 31907f54c49bf..b5d85be11dfe2 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/public/mock.tsx +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/public/mock.tsx @@ -79,12 +79,6 @@ function createStartContract(): ObservabilityAIAssistantPublicStart { selectConnector: () => {}, reloadConnectors: () => {}, }), - useUserPreferredLanguage: () => ({ - LANGUAGE_OPTIONS: [{ label: 'English' }], - selectedLanguage: 'English', - setSelectedLanguage: () => {}, - getPreferredLanguage: () => 'English', - }), getContextualInsightMessages: () => [], createScreenContextAction: () => ({} as ScreenContextActionDefinition), }; diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/public/plugin.tsx b/x-pack/plugins/observability_solution/observability_ai_assistant/public/plugin.tsx index 2c2c68f407d84..fd2a60dcdfc3a 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/public/plugin.tsx +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/public/plugin.tsx @@ -16,7 +16,6 @@ import { ObservabilityAIAssistantMultipaneFlyoutContext } from './context/observ import { ObservabilityAIAssistantProvider } from './context/observability_ai_assistant_provider'; import { useGenAIConnectorsWithoutContext } from './hooks/use_genai_connectors'; import { useObservabilityAIAssistantChatService } from './hooks/use_observability_ai_assistant_chat_service'; -import { useUserPreferredLanguage } from './hooks/use_user_preferred_language'; import { createUseChat } from './hooks/use_chat'; import { createService } from './service/create_service'; import { createScreenContextAction } from './utils/create_screen_context_action'; @@ -97,7 +96,6 @@ export class ObservabilityAIAssistantPlugin useChat: createUseChat({ notifications: coreStart.notifications, }), - useUserPreferredLanguage, ObservabilityAIAssistantMultipaneFlyoutContext, ObservabilityAIAssistantChatServiceContext, useObservabilityAIAssistantChatService, diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/public/service/complete.test.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/public/service/complete.test.ts index 4665f9b7b486b..59b3e7c9087d9 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/public/service/complete.test.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/public/service/complete.test.ts @@ -101,7 +101,6 @@ describe('complete', () => { persist: false, disableFunctions: false, signal: new AbortController().signal, - responseLanguage: 'orcish', ...params, }, requestCallback diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/public/service/complete.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/public/service/complete.ts index 90a8f16639ed6..85f5f0397ff31 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/public/service/complete.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/public/service/complete.ts @@ -42,7 +42,6 @@ export function complete( persist, disableFunctions, signal, - responseLanguage, instructions, }: { client: Pick; @@ -65,7 +64,6 @@ export function complete( disableFunctions, screenContexts, conversationId, - responseLanguage, instructions, }, }, @@ -131,7 +129,6 @@ export function complete( messages: initialMessages.concat(nextMessages), signal, persist, - responseLanguage, disableFunctions, instructions, }, diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/public/service/create_chat_service.test.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/public/service/create_chat_service.test.ts index 6555c310b14f9..6d0332602c869 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/public/service/create_chat_service.test.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/public/service/create_chat_service.test.ts @@ -229,38 +229,4 @@ describe('createChatService', () => { ).rejects.toEqual(expect.any(AbortError)); }); }); - - describe('complete', () => { - it("sends the user's preferred response language to the API", async () => { - respondWithChunks({ - chunks: [ - '{"id":"my-id","type":"chatCompletionChunk","message":{"content":"Some message"}}', - ], - }); - - const response$ = service.complete({ - connectorId: '', - getScreenContexts: () => [], - messages: [], - persist: false, - disableFunctions: false, - signal: new AbortController().signal, - responseLanguage: 'orcish', - }); - - await getConcatenatedMessage(response$); - - expect(clientSpy).toHaveBeenNthCalledWith( - 2, - 'POST /internal/observability_ai_assistant/chat/complete', - expect.objectContaining({ - params: expect.objectContaining({ - body: expect.objectContaining({ - responseLanguage: 'orcish', - }), - }), - }) - ); - }); - }); }); diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/public/service/create_chat_service.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/public/service/create_chat_service.ts index db3c8b1f5bbf3..fc8c06ef55f51 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/public/service/create_chat_service.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/public/service/create_chat_service.ts @@ -214,7 +214,7 @@ export async function createChatService({ persist, disableFunctions, signal, - responseLanguage, + instructions, }) { return complete( @@ -227,7 +227,6 @@ export async function createChatService({ disableFunctions, signal, client, - responseLanguage, instructions, }, ({ params }) => { diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/public/types.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/public/types.ts index c00cf4805ff8d..71a8a7e402748 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/public/types.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/public/types.ts @@ -29,7 +29,6 @@ import { ObservabilityAIAssistantMultipaneFlyoutContext } from './context/observ import { useChat } from './hooks/use_chat'; import type { UseGenAIConnectorsResult } from './hooks/use_genai_connectors'; import { useObservabilityAIAssistantChatService } from './hooks/use_observability_ai_assistant_chat_service'; -import type { UseUserPreferredLanguageResult } from './hooks/use_user_preferred_language'; import { createScreenContextAction } from './utils/create_screen_context_action'; /* eslint-disable @typescript-eslint/no-empty-interface*/ @@ -67,7 +66,6 @@ export interface ObservabilityAIAssistantChatService { except: string[]; }; signal: AbortSignal; - responseLanguage?: string; instructions?: AdHocInstruction[]; }) => Observable; getFunctions: (options?: { contexts?: string[]; filter?: string }) => FunctionDefinition[]; @@ -135,7 +133,6 @@ export interface ObservabilityAIAssistantPublicStart { useObservabilityAIAssistantChatService: typeof useObservabilityAIAssistantChatService; useGenAIConnectors: () => UseGenAIConnectorsResult; useChat: typeof useChat; - useUserPreferredLanguage: () => UseUserPreferredLanguageResult; getContextualInsightMessages: ({}: { message: string; instructions: string }) => Message[]; createScreenContextAction: typeof createScreenContextAction; } diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/server/index.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/server/index.ts index 03b3f4ccdc766..7d1409b29dde3 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/server/index.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/server/index.ts @@ -19,7 +19,6 @@ export type { } from './types'; export { - aiAssistantResponseLanguage, aiAssistantLogsIndexPattern, aiAssistantSimulatedFunctionCalling, aiAssistantSearchConnectorIndexPattern, diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/server/routes/chat/route.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/server/routes/chat/route.ts index 73d8b0d1354e0..d57051cf9fb62 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/server/routes/chat/route.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/server/routes/chat/route.ts @@ -33,7 +33,6 @@ const chatCompleteBaseRt = t.type({ t.partial({ conversationId: t.string, title: t.string, - responseLanguage: t.string, disableFunctions: t.union([ toBooleanRt, t.type({ @@ -241,7 +240,6 @@ async function chatComplete( title, persist, screenContexts, - responseLanguage, instructions, disableFunctions, }, @@ -266,7 +264,6 @@ async function chatComplete( persist, signal, functionClient, - responseLanguage, instructions, simulateFunctionCalling, disableFunctions, diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/index.test.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/index.test.ts index 33bd0ab49b1d7..f5c6b79b21788 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/index.test.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/index.test.ts @@ -33,7 +33,7 @@ type ChunkDelta = CreateChatCompletionResponseChunk['choices'][number]['delta']; type LlmSimulator = ReturnType; -const EXPECTED_STORED_SYSTEM_MESSAGE = `system\n\nYou MUST respond in the users preferred language which is: English.`; +const EXPECTED_STORED_SYSTEM_MESSAGE = `system`; const nextTick = () => { return new Promise(process.nextTick); @@ -366,8 +366,8 @@ describe('Observability AI Assistant client', () => { last_updated: expect.any(String), token_count: { completion: 1, - prompt: 46, - total: 47, + prompt: 33, + total: 34, }, }, type: StreamingChatResponseEventType.ConversationCreate, @@ -423,8 +423,8 @@ describe('Observability AI Assistant client', () => { last_updated: expect.any(String), token_count: { completion: 6, - prompt: 230, - total: 236, + prompt: 210, + total: 216, }, }, type: StreamingChatResponseEventType.ConversationCreate, @@ -441,8 +441,8 @@ describe('Observability AI Assistant client', () => { title: 'An auto-generated title', token_count: { completion: 6, - prompt: 230, - total: 236, + prompt: 210, + total: 216, }, }, labels: {}, @@ -572,8 +572,8 @@ describe('Observability AI Assistant client', () => { last_updated: expect.any(String), token_count: { completion: 2, - prompt: 124, - total: 126, + prompt: 111, + total: 113, }, }, type: StreamingChatResponseEventType.ConversationUpdate, @@ -591,8 +591,8 @@ describe('Observability AI Assistant client', () => { title: 'My stored conversation', token_count: { completion: 2, - prompt: 124, - total: 126, + prompt: 111, + total: 113, }, }, labels: {}, @@ -1583,39 +1583,6 @@ describe('Observability AI Assistant client', () => { ); }); - it("Adds the user's preferred language to the system prompt", async () => { - client = createClient(); - const chatSpy = jest.spyOn(client, 'chat'); - - actionsClientMock.execute.mockImplementation(async () => { - return { - actionId: '', - status: 'ok', - data: createLlmSimulator().stream, - }; - }); - - client - .complete({ - connectorId: 'foo', - messages: [system('This is a system message'), user('A user message to cause completion')], - functionClient: functionClientMock, - signal: new AbortController().signal, - title: 'My predefined title', - persist: false, - responseLanguage: 'Orcish', - }) - .subscribe(() => {}); // To trigger call to chat - await nextTick(); - - const systemMessage = chatSpy.mock.calls[0][1].messages[0]; - - expect(systemMessage.message.role).toEqual(MessageRole.System); - expect(systemMessage.message.content).toEqual( - EXPECTED_STORED_SYSTEM_MESSAGE.replace('English', 'Orcish') - ); - }); - describe('when executing an action', () => { let completePromise: Promise; diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/index.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/index.ts index 293d2da9c04b9..45309911375d1 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/index.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/index.ts @@ -166,7 +166,6 @@ export class ObservabilityAIAssistantClient { instructions: adHocInstructions = [], messages: initialMessages, signal, - responseLanguage = 'English', persist, kibanaPublicUrl, isPublic, @@ -179,7 +178,6 @@ export class ObservabilityAIAssistantClient { signal: AbortSignal; functionClient: ChatFunctionClient; persist: boolean; - responseLanguage?: string; conversationId?: string; title?: string; isPublic?: boolean; @@ -195,13 +193,6 @@ export class ObservabilityAIAssistantClient { return new LangTracer(context.active()).startActiveSpan( 'complete', ({ tracer: completeTracer }) => { - if (responseLanguage) { - adHocInstructions.push({ - instruction_type: 'application_instruction', - text: `You MUST respond in the users preferred language which is: ${responseLanguage}.`, - }); - } - const isConversationUpdate = persist && !!predefinedConversationId; const conversationId = persist ? predefinedConversationId || v4() : ''; @@ -252,7 +243,6 @@ export class ObservabilityAIAssistantClient { switchMap((messages) => getGeneratedTitle({ messages, - responseLanguage, logger: this.dependencies.logger, chat: (name, chatParams) => { return this.chat(name, { diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.test.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.test.ts index 02f5e5c294466..a8ddd5233132a 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.test.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.test.ts @@ -38,9 +38,7 @@ describe('getGeneratedTitle', () => { }; } - function callGenerateTitle( - ...rest: [ChatEvent[]] | [{ responseLanguage?: string }, ChatEvent[]] - ) { + function callGenerateTitle(...rest: [ChatEvent[]] | [{}, ChatEvent[]]) { const options = rest.length === 1 ? {} : rest[0]; const chunks = rest.length === 1 ? rest[0] : rest[1]; @@ -119,27 +117,6 @@ describe('getGeneratedTitle', () => { expect(await testTitle(`"User's request for a title"`)).toEqual(`User's request for a title`); }); - it('mentions the given response language in the instruction', async () => { - const { chatSpy, title$ } = callGenerateTitle( - { - responseLanguage: 'Orcish', - }, - [ - createChatCompletionChunk({ - function_call: { - name: 'title_conversation', - arguments: JSON.stringify({ title: 'My title' }), - }, - }), - ] - ); - - await lastValueFrom(title$); - - const [, params] = chatSpy.mock.calls[0]; - expect(params.messages[0].message.content).toContain('Orcish'); - }); - it('handles partial updates', async () => { const { title$ } = callGenerateTitle([ createChatCompletionChunk({ diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.ts index 23440c30bdcca..79dac3c036046 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.ts @@ -25,13 +25,11 @@ type ChatFunctionWithoutConnectorAndTokenCount = ( ) => Observable; export function getGeneratedTitle({ - responseLanguage, messages, chat, logger, tracer, }: { - responseLanguage?: string; messages: Message[]; chat: ChatFunctionWithoutConnectorAndTokenCount; logger: Pick; @@ -44,7 +42,7 @@ export function getGeneratedTitle({ '@timestamp': new Date().toString(), message: { role: MessageRole.System, - content: `You are a helpful assistant for Elastic Observability. Assume the following message is the start of a conversation between you and a user; give this conversation a title based on the content below. DO NOT UNDER ANY CIRCUMSTANCES wrap this title in single or double quotes. This title is shown in a list of conversations to the user, so title it for the user, not for you. Please create the title in ${responseLanguage}.`, + content: `You are a helpful assistant for Elastic Observability. Assume the following message is the start of a conversation between you and a user; give this conversation a title based on the content below. DO NOT UNDER ANY CIRCUMSTANCES wrap this title in single or double quotes. This title is shown in a list of conversations to the user, so title it for the user, not for you.`, }, }, { diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant_management/common/ui_settings.ts b/x-pack/plugins/observability_solution/observability_ai_assistant_management/common/ui_settings.ts index 967ef4a96fbf5..f972eb5742a91 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant_management/common/ui_settings.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant_management/common/ui_settings.ts @@ -10,44 +10,11 @@ import { UiSettingsParams } from '@kbn/core-ui-settings-common'; import { i18n } from '@kbn/i18n'; import { aiAssistantLogsIndexPattern, - aiAssistantResponseLanguage, aiAssistantSimulatedFunctionCalling, aiAssistantSearchConnectorIndexPattern, } from '@kbn/observability-ai-assistant-plugin/common'; -import { - DEFAULT_LANGUAGE_OPTION, - LANGUAGE_OPTIONS, -} from '@kbn/observability-ai-assistant-plugin/common'; export const uiSettings: Record = { - [aiAssistantResponseLanguage]: { - category: ['observability'], - name: i18n.translate( - 'xpack.observabilityAiAssistantManagement.settingsPage.userPreferencesLabel', - { - defaultMessage: 'Response language', - } - ), - value: DEFAULT_LANGUAGE_OPTION.value, - description: i18n.translate( - 'xpack.observabilityAiAssistantManagement.settingsPage.selectYourLanguageLabel', - { - defaultMessage: - 'Select the language you wish the Assistant to use when generating responses.', - } - ), - - // Argument of type 'Type[]' is not assignable to parameter of type '[Type]'. - // @ts-expect-error - schema: schema.oneOf(LANGUAGE_OPTIONS.map((lang) => schema.literal(lang.value))), - type: 'select', - options: LANGUAGE_OPTIONS.map((lang) => lang.value), - optionLabels: LANGUAGE_OPTIONS.reduce( - (acc, { value, label }) => ({ ...acc, [value]: label }), - {} - ), - requiresPageReload: true, - }, [aiAssistantLogsIndexPattern]: { category: ['observability'], name: i18n.translate( diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant_management/public/routes/components/settings_tab/settings_tab.test.tsx b/x-pack/plugins/observability_solution/observability_ai_assistant_management/public/routes/components/settings_tab/settings_tab.test.tsx index 9b7022efc324c..807bde0557d8d 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant_management/public/routes/components/settings_tab/settings_tab.test.tsx +++ b/x-pack/plugins/observability_solution/observability_ai_assistant_management/public/routes/components/settings_tab/settings_tab.test.tsx @@ -9,10 +9,7 @@ import React from 'react'; import { fireEvent, waitFor } from '@testing-library/react'; import { render } from '../../../helpers/test_helper'; import { SettingsTab } from './settings_tab'; -import { - aiAssistantLogsIndexPattern, - aiAssistantResponseLanguage, -} from '@kbn/observability-ai-assistant-plugin/server'; +import { aiAssistantLogsIndexPattern } from '@kbn/observability-ai-assistant-plugin/server'; import { uiSettings } from '../../../../common/ui_settings'; jest.mock('../../../hooks/use_app_context'); @@ -76,13 +73,6 @@ describe('SettingsTab', () => { target: { value: 'observability-ai-assistant-*' }, }); - fireEvent.change( - getByTestId(`management-settings-editField-${aiAssistantResponseLanguage}`), - { - target: { value: 'da' }, - } - ); - fireEvent.click(getByTestId('observabilityAiAssistantManagementBottomBarActionsButton')); await waitFor(() => expect(windowLocationReloadMock).toHaveBeenCalledTimes(1)); @@ -97,7 +87,6 @@ describe('SettingsTab', () => { aiAssistantLogsIndexPattern, 'observability-ai-assistant-*' ); - expect(settingsClientSet).toBeCalledWith(aiAssistantResponseLanguage, 'da'); }); }); }); diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant_management/public/routes/components/settings_tab/ui_settings.tsx b/x-pack/plugins/observability_solution/observability_ai_assistant_management/public/routes/components/settings_tab/ui_settings.tsx index 5b1f1c36fd3dd..5be8456954d64 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant_management/public/routes/components/settings_tab/ui_settings.tsx +++ b/x-pack/plugins/observability_solution/observability_ai_assistant_management/public/routes/components/settings_tab/ui_settings.tsx @@ -9,9 +9,9 @@ import React from 'react'; import { BottomBarActions, useEditableSettings } from '@kbn/observability-shared-plugin/public'; import { aiAssistantLogsIndexPattern, - aiAssistantResponseLanguage, aiAssistantSimulatedFunctionCalling, aiAssistantSearchConnectorIndexPattern, + aiAssistantPreferredAIAssistantType, } from '@kbn/observability-ai-assistant-plugin/public'; import { FieldRow, FieldRowProvider } from '@kbn/management-settings-components-field-row'; import { EuiSpacer } from '@elastic/eui'; @@ -21,9 +21,9 @@ import { useKibana } from '../../../hooks/use_kibana'; const settingsKeys = [ aiAssistantLogsIndexPattern, - aiAssistantResponseLanguage, aiAssistantSimulatedFunctionCalling, aiAssistantSearchConnectorIndexPattern, + aiAssistantPreferredAIAssistantType, ]; export function UISettings() { diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx b/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx index 720f31ccea3fa..bf49fa4393282 100644 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx +++ b/x-pack/plugins/observability_solution/slo/public/components/slo/slo_permissions_callout/index.tsx @@ -46,7 +46,7 @@ export function SloPermissionsCallout() {
  • @@ -62,13 +62,7 @@ export function SloPermissionsCallout() {
  • -
  • -
  • -
  • diff --git a/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts b/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts index 3a06e653c8159..fffbd7aa1e924 100644 --- a/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts +++ b/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts @@ -105,27 +105,30 @@ const createSLORoute = createSloServerRoute({ const dataViews = await dependencies.getDataViewsStart(); const spaceId = (await spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default'; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const esClient = core.elasticsearch.client.asCurrentUser; const basePath = dependencies.pluginsSetup.core.http.basePath; - const soClient = (await context.core).savedObjects.client; + const soClient = core.savedObjects.client; const repository = new KibanaSavedObjectsSLORepository(soClient, logger); const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); const transformManager = new DefaultTransformManager( transformGenerators, - esClient, + scopedClusterClient, logger, spaceId, dataViewsService ); const summaryTransformManager = new DefaultSummaryTransformManager( new DefaultSummaryTransformGenerator(), - esClient, + scopedClusterClient, logger ); const createSLO = new CreateSLO( esClient, + scopedClusterClient, repository, transformManager, summaryTransformManager, @@ -154,25 +157,28 @@ const inspectSLORoute = createSloServerRoute({ const dataViews = await dependencies.getDataViewsStart(); const spaceId = (await spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default'; const basePath = dependencies.pluginsSetup.core.http.basePath; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - const soClient = (await context.core).savedObjects.client; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const esClient = core.elasticsearch.client.asCurrentUser; + const soClient = core.savedObjects.client; const repository = new KibanaSavedObjectsSLORepository(soClient, logger); const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); const transformManager = new DefaultTransformManager( transformGenerators, - esClient, + scopedClusterClient, logger, spaceId, dataViewsService ); const summaryTransformManager = new DefaultSummaryTransformManager( new DefaultSummaryTransformGenerator(), - esClient, + scopedClusterClient, logger ); const createSLO = new CreateSLO( esClient, + scopedClusterClient, repository, transformManager, summaryTransformManager, @@ -200,20 +206,22 @@ const updateSLORoute = createSloServerRoute({ const dataViews = await dependencies.getDataViewsStart(); const basePath = dependencies.pluginsSetup.core.http.basePath; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - const soClient = (await context.core).savedObjects.client; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const esClient = core.elasticsearch.client.asCurrentUser; + const soClient = core.savedObjects.client; const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); const repository = new KibanaSavedObjectsSLORepository(soClient, logger); const transformManager = new DefaultTransformManager( transformGenerators, - esClient, + scopedClusterClient, logger, spaceId, dataViewsService ); const summaryTransformManager = new DefaultSummaryTransformManager( new DefaultSummaryTransformGenerator(), - esClient, + scopedClusterClient, logger ); @@ -222,6 +230,7 @@ const updateSLORoute = createSloServerRoute({ transformManager, summaryTransformManager, esClient, + scopedClusterClient, logger, spaceId, basePath @@ -247,8 +256,10 @@ const deleteSLORoute = createSloServerRoute({ const spaceId = (await spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default'; const dataViews = await dependencies.getDataViewsStart(); - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - const soClient = (await context.core).savedObjects.client; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const esClient = core.elasticsearch.client.asCurrentUser; + const soClient = core.savedObjects.client; const rulesClient = await dependencies.getRulesClientWithRequest(request); const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); @@ -256,7 +267,7 @@ const deleteSLORoute = createSloServerRoute({ const repository = new KibanaSavedObjectsSLORepository(soClient, logger); const transformManager = new DefaultTransformManager( transformGenerators, - esClient, + scopedClusterClient, logger, spaceId, dataViewsService @@ -264,7 +275,7 @@ const deleteSLORoute = createSloServerRoute({ const summaryTransformManager = new DefaultSummaryTransformManager( new DefaultSummaryTransformGenerator(), - esClient, + scopedClusterClient, logger ); @@ -273,6 +284,7 @@ const deleteSLORoute = createSloServerRoute({ transformManager, summaryTransformManager, esClient, + scopedClusterClient, rulesClient ); @@ -319,20 +331,22 @@ const enableSLORoute = createSloServerRoute({ const spaceId = (await spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default'; const dataViews = await dependencies.getDataViewsStart(); - const soClient = (await context.core).savedObjects.client; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const soClient = core.savedObjects.client; + const esClient = core.elasticsearch.client.asCurrentUser; const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); const repository = new KibanaSavedObjectsSLORepository(soClient, logger); const transformManager = new DefaultTransformManager( transformGenerators, - esClient, + scopedClusterClient, logger, spaceId, dataViewsService ); const summaryTransformManager = new DefaultSummaryTransformManager( new DefaultSummaryTransformGenerator(), - esClient, + scopedClusterClient, logger ); @@ -358,20 +372,22 @@ const disableSLORoute = createSloServerRoute({ const spaceId = (await spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default'; const dataViews = await dependencies.getDataViewsStart(); - const soClient = (await context.core).savedObjects.client; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const soClient = core.savedObjects.client; + const esClient = core.elasticsearch.client.asCurrentUser; const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); const repository = new KibanaSavedObjectsSLORepository(soClient, logger); const transformManager = new DefaultTransformManager( transformGenerators, - esClient, + scopedClusterClient, logger, spaceId, dataViewsService ); const summaryTransformManager = new DefaultSummaryTransformManager( new DefaultSummaryTransformGenerator(), - esClient, + scopedClusterClient, logger ); @@ -396,27 +412,30 @@ const resetSLORoute = createSloServerRoute({ const spaces = await dependencies.getSpacesStart(); const dataViews = await dependencies.getDataViewsStart(); const spaceId = (await spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default'; - const soClient = (await context.core).savedObjects.client; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const soClient = core.savedObjects.client; + const esClient = core.elasticsearch.client.asCurrentUser; const basePath = dependencies.pluginsSetup.core.http.basePath; const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); const repository = new KibanaSavedObjectsSLORepository(soClient, logger); const transformManager = new DefaultTransformManager( transformGenerators, - esClient, + scopedClusterClient, logger, spaceId, dataViewsService ); const summaryTransformManager = new DefaultSummaryTransformManager( new DefaultSummaryTransformGenerator(), - esClient, + scopedClusterClient, logger ); const resetSLO = new ResetSLO( esClient, + scopedClusterClient, repository, transformManager, summaryTransformManager, @@ -598,11 +617,13 @@ const fetchSloHealthRoute = createSloServerRoute({ handler: async ({ context, params, logger }) => { await assertPlatinumLicense(context); - const soClient = (await context.core).savedObjects.client; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const soClient = core.savedObjects.client; + const esClient = core.elasticsearch.client.asCurrentUser; const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - const getSLOHealth = new GetSLOHealth(esClient, repository); + const getSLOHealth = new GetSLOHealth(esClient, scopedClusterClient, repository); return await getSLOHealth.execute(params.body); }, diff --git a/x-pack/plugins/observability_solution/slo/server/services/create_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/create_slo.test.ts index 1acc263a2d655..9499294eeb89b 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/create_slo.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/create_slo.test.ts @@ -10,6 +10,7 @@ import { elasticsearchServiceMock, httpServiceMock, loggingSystemMock, + ScopedClusterClientMock, } from '@kbn/core/server/mocks'; import { MockedLogger } from '@kbn/logging-mocks'; import { CreateSLO } from './create_slo'; @@ -25,6 +26,7 @@ import { TransformManager } from './transform_manager'; describe('CreateSLO', () => { let mockEsClient: ElasticsearchClientMock; + let mockScopedClusterClient: ScopedClusterClientMock; let mockLogger: jest.Mocked; let mockRepository: jest.Mocked; let mockTransformManager: jest.Mocked; @@ -35,12 +37,14 @@ describe('CreateSLO', () => { beforeEach(() => { mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockLogger = loggingSystemMock.createLogger(); mockRepository = createSLORepositoryMock(); mockTransformManager = createTransformManagerMock(); mockSummaryTransformManager = createSummaryTransformManagerMock(); createSLO = new CreateSLO( mockEsClient, + mockScopedClusterClient, mockRepository, mockTransformManager, mockSummaryTransformManager, @@ -82,7 +86,9 @@ describe('CreateSLO', () => { expect(mockTransformManager.install).toHaveBeenCalled(); expect(mockTransformManager.start).toHaveBeenCalled(); - expect(mockEsClient.ingest.putPipeline.mock.calls[0]).toMatchSnapshot(); + expect( + mockScopedClusterClient.asSecondaryAuthUser.ingest.putPipeline.mock.calls[0] + ).toMatchSnapshot(); expect(mockSummaryTransformManager.install).toHaveBeenCalled(); expect(mockSummaryTransformManager.start).toHaveBeenCalled(); expect(mockEsClient.index.mock.calls[0]).toMatchSnapshot(); @@ -165,7 +171,9 @@ describe('CreateSLO', () => { ); expect(mockRepository.deleteById).toHaveBeenCalled(); - expect(mockEsClient.ingest.deletePipeline).toHaveBeenCalledTimes(1); + expect( + mockScopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline + ).toHaveBeenCalledTimes(1); expect(mockSummaryTransformManager.stop).not.toHaveBeenCalled(); expect(mockSummaryTransformManager.uninstall).not.toHaveBeenCalled(); @@ -186,7 +194,9 @@ describe('CreateSLO', () => { expect(mockRepository.deleteById).toHaveBeenCalled(); expect(mockTransformManager.stop).toHaveBeenCalled(); expect(mockTransformManager.uninstall).toHaveBeenCalled(); - expect(mockEsClient.ingest.deletePipeline).toHaveBeenCalledTimes(2); + expect( + mockScopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline + ).toHaveBeenCalledTimes(2); expect(mockSummaryTransformManager.uninstall).toHaveBeenCalled(); expect(mockSummaryTransformManager.stop).not.toHaveBeenCalled(); @@ -203,7 +213,9 @@ describe('CreateSLO', () => { expect(mockRepository.deleteById).toHaveBeenCalled(); expect(mockTransformManager.stop).toHaveBeenCalled(); expect(mockTransformManager.uninstall).toHaveBeenCalled(); - expect(mockEsClient.ingest.deletePipeline).toHaveBeenCalledTimes(2); + expect( + mockScopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline + ).toHaveBeenCalledTimes(2); expect(mockSummaryTransformManager.stop).toHaveBeenCalled(); expect(mockSummaryTransformManager.uninstall).toHaveBeenCalled(); }); diff --git a/x-pack/plugins/observability_solution/slo/server/services/create_slo.ts b/x-pack/plugins/observability_solution/slo/server/services/create_slo.ts index f3abb8554f3dd..0f6885dd44c6c 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/create_slo.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/create_slo.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import { IScopedClusterClient } from '@kbn/core/server'; import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient, IBasePath, Logger } from '@kbn/core/server'; import { ALL_VALUE, CreateSLOParams, CreateSLOResponse } from '@kbn/slo-schema'; @@ -32,6 +32,7 @@ import { getTransformQueryComposite } from './utils/get_transform_compite_query' export class CreateSLO { constructor( private esClient: ElasticsearchClient, + private scopedClusterClient: IScopedClusterClient, private repository: SLORepository, private transformManager: TransformManager, private summaryTransformManager: TransformManager, @@ -53,11 +54,14 @@ export class CreateSLO { const summaryTransformId = getSLOSummaryTransformId(slo.id, slo.revision); try { await retryTransientEsErrors( - () => this.esClient.ingest.putPipeline(getSLOPipelineTemplate(slo)), + () => + this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( + getSLOPipelineTemplate(slo) + ), { logger: this.logger } ); rollbackOperations.push(() => - this.esClient.ingest.deletePipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOPipelineId(slo.id, slo.revision) }, { ignore: [404] } ) @@ -71,13 +75,13 @@ export class CreateSLO { await retryTransientEsErrors( () => - this.esClient.ingest.putPipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( getSLOSummaryPipelineTemplate(slo, this.spaceId, this.basePath) ), { logger: this.logger } ); rollbackOperations.push(() => - this.esClient.ingest.deletePipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOSummaryPipelineId(slo.id, slo.revision) }, { ignore: [404] } ) diff --git a/x-pack/plugins/observability_solution/slo/server/services/delete_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/delete_slo.test.ts index 506151da864d3..2b8a2352f8026 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/delete_slo.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/delete_slo.test.ts @@ -8,7 +8,7 @@ import { rulesClientMock } from '@kbn/alerting-plugin/server/rules_client.mock'; import { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import { ElasticsearchClient } from '@kbn/core/server'; -import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; +import { elasticsearchServiceMock, ScopedClusterClientMock } from '@kbn/core/server/mocks'; import { DeleteSLO } from './delete_slo'; import { createAPMTransactionErrorRateIndicator, createSLO } from './fixtures/slo'; import { @@ -24,6 +24,7 @@ describe('DeleteSLO', () => { let mockTransformManager: jest.Mocked; let mockSummaryTransformManager: jest.Mocked; let mockEsClient: jest.Mocked; + let mockScopedClusterClient: ScopedClusterClientMock; let mockRulesClient: jest.Mocked; let deleteSLO: DeleteSLO; @@ -32,12 +33,14 @@ describe('DeleteSLO', () => { mockTransformManager = createTransformManagerMock(); mockSummaryTransformManager = createSummaryTransformManagerMock(); mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockRulesClient = rulesClientMock.create(); deleteSLO = new DeleteSLO( mockRepository, mockTransformManager, mockSummaryTransformManager, mockEsClient, + mockScopedClusterClient, mockRulesClient ); }); @@ -57,7 +60,7 @@ describe('DeleteSLO', () => { expect(mockSummaryTransformManager.uninstall).toMatchSnapshot(); expect(mockTransformManager.stop).toMatchSnapshot(); expect(mockTransformManager.uninstall).toMatchSnapshot(); - expect(mockEsClient.ingest.deletePipeline).toMatchSnapshot(); + expect(mockScopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline).toMatchSnapshot(); expect(mockEsClient.deleteByQuery).toMatchSnapshot(); expect(mockRulesClient.bulkDeleteRules).toMatchSnapshot(); expect(mockRepository.deleteById).toMatchSnapshot(); diff --git a/x-pack/plugins/observability_solution/slo/server/services/delete_slo.ts b/x-pack/plugins/observability_solution/slo/server/services/delete_slo.ts index 9bd64727e286b..e86fab0a1620d 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/delete_slo.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/delete_slo.ts @@ -6,7 +6,7 @@ */ import { RulesClientApi } from '@kbn/alerting-plugin/server/types'; -import { ElasticsearchClient } from '@kbn/core/server'; +import { ElasticsearchClient, IScopedClusterClient } from '@kbn/core/server'; import { getSLOPipelineId, getSLOSummaryPipelineId, @@ -25,6 +25,7 @@ export class DeleteSLO { private transformManager: TransformManager, private summaryTransformManager: TransformManager, private esClient: ElasticsearchClient, + private scopedClusterClient: IScopedClusterClient, private rulesClient: RulesClientApi ) {} @@ -40,14 +41,14 @@ export class DeleteSLO { await this.transformManager.uninstall(rollupTransformId); await retryTransientEsErrors(() => - this.esClient.ingest.deletePipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOPipelineId(slo.id, slo.revision) }, { ignore: [404] } ) ); await retryTransientEsErrors(() => - this.esClient.ingest.deletePipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOSummaryPipelineId(slo.id, slo.revision) }, { ignore: [404] } ) diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts index 38c183316a591..7a090de252c1d 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_diagnosis.ts @@ -8,17 +8,37 @@ import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { LicensingApiRequestHandlerContext } from '@kbn/licensing-plugin/server'; +export const MINIMUM_INDEX_PRIVILEGE_SET_EDITOR = [ + 'write', + 'read', + 'view_index_metadata', + 'manage', +]; +export const TOTAL_INDEX_PRIVILEGE_SET_EDITOR = [ + 'write', + 'read', + 'read_cross_cluster', + 'view_index_metadata', + 'manage', +]; +export const MINIMUM_INDEX_PRIVILEGE_SET_VIEWER = ['read']; +export const TOTAL_INDEX_PRIVILEGE_SET_VIEWER = ['read', 'read_cross_cluster']; + export async function getGlobalDiagnosis( esClient: ElasticsearchClient, licensing: LicensingApiRequestHandlerContext ) { const licenseInfo = licensing.license.toJSON(); const userWritePrivileges = await esClient.security.hasPrivileges({ - cluster: ['manage_transform', 'manage_ingest_pipelines'], - index: [{ names: '.slo-*', privileges: ['all'] }], + index: [ + { + names: '.slo-observability.*', + privileges: MINIMUM_INDEX_PRIVILEGE_SET_EDITOR, + }, + ], }); const userReadPrivileges = await esClient.security.hasPrivileges({ - index: [{ names: '.slo-*', privileges: ['read'] }], + index: [{ names: '.slo-observability.*', privileges: MINIMUM_INDEX_PRIVILEGE_SET_VIEWER }], }); return { diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.test.ts b/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.test.ts index ce1522de40ada..a6553e6f069aa 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.test.ts @@ -4,9 +4,9 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { TransformGetTransformStatsTransformStats } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient } from '@kbn/core/server'; -import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; +import { ScopedClusterClientMock, elasticsearchServiceMock } from '@kbn/core/server/mocks'; import { ALL_VALUE } from '@kbn/slo-schema'; import { getSLOSummaryTransformId, getSLOTransformId } from '../../common/constants'; import { createSLO } from './fixtures/slo'; @@ -22,12 +22,14 @@ import { SLORepository } from './slo_repository'; describe('GetSLOHealth', () => { let mockRepository: jest.Mocked; let mockEsClient: jest.Mocked; + let mockScopedClusterClient: ScopedClusterClientMock; let getSLOHealth: GetSLOHealth; beforeEach(() => { mockRepository = createSLORepositoryMock(); mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); - getSLOHealth = new GetSLOHealth(mockEsClient, mockRepository); + mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + getSLOHealth = new GetSLOHealth(mockEsClient, mockScopedClusterClient, mockRepository); }); it('returns the health and state', async () => { @@ -128,10 +130,16 @@ describe('GetSLOHealth', () => { }); // @ts-ignore - mockEsClient.transform.getTransformStats.mockResolvedValue({ + mockScopedClusterClient.asSecondaryAuthUser.transform.getTransformStats.mockResolvedValue({ transforms: [ - { id: getSLOTransformId(slo.id, slo.revision), health: { status: 'green' } }, - { id: getSLOSummaryTransformId(slo.id, slo.revision), health: { status: 'green' } }, + { + id: getSLOTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, + { + id: getSLOSummaryTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, ], }); @@ -179,10 +187,16 @@ describe('GetSLOHealth', () => { }); // @ts-ignore - mockEsClient.transform.getTransformStats.mockResolvedValue({ + mockScopedClusterClient.asSecondaryAuthUser.transform.getTransformStats.mockResolvedValue({ transforms: [ - { id: getSLOTransformId(slo.id, slo.revision), health: { status: 'yellow' } }, - { id: getSLOSummaryTransformId(slo.id, slo.revision), health: { status: 'green' } }, + { + id: getSLOTransformId(slo.id, slo.revision), + health: { status: 'yellow' }, + } as TransformGetTransformStatsTransformStats, + { + id: getSLOSummaryTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, ], }); @@ -240,10 +254,16 @@ describe('GetSLOHealth', () => { }); // @ts-ignore - mockEsClient.transform.getTransformStats.mockResolvedValue({ + mockScopedClusterClient.asSecondaryAuthUser.transform.getTransformStats.mockResolvedValue({ transforms: [ - { id: getSLOTransformId(slo.id, slo.revision), health: { status: 'green' } }, - { id: getSLOSummaryTransformId(slo.id, slo.revision), health: { status: 'green' } }, + { + id: getSLOTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, + { + id: getSLOSummaryTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, ], }); @@ -286,10 +306,16 @@ describe('GetSLOHealth', () => { }); // @ts-ignore - mockEsClient.transform.getTransformStats.mockResolvedValue({ + mockScopedClusterClient.asSecondaryAuthUser.transform.getTransformStats.mockResolvedValue({ transforms: [ - { id: getSLOTransformId(slo.id, slo.revision), health: { status: 'green' } }, - { id: getSLOSummaryTransformId(slo.id, slo.revision), health: { status: 'green' } }, + { + id: getSLOTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, + { + id: getSLOSummaryTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, ], }); @@ -332,10 +358,16 @@ describe('GetSLOHealth', () => { }); // @ts-ignore - mockEsClient.transform.getTransformStats.mockResolvedValue({ + mockScopedClusterClient.asSecondaryAuthUser.transform.getTransformStats.mockResolvedValue({ transforms: [ - { id: getSLOTransformId(slo.id, slo.revision), health: { status: 'green' } }, - { id: getSLOSummaryTransformId(slo.id, slo.revision), health: { status: 'green' } }, + { + id: getSLOTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, + { + id: getSLOSummaryTransformId(slo.id, slo.revision), + health: { status: 'green' }, + } as TransformGetTransformStatsTransformStats, ], }); diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.ts b/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.ts index 76493e8a7f4e4..585bf7ef5d4e2 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_slo_health.ts @@ -6,7 +6,7 @@ */ import { TransformGetTransformStatsTransformStats } from '@elastic/elasticsearch/lib/api/types'; -import { ElasticsearchClient } from '@kbn/core/server'; +import { ElasticsearchClient, IScopedClusterClient } from '@kbn/core/server'; import { FetchSLOHealthParams, FetchSLOHealthResponse, @@ -28,7 +28,11 @@ const LAG_THRESHOLD_MINUTES = 10; const STALE_THRESHOLD_MINUTES = 2 * 24 * 60; export class GetSLOHealth { - constructor(private esClient: ElasticsearchClient, private repository: SLORepository) {} + constructor( + private esClient: ElasticsearchClient, + private scopedClusterClient: IScopedClusterClient, + private repository: SLORepository + ) {} public async execute(params: FetchSLOHealthParams): Promise { const sloIds = params.list.map(({ sloId }) => sloId); @@ -91,19 +95,20 @@ export class GetSLOHealth { private async getTransformStats( sloList: SLODefinition[] ): Promise> { - const transformStats = await this.esClient.transform.getTransformStats( - { - transform_id: sloList - .map((slo: SLODefinition) => [ - getSLOTransformId(slo.id, slo.revision), - getSLOSummaryTransformId(slo.id, slo.revision), - ]) - .flat(), - allow_no_match: true, - size: sloList.length * 2, - }, - { ignore: [404] } - ); + const transformStats = + await this.scopedClusterClient.asSecondaryAuthUser.transform.getTransformStats( + { + transform_id: sloList + .map((slo: SLODefinition) => [ + getSLOTransformId(slo.id, slo.revision), + getSLOSummaryTransformId(slo.id, slo.revision), + ]) + .flat(), + allow_no_match: true, + size: sloList.length * 2, + }, + { ignore: [404] } + ); return keyBy(transformStats.transforms, (transform) => transform.id); } diff --git a/x-pack/plugins/observability_solution/slo/server/services/reset_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/reset_slo.test.ts index 6f9a8dda4a128..efbf3eedb52e1 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/reset_slo.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/reset_slo.test.ts @@ -10,6 +10,7 @@ import { elasticsearchServiceMock, httpServiceMock, loggingSystemMock, + ScopedClusterClientMock, } from '@kbn/core/server/mocks'; import { MockedLogger } from '@kbn/logging-mocks'; @@ -31,6 +32,7 @@ describe('ResetSLO', () => { let mockTransformManager: jest.Mocked; let mockSummaryTransformManager: jest.Mocked; let mockEsClient: jest.Mocked; + let mockScopedClusterClient: ScopedClusterClientMock; let loggerMock: jest.Mocked; let resetSLO: ResetSLO; @@ -39,9 +41,11 @@ describe('ResetSLO', () => { mockRepository = createSLORepositoryMock(); mockTransformManager = createTransformManagerMock(); mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockSummaryTransformManager = createSummaryTransformManagerMock(); resetSLO = new ResetSLO( mockEsClient, + mockScopedClusterClient, mockRepository, mockTransformManager, mockSummaryTransformManager, @@ -76,7 +80,7 @@ describe('ResetSLO', () => { expect(mockSummaryTransformManager.install).toMatchSnapshot(); expect(mockSummaryTransformManager.start).toMatchSnapshot(); - expect(mockEsClient.ingest.putPipeline).toMatchSnapshot(); + expect(mockScopedClusterClient.asSecondaryAuthUser.ingest.putPipeline).toMatchSnapshot(); expect(mockTransformManager.install).toMatchSnapshot(); expect(mockTransformManager.start).toMatchSnapshot(); diff --git a/x-pack/plugins/observability_solution/slo/server/services/reset_slo.ts b/x-pack/plugins/observability_solution/slo/server/services/reset_slo.ts index 3eb5dc6d89672..f69651ff2ad8a 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/reset_slo.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/reset_slo.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ElasticsearchClient, IBasePath, Logger } from '@kbn/core/server'; +import { ElasticsearchClient, IBasePath, Logger, IScopedClusterClient } from '@kbn/core/server'; import { resetSLOResponseSchema } from '@kbn/slo-schema'; import { getSLOPipelineId, @@ -27,6 +27,7 @@ import { TransformManager } from './transform_manager'; export class ResetSLO { constructor( private esClient: ElasticsearchClient, + private scopedClusterClient: IScopedClusterClient, private repository: SLORepository, private transformManager: TransformManager, private summaryTransformManager: TransformManager, @@ -50,7 +51,10 @@ export class ResetSLO { try { await retryTransientEsErrors( - () => this.esClient.ingest.putPipeline(getSLOPipelineTemplate(slo)), + () => + this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( + getSLOPipelineTemplate(slo) + ), { logger: this.logger } ); @@ -59,7 +63,7 @@ export class ResetSLO { await retryTransientEsErrors( () => - this.esClient.ingest.putPipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( getSLOSummaryPipelineTemplate(slo, this.spaceId, this.basePath) ), { logger: this.logger } @@ -87,12 +91,12 @@ export class ResetSLO { await this.summaryTransformManager.uninstall(summaryTransformId); await this.transformManager.stop(rollupTransformId); await this.transformManager.uninstall(rollupTransformId); - await this.esClient.ingest.deletePipeline( + await this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOSummaryPipelineId(slo.id, slo.revision) }, { ignore: [404] } ); - await this.esClient.ingest.deletePipeline( + await this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOPipelineId(slo.id, slo.revision) }, { ignore: [404] } ); diff --git a/x-pack/plugins/observability_solution/slo/server/services/summay_transform_manager.ts b/x-pack/plugins/observability_solution/slo/server/services/summay_transform_manager.ts index 5529591a81e20..27d24e7fb5039 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/summay_transform_manager.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summay_transform_manager.ts @@ -6,7 +6,7 @@ */ import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; -import { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { IScopedClusterClient, Logger } from '@kbn/core/server'; import { SLODefinition } from '../domain/models'; import { SecurityException } from '../errors'; import { retryTransientEsErrors } from '../utils/retry'; @@ -18,16 +18,19 @@ type TransformId = string; export class DefaultSummaryTransformManager implements TransformManager { constructor( private generator: SummaryTransformGenerator, - private esClient: ElasticsearchClient, + private scopedClusterClient: IScopedClusterClient, private logger: Logger ) {} async install(slo: SLODefinition): Promise { const transformParams = await this.generator.generate(slo); try { - await retryTransientEsErrors(() => this.esClient.transform.putTransform(transformParams), { - logger: this.logger, - }); + await retryTransientEsErrors( + () => this.scopedClusterClient.asSecondaryAuthUser.transform.putTransform(transformParams), + { + logger: this.logger, + } + ); } catch (err) { this.logger.error(`Cannot create summary transform for SLO [${slo.id}]`); if (err.meta?.body?.error?.type === 'security_exception') { @@ -47,7 +50,10 @@ export class DefaultSummaryTransformManager implements TransformManager { async preview(transformId: string): Promise { try { await retryTransientEsErrors( - () => this.esClient.transform.previewTransform({ transform_id: transformId }), + () => + this.scopedClusterClient.asSecondaryAuthUser.transform.previewTransform({ + transform_id: transformId, + }), { logger: this.logger } ); } catch (err) { @@ -60,8 +66,13 @@ export class DefaultSummaryTransformManager implements TransformManager { try { await retryTransientEsErrors( () => - this.esClient.transform.startTransform({ transform_id: transformId }, { ignore: [409] }), - { logger: this.logger } + this.scopedClusterClient.asSecondaryAuthUser.transform.startTransform( + { transform_id: transformId }, + { ignore: [409] } + ), + { + logger: this.logger, + } ); } catch (err) { this.logger.error(`Cannot start SLO summary transform [${transformId}]`); @@ -73,7 +84,7 @@ export class DefaultSummaryTransformManager implements TransformManager { try { await retryTransientEsErrors( () => - this.esClient.transform.stopTransform( + this.scopedClusterClient.asSecondaryAuthUser.transform.stopTransform( { transform_id: transformId, wait_for_completion: true, force: true }, { ignore: [404] } ), @@ -89,7 +100,7 @@ export class DefaultSummaryTransformManager implements TransformManager { try { await retryTransientEsErrors( () => - this.esClient.transform.deleteTransform( + this.scopedClusterClient.asSecondaryAuthUser.transform.deleteTransform( { transform_id: transformId, force: true }, { ignore: [404] } ), diff --git a/x-pack/plugins/observability_solution/slo/server/services/transform_manager.test.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_manager.test.ts index 7e6cf50c169fa..b7b5d7ba4fcd9 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/transform_manager.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_manager.test.ts @@ -7,7 +7,7 @@ /* eslint-disable max-classes-per-file */ import { - ElasticsearchClientMock, + ScopedClusterClientMock, elasticsearchServiceMock, loggingSystemMock, } from '@kbn/core/server/mocks'; @@ -30,12 +30,12 @@ import { dataViewsService } from '@kbn/data-views-plugin/server/mocks'; import { DataViewsService } from '@kbn/data-views-plugin/common'; describe('TransformManager', () => { - let esClientMock: ElasticsearchClientMock; + let scopedClusterClientMock: ScopedClusterClientMock; let loggerMock: jest.Mocked; const spaceId = 'default'; beforeEach(() => { - esClientMock = elasticsearchServiceMock.createElasticsearchClient(); + scopedClusterClientMock = elasticsearchServiceMock.createScopedClusterClient(); loggerMock = loggingSystemMock.createLogger(); }); @@ -48,7 +48,7 @@ describe('TransformManager', () => { }; const service = new DefaultTransformManager( generators, - esClientMock, + scopedClusterClientMock, loggerMock, spaceId, dataViewsService @@ -66,7 +66,7 @@ describe('TransformManager', () => { }; const transformManager = new DefaultTransformManager( generators, - esClientMock, + scopedClusterClientMock, loggerMock, spaceId, dataViewsService @@ -87,7 +87,7 @@ describe('TransformManager', () => { }; const transformManager = new DefaultTransformManager( generators, - esClientMock, + scopedClusterClientMock, loggerMock, spaceId, dataViewsService @@ -96,7 +96,9 @@ describe('TransformManager', () => { const transformId = await transformManager.install(slo); - expect(esClientMock.transform.putTransform).toHaveBeenCalledTimes(1); + expect( + scopedClusterClientMock.asSecondaryAuthUser.transform.putTransform + ).toHaveBeenCalledTimes(1); expect(transformId).toBe(`slo-${slo.id}-${slo.revision}`); }); }); @@ -109,7 +111,7 @@ describe('TransformManager', () => { }; const transformManager = new DefaultTransformManager( generators, - esClientMock, + scopedClusterClientMock, loggerMock, spaceId, dataViewsService @@ -117,7 +119,9 @@ describe('TransformManager', () => { await transformManager.preview('slo-transform-id'); - expect(esClientMock.transform.previewTransform).toHaveBeenCalledTimes(1); + expect( + scopedClusterClientMock.asSecondaryAuthUser.transform.previewTransform + ).toHaveBeenCalledTimes(1); }); }); @@ -129,7 +133,7 @@ describe('TransformManager', () => { }; const transformManager = new DefaultTransformManager( generators, - esClientMock, + scopedClusterClientMock, loggerMock, spaceId, dataViewsService @@ -137,7 +141,9 @@ describe('TransformManager', () => { await transformManager.start('slo-transform-id'); - expect(esClientMock.transform.startTransform).toHaveBeenCalledTimes(1); + expect( + scopedClusterClientMock.asSecondaryAuthUser.transform.startTransform + ).toHaveBeenCalledTimes(1); }); }); @@ -149,7 +155,7 @@ describe('TransformManager', () => { }; const transformManager = new DefaultTransformManager( generators, - esClientMock, + scopedClusterClientMock, loggerMock, spaceId, dataViewsService @@ -157,7 +163,9 @@ describe('TransformManager', () => { await transformManager.stop('slo-transform-id'); - expect(esClientMock.transform.stopTransform).toHaveBeenCalledTimes(1); + expect( + scopedClusterClientMock.asSecondaryAuthUser.transform.stopTransform + ).toHaveBeenCalledTimes(1); }); }); @@ -169,7 +177,7 @@ describe('TransformManager', () => { }; const transformManager = new DefaultTransformManager( generators, - esClientMock, + scopedClusterClientMock, loggerMock, spaceId, dataViewsService @@ -177,11 +185,13 @@ describe('TransformManager', () => { await transformManager.uninstall('slo-transform-id'); - expect(esClientMock.transform.deleteTransform).toHaveBeenCalledTimes(1); + expect( + scopedClusterClientMock.asSecondaryAuthUser.transform.deleteTransform + ).toHaveBeenCalledTimes(1); }); it('retries on transient error', async () => { - esClientMock.transform.deleteTransform.mockRejectedValueOnce( + scopedClusterClientMock.asSecondaryAuthUser.transform.deleteTransform.mockRejectedValueOnce( new EsErrors.ConnectionError('irrelevant') ); // @ts-ignore defining only a subset of the possible SLI @@ -190,7 +200,7 @@ describe('TransformManager', () => { }; const transformManager = new DefaultTransformManager( generators, - esClientMock, + scopedClusterClientMock, loggerMock, spaceId, dataViewsService @@ -198,7 +208,9 @@ describe('TransformManager', () => { await transformManager.uninstall('slo-transform-id'); - expect(esClientMock.transform.deleteTransform).toHaveBeenCalledTimes(2); + expect( + scopedClusterClientMock.asSecondaryAuthUser.transform.deleteTransform + ).toHaveBeenCalledTimes(2); }); }); }); diff --git a/x-pack/plugins/observability_solution/slo/server/services/transform_manager.ts b/x-pack/plugins/observability_solution/slo/server/services/transform_manager.ts index 822817962a2e9..7e5ddce8bcad6 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/transform_manager.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/transform_manager.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { IScopedClusterClient, Logger } from '@kbn/core/server'; import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { DataViewsService } from '@kbn/data-views-plugin/server'; @@ -28,7 +28,7 @@ export interface TransformManager { export class DefaultTransformManager implements TransformManager { constructor( private generators: Record, - private esClient: ElasticsearchClient, + private scopedClusterClient: IScopedClusterClient, private logger: Logger, private spaceId: string, private dataViewService: DataViewsService @@ -47,9 +47,12 @@ export class DefaultTransformManager implements TransformManager { this.dataViewService ); try { - await retryTransientEsErrors(() => this.esClient.transform.putTransform(transformParams), { - logger: this.logger, - }); + await retryTransientEsErrors( + () => this.scopedClusterClient.asSecondaryAuthUser.transform.putTransform(transformParams), + { + logger: this.logger, + } + ); } catch (err) { this.logger.error(`Cannot create SLO transform for indicator type [${slo.indicator.type}]`); if (err.meta?.body?.error?.type === 'security_exception') { @@ -75,7 +78,10 @@ export class DefaultTransformManager implements TransformManager { async preview(transformId: string): Promise { try { await retryTransientEsErrors( - () => this.esClient.transform.previewTransform({ transform_id: transformId }), + () => + this.scopedClusterClient.asSecondaryAuthUser.transform.previewTransform({ + transform_id: transformId, + }), { logger: this.logger } ); } catch (err) { @@ -88,7 +94,10 @@ export class DefaultTransformManager implements TransformManager { try { await retryTransientEsErrors( () => - this.esClient.transform.startTransform({ transform_id: transformId }, { ignore: [409] }), + this.scopedClusterClient.asSecondaryAuthUser.transform.startTransform( + { transform_id: transformId }, + { ignore: [409] } + ), { logger: this.logger } ); await this.scheduleNowTransform(transformId); @@ -102,7 +111,7 @@ export class DefaultTransformManager implements TransformManager { try { await retryTransientEsErrors( () => - this.esClient.transform.stopTransform( + this.scopedClusterClient.asSecondaryAuthUser.transform.stopTransform( { transform_id: transformId, wait_for_completion: true, force: true }, { ignore: [404] } ), @@ -118,7 +127,7 @@ export class DefaultTransformManager implements TransformManager { try { await retryTransientEsErrors( () => - this.esClient.transform.deleteTransform( + this.scopedClusterClient.asSecondaryAuthUser.transform.deleteTransform( { transform_id: transformId, force: true }, { ignore: [404] } ), @@ -131,7 +140,7 @@ export class DefaultTransformManager implements TransformManager { } async scheduleNowTransform(transformId: TransformId) { - this.esClient.transform + this.scopedClusterClient.asSecondaryAuthUser.transform .scheduleNowTransform({ transform_id: transformId }) .then(() => { this.logger.debug(`SLO transform [${transformId}] scheduled now successfully`); diff --git a/x-pack/plugins/observability_solution/slo/server/services/update_slo.test.ts b/x-pack/plugins/observability_solution/slo/server/services/update_slo.test.ts index 7f8f8ff1e3150..37855bd4d8fa4 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/update_slo.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/update_slo.test.ts @@ -10,6 +10,7 @@ import { elasticsearchServiceMock, httpServiceMock, loggingSystemMock, + ScopedClusterClientMock, } from '@kbn/core/server/mocks'; import { MockedLogger } from '@kbn/logging-mocks'; import { UpdateSLOParams } from '@kbn/slo-schema'; @@ -42,6 +43,7 @@ describe('UpdateSLO', () => { let mockRepository: jest.Mocked; let mockTransformManager: jest.Mocked; let mockEsClient: jest.Mocked; + let mockScopedClusterClient: ScopedClusterClientMock; let mockLogger: jest.Mocked; let mockSummaryTransformManager: jest.Mocked; let updateSLO: UpdateSLO; @@ -52,11 +54,13 @@ describe('UpdateSLO', () => { mockLogger = loggingSystemMock.createLogger(); mockSummaryTransformManager = createSummaryTransformManagerMock(); mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); updateSLO = new UpdateSLO( mockRepository, mockTransformManager, mockSummaryTransformManager, mockEsClient, + mockScopedClusterClient, mockLogger, 'some-space', httpServiceMock.createStartContract().basePath @@ -76,7 +80,7 @@ describe('UpdateSLO', () => { expect(mockSummaryTransformManager.start).not.toBeCalled(); expect(mockEsClient.deleteByQuery).not.toBeCalled(); - expect(mockEsClient.ingest.putPipeline).not.toBeCalled(); + expect(mockScopedClusterClient.asSecondaryAuthUser.ingest.putPipeline).not.toBeCalled(); } it('returns early with a fully identical SLO payload', async () => { @@ -313,7 +317,9 @@ describe('UpdateSLO', () => { ).rejects.toThrowError('Transform install error'); expect(mockRepository.save).toHaveBeenCalledWith(originalSlo); - expect(mockEsClient.ingest.deletePipeline).toHaveBeenCalledTimes(1); // for the sli only + expect( + mockScopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline + ).toHaveBeenCalledTimes(1); // for the sli only expect(mockSummaryTransformManager.stop).not.toHaveBeenCalled(); expect(mockSummaryTransformManager.uninstall).not.toHaveBeenCalled(); @@ -339,7 +345,7 @@ describe('UpdateSLO', () => { expect(mockRepository.save).toHaveBeenCalledWith(originalSlo); expect(mockSummaryTransformManager.uninstall).toHaveBeenCalled(); - expect(mockEsClient.ingest.deletePipeline).toHaveBeenCalled(); + expect(mockScopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline).toHaveBeenCalled(); expect(mockTransformManager.stop).toHaveBeenCalled(); expect(mockTransformManager.uninstall).toHaveBeenCalled(); @@ -351,7 +357,7 @@ describe('UpdateSLO', () => { expect(mockTransformManager.install).toHaveBeenCalled(); expect(mockTransformManager.start).toHaveBeenCalled(); - expect(mockEsClient.ingest.putPipeline).toHaveBeenCalled(); + expect(mockScopedClusterClient.asSecondaryAuthUser.ingest.putPipeline).toHaveBeenCalled(); expect(mockSummaryTransformManager.install).toHaveBeenCalled(); expect(mockSummaryTransformManager.start).toHaveBeenCalled(); @@ -368,7 +374,7 @@ describe('UpdateSLO', () => { expect(mockSummaryTransformManager.stop).toHaveBeenCalledWith(summaryTransformId); expect(mockSummaryTransformManager.uninstall).toHaveBeenCalledWith(summaryTransformId); - expect(mockEsClient.ingest.deletePipeline).toHaveBeenCalled(); + expect(mockScopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline).toHaveBeenCalled(); expect(mockEsClient.deleteByQuery).toHaveBeenCalledTimes(2); expect(mockEsClient.deleteByQuery).toHaveBeenNthCalledWith( diff --git a/x-pack/plugins/observability_solution/slo/server/services/update_slo.ts b/x-pack/plugins/observability_solution/slo/server/services/update_slo.ts index 3175402eb1476..0f1967800d1df 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/update_slo.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/update_slo.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ElasticsearchClient, IBasePath, Logger } from '@kbn/core/server'; +import { ElasticsearchClient, IBasePath, Logger, IScopedClusterClient } from '@kbn/core/server'; import { UpdateSLOParams, UpdateSLOResponse, updateSLOResponseSchema } from '@kbn/slo-schema'; import { asyncForEach } from '@kbn/std'; import { isEqual, pick } from 'lodash'; @@ -34,6 +34,7 @@ export class UpdateSLO { private transformManager: TransformManager, private summaryTransformManager: TransformManager, private esClient: ElasticsearchClient, + private scopedClusterClient: IScopedClusterClient, private logger: Logger, private spaceId: string, private basePath: IBasePath @@ -77,11 +78,14 @@ export class UpdateSLO { try { await retryTransientEsErrors( - () => this.esClient.ingest.putPipeline(getSLOPipelineTemplate(updatedSlo)), + () => + this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( + getSLOPipelineTemplate(updatedSlo) + ), { logger: this.logger } ); rollbackOperations.push(() => - this.esClient.ingest.deletePipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOPipelineId(updatedSlo.id, updatedSlo.revision) }, { ignore: [404] } ) @@ -89,7 +93,7 @@ export class UpdateSLO { await retryTransientEsErrors( () => - this.esClient.ingest.putPipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( getSLOSummaryPipelineTemplate(updatedSlo, this.spaceId, this.basePath) ), { logger: this.logger } @@ -122,11 +126,14 @@ export class UpdateSLO { try { await retryTransientEsErrors( - () => this.esClient.ingest.putPipeline(getSLOPipelineTemplate(updatedSlo)), + () => + this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( + getSLOPipelineTemplate(updatedSlo) + ), { logger: this.logger } ); rollbackOperations.push(() => - this.esClient.ingest.deletePipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOPipelineId(updatedSlo.id, updatedSlo.revision) }, { ignore: [404] } ) @@ -140,13 +147,13 @@ export class UpdateSLO { await retryTransientEsErrors( () => - this.esClient.ingest.putPipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( getSLOSummaryPipelineTemplate(updatedSlo, this.spaceId, this.basePath) ), { logger: this.logger } ); rollbackOperations.push(() => - this.esClient.ingest.deletePipeline( + this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOSummaryPipelineId(updatedSlo.id, updatedSlo.revision) }, { ignore: [404] } ) @@ -208,12 +215,12 @@ export class UpdateSLO { await this.summaryTransformManager.stop(originalSummaryTransformId); await this.summaryTransformManager.uninstall(originalSummaryTransformId); - await this.esClient.ingest.deletePipeline( + await this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOSummaryPipelineId(originalSlo.id, originalSlo.revision) }, { ignore: [404] } ); - await this.esClient.ingest.deletePipeline( + await this.scopedClusterClient.asSecondaryAuthUser.ingest.deletePipeline( { id: getSLOPipelineId(originalSlo.id, originalSlo.revision) }, { ignore: [404] } ); diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/fields/request_body_field.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/fields/request_body_field.test.tsx index 2882104dbcb93..7740a346ca997 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/fields/request_body_field.test.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/fields/request_body_field.test.tsx @@ -34,7 +34,7 @@ describe('', () => { type: config.type, }} onChange={useCallback( - (code) => setConfig({ type: code.type as CodeEditorMode, value: code.value }), + (code: any) => setConfig({ type: code.type as CodeEditorMode, value: code.value }), [setConfig] )} readOnly={readOnly} diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_details/monitor_history/monitor_history.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_details/monitor_history/monitor_history.tsx index 8420df9b15f81..fc151db70d1ee 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_details/monitor_history/monitor_history.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_details/monitor_history/monitor_history.tsx @@ -35,7 +35,7 @@ export const MonitorHistory = () => { const statsColumns = statsWidth && statsWidth < STATS_WIDTH_SINGLE_COLUMN_THRESHOLD ? 1 : 2; const handleStatusChartBrushed = useCallback( - ({ fromUtc, toUtc }) => { + ({ fromUtc, toUtc }: any) => { updateUrlParams({ dateRangeStart: fromUtc, dateRangeEnd: toUtc }); }, [updateUrlParams] diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/monitor_detail_flyout.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/monitor_detail_flyout.tsx index 78ac9dd2f663f..cf2f6cb97d82e 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/monitor_detail_flyout.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/monitor_detail_flyout.tsx @@ -187,7 +187,7 @@ function DetailedFlyoutHeader({ configId={configId} selectedLocation={selectedLocation} onChange={useCallback( - (id, label) => { + (id: any, label: any) => { if (currentLocation !== label) setCurrentLocation(label, id); }, [currentLocation, setCurrentLocation] diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_wrapper.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_wrapper.tsx index ed5a6b73d411e..4f155d56db833 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_wrapper.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_wrapper.tsx @@ -127,14 +127,14 @@ export const WaterfallChartWrapper: React.FC = ({ setShowCustomMarks={setShowCustomMarks} query={query} setQuery={setQuery} - renderTooltipItem={useCallback((tooltipProps) => { + renderTooltipItem={useCallback((tooltipProps: any) => { return {tooltipProps?.value}; }, [])} > `${Number(d).toFixed(0)} ms`, [])} domain={domain} - barStyleAccessor={useCallback(({ datum }) => { + barStyleAccessor={useCallback(({ datum }: any) => { if (!datum.config?.isHighlighted) { return { rect: { diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_sidebar_item.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_sidebar_item.tsx index 60898420c84b2..a5d26e33a9b5a 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_sidebar_item.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_sidebar_item.tsx @@ -35,7 +35,7 @@ export const WaterfallSidebarItem = React.memo(function WaterfallSidebarItem({ } }, [buttonRef, index, onClick]); - const setRef = useCallback((ref) => setButtonRef(ref), [setButtonRef]); + const setRef = useCallback((ref: any) => setButtonRef(ref), [setButtonRef]); const isErrorStatusCode = (statusCode: number) => { const is400 = statusCode >= 400 && statusCode <= 499; diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/test_now_mode/test_now_mode_flyout_container.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/test_now_mode/test_now_mode_flyout_container.tsx index b550cdbd2745e..b710da8cfcba7 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/test_now_mode/test_now_mode_flyout_container.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/test_now_mode/test_now_mode_flyout_container.tsx @@ -26,7 +26,7 @@ export function TestNowModeFlyoutContainer() { const flyoutOpenTestRun = useTestFlyoutOpen(); const onDone = useCallback( - (testRunId) => { + (testRunId: any) => { dispatch( manualTestRunUpdateAction({ testRunId, @@ -39,7 +39,7 @@ export function TestNowModeFlyoutContainer() { ); const handleFlyoutClose = useCallback( - (testRunId) => { + (testRunId: any) => { dispatch( manualTestRunUpdateAction({ testRunId, diff --git a/x-pack/plugins/observability_solution/synthetics/public/hooks/use_form_wrapped.tsx b/x-pack/plugins/observability_solution/synthetics/public/hooks/use_form_wrapped.tsx index 97a5d74337144..354f3f6e21c2e 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/hooks/use_form_wrapped.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/hooks/use_form_wrapped.tsx @@ -41,7 +41,7 @@ export function useFormWrapped { + (name: any, ...registerArgs: any) => { const { ref, onChange, ...restOfRegister } = register(name, ...registerArgs); return { diff --git a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/common.ts b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/common.ts index 549bbcff4cdfe..20c84109b0be1 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/common.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/common.ts @@ -359,8 +359,9 @@ export const syntheticsRuleTypeFieldMap = { ...legacyExperimentalFieldMap, }; -export const SyntheticsRuleTypeAlertDefinition: IRuleTypeAlerts = { +export const SyntheticsRuleTypeAlertDefinition: IRuleTypeAlerts = { context: SYNTHETICS_RULE_TYPES_ALERT_CONTEXT, mappings: { fieldMap: syntheticsRuleTypeFieldMap }, useLegacyAlerts: true, + shouldWrite: true, }; diff --git a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts index d042e8d323302..c823abe7d083f 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts @@ -8,13 +8,11 @@ import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; import { isEmpty } from 'lodash'; import { ActionGroupIdsOf } from '@kbn/alerting-plugin/common'; -import { PluginSetupContract } from '@kbn/alerting-plugin/server'; import { GetViewInAppRelativeUrlFnOpts, AlertInstanceContext as AlertContext, RuleExecutorOptions, AlertsClientError, - IRuleTypeAlerts, } from '@kbn/alerting-plugin/server'; import { observabilityPaths } from '@kbn/observability-plugin/common'; import { ObservabilityUptimeAlert } from '@kbn/alerts-as-data-utils'; @@ -55,16 +53,15 @@ type MonitorStatusAlert = ObservabilityUptimeAlert; export const registerSyntheticsStatusCheckRule = ( server: SyntheticsServerSetup, plugins: SyntheticsPluginsSetupDependencies, - syntheticsMonitorClient: SyntheticsMonitorClient, - alerting: PluginSetupContract + syntheticsMonitorClient: SyntheticsMonitorClient ) => { - if (!alerting) { + if (!plugins.alerting) { throw new Error( 'Cannot register the synthetics monitor status rule type. The alerting plugin needs to be enabled.' ); } - alerting.registerType({ + plugins.alerting.registerType({ id: SYNTHETICS_ALERT_RULE_TYPES.MONITOR_STATUS, category: DEFAULT_APP_CATEGORIES.observability.id, producer: 'uptime', @@ -172,10 +169,7 @@ export const registerSyntheticsStatusCheckRule = ( state: updateState(ruleState, !isEmpty(downConfigs), { downConfigs }), }; }, - alerts: { - ...SyntheticsRuleTypeAlertDefinition, - shouldWrite: true, - } as IRuleTypeAlerts, + alerts: SyntheticsRuleTypeAlertDefinition, fieldsForAAD: Object.keys(syntheticsRuleFieldMap), getViewInAppRelativeUrl: ({ rule }: GetViewInAppRelativeUrlFnOpts<{}>) => observabilityPaths.ruleDetails(rule.id), diff --git a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.test.ts b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.test.ts new file mode 100644 index 0000000000000..e07ba00c1de6c --- /dev/null +++ b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.test.ts @@ -0,0 +1,167 @@ +/* + * 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 { IBasePath } from '@kbn/core/server'; +import { AlertsLocatorParams } from '@kbn/observability-plugin/common'; +import { LocatorPublic } from '@kbn/share-plugin/common'; +import { setTLSRecoveredAlertsContext } from './message_utils'; +import { TLSLatestPing } from './tls_rule_executor'; + +describe('setTLSRecoveredAlertsContext', () => { + const timestamp = new Date().toISOString(); + const alertUuid = 'alert-id'; + const configId = '12345'; + const basePath = { + publicBaseUrl: 'https://localhost:5601', + } as IBasePath; + const alertsLocatorMock = { + getLocation: jest.fn().mockImplementation(() => ({ + path: 'https://localhost:5601/app/observability/alerts/alert-id', + })), + } as any as LocatorPublic; + const alertState = { + summary: 'test-summary', + status: 'has expired', + sha256: 'cert-1-sha256', + commonName: 'cert-1', + issuer: 'test-issuer', + monitorName: 'test-monitor', + monitorType: 'test-monitor-type', + locationName: 'test-location-name', + monitorUrl: 'test-monitor-url', + configId, + }; + + it('sets context correctly when monitor cert has been updated', async () => { + const alertsClientMock = { + report: jest.fn(), + getAlertLimitValue: jest.fn().mockReturnValue(10), + setAlertLimitReached: jest.fn(), + getRecoveredAlerts: jest.fn().mockReturnValue([ + { + alert: { + getId: () => alertUuid, + getState: () => alertState, + setContext: jest.fn(), + getUuid: () => alertUuid, + getStart: () => new Date().toISOString(), + }, + }, + ]), + setAlertData: jest.fn(), + isTrackedAlert: jest.fn(), + }; + await setTLSRecoveredAlertsContext({ + alertsClient: alertsClientMock, + basePath, + defaultStartedAt: timestamp, + spaceId: 'default', + alertsLocator: alertsLocatorMock, + latestPings: [ + { + config_id: configId, + '@timestamp': timestamp, + tls: { + server: { + hash: { + sha256: 'cert-2-sha256', + }, + x509: { + subject: { + common_name: 'cert-2', + }, + not_after: timestamp, + }, + }, + }, + } as TLSLatestPing, + ], + }); + expect(alertsClientMock.setAlertData).toBeCalledWith({ + context: { + alertDetailsUrl: 'https://localhost:5601/app/observability/alerts/alert-id', + commonName: 'cert-1', + configId: '12345', + issuer: 'test-issuer', + locationName: 'test-location-name', + monitorName: 'test-monitor', + monitorType: 'test-monitor-type', + monitorUrl: 'test-monitor-url', + newStatus: expect.stringContaining('Certificate cert-2 Expired on'), + previousStatus: 'Certificate cert-1 test-summary', + sha256: 'cert-1-sha256', + status: 'has expired', + summary: 'Monitor certificate has been updated.', + }, + id: 'alert-id', + }); + }); + + it('sets context correctly when monitor cert expiry/age threshold has been updated', async () => { + const alertsClientMock = { + report: jest.fn(), + getAlertLimitValue: jest.fn().mockReturnValue(10), + setAlertLimitReached: jest.fn(), + getRecoveredAlerts: jest.fn().mockReturnValue([ + { + alert: { + getId: () => alertUuid, + getState: () => alertState, + setContext: jest.fn(), + getUuid: () => alertUuid, + getStart: () => new Date().toISOString(), + }, + }, + ]), + setAlertData: jest.fn(), + isTrackedAlert: jest.fn(), + }; + await setTLSRecoveredAlertsContext({ + alertsClient: alertsClientMock, + basePath, + defaultStartedAt: timestamp, + spaceId: 'default', + alertsLocator: alertsLocatorMock, + latestPings: [ + { + config_id: configId, + '@timestamp': timestamp, + tls: { + server: { + hash: { + sha256: 'cert-1-sha256', + }, + x509: { + subject: { + common_name: 'cert-1', + }, + not_after: timestamp, + }, + }, + }, + } as TLSLatestPing, + ], + }); + expect(alertsClientMock.setAlertData).toBeCalledWith({ + context: { + alertDetailsUrl: 'https://localhost:5601/app/observability/alerts/alert-id', + commonName: 'cert-1', + configId: '12345', + issuer: 'test-issuer', + locationName: 'test-location-name', + monitorName: 'test-monitor', + monitorType: 'test-monitor-type', + monitorUrl: 'test-monitor-url', + newStatus: 'Certificate cert-1 test-summary', + previousStatus: 'Certificate cert-1 test-summary', + sha256: 'cert-1-sha256', + status: 'has expired', + summary: 'Expiry/Age threshold has been updated.', + }, + id: 'alert-id', + }); + }); +}); diff --git a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.ts b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.ts index 78e073d9233a9..5fc23a370caea 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/message_utils.ts @@ -9,12 +9,19 @@ import moment from 'moment/moment'; import { IBasePath } from '@kbn/core-http-server'; import { LocatorPublic } from '@kbn/share-plugin/common'; import { AlertsLocatorParams, getAlertUrl } from '@kbn/observability-plugin/common'; -import { RuleExecutorServices } from '@kbn/alerting-plugin/server'; +import { + AlertInstanceContext as AlertContext, + AlertInstanceState as AlertState, + ActionGroupIdsOf, +} from '@kbn/alerting-plugin/server'; import { i18n } from '@kbn/i18n'; +import { PublicAlertsClient } from '@kbn/alerting-plugin/server/alerts_client/types'; +import { ObservabilityUptimeAlert } from '@kbn/alerts-as-data-utils'; import { TLSLatestPing } from './tls_rule_executor'; import { ALERT_DETAILS_URL } from '../action_variables'; import { Cert } from '../../../common/runtime_types'; import { tlsTranslations } from '../translations'; +import { MonitorStatusActionGroup } from '../../../common/constants/synthetics_alerts'; interface TLSContent { summary: string; status?: string; @@ -75,35 +82,34 @@ export const getCertSummary = (cert: Cert, expirationThreshold: number, ageThres }; }; -type CertSummary = ReturnType; - export const setTLSRecoveredAlertsContext = async ({ - alertFactory, + alertsClient, basePath, defaultStartedAt, - getAlertStartedDate, spaceId, alertsLocator, - getAlertUuid, latestPings, }: { - alertFactory: RuleExecutorServices['alertFactory']; + alertsClient: PublicAlertsClient< + ObservabilityUptimeAlert, + AlertState, + AlertContext, + ActionGroupIdsOf + >; defaultStartedAt: string; - getAlertStartedDate: (alertInstanceId: string) => string | null; basePath: IBasePath; spaceId: string; alertsLocator?: LocatorPublic; - getAlertUuid?: (alertId: string) => string | null; latestPings: TLSLatestPing[]; }) => { - const { getRecoveredAlerts } = alertFactory.done(); + const recoveredAlerts = alertsClient.getRecoveredAlerts() ?? []; - for await (const alert of getRecoveredAlerts()) { - const recoveredAlertId = alert.getId(); - const alertUuid = getAlertUuid?.(recoveredAlertId) || null; - const indexedStartedAt = getAlertStartedDate(recoveredAlertId) ?? defaultStartedAt; + for (const recoveredAlert of recoveredAlerts) { + const recoveredAlertId = recoveredAlert.alert.getId(); + const alertUuid = recoveredAlert.alert.getUuid(); + const indexedStartedAt = recoveredAlert.alert.getStart() ?? defaultStartedAt; - const state = alert.getState() as CertSummary; + const state = recoveredAlert.alert.getState(); const alertUrl = await getAlertUrl( alertUuid, spaceId, @@ -144,12 +150,13 @@ export const setTLSRecoveredAlertsContext = async ({ newStatus = previousStatus; } - alert.setContext({ + const context = { ...state, newStatus, previousStatus, summary: newSummary, [ALERT_DETAILS_URL]: alertUrl, - }); + }; + alertsClient.setAlertData({ id: recoveredAlertId, context }); } }; diff --git a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/tls_rule.ts b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/tls_rule.ts index b251e950a5d4a..3aaafcaf17468 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/tls_rule.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/alert_rules/tls_rule/tls_rule.ts @@ -7,8 +7,12 @@ import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; import { ActionGroupIdsOf } from '@kbn/alerting-plugin/common'; -import { GetViewInAppRelativeUrlFnOpts } from '@kbn/alerting-plugin/server'; -import { createLifecycleRuleTypeFactory, IRuleDataClient } from '@kbn/rule-registry-plugin/server'; +import { + GetViewInAppRelativeUrlFnOpts, + AlertInstanceContext as AlertContext, + RuleExecutorOptions, + AlertsClientError, +} from '@kbn/alerting-plugin/server'; import { asyncForEach } from '@kbn/std'; import { ALERT_REASON, ALERT_UUID } from '@kbn/rule-data-utils'; import { @@ -19,6 +23,7 @@ import { } from '@kbn/observability-plugin/common'; import { LocatorPublic } from '@kbn/share-plugin/common'; import { schema } from '@kbn/config-schema'; +import { ObservabilityUptimeAlert } from '@kbn/alerts-as-data-utils'; import { syntheticsRuleFieldMap } from '../../../common/rules/synthetics_rule_field_map'; import { SyntheticsPluginsSetupDependencies, SyntheticsServerSetup } from '../../types'; import { TlsTranslations } from '../../../common/rules/synthetics/translations'; @@ -39,21 +44,27 @@ import { import { generateAlertMessage, SyntheticsRuleTypeAlertDefinition, updateState } from '../common'; import { ALERT_DETAILS_URL, getActionVariables } from '../action_variables'; import { SyntheticsMonitorClient } from '../../synthetics_service/synthetics_monitor/synthetics_monitor_client'; +import { TLSParams } from '../../../common/runtime_types/alerts/tls'; -export type ActionGroupIds = ActionGroupIdsOf; +type TLSRuleTypeParams = TLSParams; +type TLSActionGroups = ActionGroupIdsOf; +type TLSRuleTypeState = SyntheticsCommonState; +type TLSAlertState = ReturnType; +type TLSAlertContext = AlertContext; +type TLSAlert = ObservabilityUptimeAlert; export const registerSyntheticsTLSCheckRule = ( server: SyntheticsServerSetup, plugins: SyntheticsPluginsSetupDependencies, - syntheticsMonitorClient: SyntheticsMonitorClient, - ruleDataClient: IRuleDataClient + syntheticsMonitorClient: SyntheticsMonitorClient ) => { - const createLifecycleRuleType = createLifecycleRuleTypeFactory({ - ruleDataClient, - logger: server.logger, - }); + if (!plugins.alerting) { + throw new Error( + 'Cannot register the synthetics TLS check rule type. The alerting plugin needs to be enabled.' + ); + } - return createLifecycleRuleType({ + plugins.alerting.registerType({ id: SYNTHETICS_ALERT_RULE_TYPES.TLS, category: DEFAULT_APP_CATEGORIES.observability.id, producer: 'uptime', @@ -71,22 +82,25 @@ export const registerSyntheticsTLSCheckRule = ( isExportable: true, minimumLicenseRequired: 'basic', doesSetRecoveryContext: true, - async executor({ state, params, services, spaceId, previousStartedAt, startedAt }) { - const ruleState = state as SyntheticsCommonState; - + executor: async ( + options: RuleExecutorOptions< + TLSRuleTypeParams, + TLSRuleTypeState, + TLSAlertState, + TLSAlertContext, + TLSActionGroups, + TLSAlert + > + ) => { + const { state: ruleState, params, services, spaceId, previousStartedAt, startedAt } = options; + const { alertsClient, savedObjectsClient, scopedClusterClient } = services; + if (!alertsClient) { + throw new AlertsClientError(); + } const { basePath, share } = server; const alertsLocator: LocatorPublic | undefined = share.url.locators.get(alertsLocatorID); - const { - alertFactory, - getAlertUuid, - savedObjectsClient, - scopedClusterClient, - alertWithLifecycle, - getAlertStartedDate, - } = services; - const tlsRule = new TLSRuleExecutor( previousStartedAt, params, @@ -107,45 +121,45 @@ export const registerSyntheticsTLSCheckRule = ( } const alertId = cert.sha256; - const alertUuid = getAlertUuid(alertId); - const indexedStartedAt = getAlertStartedDate(alertId) ?? startedAt.toISOString(); - - const alertInstance = alertWithLifecycle({ + const { uuid, start } = alertsClient.report({ id: alertId, - fields: { - [CERT_COMMON_NAME]: cert.common_name, - [CERT_ISSUER_NAME]: cert.issuer, - [CERT_VALID_NOT_AFTER]: cert.not_after, - [CERT_VALID_NOT_BEFORE]: cert.not_before, - [CERT_HASH_SHA256]: cert.sha256, - [ALERT_UUID]: alertUuid, - [ALERT_REASON]: generateAlertMessage(TlsTranslations.defaultActionMessage, summary), - }, + actionGroup: TLS_CERTIFICATE.id, + state: { ...updateState(ruleState, foundCerts), ...summary }, }); - - alertInstance.replaceState({ - ...updateState(ruleState, foundCerts), - ...summary, - }); - - alertInstance.scheduleActions(TLS_CERTIFICATE.id, { + const indexedStartedAt = start ?? startedAt.toISOString(); + + const payload = { + [CERT_COMMON_NAME]: cert.common_name, + [CERT_ISSUER_NAME]: cert.issuer, + [CERT_VALID_NOT_AFTER]: cert.not_after, + [CERT_VALID_NOT_BEFORE]: cert.not_before, + [CERT_HASH_SHA256]: cert.sha256, + [ALERT_UUID]: uuid, + [ALERT_REASON]: generateAlertMessage(TlsTranslations.defaultActionMessage, summary), + }; + + const context = { [ALERT_DETAILS_URL]: await getAlertUrl( - alertUuid, + uuid, spaceId, indexedStartedAt, alertsLocator, basePath.publicBaseUrl ), ...summary, + }; + + alertsClient.setAlertData({ + id: alertId, + payload, + context, }); }); await setTLSRecoveredAlertsContext({ - alertFactory, + alertsClient, basePath, defaultStartedAt: startedAt.toISOString(), - getAlertStartedDate, - getAlertUuid, spaceId, alertsLocator, latestPings, diff --git a/x-pack/plugins/observability_solution/synthetics/common/config.ts b/x-pack/plugins/observability_solution/synthetics/server/config.ts similarity index 100% rename from x-pack/plugins/observability_solution/synthetics/common/config.ts rename to x-pack/plugins/observability_solution/synthetics/server/config.ts diff --git a/x-pack/plugins/observability_solution/synthetics/server/index.ts b/x-pack/plugins/observability_solution/synthetics/server/index.ts index 80cbe388a3015..e785ba27a3681 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/index.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/index.ts @@ -11,4 +11,4 @@ export const plugin = async (initializerContext: PluginInitializerContext) => { return new Plugin(initializerContext); }; -export { config } from '../common/config'; +export { config } from './config'; diff --git a/x-pack/plugins/observability_solution/synthetics/server/plugin.ts b/x-pack/plugins/observability_solution/synthetics/server/plugin.ts index 29dc85e4aa0f9..e3c0ad1ef7bf6 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/plugin.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/plugin.ts @@ -25,7 +25,7 @@ import { SyntheticsMonitorClient } from './synthetics_service/synthetics_monitor import { initSyntheticsServer } from './server'; import { syntheticsFeature } from './feature'; import { registerSyntheticsSavedObjects } from './saved_objects/saved_objects'; -import { UptimeConfig } from '../common/config'; +import { UptimeConfig } from './config'; import { SyntheticsService } from './synthetics_service/synthetics_service'; import { syntheticsServiceApiKey } from './saved_objects/service_api_key'; import { SYNTHETICS_RULE_TYPES_ALERT_CONTEXT } from '../common/constants/synthetics_alerts'; diff --git a/x-pack/plugins/observability_solution/synthetics/server/server.ts b/x-pack/plugins/observability_solution/synthetics/server/server.ts index b394e4ffc6883..77937c57590e7 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/server.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/server.ts @@ -138,16 +138,6 @@ export const initSyntheticsServer = ( } }); - const { alerting } = plugins; - - registerSyntheticsStatusCheckRule(server, plugins, syntheticsMonitorClient, alerting); - - const tlsRule = registerSyntheticsTLSCheckRule( - server, - plugins, - syntheticsMonitorClient, - ruleDataClient - ); - - alerting.registerType(tlsRule); + registerSyntheticsStatusCheckRule(server, plugins, syntheticsMonitorClient); + registerSyntheticsTLSCheckRule(server, plugins, syntheticsMonitorClient); }; diff --git a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/get_es_hosts.ts b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/get_es_hosts.ts index 23a3f5aaf27ce..32faa634df518 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/get_es_hosts.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/get_es_hosts.ts @@ -13,7 +13,7 @@ */ import type { CloudSetup } from '@kbn/cloud-plugin/server'; -import { ServiceConfig } from '../../common/config'; +import { ServiceConfig } from '../config'; export function getEsHosts({ cloud, diff --git a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/service_api_client.test.ts b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/service_api_client.test.ts index 66ef4e9faa0c8..93b3ca2fb3742 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/service_api_client.test.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/service_api_client.test.ts @@ -10,7 +10,7 @@ import { CoreStart } from '@kbn/core/server'; import { coreMock } from '@kbn/core/server/mocks'; import { Logger } from '@kbn/core/server'; import { ServiceAPIClient } from './service_api_client'; -import { ServiceConfig } from '../../common/config'; +import { ServiceConfig } from '../config'; import axios from 'axios'; import { LocationStatus, PublicLocations } from '../../common/runtime_types'; import { LicenseGetResponse } from '@elastic/elasticsearch/lib/api/types'; diff --git a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/service_api_client.ts b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/service_api_client.ts index 09ad88476ec06..3d334f32e9407 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/service_api_client.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/service_api_client.ts @@ -24,7 +24,7 @@ import { ServiceLocation, ServiceLocationErrors, } from '../../common/runtime_types'; -import { ServiceConfig } from '../../common/config'; +import { ServiceConfig } from '../config'; const TEST_SERVICE_USERNAME = 'localKibanaIntegrationTestsUser'; diff --git a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/synthetics_service.ts b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/synthetics_service.ts index 35bf0d9dc7ce6..be72ca4d9a496 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/synthetics_service.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/synthetics_service.ts @@ -25,7 +25,7 @@ import { sendErrorTelemetryEvents } from '../routes/telemetry/monitor_upgrade_se import { installSyntheticsIndexTemplates } from '../routes/synthetics_service/install_index_templates'; import { getAPIKeyForSyntheticsService } from './get_api_key'; import { getEsHosts } from './get_es_hosts'; -import { ServiceConfig } from '../../common/config'; +import { ServiceConfig } from '../config'; import { ServiceAPIClient, ServiceData } from './service_api_client'; import { diff --git a/x-pack/plugins/observability_solution/synthetics/server/types.ts b/x-pack/plugins/observability_solution/synthetics/server/types.ts index 2e1fac95023b9..032cee048e8bd 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/types.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/types.ts @@ -38,7 +38,7 @@ import { TaskManagerStartContract, } from '@kbn/task-manager-plugin/server'; import { TelemetryEventsSender } from './telemetry/sender'; -import { UptimeConfig } from '../common/config'; +import { UptimeConfig } from './config'; import { SyntheticsEsClient } from './lib'; export interface SyntheticsServerSetup { diff --git a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_wrapper.tsx b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_wrapper.tsx index 669d615dd6479..2cde284fd7afa 100644 --- a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_wrapper.tsx +++ b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_wrapper.tsx @@ -129,14 +129,14 @@ export const WaterfallChartWrapper: React.FC = ({ sidebarItems={sidebarItems} legendItems={legendItems} metadata={metadata} - renderTooltipItem={useCallback((tooltipProps) => { + renderTooltipItem={useCallback((tooltipProps: any) => { return {tooltipProps?.value}; }, [])} > `${Number(d).toFixed(0)} ms`, [])} domain={domain} - barStyleAccessor={useCallback(({ datum }) => { + barStyleAccessor={useCallback(({ datum }: any) => { if (!datum.config?.isHighlighted) { return { rect: { diff --git a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/step_detail/waterfall/waterfall_sidebar_item.tsx b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/step_detail/waterfall/waterfall_sidebar_item.tsx index 193fe33121636..249edeaa8f3a1 100644 --- a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/step_detail/waterfall/waterfall_sidebar_item.tsx +++ b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/step_detail/waterfall/waterfall_sidebar_item.tsx @@ -35,7 +35,7 @@ export const WaterfallSidebarItem = ({ } }, [buttonRef, index, onClick]); - const setRef = useCallback((ref) => setButtonRef(ref), [setButtonRef]); + const setRef = useCallback((ref: any) => setButtonRef(ref), [setButtonRef]); const isErrorStatusCode = (statusCode: number) => { const is400 = statusCode >= 400 && statusCode <= 499; diff --git a/x-pack/plugins/observability_solution/uptime/public/plugin.ts b/x-pack/plugins/observability_solution/uptime/public/plugin.ts index b02ee95e12032..b2558fe83e33b 100644 --- a/x-pack/plugins/observability_solution/uptime/public/plugin.ts +++ b/x-pack/plugins/observability_solution/uptime/public/plugin.ts @@ -311,7 +311,7 @@ function setUptimeAppStatus( } else { const hasUptimePrivileges = coreStart.application.capabilities.uptime?.show; if (hasUptimePrivileges) { - const indexStatusPromise = UptimeDataHelper(coreStart).indexStatus('now-7d', 'now'); + const indexStatusPromise = UptimeDataHelper(coreStart).indexStatus('now-7d/d', 'now/d'); indexStatusPromise.then((indexStatus) => { if (indexStatus.indexExists) { registerUptimeRoutesWithNavigation(coreStart, pluginsStart); diff --git a/x-pack/plugins/observability_solution/ux/public/components/app/rum_dashboard/charts/visitor_breakdown_chart.tsx b/x-pack/plugins/observability_solution/ux/public/components/app/rum_dashboard/charts/visitor_breakdown_chart.tsx index 2c32df316efc7..71738fbe246f9 100644 --- a/x-pack/plugins/observability_solution/ux/public/components/app/rum_dashboard/charts/visitor_breakdown_chart.tsx +++ b/x-pack/plugins/observability_solution/ux/public/components/app/rum_dashboard/charts/visitor_breakdown_chart.tsx @@ -70,7 +70,7 @@ export function VisitorBreakdownChart({ ); const filterHandler = useCallback( - (event) => { + (event: any) => { onFilter(metric, event); }, [onFilter, metric] diff --git a/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx b/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx index 6b9581249a075..3a53b3c2d9f1f 100644 --- a/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx +++ b/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx @@ -78,10 +78,13 @@ const ActionResultsSummaryComponent: React.FC = ({ } }, [edges, error, expired]); - const renderAgentIdColumn = useCallback((agentId) => , []); - const renderRowsColumn = useCallback((rowsCount) => rowsCount ?? '-', []); + const renderAgentIdColumn = useCallback( + (agentId: any) => , + [] + ); + const renderRowsColumn = useCallback((rowsCount: any) => rowsCount ?? '-', []); const renderStatusColumn = useCallback( - (_, item) => { + (_: any, item: any) => { if (item.fields['error.skipped']) { return i18n.translate('xpack.osquery.liveQueryActionResults.table.skippedStatusText', { defaultMessage: 'skipped', diff --git a/x-pack/plugins/osquery/public/actions/actions_table.tsx b/x-pack/plugins/osquery/public/actions/actions_table.tsx index a6c66855f12cc..a2b654b310c1e 100644 --- a/x-pack/plugins/osquery/public/actions/actions_table.tsx +++ b/x-pack/plugins/osquery/public/actions/actions_table.tsx @@ -66,14 +66,14 @@ const ActionsTableComponent = () => { kuery: 'user_id: *', }); - const onTableChange = useCallback(({ page = {} }) => { + const onTableChange = useCallback(({ page = {} }: any) => { const { index, size } = page; setPageIndex(index); setPageSize(size); }, []); - const renderQueryColumn = useCallback((_, item) => { + const renderQueryColumn = useCallback((_: any, item: any) => { if (item._source.pack_name) { return ( @@ -96,22 +96,28 @@ const ActionsTableComponent = () => { ); }, []); - const renderAgentsColumn = useCallback((_, item) => <>{item.fields.agents?.length ?? 0}, []); + const renderAgentsColumn = useCallback( + (_: any, item: any) => <>{item.fields.agents?.length ?? 0}, + [] + ); - const renderCreatedByColumn = useCallback((userId) => (isArray(userId) ? userId[0] : '-'), []); + const renderCreatedByColumn = useCallback( + (userId: any) => (isArray(userId) ? userId[0] : '-'), + [] + ); const renderTimestampColumn = useCallback( - (_, item) => <>{formatDate(item.fields['@timestamp'][0])}, + (_: any, item: any) => <>{formatDate(item.fields['@timestamp'][0])}, [] ); const renderActionsColumn = useCallback( - (item) => , + (item: any) => , [] ); const handlePlayClick = useCallback( - (item) => () => { + (item: any) => () => { const packId = item._source.pack_id; if (packId) { @@ -152,7 +158,7 @@ const ActionsTableComponent = () => { [push] ); const renderPlayButton = useCallback( - (item, enabled) => { + (item: any, enabled: any) => { const playText = i18n.translate('xpack.osquery.liveQueryActions.table.runActionAriaLabel', { defaultMessage: 'Run query', }); @@ -174,7 +180,7 @@ const ActionsTableComponent = () => { const existingPackIds = useMemo(() => map(packsData?.data ?? [], 'id'), [packsData]); const isPlayButtonAvailable = useCallback( - (item) => { + (item: any) => { if (item.fields.pack_id?.length) { return ( existingPackIds.includes(item.fields.pack_id[0]) && @@ -260,7 +266,7 @@ const ActionsTableComponent = () => { ); const rowProps = useCallback( - (data) => ({ + (data: any) => ({ 'data-test-subj': `row-${data._source.action_id}`, }), [] diff --git a/x-pack/plugins/osquery/public/agent_policies/agents_policy_link.tsx b/x-pack/plugins/osquery/public/agent_policies/agents_policy_link.tsx index c471d9ffcd1bc..722a0ee2073b7 100644 --- a/x-pack/plugins/osquery/public/agent_policies/agents_policy_link.tsx +++ b/x-pack/plugins/osquery/public/agent_policies/agents_policy_link.tsx @@ -38,7 +38,7 @@ const AgentsPolicyLinkComponent: React.FC = ({ policyId } ); const handleClick = useCallback( - (event) => { + (event: any) => { if (!isModifiedEvent(event) && isLeftClickEvent(event)) { event.preventDefault(); diff --git a/x-pack/plugins/osquery/public/agents/agents_table.tsx b/x-pack/plugins/osquery/public/agents/agents_table.tsx index ff9b89f73543b..913876e7019ef 100644 --- a/x-pack/plugins/osquery/public/agents/agents_table.tsx +++ b/x-pack/plugins/osquery/public/agents/agents_table.tsx @@ -173,7 +173,7 @@ const AgentsTableComponent: React.FC = ({ agentSelection, onCh } }, [agentList?.agents, agentList?.groups, agentList?.total, agentsFetched, searchValue]); - const renderOption = useCallback((option, searchVal, contentClassName) => { + const renderOption = useCallback((option: any, searchVal: any, contentClassName: any) => { const { label, value } = option; return value?.groupType === AGENT_GROUP_KEY.Agent ? ( diff --git a/x-pack/plugins/osquery/public/components/empty_state.tsx b/x-pack/plugins/osquery/public/components/empty_state.tsx index 18f5afe8eaf5f..9a25443d4aaf2 100644 --- a/x-pack/plugins/osquery/public/components/empty_state.tsx +++ b/x-pack/plugins/osquery/public/components/empty_state.tsx @@ -35,7 +35,7 @@ const OsqueryAppEmptyStateComponent = () => { ); const integrationClick = useCallback( - (event) => { + (event: any) => { if (!isModifiedEvent(event) && isLeftClickEvent(event)) { event.preventDefault(); diff --git a/x-pack/plugins/osquery/public/components/manage_integration_link.tsx b/x-pack/plugins/osquery/public/components/manage_integration_link.tsx index 44ae6421a6c25..5c8141d5b8bb9 100644 --- a/x-pack/plugins/osquery/public/components/manage_integration_link.tsx +++ b/x-pack/plugins/osquery/public/components/manage_integration_link.tsx @@ -30,7 +30,7 @@ const ManageIntegrationLinkComponent = () => { ); const integrationClick = useCallback( - (event) => { + (event: any) => { if (!isModifiedEvent(event) && isLeftClickEvent(event)) { event.preventDefault(); diff --git a/x-pack/plugins/osquery/public/fleet_integration/config_uploader.tsx b/x-pack/plugins/osquery/public/fleet_integration/config_uploader.tsx index 3d5b042769d8d..67370b42fe018 100644 --- a/x-pack/plugins/osquery/public/fleet_integration/config_uploader.tsx +++ b/x-pack/plugins/osquery/public/fleet_integration/config_uploader.tsx @@ -75,7 +75,7 @@ const ConfigUploaderComponent: React.FC = ({ onChange }) => }; const handleInputChange = useCallback( - (inputFiles) => { + (inputFiles: any) => { if (!inputFiles.length) { return; } diff --git a/x-pack/plugins/osquery/public/fleet_integration/navigation_buttons.tsx b/x-pack/plugins/osquery/public/fleet_integration/navigation_buttons.tsx index 4da470270de76..bf6ce0dcc73e8 100644 --- a/x-pack/plugins/osquery/public/fleet_integration/navigation_buttons.tsx +++ b/x-pack/plugins/osquery/public/fleet_integration/navigation_buttons.tsx @@ -14,7 +14,7 @@ import { useKibana, isModifiedEvent, isLeftClickEvent } from '../common/lib/kiba interface NavigationButtonsProps { isDisabled?: boolean; - agentPolicyId?: string | undefined; + agentPolicyId?: string | null; } const NavigationButtonsComponent: React.FC = ({ @@ -36,7 +36,7 @@ const NavigationButtonsComponent: React.FC = ({ ); const liveQueryClick = useCallback( - (event) => { + (event: any) => { if (!isModifiedEvent(event) && isLeftClickEvent(event)) { event.preventDefault(); navigateToApp(PLUGIN_ID, { @@ -54,7 +54,7 @@ const NavigationButtonsComponent: React.FC = ({ }); const packsClick = useCallback( - (event) => { + (event: any) => { if (!isModifiedEvent(event) && isLeftClickEvent(event)) { event.preventDefault(); navigateToApp(PLUGIN_ID, { diff --git a/x-pack/plugins/osquery/public/fleet_integration/osquery_managed_policy_create_import_extension.tsx b/x-pack/plugins/osquery/public/fleet_integration/osquery_managed_policy_create_import_extension.tsx index 8c41771b6f194..732c47fcdcfa7 100644 --- a/x-pack/plugins/osquery/public/fleet_integration/osquery_managed_policy_create_import_extension.tsx +++ b/x-pack/plugins/osquery/public/fleet_integration/osquery_managed_policy_create_import_extension.tsx @@ -194,7 +194,7 @@ export const OsqueryManagedPolicyCreateImportExtension = React.memo< }, [getUrlForApp, policy?.policy_id]); const handleConfigUpload = useCallback( - (newConfig) => { + (newConfig: any) => { let currentPacks = {}; try { currentPacks = JSON.parse(config)?.packs; diff --git a/x-pack/plugins/osquery/public/form/results_type_field.tsx b/x-pack/plugins/osquery/public/form/results_type_field.tsx index 37fe9d9ceee38..43eb9b88ca823 100644 --- a/x-pack/plugins/osquery/public/form/results_type_field.tsx +++ b/x-pack/plugins/osquery/public/form/results_type_field.tsx @@ -74,7 +74,7 @@ const ResultsTypeFieldComponent: React.FC = ({ euiFieldPr }); const handleChange = useCallback( - (newValue) => { + (newValue: any) => { if (newValue === SNAPSHOT_OPTION.value) { onSnapshotChange(true); onRemovedChange(false); diff --git a/x-pack/plugins/osquery/public/lens/view_results_in_lens.tsx b/x-pack/plugins/osquery/public/lens/view_results_in_lens.tsx index 53281c794e3a3..240cd6d24de09 100644 --- a/x-pack/plugins/osquery/public/lens/view_results_in_lens.tsx +++ b/x-pack/plugins/osquery/public/lens/view_results_in_lens.tsx @@ -41,7 +41,7 @@ const ViewResultsInLensActionComponent: React.FC = const { data: logsDataView } = useLogsDataView({ skip: !actionId, checkOnly: true }); const handleClick = useCallback( - (event) => { + (event: any) => { event.preventDefault(); if (logsDataView) { diff --git a/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx b/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx index 23ef0524dbb15..462d3aa94d7f7 100644 --- a/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx +++ b/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx @@ -82,7 +82,7 @@ const LiveQueryQueryFieldComponent: React.FC = ({ [resetField] ); - const handleToggle = useCallback((isOpen) => { + const handleToggle = useCallback((isOpen: any) => { const newState = isOpen ? 'open' : 'closed'; setAdvancedContentState(newState); }, []); diff --git a/x-pack/plugins/osquery/public/live_queries/form/pack_queries_status_table.tsx b/x-pack/plugins/osquery/public/live_queries/form/pack_queries_status_table.tsx index 73d66481d94fc..4fe0993306c93 100644 --- a/x-pack/plugins/osquery/public/live_queries/form/pack_queries_status_table.tsx +++ b/x-pack/plugins/osquery/public/live_queries/form/pack_queries_status_table.tsx @@ -157,7 +157,7 @@ const PackQueriesStatusTableComponent: React.FC = ( } | null>(null); const handleQueryFlyoutOpen = useCallback( - (item) => () => { + (item: any) => () => { setQueryDetailsFlyoutOpen(item); }, [] @@ -179,7 +179,7 @@ const PackQueriesStatusTableComponent: React.FC = ( ); const renderQueryColumn = useCallback( - (query: string, item) => { + (query: string, item: any) => { const singleLine = removeMultilines(query); const content = singleLine.length > 55 ? `${singleLine.substring(0, 55)}...` : singleLine; @@ -201,7 +201,7 @@ const PackQueriesStatusTableComponent: React.FC = ( return ; }, []); - const renderAgentsColumn = useCallback((item) => { + const renderAgentsColumn = useCallback((item: any) => { if (!item.action_id) return; return ( @@ -214,14 +214,17 @@ const PackQueriesStatusTableComponent: React.FC = ( }, []); const renderDiscoverResultsAction = useCallback( - (item) => , + (item: any) => , [] ); - const renderLensResultsAction = useCallback((item) => , []); + const renderLensResultsAction = useCallback( + (item: any) => , + [] + ); const getHandleErrorsToggle = useCallback( - (item) => () => { + (item: any) => () => { setItemIdToExpandedRowMap((prevValue) => { const itemIdToExpandedRowMapValues = { ...prevValue }; if (itemIdToExpandedRowMapValues[item.id]) { @@ -252,7 +255,7 @@ const PackQueriesStatusTableComponent: React.FC = ( ); const renderToggleResultsAction = useCallback( - (item) => + (item: any) => item?.action_id && data?.length && data.length > 1 ? ( ([]); const handlePackChange = useCallback( - (newSelectedOptions) => { + (newSelectedOptions: any) => { if (!newSelectedOptions.length) { setSelectedOptions(newSelectedOptions); onChange([]); @@ -86,7 +86,7 @@ export const PacksComboBoxField = ({ ); const renderOption = useCallback( - ({ value: option }) => ( + ({ value: option }: any) => ( { + (type: any) => { setQueryType(type); }, [setQueryType] diff --git a/x-pack/plugins/osquery/public/packs/form/index.tsx b/x-pack/plugins/osquery/public/packs/form/index.tsx index fd9c114a07944..5b0bb73fd1665 100644 --- a/x-pack/plugins/osquery/public/packs/form/index.tsx +++ b/x-pack/plugins/osquery/public/packs/form/index.tsx @@ -60,7 +60,7 @@ const PackFormComponent: React.FC = ({ }) => { const [shardsToggleState, setShardsToggleState] = useState('closed'); - const handleToggle = useCallback((isOpen) => { + const handleToggle = useCallback((isOpen: any) => { const newState = isOpen ? 'open' : 'closed'; setShardsToggleState(newState); }, []); diff --git a/x-pack/plugins/osquery/public/packs/form/pack_uploader.tsx b/x-pack/plugins/osquery/public/packs/form/pack_uploader.tsx index b9f9c914ed24b..7ab3218a00b9f 100644 --- a/x-pack/plugins/osquery/public/packs/form/pack_uploader.tsx +++ b/x-pack/plugins/osquery/public/packs/form/pack_uploader.tsx @@ -83,7 +83,7 @@ const OsqueryPackUploaderComponent: React.FC = ({ onCh }; const handleInputChange = useCallback( - (inputFiles) => { + (inputFiles: any) => { if (!inputFiles.length) { packName.current = ''; diff --git a/x-pack/plugins/osquery/public/packs/form/queries_field.tsx b/x-pack/plugins/osquery/public/packs/form/queries_field.tsx index 3e62a5639e1f7..f4f2f07297137 100644 --- a/x-pack/plugins/osquery/public/packs/form/queries_field.tsx +++ b/x-pack/plugins/osquery/public/packs/form/queries_field.tsx @@ -56,7 +56,7 @@ const QueriesFieldComponent: React.FC = ({ euiFieldProps }) = const handleHideEditFlyout = useCallback(() => setShowEditQueryFlyout(-1), []); const handleDeleteClick = useCallback( - (query) => { + (query: any) => { const streamIndex = findIndex(fieldValue, ['id', query.id]); if (streamIndex > -1) { @@ -67,7 +67,7 @@ const QueriesFieldComponent: React.FC = ({ euiFieldProps }) = ); const handleEditClick = useCallback( - (query) => { + (query: any) => { const streamIndex = findIndex(fieldValue, ['id', query.id]); setShowEditQueryFlyout(streamIndex); @@ -76,7 +76,7 @@ const QueriesFieldComponent: React.FC = ({ euiFieldProps }) = ); const handleEditQuery = useCallback( - (updatedQuery) => + (updatedQuery: any) => new Promise((resolve) => { if (showEditQueryFlyout >= 0) { update( @@ -114,7 +114,7 @@ const QueriesFieldComponent: React.FC = ({ euiFieldProps }) = ); const handleAddQuery = useCallback( - (newQuery) => + (newQuery: any) => new Promise((resolve) => { append(newQuery); handleHideAddFlyout(); @@ -132,7 +132,7 @@ const QueriesFieldComponent: React.FC = ({ euiFieldProps }) = }, [fieldValue, remove, tableSelectedItems]); const handlePackUpload = useCallback( - (parsedContent, uploadedPackName) => { + (parsedContent: any, uploadedPackName: any) => { replace( map(parsedContent.queries, (newQuery, newQueryId) => pickBy( diff --git a/x-pack/plugins/osquery/public/packs/form/shards/pack_type_selectable.tsx b/x-pack/plugins/osquery/public/packs/form/shards/pack_type_selectable.tsx index a64dc02cb0283..ce64d990a5dc7 100644 --- a/x-pack/plugins/osquery/public/packs/form/shards/pack_type_selectable.tsx +++ b/x-pack/plugins/osquery/public/packs/form/shards/pack_type_selectable.tsx @@ -50,7 +50,7 @@ const PackTypeSelectableComponent = ({ resetFormFields, }: PackTypeSelectableProps) => { const handleChange = useCallback( - (type) => { + (type: any) => { setPackType(type); if (resetFormFields) { resetFormFields(); diff --git a/x-pack/plugins/osquery/public/packs/form/shards/shards_form.tsx b/x-pack/plugins/osquery/public/packs/form/shards/shards_form.tsx index 8fbf05e3d7e77..c353512b66f6f 100644 --- a/x-pack/plugins/osquery/public/packs/form/shards/shards_form.tsx +++ b/x-pack/plugins/osquery/public/packs/form/shards/shards_form.tsx @@ -39,7 +39,7 @@ const ShardsFormComponent = ({ }, [index, onDelete]); const buttonWrapperCss = useCallback( - ({ euiTheme }) => (index === 0 ? { marginTop: euiTheme.size.base } : {}), + ({ euiTheme }: any) => (index === 0 ? { marginTop: euiTheme.size.base } : {}), [index] ); diff --git a/x-pack/plugins/osquery/public/packs/form/shards/shards_policy_field.tsx b/x-pack/plugins/osquery/public/packs/form/shards/shards_policy_field.tsx index bf4bdf0540bdc..bf14459f8edb0 100644 --- a/x-pack/plugins/osquery/public/packs/form/shards/shards_policy_field.tsx +++ b/x-pack/plugins/osquery/public/packs/form/shards/shards_policy_field.tsx @@ -28,15 +28,17 @@ const ShardsPolicyFieldComponent = ({ }: ShardsPolicyFieldComponent) => { const { data: { agentPoliciesById } = {} } = useAgentPolicies(); + const missingValueError = i18n.translate( + 'xpack.osquery.pack.form.shardsPolicyFieldMissingErrorMessage', + { + defaultMessage: 'Policy is a required field', + } + ); + const policyFieldValidator = useCallback( - (policy: { key: string; label: string }) => - !policy - ? i18n.translate('xpack.osquery.pack.form.shardsPolicyFieldMissingErrorMessage', { - defaultMessage: 'Policy is a required field', - }) - : undefined, + (policy: { key: string; label: string }) => (!policy ? missingValueError : undefined), - [] + [missingValueError] ); const { @@ -47,6 +49,7 @@ const ShardsPolicyFieldComponent = ({ name: `shardsArray.${index}.policy`, rules: { validate: policyFieldValidator, + required: missingValueError, }, }); diff --git a/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx b/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx index f4f941a1254eb..48f3024d499c3 100644 --- a/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx +++ b/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx @@ -187,7 +187,7 @@ const ViewResultsInLensActionComponent: React.FC { + (event: any) => { event.preventDefault(); if (logsDataView?.id) { @@ -584,7 +584,7 @@ const PackQueriesStatusTableComponent: React.FC = ( Record> >({}); - const renderQueryColumn = useCallback((query: string, item) => { + const renderQueryColumn = useCallback((query: string, item: any) => { const singleLine = removeMultilines(query); const content = singleLine.length > 55 ? `${singleLine.substring(0, 55)}...` : singleLine; @@ -618,7 +618,7 @@ const PackQueriesStatusTableComponent: React.FC = ( ); const renderLastResultsColumn = useCallback( - (item) => ( + (item: any) => ( = ( [packName] ); const renderDocsColumn = useCallback( - (item) => ( + (item: any) => ( ), [packName] ); const renderAgentsColumn = useCallback( - (item) => ( + (item: any) => ( ), [packName] ); const renderErrorsColumn = useCallback( - (item) => ( + (item: any) => ( = ( ); const renderDiscoverResultsAction = useCallback( - (item) => , + (item: any) => , [packName] ); const renderLensResultsAction = useCallback( - (item) => , + (item: any) => , [packName] ); diff --git a/x-pack/plugins/osquery/public/packs/packs_table.tsx b/x-pack/plugins/osquery/public/packs/packs_table.tsx index 3574d45891755..aa0d6d205a624 100644 --- a/x-pack/plugins/osquery/public/packs/packs_table.tsx +++ b/x-pack/plugins/osquery/public/packs/packs_table.tsx @@ -86,18 +86,18 @@ const PacksTableComponent = () => { const { data, isLoading } = usePacks({}); const renderAgentPolicy = useCallback( - (agentPolicyIds) => , + (agentPolicyIds: any) => , [] ); const renderQueries = useCallback( - (queries) => <>{(queries && Object.keys(queries).length) ?? 0}, + (queries: any) => <>{(queries && Object.keys(queries).length) ?? 0}, [] ); - const renderActive = useCallback((_, item) => , []); + const renderActive = useCallback((_: any, item: any) => , []); - const renderUpdatedAt = useCallback((updatedAt, item) => { + const renderUpdatedAt = useCallback((updatedAt: any, item: any) => { if (!updatedAt) return '-'; const updatedBy = item.updated_by !== item.created_by ? ` @ ${item.updated_by}` : ''; @@ -122,7 +122,7 @@ const PacksTableComponent = () => { ); const renderPlayAction = useCallback( - (item, enabled) => { + (item: any, enabled: any) => { const playText = i18n.translate('xpack.osquery.packs.table.runActionAriaLabel', { defaultMessage: 'Run {packName}', values: { diff --git a/x-pack/plugins/osquery/public/packs/queries/ecs_mapping_editor_field.tsx b/x-pack/plugins/osquery/public/packs/queries/ecs_mapping_editor_field.tsx index d1ca70f14b081..5cd3993033378 100644 --- a/x-pack/plugins/osquery/public/packs/queries/ecs_mapping_editor_field.tsx +++ b/x-pack/plugins/osquery/public/packs/queries/ecs_mapping_editor_field.tsx @@ -139,7 +139,7 @@ const ECSComboboxFieldComponent: React.FC = ({ const describedByIds = useMemo(() => (idAria ? [idAria] : []), [idAria]); const { ecsMappingArray: watchedEcsMapping } = watch(); const handleChange = useCallback( - (newSelectedOptions) => { + (newSelectedOptions: any) => { setSelected(newSelectedOptions); ECSField.onChange(newSelectedOptions[0]?.label ?? ''); }, @@ -148,7 +148,7 @@ const ECSComboboxFieldComponent: React.FC = ({ // TODO: Create own component for this. const renderOption = useCallback( - (option, searchValue, contentClassName) => ( + (option: any, searchValue: any, contentClassName: any) => ( = ({ const describedByIds = useMemo(() => (idAria ? [idAria] : []), [idAria]); const renderOsqueryOption = useCallback( - (option, searchValue, contentClassName) => ( + (option: any, searchValue: any, contentClassName: any) => ( = ({ ); const handleKeyChange = useCallback( - (newSelectedOptions) => { + (newSelectedOptions: any) => { setSelected(newSelectedOptions); resultField.onChange( isArray(newSelectedOptions) @@ -438,7 +438,7 @@ const OsqueryColumnFieldComponent: React.FC = ({ }, [ecsMappingArray, index, isLastItem, resultTypeField.value]); const onTypeChange = useCallback( - (newType) => { + (newType: any) => { if (newType !== resultTypeField.value) { resultTypeField.onChange(newType); resultField.onChange(newType === 'value' && isSingleSelection === false ? [] : ''); diff --git a/x-pack/plugins/osquery/public/packs/queries/query_flyout.tsx b/x-pack/plugins/osquery/public/packs/queries/query_flyout.tsx index 751f53f91ece2..1afe75f463d02 100644 --- a/x-pack/plugins/osquery/public/packs/queries/query_flyout.tsx +++ b/x-pack/plugins/osquery/public/packs/queries/query_flyout.tsx @@ -76,7 +76,7 @@ const QueryFlyoutComponent: React.FC = ({ }; const handleSetQueryValue = useCallback( - (savedQuery) => { + (savedQuery: any) => { if (savedQuery) { resetField('id', { defaultValue: savedQuery.id }); resetField('query', { defaultValue: savedQuery.query }); diff --git a/x-pack/plugins/osquery/public/packs/scheduled_query_errors_table.tsx b/x-pack/plugins/osquery/public/packs/scheduled_query_errors_table.tsx index 99b614a2c53f9..7c7f1bee0fc55 100644 --- a/x-pack/plugins/osquery/public/packs/scheduled_query_errors_table.tsx +++ b/x-pack/plugins/osquery/public/packs/scheduled_query_errors_table.tsx @@ -37,7 +37,7 @@ const ViewErrorsInLogsActionComponent: React.FC = ( const navigateToApp = useKibana().services.application.navigateToApp; const handleClick = useCallback( - (event) => { + (event: any) => { const openInNewTab = !(!isModifiedEvent(event) && isLeftClickEvent(event)); event.preventDefault(); @@ -90,10 +90,13 @@ const ScheduledQueryErrorsTableComponent: React.FC , []); + const renderAgentIdColumn = useCallback( + (agentId: any) => , + [] + ); const renderLogsErrorsAction = useCallback( - (item) => ( + (item: any) => ( = ({ } = useKibana().services; const getFleetAppUrl = useCallback( - (agentId) => + (agentId: any) => getUrlForApp('fleet', { path: pagePathGetters.agent_details({ agentId })[1], }), @@ -118,7 +118,7 @@ const ResultsTableComponent: React.FC = ({ const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 50 }); const onChangeItemsPerPage = useCallback( - (pageSize) => + (pageSize: any) => setPagination((currentPagination) => ({ ...currentPagination, pageSize, @@ -127,7 +127,7 @@ const ResultsTableComponent: React.FC = ({ [setPagination] ); const onChangePage = useCallback( - (pageIndex) => setPagination((currentPagination) => ({ ...currentPagination, pageIndex })), + (pageIndex: any) => setPagination((currentPagination) => ({ ...currentPagination, pageIndex })), [setPagination] ); diff --git a/x-pack/plugins/osquery/public/routes/saved_queries/edit/index.tsx b/x-pack/plugins/osquery/public/routes/saved_queries/edit/index.tsx index d1c78cf89de8b..ce7cda4f71fed 100644 --- a/x-pack/plugins/osquery/public/routes/saved_queries/edit/index.tsx +++ b/x-pack/plugins/osquery/public/routes/saved_queries/edit/index.tsx @@ -126,7 +126,7 @@ const EditSavedQueryPageComponent = () => { ); const handleSubmit = useCallback( - async (payload) => { + async (payload: any) => { await updateSavedQueryMutation.mutateAsync(payload); }, [updateSavedQueryMutation] diff --git a/x-pack/plugins/osquery/public/routes/saved_queries/list/index.tsx b/x-pack/plugins/osquery/public/routes/saved_queries/list/index.tsx index e9fa1d34df207..8d6d180f46bd0 100644 --- a/x-pack/plugins/osquery/public/routes/saved_queries/list/index.tsx +++ b/x-pack/plugins/osquery/public/routes/saved_queries/list/index.tsx @@ -157,7 +157,7 @@ const SavedQueriesPageComponent = () => { [permissions.runSavedQueries, permissions.writeLiveQueries] ); - const renderUpdatedAt = useCallback((updatedAt, item) => { + const renderUpdatedAt = useCallback((updatedAt: any, item: any) => { if (!updatedAt) return '-'; const updatedBy = item.updated_by !== item.created_by ? ` @ ${item.updated_by}` : ''; @@ -223,7 +223,7 @@ const SavedQueriesPageComponent = () => { [renderDescriptionColumn, renderEditAction, renderPlayAction, renderUpdatedAt] ); - const onTableChange = useCallback(({ page = {}, sort = {} }) => { + const onTableChange = useCallback(({ page = {}, sort = {} }: any) => { setPageIndex(page.index); setPageSize(page.size); setSortField(sort.field); diff --git a/x-pack/plugins/osquery/public/routes/saved_queries/new/index.tsx b/x-pack/plugins/osquery/public/routes/saved_queries/new/index.tsx index 4c8d2fa5d3a9c..b06c27aeaf0bd 100644 --- a/x-pack/plugins/osquery/public/routes/saved_queries/new/index.tsx +++ b/x-pack/plugins/osquery/public/routes/saved_queries/new/index.tsx @@ -48,7 +48,7 @@ const NewSavedQueryPageComponent = () => { ); const handleSubmit = useCallback( - async (payload) => { + async (payload: any) => { await mutateAsync(payload); }, [mutateAsync] diff --git a/x-pack/plugins/osquery/public/saved_queries/saved_queries_dropdown.tsx b/x-pack/plugins/osquery/public/saved_queries/saved_queries_dropdown.tsx index 690341fd2221f..5a5e052362ee4 100644 --- a/x-pack/plugins/osquery/public/saved_queries/saved_queries_dropdown.tsx +++ b/x-pack/plugins/osquery/public/saved_queries/saved_queries_dropdown.tsx @@ -67,7 +67,7 @@ const SavedQueriesDropdownComponent: React.FC = ({ ); const handleSavedQueryChange = useCallback( - (newSelectedOptions) => { + (newSelectedOptions: any) => { if (!newSelectedOptions.length) { onChange(null); setSelectedOptions(newSelectedOptions); @@ -87,7 +87,7 @@ const SavedQueriesDropdownComponent: React.FC = ({ ); const renderOption = useCallback( - ({ value }) => ( + ({ value }: any) => ( <> {value.id}
    diff --git a/x-pack/plugins/osquery/public/timelines/add_to_timeline_button.tsx b/x-pack/plugins/osquery/public/timelines/add_to_timeline_button.tsx index 6a03317c486d7..f59ccfee00abb 100644 --- a/x-pack/plugins/osquery/public/timelines/add_to_timeline_button.tsx +++ b/x-pack/plugins/osquery/public/timelines/add_to_timeline_button.tsx @@ -28,7 +28,7 @@ export const AddToTimelineButton = (props: AddToTimelineButtonProps) => { const queryIds = isArray(value) ? value : [value]; const TimelineIconComponent = useCallback( - (timelineComponentProps) => ( + (timelineComponentProps: any) => ( ), [iconProps] diff --git a/x-pack/plugins/saved_objects_tagging/public/components/edition_modal/utils.ts b/x-pack/plugins/saved_objects_tagging/public/components/edition_modal/utils.ts index e5b98b35a18ae..773e8a40fab21 100644 --- a/x-pack/plugins/saved_objects_tagging/public/components/edition_modal/utils.ts +++ b/x-pack/plugins/saved_objects_tagging/public/components/edition_modal/utils.ts @@ -66,7 +66,7 @@ export const useIfMounted = () => { [] ); - const ifMounted = useCallback((func) => { + const ifMounted = useCallback((func?: () => void) => { if (isMounted.current && func) { func(); } diff --git a/x-pack/plugins/search_playground/public/components/view_code/examples/__snapshots__/py_lang_client.test.tsx.snap b/x-pack/plugins/search_playground/public/components/view_code/examples/__snapshots__/py_lang_client.test.tsx.snap index e8777144ce994..e0815458898ce 100644 --- a/x-pack/plugins/search_playground/public/components/view_code/examples/__snapshots__/py_lang_client.test.tsx.snap +++ b/x-pack/plugins/search_playground/public/components/view_code/examples/__snapshots__/py_lang_client.test.tsx.snap @@ -37,7 +37,7 @@ def get_elasticsearch_results(query): result = es_client.search(index=\\"index1,index2\\", body=es_query) return result[\\"hits\\"][\\"hits\\"] -def create_openai_prompt(question, results): +def create_openai_prompt(results): context = \\"\\" for hit in results: inner_hit_path = f\\"{hit['_index']}.{index_source_fields.get(hit['_index'])[0]}\\" diff --git a/x-pack/plugins/search_playground/public/components/view_code/examples/py_lang_client.tsx b/x-pack/plugins/search_playground/public/components/view_code/examples/py_lang_client.tsx index cfb218afa6d3c..582606a4f6b14 100644 --- a/x-pack/plugins/search_playground/public/components/view_code/examples/py_lang_client.tsx +++ b/x-pack/plugins/search_playground/public/components/view_code/examples/py_lang_client.tsx @@ -37,7 +37,7 @@ def get_elasticsearch_results(query): result = es_client.search(index="${formValues.indices.join(',')}", body=es_query) return result["hits"]["hits"] -def create_openai_prompt(question, results): +def create_openai_prompt(results): context = "" for hit in results: inner_hit_path = f"{hit['_index']}.{index_source_fields.get(hit['_index'])[0]}" diff --git a/x-pack/plugins/searchprofiler/public/application/app.tsx b/x-pack/plugins/searchprofiler/public/application/app.tsx index 321b2a167a38c..08dd4b1db6470 100644 --- a/x-pack/plugins/searchprofiler/public/application/app.tsx +++ b/x-pack/plugins/searchprofiler/public/application/app.tsx @@ -46,7 +46,7 @@ export const App = () => { ); const onHighlight = useCallback( - (value) => dispatch({ type: 'setHighlightDetails', value }), + (value: any) => dispatch({ type: 'setHighlightDetails', value }), [dispatch] ); diff --git a/x-pack/plugins/searchprofiler/public/application/components/profile_query_editor/profile_query_editor.tsx b/x-pack/plugins/searchprofiler/public/application/components/profile_query_editor/profile_query_editor.tsx index 574f8c7e18b60..577c3e530e8cc 100644 --- a/x-pack/plugins/searchprofiler/public/application/components/profile_query_editor/profile_query_editor.tsx +++ b/x-pack/plugins/searchprofiler/public/application/components/profile_query_editor/profile_query_editor.tsx @@ -77,7 +77,10 @@ export const ProfileQueryEditor = memo(() => { } }; - const onEditorReady = useCallback((editorInstance) => (editorRef.current = editorInstance), []); + const onEditorReady = useCallback( + (editorInstance: any) => (editorRef.current = editorInstance), + [] + ); const licenseEnabled = getLicenseStatus().valid; return ( diff --git a/x-pack/plugins/security/public/authentication/index.mock.ts b/x-pack/plugins/security/public/authentication/index.mock.ts index 491b5b82e946a..166583b1274cb 100644 --- a/x-pack/plugins/security/public/authentication/index.mock.ts +++ b/x-pack/plugins/security/public/authentication/index.mock.ts @@ -32,6 +32,9 @@ export const authorizationMock = { deleteRole: jest.fn(), saveRole: jest.fn(), }, + privileges: { + getAll: jest.fn(), + }, }), createStart: (): jest.Mocked => ({ isRoleManagementEnabled: jest.fn(), @@ -41,5 +44,8 @@ export const authorizationMock = { deleteRole: jest.fn(), saveRole: jest.fn(), }, + privileges: { + getAll: jest.fn(), + }, }), }; diff --git a/x-pack/plugins/security/public/authorization/authorization_service.ts b/x-pack/plugins/security/public/authorization/authorization_service.ts index 6e0af055a6cda..c650d381be1af 100644 --- a/x-pack/plugins/security/public/authorization/authorization_service.ts +++ b/x-pack/plugins/security/public/authorization/authorization_service.ts @@ -9,7 +9,7 @@ import type { HttpStart } from '@kbn/core/public'; import type { AuthorizationServiceSetup } from '@kbn/security-plugin-types-public'; import type { ConfigType } from '../config'; -import { RolesAPIClient } from '../management'; +import { PrivilegesAPIClient, RolesAPIClient } from '../management'; interface SetupParams { config: ConfigType; @@ -20,6 +20,7 @@ export class AuthorizationService { public setup({ config, http }: SetupParams): AuthorizationServiceSetup { const isRoleManagementEnabled = () => config.roleManagementEnabled; const rolesAPIClient = new RolesAPIClient(http); + const privilegesAPIClient = new PrivilegesAPIClient(http); return { isRoleManagementEnabled, @@ -29,6 +30,9 @@ export class AuthorizationService { deleteRole: rolesAPIClient.deleteRole, saveRole: rolesAPIClient.saveRole, }, + privileges: { + getAll: privilegesAPIClient.getAll.bind(privilegesAPIClient), + }, }; } } diff --git a/x-pack/plugins/security/public/management/index.ts b/x-pack/plugins/security/public/management/index.ts index a47475485896d..2c1708f1c9bb0 100644 --- a/x-pack/plugins/security/public/management/index.ts +++ b/x-pack/plugins/security/public/management/index.ts @@ -7,4 +7,4 @@ export { ManagementService } from './management_service'; export { UserAPIClient } from './users/user_api_client'; -export { RolesAPIClient } from './roles'; +export { RolesAPIClient, PrivilegesAPIClient } from './roles'; diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx index b724acc58f507..e867bf0c418cc 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx @@ -775,7 +775,9 @@ export const EditRolePage: FunctionComponent = ({ - Manage Members + {i18n.translate('xpack.security.management.roles.manageRoleUsers', { + defaultMessage: 'Manage Members', + })} diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/__fixtures__/index.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/__fixtures__/index.ts index 6d9cb86ace188..01f924aaa555e 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/__fixtures__/index.ts +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/__fixtures__/index.ts @@ -8,10 +8,10 @@ import { EuiTableRow } from '@elastic/eui'; import type { ReactWrapper } from 'enzyme'; +import { FeatureTableCell } from '@kbn/security-ui-components'; import { findTestSubject } from '@kbn/test-jest-helpers'; import type { Role, RoleKibanaPrivilege } from '../../../../../../../../common'; -import { FeatureTableCell } from '../../feature_table_cell'; import { PrivilegeSummaryExpandedRow } from '../privilege_summary_expanded_row'; interface DisplayedFeaturePrivileges { diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/privilege_summary_table.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/privilege_summary_table.tsx index af15cf82b9be6..5dc856e5af5d9 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/privilege_summary_table.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/privilege_summary_table.tsx @@ -27,6 +27,7 @@ import { type PrimaryFeaturePrivilege, type SecuredFeature, } from '@kbn/security-role-management-model'; +import { FeatureTableCell } from '@kbn/security-ui-components'; import type { Space, SpacesApiUi } from '@kbn/spaces-plugin/public'; import type { EffectiveFeaturePrivileges } from './privilege_summary_calculator'; @@ -34,7 +35,6 @@ import { PrivilegeSummaryCalculator } from './privilege_summary_calculator'; import { PrivilegeSummaryExpandedRow } from './privilege_summary_expanded_row'; import { SpaceColumnHeader } from './space_column_header'; import { ALL_SPACES_ID } from '../../../../../../../common/constants'; -import { FeatureTableCell } from '../feature_table_cell'; export interface PrivilegeSummaryTableProps { role: Role; diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/privilege_selector.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/privilege_selector.tsx index 72061958ecc35..403a9026923f2 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/privilege_selector.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/privilege_selector.tsx @@ -9,7 +9,7 @@ import { EuiSelect } from '@elastic/eui'; import type { ChangeEvent } from 'react'; import React, { Component } from 'react'; -import { NO_PRIVILEGE_VALUE } from '../constants'; +import { constants } from '@kbn/security-ui-components'; interface Props { ['data-test-subj']: string; @@ -27,10 +27,10 @@ export class PrivilegeSelector extends Component { public render() { const { availablePrivileges, value, disabled, allowNone, compressed } = this.props; - const options = []; + const options: Array<{ value: string; text: string }> = []; if (allowNone) { - options.push({ value: NO_PRIVILEGE_VALUE, text: 'none' }); + options.push({ value: constants.NO_PRIVILEGE_VALUE, text: 'none' }); } options.push( diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx index b5b57921705e5..ad6415a1f4fec 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/simple_privilege_section/simple_privilege_section.tsx @@ -16,17 +16,19 @@ import { import React, { Component, Fragment } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; +import type { Role, RoleKibanaPrivilege } from '@kbn/security-plugin-types-common'; import { isGlobalPrivilegeDefinition, type KibanaPrivileges, } from '@kbn/security-role-management-model'; +import { + constants, + KibanaPrivilegeTable, + PrivilegeFormCalculator, +} from '@kbn/security-ui-components'; import { UnsupportedSpacePrivilegesWarning } from './unsupported_space_privileges_warning'; -import type { Role, RoleKibanaPrivilege } from '../../../../../../../common'; import { copyRole } from '../../../../../../../common/model'; -import { CUSTOM_PRIVILEGE_VALUE, NO_PRIVILEGE_VALUE } from '../constants'; -import { FeatureTable } from '../feature_table'; -import { PrivilegeFormCalculator } from '../privilege_form_calculator'; interface Props { role: Role; @@ -98,7 +100,7 @@ export class SimplePrivilegeSection extends Component { onChange={this.onKibanaPrivilegeChange} options={[ { - value: NO_PRIVILEGE_VALUE, + value: constants.NO_PRIVILEGE_VALUE, inputDisplay: ( { ), }, { - value: CUSTOM_PRIVILEGE_VALUE, + value: constants.CUSTOM_PRIVILEGE_VALUE, inputDisplay: ( { {this.state.isCustomizingGlobalPrivilege && ( - { public getDisplayedBasePrivilege = () => { if (this.state.isCustomizingGlobalPrivilege) { - return CUSTOM_PRIVILEGE_VALUE; + return constants.CUSTOM_PRIVILEGE_VALUE; } const { role } = this.props; const form = this.locateGlobalPrivilege(role); - return form && form.base.length > 0 ? form.base[0] : NO_PRIVILEGE_VALUE; + return form && form.base.length > 0 ? form.base[0] : constants.NO_PRIVILEGE_VALUE; }; public onKibanaPrivilegeChange = (privilege: string) => { @@ -254,10 +256,10 @@ export class SimplePrivilegeSection extends Component { const form = this.locateGlobalPrivilege(role) || this.createGlobalPrivilegeEntry(role); - if (privilege === NO_PRIVILEGE_VALUE) { + if (privilege === constants.NO_PRIVILEGE_VALUE) { // Remove global entry if no privilege value role.kibana = role.kibana.filter((entry) => !isGlobalPrivilegeDefinition(entry)); - } else if (privilege === CUSTOM_PRIVILEGE_VALUE) { + } else if (privilege === constants.CUSTOM_PRIVILEGE_VALUE) { // Remove base privilege if customizing feature privileges form.base = []; } else { @@ -267,7 +269,7 @@ export class SimplePrivilegeSection extends Component { this.props.onChange(role); this.setState({ - isCustomizingGlobalPrivilege: privilege === CUSTOM_PRIVILEGE_VALUE, + isCustomizingGlobalPrivilege: privilege === constants.CUSTOM_PRIVILEGE_VALUE, globalPrivsIndex: role.kibana.indexOf(form), }); }; diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.tsx index 52e61c6e92603..40d0da4fbb0c2 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_display.tsx @@ -11,7 +11,7 @@ import _ from 'lodash'; import type { FC, ReactNode } from 'react'; import React from 'react'; -import { NO_PRIVILEGE_VALUE } from '../constants'; +import { constants } from '@kbn/security-ui-components'; interface Props extends PropsOf { privilege: string | string[] | undefined; @@ -40,7 +40,8 @@ function getDisplayValue(privilege: string | string[] | undefined) { let displayValue: string | ReactNode; const isPrivilegeMissing = - privileges.length === 0 || (privileges.length === 1 && privileges.includes(NO_PRIVILEGE_VALUE)); + privileges.length === 0 || + (privileges.length === 1 && privileges.includes(constants.NO_PRIVILEGE_VALUE)); if (isPrivilegeMissing) { displayValue = ; diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx index 7d9d6d015c03e..406e102b4529d 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.test.tsx @@ -13,14 +13,14 @@ import { createKibanaPrivileges, kibanaFeatures, } from '@kbn/security-role-management-model/src/__fixtures__'; +import { KibanaPrivilegeTable as FeatureTable } from '@kbn/security-ui-components'; +import { getDisplayedFeaturePrivileges } from '@kbn/security-ui-components/src/kibana_privilege_table/__fixtures__'; import type { Space } from '@kbn/spaces-plugin/public'; import { findTestSubject, mountWithIntl } from '@kbn/test-jest-helpers'; import { PrivilegeSpaceForm } from './privilege_space_form'; import { SpaceSelector } from './space_selector'; import type { Role } from '../../../../../../../common'; -import { FeatureTable } from '../feature_table'; -import { getDisplayedFeaturePrivileges } from '../feature_table/__fixtures__'; const createRole = (kibana: Role['kibana'] = []): Role => { return { diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx index fbcc43a3b4b1a..a37fd799a035e 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx @@ -30,15 +30,17 @@ import React, { Component, Fragment } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { KibanaPrivileges } from '@kbn/security-role-management-model'; +import { + KibanaPrivilegeTable, + PrivilegeFormCalculator, + constants as UI_CONSTANTS, +} from '@kbn/security-ui-components'; import type { Space } from '@kbn/spaces-plugin/public'; import { SpaceSelector } from './space_selector'; import type { FeaturesPrivileges, Role } from '../../../../../../../common'; import { ALL_SPACES_ID } from '../../../../../../../common/constants'; import { copyRole } from '../../../../../../../common/model'; -import { CUSTOM_PRIVILEGE_VALUE } from '../constants'; -import { FeatureTable } from '../feature_table'; -import { PrivilegeFormCalculator } from '../privilege_form_calculator'; interface Props { role: Role; @@ -254,7 +256,7 @@ export class PrivilegeSpaceForm extends Component { - { let isCustomizingFeaturePrivileges = false; - if (privilegeName === CUSTOM_PRIVILEGE_VALUE) { + if (privilegeName === UI_CONSTANTS.CUSTOM_PRIVILEGE_VALUE) { form.base = []; isCustomizingFeaturePrivileges = true; } else { @@ -456,7 +458,8 @@ export class PrivilegeSpaceForm extends Component { } this.setState({ - selectedBasePrivilege: privilegeName === CUSTOM_PRIVILEGE_VALUE ? [] : [privilegeName], + selectedBasePrivilege: + privilegeName === UI_CONSTANTS.CUSTOM_PRIVILEGE_VALUE ? [] : [privilegeName], role, isCustomizingFeaturePrivileges, privilegeCalculator: new PrivilegeFormCalculator(this.props.kibanaPrivileges, role), @@ -507,7 +510,7 @@ export class PrivilegeSpaceForm extends Component { return `basePrivilege_${basePrivilege.id}`; } - return `basePrivilege_${CUSTOM_PRIVILEGE_VALUE}`; + return `basePrivilege_${UI_CONSTANTS.CUSTOM_PRIVILEGE_VALUE}`; }; private onFeaturePrivilegesChange = (featureId: string, privileges: string[]) => { diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx index 316419f479426..e0478394852bc 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.test.tsx @@ -12,11 +12,11 @@ import React from 'react'; import { KibanaFeature } from '@kbn/features-plugin/public'; import type { Role, RoleKibanaPrivilege } from '@kbn/security-plugin-types-common'; import { createKibanaPrivileges } from '@kbn/security-role-management-model/src/__fixtures__'; +import { PrivilegeFormCalculator } from '@kbn/security-ui-components'; import { findTestSubject, mountWithIntl } from '@kbn/test-jest-helpers'; import { PrivilegeDisplay } from './privilege_display'; import { PrivilegeSpaceTable } from './privilege_space_table'; -import { PrivilegeFormCalculator } from '../privilege_form_calculator'; interface TableRow { spaces: string[]; diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx index 28e1d50d7f71e..61a31f5575800 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_table.tsx @@ -24,13 +24,12 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { FeaturesPrivileges, Role } from '@kbn/security-plugin-types-common'; import { isGlobalPrivilegeDefinition } from '@kbn/security-role-management-model'; +import { constants, type PrivilegeFormCalculator } from '@kbn/security-ui-components'; import type { Space } from '@kbn/spaces-plugin/public'; import { getSpaceColor } from '@kbn/spaces-plugin/public'; import { PrivilegeDisplay } from './privilege_display'; import { copyRole } from '../../../../../../../common/model'; -import { CUSTOM_PRIVILEGE_VALUE } from '../constants'; -import type { PrivilegeFormCalculator } from '../privilege_form_calculator'; const SPACES_DISPLAY_COUNT = 4; @@ -120,7 +119,7 @@ export class PrivilegeSpaceTable extends Component { const isExpanded = this.state.expandedSpacesGroups.includes(record.privilegeIndex); const displayedSpaces = isExpanded ? spaces : spaces.slice(0, SPACES_DISPLAY_COUNT); - let button = null; + let button: React.ReactElement | null = null; if (spaces.length > displayedSpaces.length) { button = ( { const basePrivilege = privilegeCalculator.getBasePrivilege(record.privilegeIndex)?.id ?? - CUSTOM_PRIVILEGE_VALUE; + constants.CUSTOM_PRIVILEGE_VALUE; const privilege = privilegeCalculator.isWildcardBasePrivilege(record.privilegeIndex) ? '*' diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx index 404bd39ec9b67..e5a4cb1494d77 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/space_aware_privilege_section.tsx @@ -22,13 +22,13 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { Role } from '@kbn/security-plugin-types-common'; import type { KibanaPrivileges } from '@kbn/security-role-management-model'; +import { PrivilegeFormCalculator } from '@kbn/security-ui-components'; import type { Space, SpacesApiUi } from '@kbn/spaces-plugin/public'; import { PrivilegeSpaceForm } from './privilege_space_form'; import { PrivilegeSpaceTable } from './privilege_space_table'; import { isRoleReserved, isRoleWithWildcardBasePrivilege } from '../../../../../../../common'; import type { RoleValidator } from '../../../validate_role'; -import { PrivilegeFormCalculator } from '../privilege_form_calculator'; import { PrivilegeSummary } from '../privilege_summary'; interface Props { diff --git a/x-pack/plugins/security/public/management/roles/index.ts b/x-pack/plugins/security/public/management/roles/index.ts index 86d5990761d4d..258fd1ee558be 100644 --- a/x-pack/plugins/security/public/management/roles/index.ts +++ b/x-pack/plugins/security/public/management/roles/index.ts @@ -7,3 +7,4 @@ export { rolesManagementApp } from './roles_management_app'; export { RolesAPIClient } from './roles_api_client'; +export { PrivilegesAPIClient } from './privileges_api_client'; diff --git a/x-pack/plugins/security/public/management/roles/privileges_api_client.ts b/x-pack/plugins/security/public/management/roles/privileges_api_client.ts index 54c8992698978..5032871c41fa6 100644 --- a/x-pack/plugins/security/public/management/roles/privileges_api_client.ts +++ b/x-pack/plugins/security/public/management/roles/privileges_api_client.ts @@ -7,16 +7,15 @@ import type { HttpStart } from '@kbn/core/public'; import type { RawKibanaPrivileges } from '@kbn/security-authorization-core'; +import { PrivilegesAPIClientPublicContract } from '@kbn/security-plugin-types-public'; import type { BuiltinESPrivileges } from '../../../common/model'; -export class PrivilegesAPIClient { - constructor(private readonly http: HttpStart) {} +export class PrivilegesAPIClient extends PrivilegesAPIClientPublicContract { + constructor(private readonly http: HttpStart) { + super(); + } - /* - * respectLicenseLevel is an internal optional parameter soley for getting all sub-feature - * privilieges to use in the UI. It is not meant for any other use. - */ async getAll({ includeActions, respectLicenseLevel = true, diff --git a/x-pack/plugins/security/public/plugin.test.tsx b/x-pack/plugins/security/public/plugin.test.tsx index 433e1981e9ce9..336a42a1fd324 100644 --- a/x-pack/plugins/security/public/plugin.test.tsx +++ b/x-pack/plugins/security/public/plugin.test.tsx @@ -40,7 +40,11 @@ describe('Security Plugin', () => { }) ).toEqual({ authc: { getCurrentUser: expect.any(Function), areAPIKeysEnabled: expect.any(Function) }, - authz: { isRoleManagementEnabled: expect.any(Function), roles: expect.any(Object) }, + authz: { + isRoleManagementEnabled: expect.any(Function), + roles: expect.any(Object), + privileges: expect.any(Object), + }, license: { isLicenseAvailable: expect.any(Function), getLicenseType: expect.any(Function), @@ -129,6 +133,9 @@ describe('Security Plugin', () => { }, "authz": Object { "isRoleManagementEnabled": [Function], + "privileges": Object { + "getAll": [Function], + }, "roles": Object { "deleteRole": [Function], "getRole": [Function], diff --git a/x-pack/plugins/security/tsconfig.json b/x-pack/plugins/security/tsconfig.json index 8e3f38833248d..c3df5dda29481 100644 --- a/x-pack/plugins/security/tsconfig.json +++ b/x-pack/plugins/security/tsconfig.json @@ -86,6 +86,7 @@ "@kbn/core-security-server-mocks", "@kbn/security-authorization-core", "@kbn/security-role-management-model", + "@kbn/security-ui-components", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts index fde8e1f4537a7..7d3edafedd1a9 100644 --- a/x-pack/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -83,11 +83,6 @@ export const allowedExperimentalValues = Object.freeze({ */ responseActionsCrowdstrikeManualHostIsolationEnabled: true, - /** - * Enables scan response action on Endpoint - */ - responseActionScanEnabled: true, - /** * Enables new notes */ diff --git a/x-pack/plugins/security_solution/public/assistant/use_assistant_telemetry/index.tsx b/x-pack/plugins/security_solution/public/assistant/use_assistant_telemetry/index.tsx index 3de834c08829a..084f8ca942153 100644 --- a/x-pack/plugins/security_solution/public/assistant/use_assistant_telemetry/index.tsx +++ b/x-pack/plugins/security_solution/public/assistant/use_assistant_telemetry/index.tsx @@ -17,7 +17,7 @@ export const useAssistantTelemetry = (): AssistantTelemetry => { const baseConversations = useBaseConversations(); const getAnonymizedConversationTitle = useCallback( - async (title) => { + async (title: string) => { // With persistent storage for conversation replacing id to title, because id is UUID now // and doesn't make any value for telemetry tracking return baseConversations[title] ? title : 'Custom'; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/attack_discovery_tab/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/attack_discovery_tab/index.tsx index 23a63d0503db3..a850ed1a5d41b 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/attack_discovery_tab/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/attack_discovery_tab/index.tsx @@ -11,7 +11,7 @@ import { css } from '@emotion/react'; import React, { useMemo } from 'react'; import { AttackChain } from '../../../attack/attack_chain'; -import { InvestigateInTimelineButton } from '../../../../common/components/event_details/table/investigate_in_timeline_button'; +import { InvestigateInTimelineButton } from '../../../../common/components/event_details/investigate_in_timeline_button'; import { buildAlertsKqlFilter } from '../../../../detections/components/alerts_table/actions'; import { getTacticMetadata } from '../../../helpers'; import { AttackDiscoveryMarkdownFormatter } from '../../../attack_discovery_markdown_formatter'; diff --git a/x-pack/plugins/security_solution/public/cases/pages/index.tsx b/x-pack/plugins/security_solution/public/cases/pages/index.tsx index 1ba63b8c43662..c873e48e4975f 100644 --- a/x-pack/plugins/security_solution/public/cases/pages/index.tsx +++ b/x-pack/plugins/security_solution/public/cases/pages/index.tsx @@ -44,7 +44,8 @@ const CaseContainerComponent: React.FC = () => { const { openFlyout } = useExpandableFlyoutApi(); const getDetectionsRuleDetailsHref = useCallback( - (ruleId) => detectionsFormatUrl(getRuleDetailsUrl(ruleId ?? '', detectionsUrlSearch)), + (ruleId: string | null | undefined) => + detectionsFormatUrl(getRuleDetailsUrl(ruleId ?? '', detectionsUrlSearch)), [detectionsFormatUrl, detectionsUrlSearch] ); diff --git a/x-pack/plugins/security_solution/public/common/components/control_columns/row_action/index.tsx b/x-pack/plugins/security_solution/public/common/components/control_columns/row_action/index.tsx index 5c61900876aae..931c519ae9b57 100644 --- a/x-pack/plugins/security_solution/public/common/components/control_columns/row_action/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/control_columns/row_action/index.tsx @@ -26,7 +26,7 @@ import { useIsExperimentalFeatureEnabled } from '../../../hooks/use_experimental import { useTourContext } from '../../guided_onboarding_tour'; import { AlertsCasesTourSteps, SecurityStepId } from '../../guided_onboarding_tour/tour_config'; -type Props = EuiDataGridCellValueElementProps & { +export type RowActionProps = EuiDataGridCellValueElementProps & { columnHeaders: ColumnHeaderOptions[]; controlColumn: ControlColumnProps; data: TimelineItem; @@ -67,7 +67,7 @@ const RowActionComponent = ({ setEventsDeleted, width, refetch, -}: Props) => { +}: RowActionProps) => { const { data: timelineNonEcsData, ecs: ecsData, _id: eventId, _index: indexName } = data ?? {}; const { telemetry } = useKibana().services; const { openFlyout } = useExpandableFlyoutApi(); diff --git a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx index 9a8762cee2c07..eca4c61f9cea2 100644 --- a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx +++ b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx @@ -95,7 +95,7 @@ type RenderFunctionProp = ( state: DraggableStateSnapshot ) => React.ReactNode; -interface Props { +export interface DraggableWrapperProps { dataProvider: DataProvider; fieldType?: string; isAggregatable?: boolean; @@ -128,7 +128,7 @@ export const getStyle = ( }; }; -const DraggableOnWrapper: React.FC = React.memo( +const DraggableOnWrapper: React.FC = React.memo( ({ dataProvider, render, scopeId, truncate, hideTopN }) => { const [providerRegistered, setProviderRegistered] = useState(false); const isDisabled = dataProvider.id.includes(`-${ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID}-`); @@ -265,7 +265,7 @@ const DraggableOnWrapper: React.FC = React.memo( ); DraggableOnWrapper.displayName = 'DraggableOnWrapper'; -export const DraggableWrapper: React.FC = React.memo( +export const DraggableWrapper: React.FC = React.memo( ({ dataProvider, isDraggable = false, render, scopeId, truncate, hideTopN }) => { const content = useMemo( () => ( diff --git a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/droppable_wrapper.tsx b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/droppable_wrapper.tsx index d0b1ce4eca211..586165893408c 100644 --- a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/droppable_wrapper.tsx +++ b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/droppable_wrapper.tsx @@ -7,7 +7,7 @@ import { rgba } from 'polished'; import React, { useCallback } from 'react'; -import type { DraggableChildrenFn } from '@hello-pangea/dnd'; +import type { DraggableChildrenFn, DroppableProps } from '@hello-pangea/dnd'; import { Droppable } from '@hello-pangea/dnd'; import styled from 'styled-components'; @@ -99,7 +99,7 @@ export const DroppableWrapper = React.memo( render = null, renderClone, }) => { - const DroppableContent = useCallback( + const DroppableContent = useCallback( (provided, snapshot) => ( ( [field, id, name, queryValue, value] ); - const renderCallback = useCallback( + const renderCallback = useCallback( (dataProvider, _, snapshot) => snapshot.isDragging ? ( diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx deleted file mode 100644 index 92381ec3846bc..0000000000000 --- a/x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx +++ /dev/null @@ -1,11 +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 EventsViewType { - osqueryView = 'osquery-results-view', - responseActionsView = 'response-actions-results-view', -} diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.test.ts b/x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.test.ts deleted file mode 100644 index fc793df1025e7..0000000000000 --- a/x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.test.ts +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { UseSummaryRowsProps } from './get_alert_summary_rows'; -import { useSummaryRows } from './get_alert_summary_rows'; -import { createAppRootMockRenderer, endpointAlertDataMock } from '../../mock/endpoint'; -import type { RenderHookResult } from '@testing-library/react-hooks/src/types'; -import type { AlertSummaryRow } from './helpers'; - -describe('useSummaryRows', () => { - let hookProps: UseSummaryRowsProps; - let renderHook: () => RenderHookResult; - - beforeEach(() => { - const appContextMock = createAppRootMockRenderer(); - - appContextMock.setExperimentalFlag({ - responseActionsSentinelOneV1Enabled: true, - responseActionsCrowdstrikeManualHostIsolationEnabled: true, - }); - - hookProps = { - data: endpointAlertDataMock.generateEndpointAlertDetailsItemData(), - browserFields: {}, - scopeId: 'scope-id', - eventId: 'event-id', - investigationFields: [], - }; - - renderHook = () => { - return appContextMock.renderHook(() => - useSummaryRows(hookProps) - ); - }; - }); - - it('returns summary rows for default event categories', () => { - const { result } = renderHook(); - - expect(result.current).toEqual( - expect.arrayContaining([ - expect.objectContaining({ title: 'host.name', description: expect.anything() }), - ]) - ); - }); - - it('excludes fields not related to the event source', () => { - const { result } = renderHook(); - - expect(result.current).not.toEqual( - expect.arrayContaining([ - expect.objectContaining({ - title: 'agent.id', - description: expect.anything(), - }), - ]) - ); - }); - - it('includes sentinel_one agent status field', () => { - hookProps.data = endpointAlertDataMock.generateSentinelOneAlertDetailsItemData(); - const { result } = renderHook(); - - expect(result.current).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - title: 'Agent status', - description: expect.objectContaining({ - values: ['abfe4a35-d5b4-42a0-a539-bd054c791769'], - }), - }), - ]) - ); - }); - - it('includes crowdstrike agent status field', () => { - hookProps.data = endpointAlertDataMock.generateCrowdStrikeAlertDetailsItemData(); - const { result } = renderHook(); - - expect(result.current).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - title: 'Agent status', - description: expect.objectContaining({ - values: ['abfe4a35-d5b4-42a0-a539-bd054c791769'], - }), - }), - ]) - ); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.tsx index 357e1230ebee5..f591c3d48e0db 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/get_alert_summary_rows.tsx @@ -4,16 +4,12 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { useMemo } from 'react'; -import { find, isEmpty, uniqBy } from 'lodash/fp'; +import { find, uniqBy } from 'lodash/fp'; import { ALERT_RULE_PARAMETERS, ALERT_RULE_TYPE } from '@kbn/rule-data-utils'; import { EventCode, EventCategory } from '@kbn/securitysolution-ecs'; +import { i18n } from '@kbn/i18n'; import { SUPPORTED_AGENT_ID_ALERT_FIELDS } from '../../../../common/endpoint/service/response_actions/constants'; -import { isResponseActionsAlertAgentIdField } from '../../lib/endpoint'; -import { useAlertResponseActionsSupport } from '../../hooks/endpoint/use_alert_response_actions_support'; -import * as i18n from './translations'; -import type { BrowserFields } from '../../../../common/search_strategy/index_fields'; import { ALERTS_HEADERS_THRESHOLD_CARDINALITY, ALERTS_HEADERS_THRESHOLD_COUNT, @@ -31,17 +27,27 @@ import { AGENT_STATUS_FIELD_NAME, QUARANTINED_PATH_FIELD_NAME, } from '../../../timelines/components/timeline/body/renderers/constants'; -import type { AlertSummaryRow } from './helpers'; -import { getEnrichedFieldInfo } from './helpers'; -import type { EventSummaryField, EnrichedFieldInfo } from './types'; +import type { EventSummaryField } from './types'; import type { TimelineEventsDetailsItem } from '../../../../common/search_strategy/timeline'; const THRESHOLD_TERMS_FIELD = `${ALERT_THRESHOLD_RESULT}.terms.field`; const THRESHOLD_TERMS_VALUE = `${ALERT_THRESHOLD_RESULT}.terms.value`; const THRESHOLD_CARDINALITY_FIELD = `${ALERT_THRESHOLD_RESULT}.cardinality.field`; -const THRESHOLD_CARDINALITY_VALUE = `${ALERT_THRESHOLD_RESULT}.cardinality.value`; const THRESHOLD_COUNT = `${ALERT_THRESHOLD_RESULT}.count`; +const AGENT_STATUS = i18n.translate('xpack.securitySolution.detections.alerts.agentStatus', { + defaultMessage: 'Agent status', +}); +const QUARANTINED_FILE_PATH = i18n.translate( + 'xpack.securitySolution.detections.alerts.quarantinedFilePath', + { + defaultMessage: 'Quarantined file path', + } +); +const RULE_TYPE = i18n.translate('xpack.securitySolution.detections.alerts.ruleType', { + defaultMessage: 'Rule type', +}); + /** Always show these fields */ const alwaysDisplayedFields: EventSummaryField[] = [ { id: 'host.name' }, @@ -52,7 +58,7 @@ const alwaysDisplayedFields: EventSummaryField[] = [ return { id: fieldPath, overrideField: AGENT_STATUS_FIELD_NAME, - label: i18n.AGENT_STATUS, + label: AGENT_STATUS, }; }), @@ -72,7 +78,7 @@ const alwaysDisplayedFields: EventSummaryField[] = [ { id: 'orchestrator.resource.type' }, { id: 'process.executable' }, { id: 'file.path' }, - { id: ALERT_RULE_TYPE, label: i18n.RULE_TYPE }, + { id: ALERT_RULE_TYPE, label: RULE_TYPE }, ]; /** @@ -163,7 +169,7 @@ function getFieldsByEventCode( { id: 'file.Ext.quarantine_path', overrideField: QUARANTINED_PATH_FIELD_NAME, - label: i18n.QUARANTINED_FILE_PATH, + label: QUARANTINED_FILE_PATH, }, ]; default: @@ -297,192 +303,3 @@ export function getEventCategoriesFromData(data: TimelineEventsDetailsItem[]): E return { primaryEventCategory, allEventCategories }; } - -export interface UseSummaryRowsProps { - data: TimelineEventsDetailsItem[]; - browserFields: BrowserFields; - scopeId: string; - eventId: string; - investigationFields?: string[]; - isDraggable?: boolean; - isReadOnly?: boolean; -} - -export const useSummaryRows = ({ - data, - browserFields, - scopeId, - eventId, - isDraggable = false, - isReadOnly = false, - investigationFields, -}: UseSummaryRowsProps): AlertSummaryRow[] => { - const responseActionsSupport = useAlertResponseActionsSupport(data); - - return useMemo(() => { - const eventCategories = getEventCategoriesFromData(data); - - const eventCodeField = find({ category: 'event', field: 'event.code' }, data); - - const eventCode = Array.isArray(eventCodeField?.originalValue) - ? eventCodeField?.originalValue?.[0] - : eventCodeField?.originalValue; - - const eventRuleTypeField = find({ category: 'kibana', field: ALERT_RULE_TYPE }, data); - const eventRuleType = Array.isArray(eventRuleTypeField?.originalValue) - ? eventRuleTypeField?.originalValue?.[0] - : eventRuleTypeField?.originalValue; - - const tableFields = getEventFieldsToDisplay({ - eventCategories, - eventCode, - eventRuleType, - highlightedFieldsOverride: investigationFields ?? [], - }); - - return data != null - ? tableFields.reduce((acc, field) => { - const item = data.find( - (d) => d.field === field.id || (field.legacyId && d.field === field.legacyId) - ); - if (!item || isEmpty(item.values)) { - return acc; - } - - // If we found the data by its legacy id we swap the ids to display the correct one - if (item.field === field.legacyId) { - field.id = field.legacyId; - } - - const linkValueField = - field.linkField != null && data.find((d) => d.field === field.linkField); - const description = { - ...getEnrichedFieldInfo({ - item, - linkValueField: linkValueField || undefined, - contextId: scopeId, - scopeId, - browserFields, - eventId, - field, - }), - isDraggable, - isReadOnly, - }; - - // If the field is one used by a supported Response Actions agentType, - // and the alert's host supports response actions - // but the alert field is not the one that the agentType on the alert host uses, - // then exit and return accumulator - if ( - isResponseActionsAlertAgentIdField(field.id) && - responseActionsSupport.isSupported && - responseActionsSupport.details.agentIdField !== field.id - ) { - return acc; - } - - if (field.id === THRESHOLD_TERMS_FIELD) { - const enrichedInfo = enrichThresholdTerms(item, data, description); - if (enrichedInfo) { - return [...acc, ...enrichedInfo]; - } else { - return acc; - } - } - - if (field.id === THRESHOLD_CARDINALITY_FIELD) { - const enrichedInfo = enrichThresholdCardinality(item, data, description); - if (enrichedInfo) { - return [...acc, enrichedInfo]; - } else { - return acc; - } - } - - return [ - ...acc, - { - title: field.label ?? field.id, - description, - }, - ]; - }, []) - : []; - }, [ - data, - investigationFields, - scopeId, - browserFields, - eventId, - isDraggable, - isReadOnly, - responseActionsSupport.details.agentIdField, - responseActionsSupport.isSupported, - ]); -}; - -/** - * Enriches the summary data for threshold terms. - * For any given threshold term, it generates a row with the term's name and the associated value. - */ -function enrichThresholdTerms( - { values: termsFieldArr }: TimelineEventsDetailsItem, - data: TimelineEventsDetailsItem[], - description: EnrichedFieldInfo -) { - const termsValueItem = data.find((d) => d.field === THRESHOLD_TERMS_VALUE); - const termsValueArray = termsValueItem && termsValueItem.values; - - // Make sure both `fields` and `values` are an array and that they have the same length - if ( - Array.isArray(termsFieldArr) && - termsFieldArr.length > 0 && - Array.isArray(termsValueArray) && - termsFieldArr.length === termsValueArray.length - ) { - return termsFieldArr - .map((field, index) => ({ - title: field, - description: { - ...description, - values: [termsValueArray[index]], - }, - })) - .filter( - (entry) => - !alwaysDisplayedFields - .map((alwaysThereEntry) => alwaysThereEntry.id) - .includes(entry.title) - ); - } -} - -/** - * Enriches the summary data for threshold cardinality. - * Reads out the cardinality field and the value and interpolates them into a combined string value. - */ -function enrichThresholdCardinality( - { values: cardinalityFieldArr }: TimelineEventsDetailsItem, - data: TimelineEventsDetailsItem[], - description: EnrichedFieldInfo -) { - const cardinalityValueItem = data.find((d) => d.field === THRESHOLD_CARDINALITY_VALUE); - const cardinalityValueArray = cardinalityValueItem && cardinalityValueItem.values; - - // Only return a summary row if we actually have the correct field and value - if ( - Array.isArray(cardinalityFieldArr) && - cardinalityFieldArr.length === 1 && - Array.isArray(cardinalityValueArray) && - cardinalityFieldArr.length === cardinalityValueArray.length - ) { - return { - title: ALERTS_HEADERS_THRESHOLD_CARDINALITY, - description: { - ...description, - values: [`count(${cardinalityFieldArr[0]}) >= ${cardinalityValueArray[0]}`], - }, - }; - } -} diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx index 6b3bd565f0eef..46f6449cce85e 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx @@ -5,42 +5,7 @@ * 2.0. */ -import { get, getOr, isEmpty } from 'lodash/fp'; - -import { - elementOrChildrenHasFocus, - getFocusedDataColindexCell, - getTableSkipFocus, - handleSkipFocus, - stopPropagationAndPreventDefault, -} from '@kbn/timelines-plugin/public'; -import type { BrowserFields } from '../../containers/source'; -import type { TimelineEventsDetailsItem } from '../../../../common/search_strategy/timeline'; -import type { EnrichedFieldInfo, EventSummaryField } from './types'; - -import { - AGENT_STATUS_FIELD_NAME, - QUARANTINED_PATH_FIELD_NAME, -} from '../../../timelines/components/timeline/body/renderers/constants'; - -/** - * An item rendered in the table - */ -export interface Item { - description: string; - field: JSX.Element; - fieldId: string; - type: string; - values: string[]; -} - -export interface AlertSummaryRow { - title: string; - description: EnrichedFieldInfo & { - isDraggable?: boolean; - isReadOnly?: boolean; - }; -} +import { isEmpty } from 'lodash/fp'; /** Returns example text, or an empty string if the field does not have an example */ export const getExampleText = (example: string | number | null | undefined): string => @@ -69,111 +34,3 @@ export const getIconFromType = (type: string | null | undefined) => { }; export const EVENT_FIELDS_TABLE_CLASS_NAME = 'event-fields-table'; - -/** - * Returns `true` if the Event Details "event fields" table, or it's children, - * has focus - */ -export const tableHasFocus = (containerElement: HTMLElement | null): boolean => - elementOrChildrenHasFocus( - containerElement?.querySelector(`.${EVENT_FIELDS_TABLE_CLASS_NAME}`) - ); - -/** - * This function has a side effect. It will skip focus "after" or "before" - * the Event Details table, with exceptions as noted below. - * - * If the currently-focused table cell has additional focusable children, - * i.e. draggables or always-open popover content, the browser's "natural" - * focus management will determine which element is focused next. - */ -export const onEventDetailsTabKeyPressed = ({ - containerElement, - keyboardEvent, - onSkipFocusBeforeEventsTable, - onSkipFocusAfterEventsTable, -}: { - containerElement: HTMLElement | null; - keyboardEvent: React.KeyboardEvent; - onSkipFocusBeforeEventsTable: () => void; - onSkipFocusAfterEventsTable: () => void; -}) => { - const { shiftKey } = keyboardEvent; - - const eventFieldsTableSkipFocus = getTableSkipFocus({ - containerElement, - getFocusedCell: getFocusedDataColindexCell, - shiftKey, - tableHasFocus, - tableClassName: EVENT_FIELDS_TABLE_CLASS_NAME, - }); - - if (eventFieldsTableSkipFocus !== 'SKIP_FOCUS_NOOP') { - stopPropagationAndPreventDefault(keyboardEvent); - handleSkipFocus({ - onSkipFocusBackwards: onSkipFocusBeforeEventsTable, - onSkipFocusForward: onSkipFocusAfterEventsTable, - skipFocus: eventFieldsTableSkipFocus, - }); - } -}; - -export function getEnrichedFieldInfo({ - browserFields, - contextId, - eventId, - field, - item, - linkValueField, - scopeId, -}: { - browserFields: BrowserFields; - contextId: string; - item: TimelineEventsDetailsItem; - eventId: string; - field?: EventSummaryField; - scopeId: string; - linkValueField?: TimelineEventsDetailsItem; -}): EnrichedFieldInfo { - const fieldInfo = { - contextId, - eventId, - fieldType: 'string', - linkValue: undefined, - scopeId, - }; - const linkValue = getOr(null, 'originalValue.0', linkValueField); - const category = item.category ?? ''; - const fieldName = item.field ?? ''; - - const browserField = get([category, 'fields', fieldName], browserFields); - const overrideField = field?.overrideField; - return { - ...fieldInfo, - data: { - field: overrideField ?? fieldName, - format: browserField?.format?.id ?? '', - type: browserField?.type ?? '', - isObjectArray: item.isObjectArray, - }, - values: item.values, - linkValue: linkValue ?? undefined, - fieldFromBrowserField: browserField, - }; -} - -/** - * A lookup table for fields that should not have actions - */ -export const FIELDS_WITHOUT_ACTIONS: { [field: string]: boolean } = { - [AGENT_STATUS_FIELD_NAME]: true, - [QUARANTINED_PATH_FIELD_NAME]: true, -}; - -/** - * Checks whether the given field should have hover or row actions. - * The lookup is fast, so it is not necessary to memoize the result. - */ -export function hasHoverOrRowActions(field: string): boolean { - return !FIELDS_WITHOUT_ACTIONS[field]; -} diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/insights/translations.ts b/x-pack/plugins/security_solution/public/common/components/event_details/insights/translations.ts deleted file mode 100644 index 6afd236caf3d6..0000000000000 --- a/x-pack/plugins/security_solution/public/common/components/event_details/insights/translations.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. - */ - -import { i18n } from '@kbn/i18n'; - -// TODO: MOVE TO FLYOUT FOLDER - https://github.com/elastic/security-team/issues/7462 -export const SUPPRESSED_ALERTS_COUNT_TECHNICAL_PREVIEW = i18n.translate( - 'xpack.securitySolution.alertDetails.overview.insights.suppressedAlertsCountTechnicalPreview', - { - defaultMessage: 'Technical Preview', - } -); diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/table/investigate_in_timeline_button.test.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/investigate_in_timeline_button.test.tsx similarity index 85% rename from x-pack/plugins/security_solution/public/common/components/event_details/table/investigate_in_timeline_button.test.tsx rename to x-pack/plugins/security_solution/public/common/components/event_details/investigate_in_timeline_button.test.tsx index 1c364e97fbd10..c9b2312c28f5e 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/table/investigate_in_timeline_button.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/investigate_in_timeline_button.test.tsx @@ -9,12 +9,12 @@ import { render, screen } from '@testing-library/react'; import React from 'react'; import { InvestigateInTimelineButton } from './investigate_in_timeline_button'; -import { TestProviders } from '../../../mock'; +import { TestProviders } from '../../mock'; import { getDataProvider } from './use_action_cell_data_provider'; -import { ACTION_INVESTIGATE_IN_TIMELINE } from '../../../../detections/components/alerts_table/translations'; +import { ACTION_INVESTIGATE_IN_TIMELINE } from '../../../detections/components/alerts_table/translations'; -jest.mock('../../../lib/kibana'); +jest.mock('../../lib/kibana'); describe('InvestigateInTimelineButton', () => { describe('When all props are provided', () => { diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/table/investigate_in_timeline_button.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/investigate_in_timeline_button.tsx similarity index 80% rename from x-pack/plugins/security_solution/public/common/components/event_details/table/investigate_in_timeline_button.tsx rename to x-pack/plugins/security_solution/public/common/components/event_details/investigate_in_timeline_button.tsx index eb43d61b2f8d4..f496ecc89b90b 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/table/investigate_in_timeline_button.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/investigate_in_timeline_button.tsx @@ -12,18 +12,18 @@ import type { IconType } from '@elastic/eui'; import type { Filter } from '@kbn/es-query'; import { useDispatch, useSelector } from 'react-redux'; -import { sourcererSelectors } from '../../../store'; -import { InputsModelId } from '../../../store/inputs/constants'; -import type { TimeRange } from '../../../store/inputs/model'; -import { inputsActions } from '../../../store/inputs'; -import { updateProviders, setFilters } from '../../../../timelines/store/actions'; -import { sourcererActions } from '../../../store/actions'; -import { SourcererScopeName } from '../../../../sourcerer/store/model'; -import type { DataProvider } from '../../../../../common/types'; -import { TimelineId } from '../../../../../common/types/timeline'; -import { TimelineTypeEnum } from '../../../../../common/api/timeline'; -import { useCreateTimeline } from '../../../../timelines/hooks/use_create_timeline'; -import { ACTION_INVESTIGATE_IN_TIMELINE } from '../../../../detections/components/alerts_table/translations'; +import { sourcererSelectors } from '../../store'; +import { InputsModelId } from '../../store/inputs/constants'; +import type { TimeRange } from '../../store/inputs/model'; +import { inputsActions } from '../../store/inputs'; +import { updateProviders, setFilters } from '../../../timelines/store/actions'; +import { sourcererActions } from '../../store/actions'; +import { SourcererScopeName } from '../../../sourcerer/store/model'; +import type { DataProvider } from '../../../../common/types'; +import { TimelineId } from '../../../../common/types/timeline'; +import { TimelineTypeEnum } from '../../../../common/api/timeline'; +import { useCreateTimeline } from '../../../timelines/hooks/use_create_timeline'; +import { ACTION_INVESTIGATE_IN_TIMELINE } from '../../../detections/components/alerts_table/translations'; export interface InvestigateInTimelineButtonProps { asEmptyButton: boolean; diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/__mocks__/index.ts b/x-pack/plugins/security_solution/public/common/components/event_details/mocks.ts similarity index 99% rename from x-pack/plugins/security_solution/public/common/components/event_details/__mocks__/index.ts rename to x-pack/plugins/security_solution/public/common/components/event_details/mocks.ts index 0f2cce38662d2..ffaf78cb29b4e 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/__mocks__/index.ts +++ b/x-pack/plugins/security_solution/public/common/components/event_details/mocks.ts @@ -5,7 +5,7 @@ * 2.0. */ -export const generateAlertDetailsDataMock = () => [ +const generateAlertDetailsDataMock = () => [ { category: 'process', field: 'process.name', values: ['-'], originalValue: '-' }, { category: 'process', field: 'process.pid', values: [0], originalValue: 0 }, { category: 'process', field: 'process.executable', values: ['-'], originalValue: '-' }, diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/table/use_action_cell_data_provider.ts b/x-pack/plugins/security_solution/public/common/components/event_details/table/use_action_cell_data_provider.ts deleted file mode 100644 index d9bec6670766b..0000000000000 --- a/x-pack/plugins/security_solution/public/common/components/event_details/table/use_action_cell_data_provider.ts +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -/* eslint-disable complexity */ - -import type { Filter } from '@kbn/es-query'; -import { escapeDataProviderId } from '@kbn/securitysolution-t-grid'; -import { isArray, isEmpty, isString } from 'lodash/fp'; -import { useMemo } from 'react'; -import type { FieldSpec } from '@kbn/data-plugin/common'; - -import { - AGENT_STATUS_FIELD_NAME, - EVENT_MODULE_FIELD_NAME, - EVENT_URL_FIELD_NAME, - GEO_FIELD_TYPE, - HOST_NAME_FIELD_NAME, - IP_FIELD_TYPE, - MESSAGE_FIELD_NAME, - REFERENCE_URL_FIELD_NAME, - RULE_REFERENCE_FIELD_NAME, - SIGNAL_RULE_NAME_FIELD_NAME, - SIGNAL_STATUS_FIELD_NAME, -} from '../../../../timelines/components/timeline/body/renderers/constants'; -import { BYTES_FORMAT } from '../../../../timelines/components/timeline/body/renderers/bytes'; -import { EVENT_DURATION_FIELD_NAME } from '../../../../timelines/components/duration'; -import { getDisplayValue } from '../../../../timelines/components/timeline/data_providers/helpers'; -import { PORT_NAMES } from '../../../../explore/network/components/port/helpers'; -import { INDICATOR_REFERENCE } from '../../../../../common/cti/constants'; -import type { DataProvider, DataProvidersAnd, QueryOperator } from '../../../../../common/types'; -import { IS_OPERATOR } from '../../../../../common/types'; - -export interface UseActionCellDataProvider { - contextId?: string; - eventId?: string; - field: string; - fieldFormat?: string; - fieldFromBrowserField?: Partial; - fieldType?: string; - isObjectArray?: boolean; - linkValue?: string | null; - values: string[] | null | undefined; -} - -export interface ActionCellValuesAndDataProvider { - values: string[]; - dataProviders: DataProvider[]; - filters: Filter[]; -} - -export const getDataProvider = ( - field: string, - id: string, - value: string | string[], - operator: QueryOperator = IS_OPERATOR, - excluded: boolean = false -): DataProvider => ({ - and: [], - enabled: true, - id: escapeDataProviderId(id), - name: field, - excluded, - kqlQuery: '', - queryMatch: { - field, - value, - operator, - displayValue: getDisplayValue(value), - }, -}); - -export const getDataProviderAnd = ( - field: string, - id: string, - value: string | string[], - operator: QueryOperator = IS_OPERATOR, - excluded: boolean = false -): DataProvidersAnd => { - const { and, ...dataProvider } = getDataProvider(field, id, value, operator, excluded); - return dataProvider; -}; - -export const useActionCellDataProvider = ({ - contextId, - eventId, - field, - fieldFormat, - fieldFromBrowserField, - fieldType, - isObjectArray, - linkValue, - values, -}: UseActionCellDataProvider): ActionCellValuesAndDataProvider | null => { - const cellData = useMemo(() => { - if (values === null || values === undefined) return null; - const arrayValues = Array.isArray(values) ? values : [values]; - - // For fields with multiple values we need add an extra filter that makes sure - // that only fields that match ALL the values are queried later on. - let filters: Filter[] = []; - if (arrayValues.length > 1) { - filters = [ - { - meta: {}, - query: { - bool: { - must: arrayValues.map((value) => ({ term: { [field]: value } })), - }, - }, - }, - ]; - } - - return arrayValues.reduce( - (memo, value, index) => { - let id: string = ''; - let valueAsString: string = isString(value) ? value : `${values}`; - const appendedUniqueId = `${contextId}-${eventId}-${field}-${index}-${value}`; - if (fieldFromBrowserField == null) { - memo.values.push(valueAsString); - return memo; - } - - if (isObjectArray || fieldType === GEO_FIELD_TYPE || [MESSAGE_FIELD_NAME].includes(field)) { - memo.values.push(valueAsString); - return memo; - } else if (fieldType === IP_FIELD_TYPE) { - id = `formatted-ip-data-provider-${contextId}-${field}-${value}-${eventId}`; - if (isString(value) && !isEmpty(value)) { - let addresses = value; - try { - addresses = JSON.parse(value); - } catch (_) { - // Default to keeping the existing string value - } - if (isArray(addresses)) { - valueAsString = addresses.join(','); - addresses.forEach((ip) => memo.dataProviders.push(getDataProvider(field, id, ip))); - } - memo.dataProviders.push(getDataProvider(field, id, addresses)); - memo.values.push(valueAsString); - return memo; - } - } else if (PORT_NAMES.some((portName) => field === portName)) { - id = `port-default-draggable-${appendedUniqueId}`; - } else if (field === EVENT_DURATION_FIELD_NAME) { - id = `duration-default-draggable-${appendedUniqueId}`; - } else if (field === HOST_NAME_FIELD_NAME) { - id = `event-details-value-default-draggable-${appendedUniqueId}`; - } else if (fieldFormat === BYTES_FORMAT) { - id = `bytes-default-draggable-${appendedUniqueId}`; - } else if (field === SIGNAL_RULE_NAME_FIELD_NAME) { - id = `event-details-value-default-draggable-${appendedUniqueId}-${linkValue}`; - } else if (field === EVENT_MODULE_FIELD_NAME) { - id = `event-details-value-default-draggable-${appendedUniqueId}-${value}`; - } else if (field === SIGNAL_STATUS_FIELD_NAME) { - id = `alert-details-value-default-draggable-${appendedUniqueId}`; - } else if (field === AGENT_STATUS_FIELD_NAME) { - const valueToUse = typeof value === 'string' ? value : ''; - id = `event-details-value-default-draggable-${appendedUniqueId}`; - valueAsString = valueToUse; - } else if ( - [ - RULE_REFERENCE_FIELD_NAME, - REFERENCE_URL_FIELD_NAME, - EVENT_URL_FIELD_NAME, - INDICATOR_REFERENCE, - ].includes(field) - ) { - id = `event-details-value-default-draggable-${appendedUniqueId}-${value}`; - } else { - id = `event-details-value-default-draggable-${appendedUniqueId}`; - } - memo.values.push(valueAsString); - memo.dataProviders.push(getDataProvider(field, id, value)); - return memo; - }, - { values: [], dataProviders: [], filters } - ); - }, [ - contextId, - eventId, - field, - fieldFormat, - fieldFromBrowserField, - fieldType, - isObjectArray, - linkValue, - values, - ]); - return cellData; -}; diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/translations.ts b/x-pack/plugins/security_solution/public/common/components/event_details/translations.ts index 2362284b3f696..f991db91582db 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/translations.ts +++ b/x-pack/plugins/security_solution/public/common/components/event_details/translations.ts @@ -7,64 +7,6 @@ import { i18n } from '@kbn/i18n'; -export const TABLE = i18n.translate('xpack.securitySolution.eventDetails.table', { - defaultMessage: 'Table', -}); - -export const DESCRIPTION = i18n.translate('xpack.securitySolution.eventDetails.description', { - defaultMessage: 'Description', -}); - -export const AGENT_STATUS = i18n.translate('xpack.securitySolution.detections.alerts.agentStatus', { - defaultMessage: 'Agent status', -}); - -export const QUARANTINED_FILE_PATH = i18n.translate( - 'xpack.securitySolution.detections.alerts.quarantinedFilePath', - { - defaultMessage: 'Quarantined file path', - } -); - -export const RULE_TYPE = i18n.translate('xpack.securitySolution.detections.alerts.ruleType', { - defaultMessage: 'Rule type', -}); - -export const ACTIONS = i18n.translate('xpack.securitySolution.eventDetails.table.actions', { - defaultMessage: 'Actions', -}); - -export const ALERT_REASON = i18n.translate('xpack.securitySolution.eventDetails.alertReason', { - defaultMessage: 'Alert reason', -}); - -export const ENDPOINT_COMMANDS = Object.freeze({ - tried: (command: string) => - i18n.translate('xpack.securitySolution.eventDetails.responseActions.endpoint.tried', { - values: { command }, - defaultMessage: 'tried to execute {command} command', - }), - executed: (command: string) => - i18n.translate('xpack.securitySolution.eventDetails.responseActions.endpoint.executed', { - values: { command }, - defaultMessage: 'executed {command} command', - }), - pending: (command: string) => - i18n.translate('xpack.securitySolution.eventDetails.responseActions.endpoint.pending', { - values: { command }, - defaultMessage: 'is executing {command} command', - }), - failed: (command: string) => - i18n.translate('xpack.securitySolution.eventDetails.responseActions.endpoint.failed', { - values: { command }, - defaultMessage: 'failed to execute {command} command', - }), -}); - -export const SUMMARY_VIEW = i18n.translate('xpack.securitySolution.eventDetails.summaryView', { - defaultMessage: 'summary', -}); - export const ALERT_SUMMARY_CONVERSATION_ID = i18n.translate( 'xpack.securitySolution.alertSummaryView.alertSummaryViewConversationId', { diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/types.ts b/x-pack/plugins/security_solution/public/common/components/event_details/types.ts index 7db13725d9eb3..7aff42e2a0ebc 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/event_details/types.ts @@ -17,17 +17,6 @@ export interface FieldsData { isObjectArray: boolean; } -export interface EnrichedFieldInfo { - data: FieldsData | EventFieldsData; - eventId: string; - fieldFromBrowserField?: Partial; - scopeId: string; - values: string[] | null | undefined; - linkValue?: string; -} - -export type EnrichedFieldInfoWithValues = EnrichedFieldInfo & { values: string[] }; - export interface EventSummaryField { id: string; legacyId?: string; diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/use_action_cell_data_provider.ts b/x-pack/plugins/security_solution/public/common/components/event_details/use_action_cell_data_provider.ts new file mode 100644 index 0000000000000..ded9ced84b3ac --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/event_details/use_action_cell_data_provider.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { escapeDataProviderId } from '@kbn/securitysolution-t-grid'; + +import { getDisplayValue } from '../../../timelines/components/timeline/data_providers/helpers'; +import type { DataProvider, DataProvidersAnd, QueryOperator } from '../../../../common/types'; +import { IS_OPERATOR } from '../../../../common/types'; + +export const getDataProvider = ( + field: string, + id: string, + value: string | string[], + operator: QueryOperator = IS_OPERATOR, + excluded: boolean = false +): DataProvider => ({ + and: [], + enabled: true, + id: escapeDataProviderId(id), + name: field, + excluded, + kqlQuery: '', + queryMatch: { + field, + value, + operator, + displayValue: getDisplayValue(value), + }, +}); + +export const getDataProviderAnd = ( + field: string, + id: string, + value: string | string[], + operator: QueryOperator = IS_OPERATOR, + excluded: boolean = false +): DataProvidersAnd => { + const { and, ...dataProvider } = getDataProvider(field, id, value, operator, excluded); + return dataProvider; +}; diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx index ea81a232cff52..e251370c7e4d3 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx @@ -24,6 +24,7 @@ import { connect, useDispatch, useSelector } from 'react-redux'; import { ThemeContext } from 'styled-components'; import type { Filter } from '@kbn/es-query'; import type { + ColumnHeaderOptions, DeprecatedCellValueElementProps, DeprecatedRowRenderer, Direction, @@ -249,11 +250,12 @@ const StatefulEventsViewerComponent: React.FC dispatch(dataTableActions.upsertColumn({ column, id: tableId, index })), + (column: ColumnHeaderOptions, index: number) => + dispatch(dataTableActions.upsertColumn({ column, id: tableId, index })), [dispatch, tableId] ), removeColumn: useCallback( - (columnId) => dispatch(dataTableActions.removeColumn({ columnId, id: tableId })), + (columnId: string) => dispatch(dataTableActions.removeColumn({ columnId, id: tableId })), [dispatch, tableId] ), }); @@ -328,7 +330,8 @@ const StatefulEventsViewerComponent: React.FC dispatch(inputsActions.deleteOneQuery({ inputId: InputsModelId.global, id })), + ({ id }: { id: string }) => + dispatch(inputsActions.deleteOneQuery({ inputId: InputsModelId.global, id })), [dispatch] ); @@ -375,7 +378,7 @@ const StatefulEventsViewerComponent: React.FC { + (itemsChangedPerPage: number) => { dispatch( dataTableActions.updateItemsPerPage({ id: tableId, itemsPerPage: itemsChangedPerPage }) ); @@ -384,7 +387,7 @@ const StatefulEventsViewerComponent: React.FC { + (page: number) => { loadPage(page); }, [loadPage] diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/summary_view_select/index.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/summary_view_select/index.tsx index 88a2638976cf8..40d0d4e1a7c08 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/summary_view_select/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/summary_view_select/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import type { EuiSelectableOption } from '@elastic/eui'; +import type { EuiSelectableOption, EuiSelectableProps } from '@elastic/eui'; import { EuiButtonEmpty, EuiPopover, EuiSelectable, EuiTitle, EuiTextColor } from '@elastic/eui'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import { i18n } from '@kbn/i18n'; @@ -116,7 +116,9 @@ const SummaryViewSelectorComponent = ({ viewSelected, onViewChange }: SummaryVie [viewSelected] ); - const renderOption = useCallback((option) => { + const renderOption = useCallback< + NonNullable }>['renderOption']> + >((option) => { return ( <> diff --git a/x-pack/plugins/security_solution/public/common/components/hover_popover/hover_popover.tsx b/x-pack/plugins/security_solution/public/common/components/hover_popover/hover_popover.tsx index 827290565f287..28a72a1bb87c7 100644 --- a/x-pack/plugins/security_solution/public/common/components/hover_popover/hover_popover.tsx +++ b/x-pack/plugins/security_solution/public/common/components/hover_popover/hover_popover.tsx @@ -16,7 +16,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; */ const HOVER_INTENT_DELAY = 100; // ms -interface Props { +export interface HoverPopoverProps { hoverContent: React.ReactNode; anchorPosition?: PopoverAnchorPosition; } @@ -37,7 +37,7 @@ interface Props { * otherwise it will be difficult for keyboard-only and screen * reader users to navigate to and from your popover. */ -export const HoverPopover = React.memo>( +export const HoverPopover = React.memo>( ({ hoverContent, anchorPosition = 'downCenter', children }) => { const [isOpen, setIsOpen] = useState(hoverContent != null); const [showHoverContent, setShowHoverContent] = useState(false); diff --git a/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/card_step/index.tsx b/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/card_step/index.tsx index 2e6886af03afa..07a73681ec874 100644 --- a/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/card_step/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/card_step/index.tsx @@ -71,7 +71,7 @@ const CardStepComponent: React.FC<{ const isDone = finishedSteps.has(stepId); const toggleStep = useCallback( - (e) => { + (e: React.SyntheticEvent) => { e.preventDefault(); const newStatus = !isExpandedStep; diff --git a/x-pack/plugins/security_solution/public/common/components/links/helpers.tsx b/x-pack/plugins/security_solution/public/common/components/links/helpers.tsx index 9dd3accd15e32..5aed35ccb4b4c 100644 --- a/x-pack/plugins/security_solution/public/common/components/links/helpers.tsx +++ b/x-pack/plugins/security_solution/public/common/components/links/helpers.tsx @@ -82,7 +82,7 @@ export const PortContainer = styled.div` } `; -interface ReputationLinkOverflowProps { +export interface ReputationLinkOverflowProps { rowItems: ReputationLinkSetting[]; render?: (item: ReputationLinkSetting) => React.ReactNode; overflowIndexStart?: number; diff --git a/x-pack/plugins/security_solution/public/common/components/links/index.tsx b/x-pack/plugins/security_solution/public/common/components/links/index.tsx index 4f07d53023e9e..9d615d80be63f 100644 --- a/x-pack/plugins/security_solution/public/common/components/links/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/links/index.tsx @@ -31,7 +31,7 @@ import { isUrlInvalid } from '../../utils/validators'; import * as i18n from './translations'; import { SecurityPageName } from '../../../app/types'; import { getTabsOnUsersDetailsUrl, getUsersDetailsUrl } from '../link_to/redirect_to_users'; -import type { ReputationLinkSetting } from './helpers'; +import type { ReputationLinkSetting, ReputationLinkOverflowProps } from './helpers'; import { LinkAnchor, GenericLinkButton, @@ -72,7 +72,7 @@ const UserDetailsLinkComponent: React.FC<{ telemetry, } = useKibana().services; const goToUsersDetails = useCallback( - (ev) => { + (ev: SyntheticEvent) => { ev.preventDefault(); navigateToApp(APP_UI_ID, { deepLinkId: SecurityPageName.users, @@ -122,7 +122,7 @@ const UserDetailsLinkComponent: React.FC<{ export const UserDetailsLink = React.memo(UserDetailsLinkComponent); -const HostDetailsLinkComponent: React.FC<{ +export interface HostDetailsLinkProps { children?: React.ReactNode; /** `Component` is only used with `EuiDataGrid`; the grid keeps a reference to `Component` for show / hide functionality */ Component?: typeof EuiButtonEmpty | typeof EuiButtonIcon; @@ -131,7 +131,16 @@ const HostDetailsLinkComponent: React.FC<{ onClick?: (e: SyntheticEvent) => void; hostTab?: HostsTableType; title?: string; -}> = ({ children, Component, hostName, isButton, onClick: onClickParam, title, hostTab }) => { +} +const HostDetailsLinkComponent: React.FC = ({ + children, + Component, + hostName, + isButton, + onClick: onClickParam, + title, + hostTab, +}) => { const { formatUrl, search } = useFormatUrl(SecurityPageName.hosts); const { application: { navigateToApp }, @@ -141,7 +150,7 @@ const HostDetailsLinkComponent: React.FC<{ const encodedHostName = encodeURIComponent(hostName); const goToHostDetails = useCallback( - (ev) => { + (ev: SyntheticEvent) => { ev.preventDefault(); navigateToApp(APP_UI_ID, { deepLinkId: SecurityPageName.hosts, @@ -226,7 +235,7 @@ export const ExternalLink = React.memo<{ ExternalLink.displayName = 'ExternalLink'; -const NetworkDetailsLinkComponent: React.FC<{ +export interface NetworkDetailsLinkProps { children?: React.ReactNode; /** `Component` is only used with `EuiDataGrid`; the grid keeps a reference to `Component` for show / hide functionality */ Component?: typeof EuiButtonEmpty | typeof EuiButtonIcon; @@ -235,7 +244,17 @@ const NetworkDetailsLinkComponent: React.FC<{ isButton?: boolean; onClick?: (e: SyntheticEvent) => void | undefined; title?: string; -}> = ({ Component, children, ip, flowTarget = FlowTarget.source, isButton, onClick, title }) => { +} + +const NetworkDetailsLinkComponent: React.FC = ({ + Component, + children, + ip, + flowTarget = FlowTarget.source, + isButton, + onClick, + title, +}) => { const getSecuritySolutionLinkProps = useGetSecuritySolutionLinkProps(); const getLink = useCallback( @@ -310,7 +329,7 @@ const CaseDetailsLinkComponent: React.FC = ({ ); const goToCaseDetails = useCallback( - async (ev?) => { + async (ev?: SyntheticEvent) => { if (ev) ev.preventDefault(); return navigateToApp(APP_UI_ID, { deepLinkId: SecurityPageName.case, @@ -350,7 +369,7 @@ export const CreateCaseLink = React.memo<{ children: React.ReactNode }>(({ child const { formatUrl, search } = useFormatUrl(SecurityPageName.case); const { navigateToApp } = useKibana().services.application; const goToCreateCase = useCallback( - async (ev) => { + async (ev: SyntheticEvent) => { ev.preventDefault(); return navigateToApp(APP_UI_ID, { deepLinkId: SecurityPageName.case, @@ -508,7 +527,7 @@ const ReputationLinkComponent: React.FC<{ [ipReputationLinksSetting, domain, defaultNameMapping, allItemsLimit] ); - const renderCallback = useCallback( + const renderCallback: NonNullable = useCallback( (rowItem) => isReputationLink(rowItem) && ( { - const [markdownErrorMessages, setMarkdownErrorMessages] = useState([]); - const onParse = useCallback( + const [markdownErrorMessages, setMarkdownErrorMessages] = useState([]); + const onParse = useCallback>( (err, { messages }) => { setMarkdownErrorMessages(err ? [err] : messages); setIsMarkdownInvalid(err ? true : false); diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/index.test.tsx index 8ea10b1c54f8c..37d4e004edf54 100644 --- a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/index.test.tsx @@ -16,15 +16,15 @@ import { import { KibanaServices } from '../../../../lib/kibana'; import type { DefaultTimeRangeSetting } from '../../../../utils/default_date_settings'; import { plugin, renderer as Renderer } from '.'; -import type { InvestigateInTimelineButtonProps } from '../../../event_details/table/investigate_in_timeline_button'; +import type { InvestigateInTimelineButtonProps } from '../../../event_details/investigate_in_timeline_button'; import { useUpsellingMessage } from '../../../../hooks/use_upselling'; jest.mock('../../../../lib/kibana'); const mockGetServices = KibanaServices.get as jest.Mock; -jest.mock('../../../event_details/table/investigate_in_timeline_button', () => { +jest.mock('../../../event_details/investigate_in_timeline_button', () => { const originalModule = jest.requireActual( - '../../../event_details/table/investigate_in_timeline_button' + '../../../event_details/investigate_in_timeline_button' ); return { ...originalModule, diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/index.tsx b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/index.tsx index 791bace753ff8..0496033b0ab45 100644 --- a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/index.tsx @@ -9,7 +9,7 @@ import { pickBy, isEmpty } from 'lodash'; import type { Plugin } from 'unified'; import moment from 'moment'; import React, { useContext, useMemo, useCallback, useState } from 'react'; -import type { RemarkTokenizer } from '@elastic/eui'; +import type { RemarkTokenizer, EuiSelectProps } from '@elastic/eui'; import { EuiLoadingSpinner, EuiIcon, @@ -43,7 +43,7 @@ import { useKibana } from '../../../../lib/kibana'; import { useInsightQuery } from './use_insight_query'; import { useInsightDataProviders, type Provider } from './use_insight_data_providers'; import { BasicAlertDataContext } from '../../../../../flyout/document_details/left/components/investigation_guide_view'; -import { InvestigateInTimelineButton } from '../../../event_details/table/investigate_in_timeline_button'; +import { InvestigateInTimelineButton } from '../../../event_details/investigate_in_timeline_button'; import { getTimeRangeSettings, parseDateWithDefault, @@ -382,7 +382,7 @@ const InsightEditorComponent = ({ const onChange = useCallback((filters: Filter[]) => { setProviders(filtersToInsightProviders(filters)); }, []); - const selectOnChange = useCallback( + const selectOnChange = useCallback>( (event) => { relativeTimerangeController.field.onChange(event.target.value); }, diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/use_insight_data_providers.test.ts b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/use_insight_data_providers.test.ts index 9ab25b00eabd3..4d1807b91b718 100644 --- a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/use_insight_data_providers.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/use_insight_data_providers.test.ts @@ -11,7 +11,7 @@ import { useInsightDataProviders, type UseInsightDataProvidersResult, } from './use_insight_data_providers'; -import { mockAlertDetailsData } from '../../../event_details/__mocks__'; +import { mockAlertDetailsData } from '../../../event_details/mocks'; const mockAlertDetailsDataWithIsObject = mockAlertDetailsData.map((detail) => { return { diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/plugin.tsx b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/plugin.tsx index 6cc54184db60c..6a37280f9ef23 100644 --- a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/plugin.tsx +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/plugin.tsx @@ -25,6 +25,12 @@ import { LabelField } from './label_field'; import { OsqueryNotAvailablePrompt } from './not_available_prompt'; import { useKibana } from '../../../../lib/kibana'; +interface FormData { + label: string; + query: string; + ecs_mapping: Record; +} + const OsqueryEditorComponent = ({ node, onSave, @@ -43,11 +49,7 @@ const OsqueryEditorComponent = ({ capabilities: { osquery: osqueryPermissions }, }, } = useKibana().services; - const formMethods = useForm<{ - label: string; - query: string; - ecs_mapping: Record; - }>({ + const formMethods = useForm({ defaultValues: { label: node?.configuration?.label, query: node?.configuration?.query, @@ -56,7 +58,7 @@ const OsqueryEditorComponent = ({ }); const onSubmit = useCallback( - (data) => { + (data: FormData) => { onSave( `!{osquery${JSON.stringify( pickBy( diff --git a/x-pack/plugins/security_solution/public/common/components/ml/tables/select_interval.tsx b/x-pack/plugins/security_solution/public/common/components/ml/tables/select_interval.tsx index 717c0d0a48409..e273487d31173 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/tables/select_interval.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml/tables/select_interval.tsx @@ -5,6 +5,7 @@ * 2.0. */ import React, { useCallback } from 'react'; +import type { EuiSelectProps } from '@elastic/eui'; import { EuiSelect, EuiIcon, EuiToolTip } from '@elastic/eui'; import * as i18n from './translations'; @@ -31,7 +32,7 @@ export const SelectInterval: React.FC<{ interval: string; onChange: (interval: string) => void; }> = ({ interval, onChange }) => { - const onChangeCb = useCallback( + const onChangeCb = useCallback>( (e) => { onChange(e.target.value); }, diff --git a/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_security_jobs.ts b/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_security_jobs.ts index e7a7571c6e516..b1064431f4266 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_security_jobs.ts +++ b/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_security_jobs.ts @@ -47,7 +47,7 @@ export const useSecurityJobs = (): UseSecurityJobsReturn => { const isMlEnabled = isMlAdmin && isLicensed; const onError = useCallback( - (error) => { + (error: unknown) => { addError(error, { title: i18n.SIEM_JOB_FETCH_FAILURE }); }, [addError] diff --git a/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/job_switch.tsx b/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/job_switch.tsx index 45fb359c0e121..46fbd4c5f70e6 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/job_switch.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/job_switch.tsx @@ -7,6 +7,7 @@ import styled from 'styled-components'; import React, { useState, useCallback } from 'react'; +import type { EuiSwitchProps } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner, EuiSwitch } from '@elastic/eui'; import { isJobLoading, @@ -36,7 +37,7 @@ export const JobSwitchComponent = ({ onJobStateChange, }: JobSwitchProps) => { const [isLoading, setIsLoading] = useState(false); - const handleChange = useCallback( + const handleChange: EuiSwitchProps['onChange'] = useCallback( async (e) => { setIsLoading(true); await onJobStateChange(job, job.latestTimestampMs || 0, e.target.checked); diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/tab_navigation.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/tab_navigation.tsx index 0f38ff32cfefa..c37fed0c02818 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/tab_navigation.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/tab_navigation.tsx @@ -29,7 +29,7 @@ const TabNavigationItemComponent = ({ const { getAppUrl, navigateTo } = useNavigation(); const handleClick = useCallback( - (ev) => { + (ev: React.SyntheticEvent) => { ev.preventDefault(); navigateTo({ path: hrefWithSearch, restoreScroll: true }); track(METRIC_TYPE.CLICK, `${TELEMETRY_EVENT.TAB_CLICKED}${id}`); diff --git a/x-pack/plugins/security_solution/public/common/components/response_actions/endpoint_action_results.tsx b/x-pack/plugins/security_solution/public/common/components/response_actions/endpoint_action_results.tsx index 7444a53ee441f..f0d21c00287fd 100644 --- a/x-pack/plugins/security_solution/public/common/components/response_actions/endpoint_action_results.tsx +++ b/x-pack/plugins/security_solution/public/common/components/response_actions/endpoint_action_results.tsx @@ -15,7 +15,7 @@ import type { import { useUserPrivileges } from '../user_privileges'; import { useGetAutomatedActionResponseList } from '../../../management/hooks/response_actions/use_get_automated_action_list'; import { ActionsLogExpandedTray } from '../../../management/components/endpoint_response_actions_list/components/action_log_expanded_tray'; -import { ENDPOINT_COMMANDS } from '../event_details/translations'; +import { ENDPOINT_COMMANDS } from './translations'; import { ResponseActionsEmptyPrompt } from './response_actions_empty_prompt'; interface EndpointResponseActionResultsProps { diff --git a/x-pack/plugins/security_solution/public/common/components/response_actions/translations.ts b/x-pack/plugins/security_solution/public/common/components/response_actions/translations.ts index c71d344539bb6..2c59cfef1bfd8 100644 --- a/x-pack/plugins/security_solution/public/common/components/response_actions/translations.ts +++ b/x-pack/plugins/security_solution/public/common/components/response_actions/translations.ts @@ -13,3 +13,26 @@ export const LOAD_CONNECTORS_ERROR_MESSAGE = i18n.translate( defaultMessage: 'Error loading connectors. Please check your configuration and try again.', } ); + +export const ENDPOINT_COMMANDS = Object.freeze({ + tried: (command: string) => + i18n.translate('xpack.securitySolution.eventDetails.responseActions.endpoint.tried', { + values: { command }, + defaultMessage: 'tried to execute {command} command', + }), + executed: (command: string) => + i18n.translate('xpack.securitySolution.eventDetails.responseActions.endpoint.executed', { + values: { command }, + defaultMessage: 'executed {command} command', + }), + pending: (command: string) => + i18n.translate('xpack.securitySolution.eventDetails.responseActions.endpoint.pending', { + values: { command }, + defaultMessage: 'is executing {command} command', + }), + failed: (command: string) => + i18n.translate('xpack.securitySolution.eventDetails.responseActions.endpoint.failed', { + values: { command }, + defaultMessage: 'failed to execute {command} command', + }), +}); diff --git a/x-pack/plugins/security_solution/public/common/components/rule_name/index.tsx b/x-pack/plugins/security_solution/public/common/components/rule_name/index.tsx index 07592457de41c..ebd0e0842dd12 100644 --- a/x-pack/plugins/security_solution/public/common/components/rule_name/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/rule_name/index.tsx @@ -32,7 +32,7 @@ const RuleNameComponents = ({ name, id, appId }: RuleNameProps) => { [getUrlForApp, id, appId] ); const goToRuleDetails = useCallback( - (ev) => { + (ev: React.SyntheticEvent) => { ev.preventDefault(); navigateToApp(appId, { deepLinkId: 'rules', diff --git a/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx b/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx index af4c0aa7b0c19..792074b39cfeb 100644 --- a/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx @@ -305,7 +305,7 @@ export const SearchBarComponent = memo( }, [sourcererDataView, fieldFormats]); const onTimeRangeChange = useCallback( - ({ query, dateRange }) => { + ({ dateRange }: { dateRange: TimeRange }) => { const isQuickSelection = dateRange.from.includes('now') || dateRange.to.includes('now'); updateSearch({ end: dateRange.to, @@ -313,7 +313,6 @@ export const SearchBarComponent = memo( id, isInvalid: false, isQuickSelection, - query, setTablesActivePageToZero, start: dateRange.from, updateTime: true, diff --git a/x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/alert_bulk_assignees.tsx b/x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/alert_bulk_assignees.tsx index e152a5f96d61e..f4838a414b1c8 100644 --- a/x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/alert_bulk_assignees.tsx +++ b/x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/alert_bulk_assignees.tsx @@ -12,9 +12,10 @@ import type { TimelineItem } from '@kbn/timelines-plugin/common'; import { ALERT_WORKFLOW_ASSIGNEE_IDS } from '@kbn/rule-data-utils'; import type { SetAlertAssigneesFunc } from './use_set_alert_assignees'; +import type { AssigneesApplyPanelProps } from '../../assignees/assignees_apply_panel'; import { AssigneesApplyPanel } from '../../assignees/assignees_apply_panel'; -interface BulkAlertAssigneesPanelComponentProps { +export interface BulkAlertAssigneesPanelComponentProps { alertItems: TimelineItem[]; setIsLoading: (isLoading: boolean) => void; refresh?: () => void; @@ -47,7 +48,7 @@ const BulkAlertAssigneesPanelComponent: React.FC( async (assignees) => { closePopoverMenu(); if (onSubmit) { diff --git a/x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/alert_bulk_tags.tsx b/x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/alert_bulk_tags.tsx index 67ba6562abc23..8c3b48d64b63e 100644 --- a/x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/alert_bulk_tags.tsx +++ b/x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/alert_bulk_tags.tsx @@ -18,7 +18,7 @@ import { createInitialTagsState } from './helpers'; import { createAlertTagsReducer, initialState } from './reducer'; import type { SetAlertTagsFunc } from './use_set_alert_tags'; -interface BulkAlertTagsPanelComponentProps { +export interface BulkAlertTagsPanelComponentProps { alertItems: TimelineItem[]; refetchQuery?: () => void; setIsLoading: (isLoading: boolean) => void; diff --git a/x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/use_bulk_alert_assignees_items.tsx b/x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/use_bulk_alert_assignees_items.tsx index 4c25665afa5ca..a91fc5ad8aede 100644 --- a/x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/use_bulk_alert_assignees_items.tsx +++ b/x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/use_bulk_alert_assignees_items.tsx @@ -19,6 +19,7 @@ import { isEmpty } from 'lodash/fp'; import { useLicense } from '../../../hooks/use_license'; import { useAlertsPrivileges } from '../../../../detections/containers/detection_engine/alerts/use_alerts_privileges'; import { ASSIGNEES_PANEL_WIDTH } from '../../assignees/constants'; +import type { BulkAlertAssigneesPanelComponentProps } from './alert_bulk_assignees'; import { BulkAlertAssigneesPanel } from './alert_bulk_assignees'; import * as i18n from './translations'; import { useSetAlertAssignees } from './use_set_alert_assignees'; @@ -45,7 +46,9 @@ export const useBulkAlertAssigneesItems = ({ const { hasIndexWrite } = useAlertsPrivileges(); const setAlertAssignees = useSetAlertAssignees(); - const handleOnAlertAssigneesSubmit = useCallback( + const handleOnAlertAssigneesSubmit = useCallback< + BulkAlertAssigneesPanelComponentProps['onSubmit'] + >( async (assignees, ids, onSuccess, setIsLoading) => { if (setAlertAssignees) { await setAlertAssignees(assignees, ids, onSuccess, setIsLoading); diff --git a/x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/use_bulk_alert_tags_items.tsx b/x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/use_bulk_alert_tags_items.tsx index c155d39e2a3a5..d83d2c7dad0dd 100644 --- a/x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/use_bulk_alert_tags_items.tsx +++ b/x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/use_bulk_alert_tags_items.tsx @@ -9,6 +9,7 @@ import { EuiFlexGroup, EuiIconTip, EuiFlexItem } from '@elastic/eui'; import type { RenderContentPanelProps } from '@kbn/triggers-actions-ui-plugin/public/types'; import React, { useCallback, useMemo } from 'react'; import { useAlertsPrivileges } from '../../../../detections/containers/detection_engine/alerts/use_alerts_privileges'; +import type { BulkAlertTagsPanelComponentProps } from './alert_bulk_tags'; import { BulkAlertTagsPanel } from './alert_bulk_tags'; import * as i18n from './translations'; import { useSetAlertTags } from './use_set_alert_tags'; @@ -27,7 +28,7 @@ export interface UseBulkAlertTagsPanel { export const useBulkAlertTagsItems = ({ refetch }: UseBulkAlertTagsItemsProps) => { const { hasIndexWrite } = useAlertsPrivileges(); const setAlertTags = useSetAlertTags(); - const handleOnAlertTagsSubmit = useCallback( + const handleOnAlertTagsSubmit = useCallback( async (tags, ids, onSuccess, setIsLoading) => { if (setAlertTags) { await setAlertTags(tags, ids, onSuccess, setIsLoading); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_embeddable.tsx b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_embeddable.tsx index debeca81783d6..a72675d381404 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_embeddable.tsx +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_embeddable.tsx @@ -19,6 +19,7 @@ import type { TypedLensByValueInput, XYState, } from '@kbn/lens-plugin/public'; +import type { LensBaseEmbeddableInput } from '@kbn/lens-plugin/public/embeddable'; import { setAbsoluteRangeDatePicker } from '../../store/inputs/actions'; import { useKibana } from '../../lib/kibana'; import { useLensAttributes } from './use_lens_attributes'; @@ -159,7 +160,7 @@ const LensEmbeddableComponent: React.FC = ({ }); const updateDateRange = useCallback( - ({ range }) => { + ({ range }: { range: Array }) => { const [min, max] = range; dispatch( setAbsoluteRangeDatePicker({ @@ -172,7 +173,7 @@ const LensEmbeddableComponent: React.FC = ({ [dispatch, inputsModelId] ); - const onFilterCallback = useCallback( + const onFilterCallback = useCallback['onFilter']>( (event) => { if (disableOnClickFilter) { event.preventDefault(); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/types.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/types.ts index 6d285e0407292..f6a90ebfd479b 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/types.ts @@ -11,6 +11,7 @@ import type { FormBasedPersistedState, TypedLensByValueInput, } from '@kbn/lens-plugin/public'; +import type { IKibanaSearchResponse } from '@kbn/search-types'; import type { DataViewSpec } from '@kbn/data-views-plugin/common'; import type { Action } from '@kbn/ui-actions-plugin/public'; import type { Filter, Query } from '@kbn/es-query'; @@ -145,7 +146,7 @@ export interface RequestStatistic { } export interface Response { - json?: { rawResponse?: object }; + json?: IKibanaSearchResponse; time?: number; } diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_embeddable_inspect.tsx b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_embeddable_inspect.tsx index ca80999a81062..ee577d4a310d9 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_embeddable_inspect.tsx +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_embeddable_inspect.tsx @@ -5,18 +5,19 @@ * 2.0. */ +import type { LensBaseEmbeddableInput } from '@kbn/lens-plugin/public/embeddable'; import { useCallback } from 'react'; -import type { OnEmbeddableLoaded } from './types'; +import type { OnEmbeddableLoaded, Request } from './types'; import { getRequestsAndResponses } from './utils'; export const useEmbeddableInspect = (onEmbeddableLoad?: OnEmbeddableLoaded) => { - const setInspectData = useCallback( + const setInspectData = useCallback>( (isLoading, adapters) => { if (!adapters) { return; } - const data = getRequestsAndResponses(adapters?.requests?.getRequests()); + const data = getRequestsAndResponses(adapters?.requests?.getRequests() as Request[]); onEmbeddableLoad?.({ requests: data.requests, diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_redirect_to_dashboard_from_lens.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_redirect_to_dashboard_from_lens.ts index 1aebf72217c5b..3aee19bf6edd2 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_redirect_to_dashboard_from_lens.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_redirect_to_dashboard_from_lens.ts @@ -5,6 +5,7 @@ * 2.0. */ +import type { RedirectToProps } from '@kbn/dashboard-plugin/public/dashboard_container/types'; import { useMemo, useCallback } from 'react'; import { SecurityPageName } from '../../../../common'; import { useNavigateTo } from '../../lib/kibana'; @@ -39,11 +40,11 @@ export const useRedirectToDashboardFromLens = ({ ); const redirectTo = useCallback( - (props) => { - if (props.destination === 'listing') { + (props?: RedirectToProps) => { + if (props?.destination === 'listing') { navigateTo({ url: dashboardListingUrl }); } - if (props.destination === 'dashboard') { + if (props?.destination === 'dashboard') { navigateTo({ url: getEditOrCreateDashboardUrl(props.id) }); } }, diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_save_to_library.tsx b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_save_to_library.tsx index 8940853444d1b..c7a44842fc513 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_save_to_library.tsx +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_save_to_library.tsx @@ -38,6 +38,8 @@ export const useSaveToLibrary = ({ getOriginatingPath={(dashboardId) => `${SecurityPageName.dashboards}/${getEditOrCreateDashboardPath(dashboardId)}` } + // Type 'string' is not assignable to type 'RedirectToProps | undefined'. + // @ts-expect-error redirectTo={redirectTo} />, startServices diff --git a/x-pack/plugins/security_solution/public/common/containers/source/index.tsx b/x-pack/plugins/security_solution/public/common/containers/source/index.tsx index f305088ef3d32..a121919b412e5 100644 --- a/x-pack/plugins/security_solution/public/common/containers/source/index.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/source/index.tsx @@ -105,14 +105,17 @@ export const useFetchIndex = ( const { addError } = useAppToasts(); const indexFieldsSearch = useCallback( - (iNames) => { + (iNames: string[]) => { const asyncSearch = async () => { try { setState({ ...state, loading: true }); abortCtrl.current = new AbortController(); const dv = await data.dataViews.create({ title: iNames.join(','), allowNoIndex: true }); const dataView = dv.toSpec(); - const { browserFields } = getDataViewStateFromIndexFields(iNames, dataView.fields); + const { browserFields } = getDataViewStateFromIndexFields( + iNames.join(','), + dataView.fields + ); previousIndexesName.current = dv.getIndexPattern().split(','); diff --git a/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_navigate_by_router_event_handler.ts b/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_navigate_by_router_event_handler.ts index b140252e13a68..2c0988e29ed85 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_navigate_by_router_event_handler.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_navigate_by_router_event_handler.ts @@ -27,7 +27,7 @@ export const useNavigateByRouterEventHandler = ( ): EventHandlerCallback => { const history = useHistory(); return useCallback( - (ev) => { + (ev: React.MouseEvent) => { try { if (onClick) { onClick(ev); diff --git a/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_navigate_to_app_event_handler.ts b/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_navigate_to_app_event_handler.ts index a4b998d3bca98..1d284d21e9144 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_navigate_to_app_event_handler.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_navigate_to_app_event_handler.ts @@ -41,7 +41,7 @@ export const useNavigateToAppEventHandler = ( const { path, state, onClick, deepLinkId, openInNewTab } = options || {}; return useCallback( - (ev) => { + (ev: React.MouseEvent) => { try { if (onClick) { onClick(ev); diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_add_integrations_url.ts b/x-pack/plugins/security_solution/public/common/hooks/use_add_integrations_url.ts index 07a63013b0687..e80c1e871d49a 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_add_integrations_url.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/use_add_integrations_url.ts @@ -27,7 +27,7 @@ export const useAddIntegrationsUrl = () => { const href = useMemo(() => prepend(integrationsUrl), [prepend, integrationsUrl]); const onClick = useCallback( - (e) => { + (e: React.SyntheticEvent) => { e.preventDefault(); navigateTo({ url: href }); }, diff --git a/x-pack/plugins/security_solution/public/common/utils/use_set_field_value_cb.ts b/x-pack/plugins/security_solution/public/common/utils/use_set_field_value_cb.ts index 8f57dd78d8a53..c067e1747b4ff 100644 --- a/x-pack/plugins/security_solution/public/common/utils/use_set_field_value_cb.ts +++ b/x-pack/plugins/security_solution/public/common/utils/use_set_field_value_cb.ts @@ -18,7 +18,7 @@ export const useSetFieldValueWithCallback = ({ setFieldValue: FormHook['setFieldValue']; }) => { const isWaitingRef = useRef(false); - const valueRef = useRef(); + const valueRef = useRef(); const [callback, setCallback] = useState<() => void>(() => null); useEffect(() => { @@ -30,7 +30,7 @@ export const useSetFieldValueWithCallback = ({ }, [value, callback]); return useCallback( - (v, cb) => { + (v: unknown, cb: () => void) => { setFieldValue(field, v); setCallback(() => cb); diff --git a/x-pack/plugins/security_solution/public/dashboards/components/dashboard_renderer.tsx b/x-pack/plugins/security_solution/public/dashboards/components/dashboard_renderer.tsx index 9fc53f1a4175b..83f48d76246e5 100644 --- a/x-pack/plugins/security_solution/public/dashboards/components/dashboard_renderer.tsx +++ b/x-pack/plugins/security_solution/public/dashboards/components/dashboard_renderer.tsx @@ -8,13 +8,18 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import type { DashboardContainerInput } from '@kbn/dashboard-plugin/common'; -import type { DashboardAPI, DashboardCreationOptions } from '@kbn/dashboard-plugin/public'; +import type { + DashboardAPI, + DashboardCreationOptions, + DashboardLocatorParams, +} from '@kbn/dashboard-plugin/public'; import { DashboardRenderer as DashboardContainerRenderer } from '@kbn/dashboard-plugin/public'; import { ViewMode } from '@kbn/embeddable-plugin/public'; import type { Filter, Query } from '@kbn/es-query'; import { useDispatch } from 'react-redux'; import { BehaviorSubject } from 'rxjs'; +import type { DashboardRendererProps } from '@kbn/dashboard-plugin/public/dashboard_container/external_api/dashboard_renderer'; import { APP_UI_ID } from '../../../common'; import { DASHBOARDS_PATH, SecurityPageName } from '../../../common/constants'; import { useGetSecuritySolutionUrl } from '../../common/components/link_to'; @@ -64,7 +69,7 @@ const DashboardRendererComponent = ({ const isCreateDashboard = !savedObjectId; const getSecuritySolutionDashboardUrl = useCallback( - ({ dashboardId }) => { + ({ dashboardId }: DashboardLocatorParams) => { return getSecuritySolutionUrl({ deepLinkId: SecurityPageName.dashboards, path: dashboardId, @@ -73,7 +78,7 @@ const DashboardRendererComponent = ({ [getSecuritySolutionUrl] ); - const goToDashboard = useCallback( + const goToDashboard = useCallback['navigate']>( /** * Note: Due to the query bar being separate from the portable dashboard, the "Use filters and query from origin * dashboard" and "Use date range from origin dashboard" Link embeddable settings do not make sense in this context. diff --git a/x-pack/plugins/security_solution/public/dashboards/components/dashboard_tool_bar.tsx b/x-pack/plugins/security_solution/public/dashboards/components/dashboard_tool_bar.tsx index eb74f7c563500..3a5e3d43eae63 100644 --- a/x-pack/plugins/security_solution/public/dashboards/components/dashboard_tool_bar.tsx +++ b/x-pack/plugins/security_solution/public/dashboards/components/dashboard_tool_bar.tsx @@ -12,6 +12,7 @@ import { ViewMode } from '@kbn/embeddable-plugin/public'; import type { ChromeBreadcrumb } from '@kbn/core/public'; import type { DashboardCapabilities } from '@kbn/dashboard-plugin/common'; +import type { RedirectToProps } from '@kbn/dashboard-plugin/public/dashboard_container/types'; import { SecurityPageName } from '../../../common'; import { useCapabilities, useKibana, useNavigation } from '../../common/lib/kibana'; import { APP_NAME } from '../../../common/constants'; @@ -30,7 +31,7 @@ const DashboardToolBarComponent = ({ const { navigateTo, getAppUrl } = useNavigation(); const redirectTo = useCallback( - ({ destination, id }) => { + ({ destination, id }: RedirectToProps & { id?: string }) => { if (destination === 'listing') { navigateTo({ deepLinkId: SecurityPageName.dashboards }); } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/ml_jobs_description/admin/ml_admin_job_description.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/ml_jobs_description/admin/ml_admin_job_description.tsx index 7f1236aef08cd..af30519a33777 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/ml_jobs_description/admin/ml_admin_job_description.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/ml_jobs_description/admin/ml_admin_job_description.tsx @@ -10,6 +10,7 @@ import React, { useCallback, useMemo, memo } from 'react'; import { useEnableDataFeed } from '../../../../../common/components/ml_popover/hooks/use_enable_data_feed'; import type { SecurityJob } from '../../../../../common/components/ml_popover/types'; +import type { JobSwitchProps } from '../../../../../common/components/ml_popover/jobs_table/job_switch'; import { JobSwitch } from '../../../../../common/components/ml_popover/jobs_table/job_switch'; import { MlJobItem } from '../ml_job_item'; @@ -31,8 +32,8 @@ const MlAdminJobDescriptionComponent: FC = ({ isLoading: isLoadingEnableDataFeed, } = useEnableDataFeed(); - const handleJobStateChange = useCallback( - async (_, latestTimestampMs: number, enable: boolean) => { + const handleJobStateChange = useCallback( + async (_, latestTimestampMs, enable) => { if (enable) { await enableDatafeed(job, latestTimestampMs); } else { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/schedule_item_form/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/schedule_item_form/index.tsx index 4dbbf1f3a9206..997930926f26f 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/schedule_item_form/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/schedule_item_form/index.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import type { EuiSelectProps, EuiFieldNumberProps } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, @@ -106,7 +107,7 @@ export const ScheduleItem = ({ const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(field); const { value, setValue } = field; - const onChangeTimeType = useCallback( + const onChangeTimeType = useCallback>( (e) => { setTimeType(e.target.value); setValue(`${timeVal}${e.target.value}`); @@ -114,7 +115,7 @@ export const ScheduleItem = ({ [setValue, timeVal] ); - const onChangeTimeVal = useCallback( + const onChangeTimeVal = useCallback>( (e) => { const sanitizedValue = getNumberFromUserInput(e.target.value, minimumValue); setTimeVal(sanitizedValue); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/eql_query_bar/footer.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/eql_query_bar/footer.tsx index 7f7a6ab21a385..fd2bc98a048b0 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/eql_query_bar/footer.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/eql_query_bar/footer.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import type { EuiComboBoxOptionOption } from '@elastic/eui'; +import type { EuiComboBoxOptionOption, EuiFieldNumberProps } from '@elastic/eui'; import { EuiButtonIcon, EuiComboBox, @@ -78,7 +78,7 @@ export const EqlQueryBarFooter: FC = ({ onOptionsChange, }) => { const [openEqlSettings, setIsOpenEqlSettings] = useState(false); - const [localSize, setLocalSize] = useState(optionsSelected?.size ?? 100); + const [localSize, setLocalSize] = useState(optionsSelected?.size ?? 100); const debounceSize = useRef(); const openEqlSettingsHandler = useCallback(() => { @@ -124,10 +124,10 @@ export const EqlQueryBarFooter: FC = ({ }, [onOptionsChange] ); - const handleSizeField = useCallback( + const handleSizeField = useCallback>( (evt) => { if (onOptionsChange) { - setLocalSize(evt?.target?.value); + setLocalSize(evt?.target?.valueAsNumber); if (debounceSize.current?.cancel) { debounceSize.current?.cancel(); } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.tsx index 1ef86c1cab1ed..cc4d968d1b525 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.tsx @@ -33,6 +33,7 @@ import type { SavedQuery } from '@kbn/data-plugin/public'; import type { DataViewBase } from '@kbn/es-query'; import { FormattedMessage } from '@kbn/i18n-react'; import { useSetFieldValueWithCallback } from '../../../../common/utils/use_set_field_value_cb'; +import type { SetRuleQuery } from '../../../../detections/containers/detection_engine/rules/use_rule_from_timeline'; import { useRuleFromTimeline } from '../../../../detections/containers/detection_engine/rules/use_rule_from_timeline'; import { isMlRule } from '../../../../../common/machine_learning/helpers'; import type { EqlOptionsSelected, FieldsEqlOptions } from '../../../../../common/search_strategy'; @@ -65,7 +66,7 @@ import { useFormData, UseMultiFields, } from '../../../../shared_imports'; -import type { FormHook } from '../../../../shared_imports'; +import type { FormHook, FieldHook } from '../../../../shared_imports'; import { schema } from './schema'; import { getTermsAggregationFields } from './utils'; import { useExperimentalFeatureFieldsTransform } from './use_experimental_feature_fields_transform'; @@ -161,6 +162,14 @@ const IntendedRuleTypeEuiFormRow = styled(RuleTypeEuiFormRow)` ${({ theme }) => `padding-left: ${theme.eui.euiSizeXL};`} `; +/* eslint-disable react/no-unused-prop-types */ +interface GroupByChildrenProps { + groupByRadioSelection: FieldHook; + groupByDurationUnit: FieldHook; + groupByDurationValue: FieldHook; +} +/* eslint-enable react/no-unused-prop-types */ + // eslint-disable-next-line complexity const StepDefineRuleComponent: FC = ({ dataSourceType, @@ -225,7 +234,7 @@ const StepDefineRuleComponent: FC = ({ setFieldValue, }); - const handleSetRuleFromTimeline = useCallback( + const handleSetRuleFromTimeline = useCallback( ({ index: timelineIndex, queryBar: timelineQueryBar, eqlOptions }) => { const setQuery = () => { setFieldValue('index', timelineIndex); @@ -426,7 +435,12 @@ const StepDefineRuleComponent: FC = ({ }, []); const ThresholdInputChildren = useCallback( - ({ thresholdField, thresholdValue, thresholdCardinalityField, thresholdCardinalityValue }) => ( + ({ + thresholdField, + thresholdValue, + thresholdCardinalityField, + thresholdCardinalityValue, + }: Record) => ( = ({ ); const ThreatMatchInputChildren = useCallback( - ({ threatMapping }) => ( + ({ threatMapping }: Record) => ( = ({ const isMissingFieldsDisabled = areSuppressionFieldsDisabled || !areSuppressionFieldsSelected; const GroupByChildren = useCallback( - ({ groupByRadioSelection, groupByDurationUnit, groupByDurationValue }) => ( + ({ + groupByRadioSelection, + groupByDurationUnit, + groupByDurationValue, + }: GroupByChildrenProps) => ( = ({ ); const AlertSuppressionMissingFields = useCallback( - ({ suppressionMissingFields }) => ( + ({ suppressionMissingFields }: Record>) => ( { const { setValue } = props.field; const onChange = useCallback( - (e) => { + (e: React.ChangeEvent) => { const throttle = e.target.value; setValue(throttle); }, diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx index 5e6ed40d4d282..deb58fbed49a3 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx @@ -455,7 +455,7 @@ const EditRulePageComponent: FC<{ rule: RuleResponse }> = ({ rule }) => { }; const goToDetailsRule = useCallback( - (ev) => { + (ev: React.SyntheticEvent) => { ev.preventDefault(); navigateToApp(APP_UI_ID, { deepLinkId: SecurityPageName.rules, diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/search_bar.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/search_bar.tsx index 36dac931265c2..5bcfc5b0784d0 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/search_bar.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/search_bar.tsx @@ -6,6 +6,7 @@ */ import React, { useCallback, useMemo } from 'react'; +import type { EuiSearchBarProps } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiButton, EuiSearchBar } from '@elastic/eui'; import * as i18n from './translations'; @@ -61,8 +62,8 @@ const ExceptionsViewerSearchBarComponent = ({ onSearch, onAddExceptionClick, }: ExceptionsViewerSearchBarProps): JSX.Element => { - const handleOnSearch = useCallback( - ({ queryText }): void => { + const handleOnSearch = useCallback>( + ({ queryText }) => { onSearch({ search: queryText }); }, [onSearch] diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_lists_table/link_list_switch/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_lists_table/link_list_switch/index.tsx index 486f0c7a5bf4c..cb87fea8cd253 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_lists_table/link_list_switch/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_lists_table/link_list_switch/index.tsx @@ -5,6 +5,7 @@ * 2.0. */ import React, { memo, useCallback, useMemo } from 'react'; +import type { EuiSwitchProps } from '@elastic/eui'; import { EuiFlexItem, EuiSwitch } from '@elastic/eui'; import type { ExceptionListRuleReferencesSchema } from '../../../../../../../common/api/detection_engine/rule_exceptions'; @@ -26,7 +27,7 @@ export const LinkListSwitch = memo( () => Boolean(linkedList.find((l) => l.id === list.id)), [linkedList, list.id] ); - const onLinkOrUnlinkList = useCallback( + const onLinkOrUnlinkList = useCallback( ({ target: { checked } }) => { const newLinkedLists = !checked ? linkedList?.filter((item) => item.id !== list.id) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/link_rule_switch/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/link_rule_switch/index.tsx index 080a59a8082f9..25fcf6f942c67 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/link_rule_switch/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/link_rule_switch/index.tsx @@ -5,6 +5,7 @@ * 2.0. */ import React, { memo, useCallback, useMemo } from 'react'; +import type { EuiSwitchProps } from '@elastic/eui'; import { EuiFlexItem, EuiSwitch } from '@elastic/eui'; import type { RuleResponse } from '../../../../../../../common/api/detection_engine'; @@ -22,7 +23,7 @@ export const LinkRuleSwitch = memo( () => Boolean(linkedRules.find((r) => r.id === rule.id)), [linkedRules, rule.id] ); - const onLinkOrUnlinkRule = useCallback( + const onLinkOrUnlinkRule = useCallback( ({ target: { checked } }) => { const newLinkedRules = !checked ? linkedRules?.filter((item) => item.id !== rule.id) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/add_prebuilt_rules_table/add_prebuilt_rules_table_filters.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/add_prebuilt_rules_table/add_prebuilt_rules_table_filters.tsx index 913dbd5a0fbc1..5640f64cd7a0b 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/add_prebuilt_rules_table/add_prebuilt_rules_table_filters.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/add_prebuilt_rules_table/add_prebuilt_rules_table_filters.tsx @@ -31,7 +31,7 @@ const AddPrebuiltRulesTableFiltersComponent = () => { const { tags: selectedTags } = filterOptions; const handleOnSearch = useCallback( - (filterString) => { + (filterString: string) => { setFilterOptions((filters) => ({ ...filters, filter: filterString.trim(), diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/bulk_duplicate_exceptions_confirmation.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/bulk_duplicate_exceptions_confirmation.tsx index 74575c327fbc8..fe01accf5e104 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/bulk_duplicate_exceptions_confirmation.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/bulk_actions/bulk_duplicate_exceptions_confirmation.tsx @@ -27,8 +27,8 @@ const BulkActionDuplicateExceptionsConfirmationComponent = ({ ); const handleRadioChange = useCallback( - (optionId) => { - setSelectedDuplicateOption(optionId); + (optionId: string) => { + setSelectedDuplicateOption(optionId as DuplicateOptions); }, [setSelectedDuplicateOption] ); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table_filters/rules_table_filters.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table_filters/rules_table_filters.tsx index e7e81b8dd3342..e900c20eae9a4 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table_filters/rules_table_filters.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table_filters/rules_table_filters.tsx @@ -47,7 +47,7 @@ const RulesTableFiltersComponent = () => { } = filterOptions; const handleOnSearch = useCallback( - (filterString) => { + (filterString: string) => { startTransaction({ name: RULES_TABLE_ACTIONS.FILTER }); setFilterOptions({ filter: filterString.trim() }); }, diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_filters.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_filters.tsx index fc8fecab1e07c..215a810bf3aa2 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_filters.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_filters.tsx @@ -31,7 +31,7 @@ const UpgradePrebuiltRulesTableFiltersComponent = () => { const { tags: selectedTags } = filterOptions; const handleOnSearch = useCallback( - (filterString) => { + (filterString: string) => { setFilterOptions((filters) => ({ ...filters, filter: filterString.trim(), diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.ts index ecd67546e7627..4e6d42e4dc609 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.ts @@ -28,10 +28,12 @@ export const extractSelected = < return options.filter((option) => option.checked === 'on').map((option) => option.label); }; -export const populateSelected = ( - allOptions: EuiSelectableOption[], +export const populateSelected = < + T extends CoverageOverviewRuleSource | CoverageOverviewRuleActivity +>( + allOptions: Array>, selected: string[] -): EuiSelectableOption[] => +): Array> => allOptions.map((option) => selected.includes(option.label) ? { ...option, checked: 'on' } : option ); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/rule_activity_filter.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/rule_activity_filter.tsx index 43159822deab3..ae7b6445a70c4 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/rule_activity_filter.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/rule_activity_filter.tsx @@ -51,7 +51,7 @@ const RuleActivityFilterComponent = ({ const options = populateSelected(ruleActivityFilterDefaultOptions, selected); const handleSelectableOnChange = useCallback( - (newOptions) => { + (newOptions: Array>) => { const formattedOptions = extractSelected(newOptions); onChange(formattedOptions); }, @@ -95,7 +95,7 @@ const RuleActivityFilterComponent = ({ panelPaddingSize="none" > {i18n.CoverageOverviewFilterPopoverTitle} - data-test-subj="coverageOverviewFilterList" options={options} onChange={handleSelectableOnChange} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/rule_source_filter.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/rule_source_filter.tsx index e55450f0a069a..08bc8c334743b 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/rule_source_filter.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/rule_source_filter.tsx @@ -48,7 +48,10 @@ const RuleSourceFilterComponent = ({ const numActiveFilters = useMemo(() => selected.length, [selected]); - const options = populateSelected(ruleSourceFilterDefaultOptions, selected); + const options = populateSelected( + ruleSourceFilterDefaultOptions, + selected + ) as EuiSelectableOption[]; const handleSelectableOnChange = useCallback( (newOptions) => { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/osquery/osquery_response_action_form_field.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/osquery/osquery_response_action_form_field.tsx index 7898dfef3ea90..d355187b1d0bc 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/osquery/osquery_response_action_form_field.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/osquery/osquery_response_action_form_field.tsx @@ -5,7 +5,10 @@ * 2.0. */ -import type { FieldHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import type { + FieldHook, + ValidationError, +} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import React, { useCallback, useMemo } from 'react'; import { isEmpty, map } from 'lodash'; import { useFormContext } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; @@ -22,7 +25,7 @@ export const ResponseActionFormField = React.memo(({ field }: { field: FieldHook ); const handleError = useCallback( - (newErrors) => { + (newErrors: ValidationError) => { if (isEmpty(newErrors)) { clearErrors(); } else { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_action_add_button.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_action_add_button.tsx index a8fcccee30eff..4dc903bbd1c0e 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_action_add_button.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_action_add_button.tsx @@ -46,7 +46,7 @@ export const ResponseActionAddButton = ({ const isPlatinumPlus = useLicense().isPlatinumPlus(); const handleAddActionType = useCallback( - (item) => { + (item: ResponseActionType) => { setAddResponseActionButtonShown(false); addActionType(); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_actions_wrapper.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_actions_wrapper.tsx index 39f036a1b3322..7e2fb59cea848 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_actions_wrapper.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_actions_wrapper.tsx @@ -23,7 +23,7 @@ interface ResponseActionsWrapperProps { export const ResponseActionsWrapper = React.memo( ({ items, removeItem, supportedResponseActionTypes, addItem }) => { const actionTypeIdRef = useRef(null); - const updateActionTypeId = useCallback((id) => { + const updateActionTypeId = useCallback((id: string) => { actionTypeIdRef.current = id; }, []); diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.tsx index c2f25b4b5c80c..0c1c33da81e50 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.tsx @@ -8,6 +8,7 @@ import type { Action } from '@kbn/ui-actions-plugin/public'; import type { EuiComboBox, EuiTitleSize } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiToolTip } from '@elastic/eui'; +import type { SyntheticEvent } from 'react'; import React, { memo, useCallback, useMemo, useState, useEffect } from 'react'; import styled from 'styled-components'; import { isEmpty, noop } from 'lodash/fp'; @@ -160,7 +161,7 @@ export const AlertsHistogramPanel = memo( }); const goToDetectionEngine = useCallback( - (ev) => { + (ev: SyntheticEvent) => { ev.preventDefault(); navigateToApp(APP_UI_ID, { deepLinkId: SecurityPageName.alerts, diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/components.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/components.tsx index bf050c2eedab9..3a0dccc492475 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/components.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/components.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import type { EuiComboBoxOptionOption } from '@elastic/eui'; +import type { EuiComboBoxOptionOption, EuiComboBoxProps } from '@elastic/eui'; import { EuiPanel, EuiComboBox } from '@elastic/eui'; import styled from 'styled-components'; import type { LegacyRef } from 'react'; @@ -53,7 +53,7 @@ export const KpiPanel = styled(EuiPanel)<{ interface StackedBySelectProps { 'aria-label'?: string; 'data-test-subj'?: string; - dropDownoptions?: Array>; + dropDownoptions?: Array>; inputRef?: (inputRef: HTMLInputElement | null) => void; isDisabled?: boolean; onSelect: (selected: string) => void; @@ -84,9 +84,9 @@ export const StackByComboBox = React.forwardRef( }: StackedBySelectProps, ref ) => { - const onChange = useCallback( + const onChange = useCallback['onChange']>>( (options) => { - if (options && options.length > 0) { + if (options && options.length && options[0].value) { onSelect(options[0].value); } else { onSelect(''); @@ -117,7 +117,7 @@ export const StackByComboBox = React.forwardRef( isDisabled={isDisabled} placeholder={i18n.STACK_BY_PLACEHOLDER} prepend={prepend} - ref={ref as LegacyRef> | undefined} + ref={ref as LegacyRef> | undefined} singleSelection={singleSelection} isClearable={false} sortMatchesBy="startsWith" diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/hooks.ts b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/hooks.ts index 75d86873c52bc..a666d25b1df10 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/hooks.ts +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/hooks.ts @@ -76,7 +76,7 @@ export interface GetAggregatableFields { export function getAggregatableFields( fields: GetAggregatableFields, useLensCompatibleFields?: boolean -): EuiComboBoxOptionOption[] { +): Array> { const result = []; for (const [key, field] of Object.entries(fields)) { if (useLensCompatibleFields) { diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/alerts_grouping.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/alerts_grouping.tsx index fd7ca232ca8ea..8b02530fec07a 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/alerts_grouping.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/alerts_grouping.tsx @@ -12,6 +12,7 @@ import { isNoneGroup, useGrouping } from '@kbn/grouping'; import { isEmpty, isEqual } from 'lodash/fp'; import type { Storage } from '@kbn/kibana-utils-plugin/public'; import type { TableIdLiteral } from '@kbn/securitysolution-data-table'; +import type { GroupingArgs } from '@kbn/grouping/src'; import { groupIdSelector } from '../../../common/store/grouping/selectors'; import { getDefaultGroupingOptions } from '../../../common/utils/alerts'; import { useDeepEqualSelector } from '../../../common/hooks/use_selector'; @@ -89,7 +90,7 @@ const GroupedAlertsTableComponent: React.FC = (props) [telemetry] ); - const onOptionsChange = useCallback( + const onOptionsChange = useCallback['onOptionsChange']>>( (options) => { dispatch( updateGroups({ diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_bulk_to_timeline.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_bulk_to_timeline.tsx index e0e11ad0251b5..044fb10a6ac12 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_bulk_to_timeline.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_bulk_to_timeline.tsx @@ -143,7 +143,8 @@ export const useAddBulkToTimelineAction = ({ }); const updateTimelineIsLoading = useCallback( - (payload) => dispatch(timelineActions.updateIsLoading(payload)), + (payload: Parameters[0]) => + dispatch(timelineActions.updateIsLoading(payload)), [dispatch] ); diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_exception_flyout.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_exception_flyout.tsx index 40c855341a1e9..dba19fda539cb 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_exception_flyout.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_exception_flyout.tsx @@ -55,7 +55,7 @@ export const useExceptionFlyout = ({ }, [setAllTourStepsHidden]); const onAddExceptionConfirm = useCallback( - (didRuleChange: boolean, didCloseAlert: boolean, didBulkCloseAlert) => { + (didRuleChange: boolean, didCloseAlert: boolean, didBulkCloseAlert: boolean) => { if (refetch && (isActiveTimelines === false || didBulkCloseAlert)) { refetch(); } diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.tsx index 211bfd0db2dc1..a68d773468e75 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.tsx @@ -136,7 +136,8 @@ export const useInvestigateInTimeline = ({ ); const updateTimelineIsLoading = useCallback( - (payload) => dispatch(timelineActions.updateIsLoading(payload)), + (payload: Parameters[0]) => + dispatch(timelineActions.updateIsLoading(payload)), [dispatch] ); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx index 29cec20f12d79..a8eec62f2d58a 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx @@ -31,7 +31,7 @@ export interface RuleFromTimeline { onOpenTimeline: (timeline: TimelineModel) => void; } -type SetRuleQuery = ({ +export type SetRuleQuery = ({ index, queryBar, eqlOptions, diff --git a/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_actions_column.tsx b/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_actions_column.tsx index 4f2c995b163d5..59e3cf9f07f9c 100644 --- a/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_actions_column.tsx +++ b/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_actions_column.tsx @@ -8,7 +8,10 @@ import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; import React, { useCallback, useContext, useMemo } from 'react'; import { useSelector } from 'react-redux'; -import type { AlertsTableConfigurationRegistry } from '@kbn/triggers-actions-ui-plugin/public/types'; +import type { + AlertsTableConfigurationRegistry, + RenderCustomActionsRowArgs, +} from '@kbn/triggers-actions-ui-plugin/public/types'; import { TableId } from '@kbn/securitysolution-data-table'; import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; import { StatefulEventContext } from '../../../common/components/events_viewer/stateful_event_context'; @@ -61,7 +64,7 @@ export const getUseActionColumnHook = clearSelection, ecsAlert: alert, nonEcsData, - }) => { + }: RenderCustomActionsRowArgs) => { const timelineItem: TimelineItem = { _id: (alert as Ecs)._id, _index: (alert as Ecs)._index, diff --git a/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_trigger_actions_browser_fields_options.tsx b/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_trigger_actions_browser_fields_options.tsx index e2876e962fd20..a627131ff05c0 100644 --- a/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_trigger_actions_browser_fields_options.tsx +++ b/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_trigger_actions_browser_fields_options.tsx @@ -6,6 +6,7 @@ */ import { useCallback, useMemo } from 'react'; import type { AlertsTableConfigurationRegistry } from '@kbn/triggers-actions-ui-plugin/public/types'; +import type { EuiDataGridColumn } from '@elastic/eui'; import { useFieldBrowserOptions } from '../../../timelines/components/fields_browser'; import type { SourcererScopeName } from '../../../sourcerer/store/model'; @@ -13,7 +14,7 @@ export const getUseTriggersActionsFieldBrowserOptions = (scopeId: SourcererScope const useTriggersActionsFieldBrowserOptions: AlertsTableConfigurationRegistry['useFieldBrowserOptions'] = ({ onToggleColumn }) => { const upsertColumn = useCallback( - (column) => { + (column: EuiDataGridColumn) => { onToggleColumn(column.id); }, [onToggleColumn] diff --git a/x-pack/plugins/security_solution/public/detections/mitre/get_mitre_threat_component.ts b/x-pack/plugins/security_solution/public/detections/mitre/get_mitre_threat_component.ts deleted file mode 100644 index 0848cbcca15c6..0000000000000 --- a/x-pack/plugins/security_solution/public/detections/mitre/get_mitre_threat_component.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { Threats } from '@kbn/securitysolution-io-ts-alerting-types'; -import type { SearchHit } from '../../../common/search_strategy'; -import { buildThreatDescription } from '../../detection_engine/rule_creation_ui/components/description_step/helpers'; - -// TODO: MOVE TO FLYOUT FOLDER - https://github.com/elastic/security-team/issues/7462 -export const getMitreComponentParts = (searchHit?: SearchHit) => { - const ruleParameters = searchHit?.fields - ? searchHit?.fields['kibana.alert.rule.parameters'] - : null; - const threat = ruleParameters ? (ruleParameters[0]?.threat as Threats) : null; - return threat && threat.length > 0 - ? buildThreatDescription({ - label: threat[0].framework, - threat, - }) - : null; -}; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx index d7e16697ce250..18efc5fcbad7f 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx @@ -155,16 +155,6 @@ jest.mock('../../../common/lib/kibana', () => { }; }); -jest.mock('../../../timelines/components/side_panel/hooks/use_detail_panel', () => { - return { - useDetailPanel: () => ({ - openEventDetailsPanel: jest.fn(), - handleOnDetailsPanelClosed: () => {}, - DetailsPanel: () =>
    , - shouldShowDetailsPanel: false, - }), - }; -}); const dataViewId = 'security-solution-default'; const stateWithBuildingBlockAlertsEnabled: State = { diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx index 31116f7c5ecd9..7784fbb5760c3 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx @@ -223,7 +223,7 @@ const DetectionEnginePageComponent: React.FC = () ); const goToRules = useCallback( - (ev) => { + (ev: React.MouseEvent) => { ev.preventDefault(); navigateToUrl(formatUrl(getRulesUrl())); }, diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/components/edit_rule_settings_button_link.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/components/edit_rule_settings_button_link.tsx index 6ef7ebb0cae4c..f1572b326a90a 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/components/edit_rule_settings_button_link.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/components/edit_rule_settings_button_link.tsx @@ -29,7 +29,7 @@ export function EditRuleSettingButtonLink({ application: { navigateToApp }, } = useKibana().services; const goToEditRule = useCallback( - (ev) => { + (ev: React.SyntheticEvent) => { ev.preventDefault(); navigateToApp(APP_UI_ID, { deepLinkId: SecurityPageName.rules, diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/asset_criticality_file_uploader.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/asset_criticality_file_uploader.tsx index ddffe01955b29..0acd1f831ca71 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/asset_criticality_file_uploader.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/asset_criticality_file_uploader.tsx @@ -61,7 +61,7 @@ export const AssetCriticalityFileUploader: React.FC = () => { }, [telemetry] ); - const onValidationError = useCallback((message) => { + const onValidationError = useCallback((message: string) => { dispatch({ type: 'fileError', payload: { message } }); }, []); diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/host_risk_score_table/index.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/host_risk_score_table/index.tsx index 5dca054f013cd..a451c5030212d 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/host_risk_score_table/index.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/host_risk_score_table/index.tsx @@ -9,7 +9,12 @@ import React, { useMemo, useCallback } from 'react'; import { useDispatch } from 'react-redux'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import type { Columns, Criteria, ItemsPerRow } from '../../../explore/components/paginated_table'; +import type { + Columns, + Criteria, + ItemsPerRow, + SiemTables, +} from '../../../explore/components/paginated_table'; import { PaginatedTable } from '../../../explore/components/paginated_table'; import { useDeepEqualSelector } from '../../../common/hooks/use_selector'; import { hostsActions, hostsModel, hostsSelectors } from '../../../explore/hosts/store'; @@ -81,7 +86,7 @@ const HostRiskScoreTableComponent: React.FC = ({ const { activePage, limit, sort } = useDeepEqualSelector((state: State) => getHostRiskScoreSelector(state, hostsModel.HostsType.page) ); - const updateLimitPagination = useCallback( + const updateLimitPagination = useCallback( (newLimit) => dispatch( hostsActions.updateTableLimit({ @@ -93,7 +98,7 @@ const HostRiskScoreTableComponent: React.FC = ({ [type, dispatch] ); - const updateActivePage = useCallback( + const updateActivePage = useCallback( (newPage) => dispatch( hostsActions.updateTableActivePage({ diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx index 21ea627d3f65d..b0d988eaeac1a 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx @@ -95,7 +95,7 @@ const FlyoutRiskSummaryComponent = ({ ); const onToggle = useCallback( - (isOpen) => { + (isOpen: boolean) => { const entity = isUserRiskData(riskData) ? 'user' : 'host'; telemetry.reportToggleRiskSummaryClicked({ diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/severity/severity_filter_group.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/severity/severity_filter_group.tsx index 9ecb9d9cd6cdb..df99f39091a92 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/severity/severity_filter_group.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/severity/severity_filter_group.tsx @@ -6,7 +6,7 @@ */ import React, { useCallback, useMemo, useState } from 'react'; -import type { FilterChecked } from '@elastic/eui'; +import type { FilterChecked, EuiSelectableProps } from '@elastic/eui'; import { EuiFilterButton, EuiFilterGroup, @@ -67,8 +67,10 @@ export const SeverityFilterGroup: React.FC<{ })); }, [severityCount, selectedSeverities]); - const updateSeverityFilter = useCallback( - (newSelection: SeverityItems[], _, changedSeverity: SeverityItems) => { + const updateSeverityFilter = useCallback< + NonNullable['onChange']> + >( + (newSelection, _, changedSeverity) => { if (changedSeverity.checked === 'on') { telemetry.reportEntityRiskFiltered({ entity: riskEntity, diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/user_risk_score_table/index.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/user_risk_score_table/index.tsx index 6a99e64d04b27..0e2c64f84d610 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/user_risk_score_table/index.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/user_risk_score_table/index.tsx @@ -9,7 +9,12 @@ import React, { useMemo, useCallback } from 'react'; import { useDispatch } from 'react-redux'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import type { Columns, Criteria, ItemsPerRow } from '../../../explore/components/paginated_table'; +import type { + Columns, + Criteria, + ItemsPerRow, + SiemTables, +} from '../../../explore/components/paginated_table'; import { PaginatedTable } from '../../../explore/components/paginated_table'; import { getUserRiskScoreColumns } from './columns'; @@ -82,7 +87,7 @@ const UserRiskScoreTableComponent: React.FC = ({ const { activePage, limit, sort } = useDeepEqualSelector((state: State) => getUserRiskScoreSelector(state) ); - const updateLimitPagination = useCallback( + const updateLimitPagination = useCallback( (newLimit) => { dispatch( usersActions.updateTableLimit({ @@ -95,7 +100,7 @@ const UserRiskScoreTableComponent: React.FC = ({ [type, dispatch] ); - const updateActivePage = useCallback( + const updateActivePage = useCallback( (newPage) => { dispatch( usersActions.updateTableActivePage({ diff --git a/x-pack/plugins/security_solution/public/exceptions/components/create_shared_exception_list/index.tsx b/x-pack/plugins/security_solution/public/exceptions/components/create_shared_exception_list/index.tsx index 9c465b202b8ca..bf345daa1aea1 100644 --- a/x-pack/plugins/security_solution/public/exceptions/components/create_shared_exception_list/index.tsx +++ b/x-pack/plugins/security_solution/public/exceptions/components/create_shared_exception_list/index.tsx @@ -23,7 +23,7 @@ import { EuiFlexItem, useGeneratedHtmlId, } from '@elastic/eui'; -import type { HttpSetup } from '@kbn/core-http-browser'; +import type { HttpSetup, IHttpFetchError, ResponseErrorBody } from '@kbn/core-http-browser'; import type { ErrorToastOptions, Toast, ToastInput } from '@kbn/core-notifications-browser'; import { i18n as translate } from '@kbn/i18n'; import type { ListDetails } from '@kbn/securitysolution-exception-list-components'; @@ -109,22 +109,22 @@ export const CreateSharedListFlyout = memo( http, ]); - const handleCreateSuccess = useCallback( - (response) => { - addSuccess({ - text: getSuccessText(newListDetails.name), - title: SUCCESS_TITLE, - }); - handleRefresh(); + const handleCreateSuccess = useCallback(() => { + addSuccess({ + text: getSuccessText(newListDetails.name), + title: SUCCESS_TITLE, + }); + handleRefresh(); - handleCloseFlyout(); - }, - [addSuccess, handleCloseFlyout, handleRefresh, newListDetails] - ); + handleCloseFlyout(); + }, [addSuccess, handleCloseFlyout, handleRefresh, newListDetails]); const handleCreateError = useCallback( - (error) => { - if (!error.message.includes('AbortError') && !error?.body?.message.includes('AbortError')) { + (error: IHttpFetchError | undefined) => { + if ( + !error?.message?.includes('AbortError') && + !error?.body?.message.includes('AbortError') + ) { addError(error, { title: translate.translate( 'xpack.securitySolution.exceptions.createSharedExceptionListErrorTitle', @@ -141,9 +141,11 @@ export const CreateSharedListFlyout = memo( useEffect(() => { if (!createSharedExceptionListState.loading) { if (createSharedExceptionListState?.result) { - handleCreateSuccess(createSharedExceptionListState.result); + handleCreateSuccess(); } else if (createSharedExceptionListState?.error) { - handleCreateError(createSharedExceptionListState?.error); + handleCreateError( + createSharedExceptionListState?.error as IHttpFetchError + ); } } }, [ diff --git a/x-pack/plugins/security_solution/public/exceptions/hooks/use_list_detail_view/index.ts b/x-pack/plugins/security_solution/public/exceptions/hooks/use_list_detail_view/index.ts index 99f3288379537..afee35da444cb 100644 --- a/x-pack/plugins/security_solution/public/exceptions/hooks/use_list_detail_view/index.ts +++ b/x-pack/plugins/security_solution/public/exceptions/hooks/use_list_detail_view/index.ts @@ -102,10 +102,15 @@ export const useListDetailsView = (exceptionListId: string) => { [toasts] ); - const initializeListRules = useCallback(async (result) => { - const listRules = await getListRules(result.list_id); - setLinkedRules(listRules); - }, []); + const initializeListRules = useCallback( + async (result: Awaited>) => { + if (result) { + const listRules = await getListRules(result.list_id); + setLinkedRules(listRules); + } + }, + [] + ); const initializeList = useCallback(async () => { try { @@ -329,7 +334,7 @@ export const useListDetailsView = (exceptionListId: string) => { return linkedRules.filter((rule) => !newLinkedRules.includes(rule)); }, [linkedRules, newLinkedRules]); - const onRuleSelectionChange = useCallback((value) => { + const onRuleSelectionChange = useCallback((value: UIRule[]) => { setNewLinkedRules(value); setDisableManageButton(false); }, []); diff --git a/x-pack/plugins/security_solution/public/exceptions/hooks/use_list_exception_items/index.ts b/x-pack/plugins/security_solution/public/exceptions/hooks/use_list_exception_items/index.ts index 9c466859334fe..bacd0377982a5 100644 --- a/x-pack/plugins/security_solution/public/exceptions/hooks/use_list_exception_items/index.ts +++ b/x-pack/plugins/security_solution/public/exceptions/hooks/use_list_exception_items/index.ts @@ -7,7 +7,10 @@ import { useCallback, useState } from 'react'; import type { Pagination } from '@elastic/eui'; import { ViewerStatus } from '@kbn/securitysolution-exception-list-components'; -import type { RuleReferences } from '@kbn/securitysolution-exception-list-components'; +import type { + RuleReferences, + GetExceptionItemProps, +} from '@kbn/securitysolution-exception-list-components'; import type { ExceptionListItemSchema, ExceptionListSchema, @@ -19,6 +22,7 @@ import { getExceptionItemsReferences, prepareFetchExceptionItemsParams, } from '../../api'; +import type { DeleteExceptionItem } from '../../api/types'; export interface UseListExceptionItemsProps { list: ExceptionListSchema; @@ -73,19 +77,26 @@ export const useListExceptionItems = ({ } }, [handleErrorStatus, list, setExceptionListReferences]); - const updateViewer = useCallback((paginationResult, dataLength, viewStatus) => { - setPagination(paginationResult); - setLastUpdated(Date.now()); - setTimeout(() => { - if (viewStatus === ViewerStatus.EMPTY_SEARCH) - return setViewerStatus(!dataLength ? viewStatus : ''); + const updateViewer = useCallback( + ( + paginationResult: Awaited>['pagination'], + dataLength: number, + viewStatus?: ViewerStatus + ) => { + setPagination(paginationResult); + setLastUpdated(Date.now()); + setTimeout(() => { + if (viewStatus === ViewerStatus.EMPTY_SEARCH) + return setViewerStatus(!dataLength ? viewStatus : ''); - setViewerStatus(!dataLength ? ViewerStatus.EMPTY : ''); - }, 200); - }, []); + setViewerStatus(!dataLength ? ViewerStatus.EMPTY : ''); + }, 200); + }, + [] + ); const fetchItems = useCallback( - async (options?, viewStatus?) => { + async (options?: GetExceptionItemProps | null, viewStatus?: ViewerStatus) => { try { setViewerStatus(ViewerStatus.LOADING); const { data, pagination: paginationResult } = await fetchListExceptionItems({ @@ -104,7 +115,15 @@ export const useListExceptionItems = ({ ); const onDeleteException = useCallback( - async ({ id, name, namespaceType }) => { + async ({ + id, + name, + namespaceType, + }: { + id: DeleteExceptionItem['id']; + name: string; + namespaceType: DeleteExceptionItem['namespaceType']; + }) => { try { setViewerStatus(ViewerStatus.LOADING); await deleteException({ id, http, namespaceType }); @@ -123,7 +142,7 @@ export const useListExceptionItems = ({ if (typeof onEditListExceptionItem === 'function') onEditListExceptionItem(exception); }; const onPaginationChange = useCallback( - async (options) => { + async (options?: GetExceptionItemProps | null) => { fetchItems(options); }, [fetchItems] diff --git a/x-pack/plugins/security_solution/public/explore/components/authentication/authentications_host_table.tsx b/x-pack/plugins/security_solution/public/explore/components/authentication/authentications_host_table.tsx index 732e4f242aa43..4f8aa2f96e87b 100644 --- a/x-pack/plugins/security_solution/public/explore/components/authentication/authentications_host_table.tsx +++ b/x-pack/plugins/security_solution/public/explore/components/authentication/authentications_host_table.tsx @@ -9,6 +9,7 @@ import React, { useCallback, useEffect, useState } from 'react'; import { getOr } from 'lodash/fp'; import { useDispatch } from 'react-redux'; +import type { SiemTables } from '../paginated_table'; import { PaginatedTable } from '../paginated_table'; import * as i18n from './translations'; @@ -70,7 +71,7 @@ const AuthenticationsHostTableComponent: React.FC = ( ? getHostDetailsAuthenticationColumns() : getHostsPageAuthenticationColumns(); - const updateLimitPagination = useCallback( + const updateLimitPagination = useCallback( (newLimit) => dispatch( hostsActions.updateTableLimit({ @@ -82,7 +83,7 @@ const AuthenticationsHostTableComponent: React.FC = ( [type, dispatch] ); - const updateActivePage = useCallback( + const updateActivePage = useCallback( (newPage) => dispatch( hostsActions.updateTableActivePage({ diff --git a/x-pack/plugins/security_solution/public/explore/components/authentication/authentications_user_table.tsx b/x-pack/plugins/security_solution/public/explore/components/authentication/authentications_user_table.tsx index f6c5fc86e761c..28855562cf101 100644 --- a/x-pack/plugins/security_solution/public/explore/components/authentication/authentications_user_table.tsx +++ b/x-pack/plugins/security_solution/public/explore/components/authentication/authentications_user_table.tsx @@ -10,6 +10,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { getOr } from 'lodash/fp'; import { useDispatch } from 'react-redux'; import { AuthStackByField } from '../../../../common/search_strategy/security_solution/users/authentications'; +import type { SiemTables } from '../paginated_table'; import { PaginatedTable } from '../paginated_table'; import * as i18n from './translations'; @@ -67,7 +68,7 @@ const AuthenticationsUserTableComponent: React.FC [userName] ); - const updateLimitPagination = useCallback( + const updateLimitPagination = useCallback( (newLimit) => dispatch( usersActions.updateTableLimit({ @@ -79,7 +80,7 @@ const AuthenticationsUserTableComponent: React.FC [type, dispatch] ); - const updateActivePage = useCallback( + const updateActivePage = useCallback( (newPage) => dispatch( usersActions.updateTableActivePage({ diff --git a/x-pack/plugins/security_solution/public/explore/components/paginated_table/index.tsx b/x-pack/plugins/security_solution/public/explore/components/paginated_table/index.tsx index c7825d56aedd4..3aa025b30eb1b 100644 --- a/x-pack/plugins/security_solution/public/explore/components/paginated_table/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/components/paginated_table/index.tsx @@ -96,7 +96,7 @@ declare type BasicTableColumns = | UsersColumns | UsersTableColumns; -declare type SiemTables = BasicTableProps; +export declare type SiemTables = BasicTableProps; // Using telescoping templates to remove 'any' that was polluting downstream column type checks export interface BasicTableProps { diff --git a/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/index.tsx b/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/index.tsx index ef9a368dac370..20299d564d587 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/components/hosts_table/index.tsx @@ -16,6 +16,7 @@ import type { Columns, Criteria, ItemsPerRow, + SiemTables, SortingBasicTable, } from '../../../components/paginated_table'; import { PaginatedTable } from '../../../components/paginated_table'; @@ -96,7 +97,7 @@ const HostsTableComponent: React.FC = ({ getHostsSelector(state, type) ); - const updateLimitPagination = useCallback( + const updateLimitPagination = useCallback( (newLimit) => dispatch( hostsActions.updateTableLimit({ @@ -108,7 +109,7 @@ const HostsTableComponent: React.FC = ({ [type, dispatch] ); - const updateActivePage = useCallback( + const updateActivePage = useCallback( (newPage) => dispatch( hostsActions.updateTableActivePage({ diff --git a/x-pack/plugins/security_solution/public/explore/hosts/pages/details/index.tsx b/x-pack/plugins/security_solution/public/explore/hosts/pages/details/index.tsx index f60866be1e3ea..6e5b69f408263 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/pages/details/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/pages/details/index.tsx @@ -20,6 +20,7 @@ import type { Filter } from '@kbn/es-query'; import { buildEsQuery } from '@kbn/es-query'; import { getEsQueryConfig } from '@kbn/data-plugin/common'; import { dataTableSelectors, tableDefaults, TableId } from '@kbn/securitysolution-data-table'; +import type { NarrowDateRange } from '../../../../common/components/ml/types'; import { useCalculateEntityRiskScore } from '../../../../entity_analytics/api/hooks/use_calculate_entity_risk_score'; import { useAssetCriticalityData, @@ -113,7 +114,7 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta const isEnterprisePlus = useLicense().isEnterprise(); - const narrowDateRange = useCallback( + const narrowDateRange = useCallback( (score, interval) => { const fromTo = scoreIntervalToDateTime(score, interval); dispatch( diff --git a/x-pack/plugins/security_solution/public/explore/network/components/network_dns_table/index.tsx b/x-pack/plugins/security_solution/public/explore/network/components/network_dns_table/index.tsx index be0558b00f670..3af67736d6837 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/network_dns_table/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/network_dns_table/index.tsx @@ -16,7 +16,7 @@ import type { NetworkDnsEdges, NetworkDnsFields, } from '../../../../../common/search_strategy'; -import type { Criteria, ItemsPerRow } from '../../../components/paginated_table'; +import type { Criteria, ItemsPerRow, SiemTables } from '../../../components/paginated_table'; import { PaginatedTable } from '../../../components/paginated_table'; import { useDeepEqualSelector } from '../../../../common/hooks/use_selector'; @@ -66,7 +66,7 @@ const NetworkDnsTableComponent: React.FC = ({ const getNetworkDnsSelector = useMemo(() => networkSelectors.dnsSelector(), []); const { activePage, isPtrIncluded, limit, sort } = useDeepEqualSelector(getNetworkDnsSelector); - const updateLimitPagination = useCallback( + const updateLimitPagination = useCallback( (newLimit) => dispatch( networkActions.updateNetworkTable({ @@ -78,7 +78,7 @@ const NetworkDnsTableComponent: React.FC = ({ [type, dispatch] ); - const updateActivePage = useCallback( + const updateActivePage = useCallback( (newPage) => dispatch( networkActions.updateNetworkTable({ diff --git a/x-pack/plugins/security_solution/public/explore/network/components/network_http_table/index.tsx b/x-pack/plugins/security_solution/public/explore/network/components/network_http_table/index.tsx index 4d6cd8773d06c..642fb1a13604f 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/network_http_table/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/network_http_table/index.tsx @@ -12,7 +12,7 @@ import { networkActions, networkModel, networkSelectors } from '../../store'; import type { NetworkHttpEdges } from '../../../../../common/search_strategy'; import { NetworkHttpFields } from '../../../../../common/search_strategy'; import { useDeepEqualSelector } from '../../../../common/hooks/use_selector'; -import type { Criteria, ItemsPerRow } from '../../../components/paginated_table'; +import type { Criteria, ItemsPerRow, SiemTables } from '../../../components/paginated_table'; import { PaginatedTable } from '../../../components/paginated_table'; import { getNetworkHttpColumns } from './columns'; @@ -64,7 +64,7 @@ const NetworkHttpTableComponent: React.FC = ({ ? networkModel.NetworkTableType.http : networkModel.NetworkDetailsTableType.http; - const updateLimitPagination = useCallback( + const updateLimitPagination = useCallback( (newLimit) => dispatch( networkActions.updateNetworkTable({ @@ -76,7 +76,7 @@ const NetworkHttpTableComponent: React.FC = ({ [dispatch, type, tableType] ); - const updateActivePage = useCallback( + const updateActivePage = useCallback( (newPage) => dispatch( networkActions.updateNetworkTable({ diff --git a/x-pack/plugins/security_solution/public/explore/network/components/network_top_countries_table/index.tsx b/x-pack/plugins/security_solution/public/explore/network/components/network_top_countries_table/index.tsx index d149e1bb474ef..3f34d79775f6f 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/network_top_countries_table/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/network_top_countries_table/index.tsx @@ -20,7 +20,7 @@ import { } from '../../../../../common/search_strategy'; import { useDeepEqualSelector } from '../../../../common/hooks/use_selector'; -import type { Criteria, ItemsPerRow } from '../../../components/paginated_table'; +import type { Criteria, ItemsPerRow, SiemTables } from '../../../components/paginated_table'; import { PaginatedTable } from '../../../components/paginated_table'; import { getCountriesColumnsCurated } from './columns'; @@ -100,7 +100,7 @@ const NetworkTopCountriesTableComponent: React.FC ? `node.network.${sort.field}` : `node.${flowTargeted}.${sort.field}`; - const updateLimitPagination = useCallback( + const updateLimitPagination = useCallback( (newLimit) => dispatch( networkActions.updateNetworkTable({ @@ -112,7 +112,7 @@ const NetworkTopCountriesTableComponent: React.FC [dispatch, type, tableType] ); - const updateActivePage = useCallback( + const updateActivePage = useCallback( (newPage) => dispatch( networkActions.updateNetworkTable({ diff --git a/x-pack/plugins/security_solution/public/explore/network/components/network_top_n_flow_table/index.tsx b/x-pack/plugins/security_solution/public/explore/network/components/network_top_n_flow_table/index.tsx index f620d5fc17df5..4359520ea8f21 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/network_top_n_flow_table/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/network_top_n_flow_table/index.tsx @@ -17,7 +17,7 @@ import { NetworkTopTablesFields, } from '../../../../../common/search_strategy'; import { useDeepEqualSelector } from '../../../../common/hooks/use_selector'; -import type { Criteria, ItemsPerRow } from '../../../components/paginated_table'; +import type { Criteria, ItemsPerRow, SiemTables } from '../../../components/paginated_table'; import { PaginatedTable } from '../../../components/paginated_table'; import { networkActions, networkModel, networkSelectors } from '../../store'; import { getNFlowColumnsCurated } from './columns'; @@ -125,7 +125,7 @@ const NetworkTopNFlowTableComponent: React.FC = ({ [flowTargeted, sort] ); - const updateActivePage = useCallback( + const updateActivePage = useCallback( (newPage) => dispatch( networkActions.updateNetworkTable({ @@ -137,7 +137,7 @@ const NetworkTopNFlowTableComponent: React.FC = ({ [dispatch, type, tableType] ); - const updateLimitPagination = useCallback( + const updateLimitPagination = useCallback( (newLimit) => dispatch( networkActions.updateNetworkTable({ diff --git a/x-pack/plugins/security_solution/public/explore/network/components/tls_table/index.tsx b/x-pack/plugins/security_solution/public/explore/network/components/tls_table/index.tsx index b981dba31c2b6..be7318daf2839 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/tls_table/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/tls_table/index.tsx @@ -13,7 +13,12 @@ import { networkActions, networkModel, networkSelectors } from '../../store'; import type { Direction, NetworkTlsEdges, SortField } from '../../../../../common/search_strategy'; import { NetworkTlsFields } from '../../../../../common/search_strategy'; import { useDeepEqualSelector } from '../../../../common/hooks/use_selector'; -import type { Criteria, ItemsPerRow, SortingBasicTable } from '../../../components/paginated_table'; +import type { + Criteria, + ItemsPerRow, + SiemTables, + SortingBasicTable, +} from '../../../components/paginated_table'; import { PaginatedTable } from '../../../components/paginated_table'; import { getTlsColumns } from './columns'; import * as i18n from './translations'; @@ -64,7 +69,7 @@ const TlsTableComponent: React.FC = ({ ? networkModel.NetworkTableType.tls : networkModel.NetworkDetailsTableType.tls; - const updateLimitPagination = useCallback( + const updateLimitPagination = useCallback( (newLimit) => dispatch( networkActions.updateNetworkTable({ @@ -76,7 +81,7 @@ const TlsTableComponent: React.FC = ({ [dispatch, type, tableType] ); - const updateActivePage = useCallback( + const updateActivePage = useCallback( (newPage) => dispatch( networkActions.updateNetworkTable({ diff --git a/x-pack/plugins/security_solution/public/explore/network/components/users_table/index.tsx b/x-pack/plugins/security_solution/public/explore/network/components/users_table/index.tsx index 909f4fa77d94d..c88d90dc27567 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/users_table/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/users_table/index.tsx @@ -19,7 +19,12 @@ import type { SortField, } from '../../../../../common/search_strategy'; import { NetworkUsersFields } from '../../../../../common/search_strategy'; -import type { Criteria, ItemsPerRow, SortingBasicTable } from '../../../components/paginated_table'; +import type { + Criteria, + ItemsPerRow, + SiemTables, + SortingBasicTable, +} from '../../../components/paginated_table'; import { PaginatedTable } from '../../../components/paginated_table'; import { getUsersColumns } from './columns'; @@ -70,7 +75,7 @@ const UsersTableComponent: React.FC = ({ const getUsersSelector = useMemo(() => networkSelectors.usersSelector(), []); const { activePage, sort, limit } = useDeepEqualSelector(getUsersSelector); - const updateLimitPagination = useCallback( + const updateLimitPagination = useCallback( (newLimit) => dispatch( networkActions.updateNetworkTable({ @@ -82,7 +87,7 @@ const UsersTableComponent: React.FC = ({ [dispatch, type] ); - const updateActivePage = useCallback( + const updateActivePage = useCallback( (newPage) => dispatch( networkActions.updateNetworkTable({ diff --git a/x-pack/plugins/security_solution/public/explore/network/pages/details/index.tsx b/x-pack/plugins/security_solution/public/explore/network/pages/details/index.tsx index c2f0340382714..adcf8a21ba47c 100644 --- a/x-pack/plugins/security_solution/public/explore/network/pages/details/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/pages/details/index.tsx @@ -28,6 +28,7 @@ import { networkToCriteria } from '../../../../common/components/ml/criteria/net import { scoreIntervalToDateTime } from '../../../../common/components/ml/score/score_interval_to_datetime'; import { manageQuery } from '../../../../common/components/page/manage_query'; import { FlowTargetSelectConnected } from '../../components/flow_target_select_connected'; +import type { IpOverviewProps } from '../../components/details'; import { IpOverview } from '../../components/details'; import { SiemSearchBar } from '../../../../common/components/search_bar'; import { SecuritySolutionPageWrapper } from '../../../../common/components/page_wrapper'; @@ -82,7 +83,7 @@ const NetworkDetailsComponent: React.FC = () => { const globalFilters = useDeepEqualSelector(getGlobalFiltersQuerySelector); const type = networkModel.NetworkType.details; - const narrowDateRange = useCallback( + const narrowDateRange = useCallback( (score, interval) => { const fromTo = scoreIntervalToDateTime(score, interval); dispatch( diff --git a/x-pack/plugins/security_solution/public/explore/users/components/all_users/index.tsx b/x-pack/plugins/security_solution/public/explore/users/components/all_users/index.tsx index d05c9551a2518..92303187f231a 100644 --- a/x-pack/plugins/security_solution/public/explore/users/components/all_users/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/users/components/all_users/index.tsx @@ -19,7 +19,12 @@ import { getOrEmptyTagFromValue, } from '../../../../common/components/empty_value'; -import type { Columns, Criteria, ItemsPerRow } from '../../../components/paginated_table'; +import type { + Columns, + Criteria, + ItemsPerRow, + SiemTables, +} from '../../../components/paginated_table'; import { PaginatedTable } from '../../../components/paginated_table'; import { getRowItemsWithActions } from '../../../../common/components/tables/helpers'; @@ -183,7 +188,7 @@ const UsersTableComponent: React.FC = ({ const isPlatinumOrTrialLicense = useMlCapabilities().isPlatinumOrTrialLicense; const { navigateTo } = useNavigateTo(); - const updateLimitPagination = useCallback( + const updateLimitPagination = useCallback( (newLimit) => { dispatch( usersActions.updateTableLimit({ @@ -196,7 +201,7 @@ const UsersTableComponent: React.FC = ({ [type, dispatch] ); - const updateActivePage = useCallback( + const updateActivePage = useCallback( (newPage) => { dispatch( usersActions.updateTableActivePage({ diff --git a/x-pack/plugins/security_solution/public/explore/users/pages/details/index.tsx b/x-pack/plugins/security_solution/public/explore/users/pages/details/index.tsx index 0ff2797621615..a53eaf43269bf 100644 --- a/x-pack/plugins/security_solution/public/explore/users/pages/details/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/users/pages/details/index.tsx @@ -64,6 +64,7 @@ import { LastEventTime } from '../../../../common/components/last_event_time'; import { LastEventIndexKey, RiskScoreEntity } from '../../../../../common/search_strategy'; import { AnomalyTableProvider } from '../../../../common/components/ml/anomaly/anomaly_table_provider'; +import type { UserSummaryProps } from '../../../../overview/components/user_overview'; import { UserOverview, USER_OVERVIEW_RISK_SCORE_QUERY_ID, @@ -159,7 +160,7 @@ const UsersDetailsComponent: React.FC = ({ useQueryInspector({ setQuery, deleteQuery, refetch, inspect, loading, queryId: QUERY_ID }); - const narrowDateRange = useCallback( + const narrowDateRange = useCallback( (score, interval) => { const fromTo = scoreIntervalToDateTime(score, interval); dispatch( diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details_alerts_table.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details_alerts_table.tsx index 70b238825d66a..ea16fcfa80e93 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details_alerts_table.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/correlations_details_alerts_table.tsx @@ -20,9 +20,9 @@ import { CellTooltipWrapper } from '../../shared/components/cell_tooltip_wrapper import type { DataProvider } from '../../../../../common/types'; import { SeverityBadge } from '../../../../common/components/severity_badge'; import { usePaginatedAlerts } from '../hooks/use_paginated_alerts'; -import { InvestigateInTimelineButton } from '../../../../common/components/event_details/table/investigate_in_timeline_button'; +import { InvestigateInTimelineButton } from '../../../../common/components/event_details/investigate_in_timeline_button'; import { ACTION_INVESTIGATE_IN_TIMELINE } from '../../../../detections/components/alerts_table/translations'; -import { getDataProvider } from '../../../../common/components/event_details/table/use_action_cell_data_provider'; +import { getDataProvider } from '../../../../common/components/event_details/use_action_cell_data_provider'; import { AlertPreviewButton } from '../../../shared/components/alert_preview_button'; export const TIMESTAMP_DATE_FORMAT = 'MMM D, YYYY @ HH:mm:ss.SSS'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/prevalence_details.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/prevalence_details.tsx index e3134591d6c9b..5aae6c4b39269 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/prevalence_details.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/prevalence_details.tsx @@ -26,7 +26,7 @@ import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { FormattedCount } from '../../../../common/components/formatted_number'; import { useLicense } from '../../../../common/hooks/use_license'; -import { InvestigateInTimelineButton } from '../../../../common/components/event_details/table/investigate_in_timeline_button'; +import { InvestigateInTimelineButton } from '../../../../common/components/event_details/investigate_in_timeline_button'; import type { PrevalenceData } from '../../shared/hooks/use_prevalence'; import { usePrevalence } from '../../shared/hooks/use_prevalence'; import { @@ -47,7 +47,7 @@ import { useDocumentDetailsContext } from '../../shared/context'; import { getDataProvider, getDataProviderAnd, -} from '../../../../common/components/event_details/table/use_action_cell_data_provider'; +} from '../../../../common/components/event_details/use_action_cell_data_provider'; import { getEmptyTagValue } from '../../../../common/components/empty_value'; import { IS_OPERATOR } from '../../../../../common/types'; import { useKibana } from '../../../../common/lib/kibana'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/suppressed_alerts.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/suppressed_alerts.tsx index efd1628f9d70a..b817be7a308b5 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/suppressed_alerts.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/suppressed_alerts.tsx @@ -11,15 +11,22 @@ import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; import { ALERT_RULE_TYPE } from '@kbn/rule-data-utils'; import { EuiBetaBadge, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; +import { i18n } from '@kbn/i18n'; import { ExpandablePanel } from '@kbn/security-solution-common'; import { CORRELATIONS_DETAILS_SUPPRESSED_ALERTS_SECTION_TEST_ID, SUPPRESSED_ALERTS_SECTION_TECHNICAL_PREVIEW_TEST_ID, } from './test_ids'; -import { SUPPRESSED_ALERTS_COUNT_TECHNICAL_PREVIEW } from '../../../../common/components/event_details/insights/translations'; import { InvestigateInTimelineAction } from '../../../../detections/components/alerts_table/timeline_actions/investigate_in_timeline_action'; import { isSuppressionRuleInGA } from '../../../../../common/detection_engine/utils'; +const SUPPRESSED_ALERTS_COUNT_TECHNICAL_PREVIEW = i18n.translate( + 'xpack.securitySolution.flyout.left.insights.suppressedAlertsCountTechnicalPreview', + { + defaultMessage: 'Technical Preview', + } +); + export interface SuppressedAlertsProps { /** * An object with top level fields from the ECS object diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.tsx index 5e9905107c877..fc9a09d4e37da 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.tsx @@ -23,6 +23,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { useSetAlertAssignees } from '../../../../common/components/toolbar/bulk_actions/use_set_alert_assignees'; import { getEmptyTagValue } from '../../../../common/components/empty_value'; import { ASSIGNEES_PANEL_WIDTH } from '../../../../common/components/assignees/constants'; +import type { AssigneesApplyPanelProps } from '../../../../common/components/assignees/assignees_apply_panel'; import { AssigneesApplyPanel } from '../../../../common/components/assignees/assignees_apply_panel'; import { useUpsellingMessage } from '../../../../common/hooks/use_upselling'; import { useLicense } from '../../../../common/hooks/use_license'; @@ -98,7 +99,7 @@ export const Assignees: FC = memo( setIsPopoverOpen((value) => !value); }, []); - const handleApplyAssignees = useCallback( + const handleApplyAssignees = useCallback( async (assignees) => { setIsPopoverOpen(false); if (setAlertAssignees) { diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/mitre_attack.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/mitre_attack.tsx index 2c7a45dc17346..7aabc3eefb964 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/mitre_attack.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/mitre_attack.tsx @@ -8,9 +8,27 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elastic/eui'; import type { FC } from 'react'; import React, { useMemo } from 'react'; -import { MITRE_ATTACK_DETAILS_TEST_ID, MITRE_ATTACK_TITLE_TEST_ID } from './test_ids'; -import { getMitreComponentParts } from '../../../../detections/mitre/get_mitre_threat_component'; +import type { Threats } from '@kbn/securitysolution-io-ts-alerting-types'; +import type { SearchHit } from '../../../../../common/search_strategy'; +import { buildThreatDescription } from '../../../../detection_engine/rule_creation_ui/components/description_step/helpers'; import { useDocumentDetailsContext } from '../../shared/context'; +import { MITRE_ATTACK_DETAILS_TEST_ID, MITRE_ATTACK_TITLE_TEST_ID } from './test_ids'; + +/** + * Retrieves mitre attack information from the alert information + */ +const getMitreComponentParts = (searchHit?: SearchHit) => { + const ruleParameters = searchHit?.fields + ? searchHit?.fields['kibana.alert.rule.parameters'] + : null; + const threat = ruleParameters ? (ruleParameters[0]?.threat as Threats) : null; + return threat && threat.length > 0 + ? buildThreatDescription({ + label: threat[0].framework, + threat, + }) + : null; +}; export const MitreAttack: FC = () => { const { searchHit } = useDocumentDetailsContext(); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/status.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/status.tsx index 2737a5a608b5a..c75e1426da10b 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/status.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/status.tsx @@ -9,17 +9,13 @@ import type { FC } from 'react'; import React, { useMemo } from 'react'; import { find } from 'lodash/fp'; import { FormattedMessage } from '@kbn/i18n-react'; -import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; import { getEmptyTagValue } from '../../../../common/components/empty_value'; -import type { - EnrichedFieldInfo, - EnrichedFieldInfoWithValues, -} from '../../../../common/components/event_details/types'; import { SIGNAL_STATUS_FIELD_NAME } from '../../../../timelines/components/timeline/body/renderers/constants'; -import { StatusPopoverButton } from '../../../../common/components/event_details/overview/status_popover_button'; +import { StatusPopoverButton } from './status_popover_button'; import { useDocumentDetailsContext } from '../../shared/context'; -import { getEnrichedFieldInfo } from '../../../../common/components/event_details/helpers'; +import type { EnrichedFieldInfo, EnrichedFieldInfoWithValues } from '../utils/enriched_field_info'; +import { getEnrichedFieldInfo } from '../utils/enriched_field_info'; import { CellActions } from './cell_actions'; import { STATUS_TITLE_TEST_ID } from './test_ids'; @@ -34,7 +30,6 @@ function hasData(fieldInfo?: EnrichedFieldInfo): fieldInfo is EnrichedFieldInfoW * Document details status displayed in flyout right section header */ export const DocumentStatus: FC = () => { - const { closeFlyout } = useExpandableFlyoutApi(); const { eventId, browserFields, dataFormattedForFieldBrowser, scopeId, isPreview } = useDocumentDetailsContext(); @@ -77,7 +72,6 @@ export const DocumentStatus: FC = () => { contextId={scopeId} enrichedFieldInfo={statusData} scopeId={scopeId} - handleOnEventClosed={closeFlyout} /> )} diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/overview/status_popover_button.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/status_popover_button.test.tsx similarity index 98% rename from x-pack/plugins/security_solution/public/common/components/event_details/overview/status_popover_button.test.tsx rename to x-pack/plugins/security_solution/public/flyout/document_details/right/components/status_popover_button.test.tsx index e6cb909bfaf01..e9161ba909ec6 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/overview/status_popover_button.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/status_popover_button.test.tsx @@ -9,8 +9,9 @@ import React from 'react'; import { render } from '@testing-library/react'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; import { StatusPopoverButton } from './status_popover_button'; -import { TestProviders } from '../../../mock'; +import { TestProviders } from '../../../../common/mock'; import { useAlertsPrivileges } from '../../../../detections/containers/detection_engine/alerts/use_alerts_privileges'; + const props = { eventId: 'testid', contextId: 'alerts-page', diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/overview/status_popover_button.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/status_popover_button.tsx similarity index 75% rename from x-pack/plugins/security_solution/public/common/components/event_details/overview/status_popover_button.tsx rename to x-pack/plugins/security_solution/public/flyout/document_details/right/components/status_popover_button.tsx index f02b37672545a..b5ff44ede0dd7 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/overview/status_popover_button.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/status_popover_button.tsx @@ -6,8 +6,10 @@ */ import { EuiContextMenu, EuiPopover, EuiPopoverTitle } from '@elastic/eui'; -import React, { useCallback, useMemo, useState } from 'react'; - +import React, { memo, useCallback, useMemo, useState } from 'react'; +import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { getFieldFormat } from '../utils/get_field_format'; +import type { EnrichedFieldInfoWithValues } from '../utils/enriched_field_info'; import { useAlertsActions } from '../../../../detections/components/alerts_table/timeline_actions/use_alerts_actions'; import type { Status } from '../../../../../common/api/detection_engine'; import { @@ -15,30 +17,44 @@ import { CLICK_TO_CHANGE_ALERT_STATUS, } from '../../../../detections/components/alerts_table/translations'; import { FormattedFieldValue } from '../../../../timelines/components/timeline/body/renderers/formatted_field'; -import type { EnrichedFieldInfoWithValues } from '../types'; -import type { inputsModel } from '../../../store'; -import { inputsSelectors } from '../../../store'; -import { useDeepEqualSelector } from '../../../hooks/use_selector'; -import { getFieldFormat } from '../get_field_format'; +import type { inputsModel } from '../../../../common/store'; +import { inputsSelectors } from '../../../../common/store'; +import { useDeepEqualSelector } from '../../../../common/hooks/use_selector'; interface StatusPopoverButtonProps { + /** + * Id of the document + */ eventId: string; + /** + * Value used to create a unique identifier in children components + */ contextId: string; + /** + * Information used to + */ enrichedFieldInfo: EnrichedFieldInfoWithValues; + /** + * Maintain backwards compatibility // TODO remove when possible + */ scopeId: string; - handleOnEventClosed: () => void; } -// TODO: MOVE TO FLYOUT FOLDER - https://github.com/elastic/security-team/issues/7462 -export const StatusPopoverButton = React.memo( - ({ eventId, contextId, enrichedFieldInfo, scopeId, handleOnEventClosed }) => { +/** + * Renders a button and its popover to display the status of an alert and allows the user to change it. + * It is used in the header of the document details flyout. + */ +export const StatusPopoverButton = memo( + ({ eventId, contextId, enrichedFieldInfo, scopeId }: StatusPopoverButtonProps) => { + const { closeFlyout } = useExpandableFlyoutApi(); + const [isPopoverOpen, setIsPopoverOpen] = useState(false); const togglePopover = useCallback(() => setIsPopoverOpen(!isPopoverOpen), [isPopoverOpen]); const closePopover = useCallback(() => setIsPopoverOpen(false), []); const closeAfterAction = useCallback(() => { closePopover(); - handleOnEventClosed(); - }, [closePopover, handleOnEventClosed]); + closeFlyout(); + }, [closeFlyout, closePopover]); const getGlobalQuerySelector = useMemo(() => inputsSelectors.globalQuery(), []); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/suppressed_alerts.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/suppressed_alerts.tsx index e8ef71bbe594e..a8cd147a4ac14 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/suppressed_alerts.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/suppressed_alerts.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiBetaBadge } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import type { Type } from '@kbn/securitysolution-io-ts-alerting-types'; +import { i18n } from '@kbn/i18n'; import { isSuppressionRuleInGA } from '../../../../../common/detection_engine/utils'; import { @@ -16,7 +17,13 @@ import { CORRELATIONS_SUPPRESSED_ALERTS_TECHNICAL_PREVIEW_TEST_ID, } from './test_ids'; import { InsightsSummaryRow } from './insights_summary_row'; -import { SUPPRESSED_ALERTS_COUNT_TECHNICAL_PREVIEW } from '../../../../common/components/event_details/insights/translations'; + +const SUPPRESSED_ALERTS_COUNT_TECHNICAL_PREVIEW = i18n.translate( + 'xpack.securitySolution.flyout.right.overview.insights.suppressedAlertsCountTechnicalPreview', + { + defaultMessage: 'Technical Preview', + } +); export interface SuppressedAlertsProps { /** diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/table_field_value_cell.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/table_field_value_cell.tsx index 8212ddc70c420..86950fa31837f 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/table_field_value_cell.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/table_field_value_cell.tsx @@ -8,7 +8,7 @@ import React, { memo } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; import type { FieldSpec } from '@kbn/data-plugin/common'; -import { getFieldFormat } from '../../../../common/components/event_details/get_field_format'; +import { getFieldFormat } from '../utils/get_field_format'; import type { EventFieldsData } from '../../../../common/components/event_details/types'; import { OverflowField } from '../../../../common/components/tables/helpers'; import { FormattedFieldValue } from '../../../../timelines/components/timeline/body/renderers/formatted_field'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/take_action_dropdown.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/take_action_dropdown.test.tsx index 6a902ef2b5ce6..6189f1b353ec8 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/take_action_dropdown.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/take_action_dropdown.test.tsx @@ -11,7 +11,7 @@ import { waitFor } from '@testing-library/react'; import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; import type { TakeActionDropdownProps } from './take_action_dropdown'; import { TakeActionDropdown } from './take_action_dropdown'; -import { generateAlertDetailsDataMock } from '../../../../common/components/event_details/__mocks__'; +import { mockAlertDetailsData } from '../../../../common/components/event_details/mocks'; import { getDetectionAlertMock } from '../../../../common/mock/mock_detection_alerts'; import { TimelineId } from '../../../../../common/types/timeline'; import { TestProviders } from '../../../../common/mock'; @@ -77,7 +77,7 @@ describe('take action dropdown', () => { beforeEach(() => { defaultProps = { - dataFormattedForFieldBrowser: generateAlertDetailsDataMock() as TimelineEventsDetailsItem[], + dataFormattedForFieldBrowser: mockAlertDetailsData as TimelineEventsDetailsItem[], dataAsNestedObject: getDetectionAlertMock(), handleOnEventClosed: jest.fn(), isHostIsolationPanelOpen: false, diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_assistant.ts b/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_assistant.ts index 2196674964cfe..da65a684b026c 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_assistant.ts +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_assistant.ts @@ -8,6 +8,7 @@ import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; import { useAssistantOverlay } from '@kbn/elastic-assistant'; import { useCallback } from 'react'; +import { i18n } from '@kbn/i18n'; import { useAssistantAvailability } from '../../../../assistant/use_assistant_availability'; import { getRawData } from '../../../../assistant/helpers'; import { @@ -17,7 +18,6 @@ import { EVENT_SUMMARY_CONTEXT_DESCRIPTION, EVENT_SUMMARY_CONVERSATION_ID, EVENT_SUMMARY_VIEW_CONTEXT_TOOLTIP, - SUMMARY_VIEW, } from '../../../../common/components/event_details/translations'; import { PROMPT_CONTEXT_ALERT_CATEGORY, @@ -25,6 +25,10 @@ import { PROMPT_CONTEXTS, } from '../../../../assistant/content/prompt_contexts'; +const SUMMARY_VIEW = i18n.translate('xpack.securitySolution.eventDetails.summaryView', { + defaultMessage: 'summary', +}); + const useAssistantNoop = () => ({ promptContextId: undefined }); export interface UseAssistantParams { diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/utils/enriched_field_info.ts b/x-pack/plugins/security_solution/public/flyout/document_details/right/utils/enriched_field_info.ts new file mode 100644 index 0000000000000..110cd30556e98 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/utils/enriched_field_info.ts @@ -0,0 +1,70 @@ +/* + * 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 { BrowserFields, TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; +import { get, getOr } from 'lodash/fp'; +import type { FieldSpec } from '@kbn/data-views-plugin/common'; +import type { + EventFieldsData, + EventSummaryField, + FieldsData, +} from '../../../../common/components/event_details/types'; + +export interface EnrichedFieldInfo { + data: FieldsData | EventFieldsData; + eventId: string; + fieldFromBrowserField?: Partial; + scopeId: string; + values: string[] | null | undefined; + linkValue?: string; +} + +export type EnrichedFieldInfoWithValues = EnrichedFieldInfo & { values: string[] }; + +export function getEnrichedFieldInfo({ + browserFields, + contextId, + eventId, + field, + item, + linkValueField, + scopeId, +}: { + browserFields: BrowserFields; + contextId: string; + item: TimelineEventsDetailsItem; + eventId: string; + field?: EventSummaryField; + scopeId: string; + linkValueField?: TimelineEventsDetailsItem; +}): EnrichedFieldInfo { + const fieldInfo = { + contextId, + eventId, + fieldType: 'string', + linkValue: undefined, + scopeId, + }; + const linkValue = getOr(null, 'originalValue.0', linkValueField); + const category = item.category ?? ''; + const fieldName = item.field ?? ''; + + const browserField = get([category, 'fields', fieldName], browserFields); + const overrideField = field?.overrideField; + return { + ...fieldInfo, + data: { + field: overrideField ?? fieldName, + format: browserField?.format?.id ?? '', + type: browserField?.type ?? '', + isObjectArray: item.isObjectArray, + }, + values: item.values, + linkValue: linkValue ?? undefined, + fieldFromBrowserField: browserField, + }; +} diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/get_field_format.ts b/x-pack/plugins/security_solution/public/flyout/document_details/right/utils/get_field_format.ts similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/event_details/get_field_format.ts rename to x-pack/plugins/security_solution/public/flyout/document_details/right/utils/get_field_format.ts diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/anomalies_field.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/anomalies_field.tsx index ea5e7b17202f0..b050e2a55ed52 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/anomalies_field.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/anomalies_field.tsx @@ -7,6 +7,7 @@ import React, { useCallback } from 'react'; import { useDispatch } from 'react-redux'; +import type { NarrowDateRange } from '../../../../common/components/ml/types'; import type { EntityAnomalies } from './observed_entity/types'; import { AnomalyScores } from '../../../../common/components/ml/score/anomaly_scores'; import { useGlobalTime } from '../../../../common/containers/use_global_time'; @@ -18,7 +19,7 @@ export const AnomaliesField = ({ anomalies }: { anomalies: EntityAnomalies }) => const { to, from } = useGlobalTime(); const dispatch = useDispatch(); - const narrowDateRange = useCallback( + const narrowDateRange = useCallback( (score, interval) => { const fromTo = scoreIntervalToDateTime(score, interval); dispatch( diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_list_page/hooks/use_set_url_params.ts b/x-pack/plugins/security_solution/public/management/components/artifact_list_page/hooks/use_set_url_params.ts index f6199f1c6c171..cf3cce3dc9f03 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_list_page/hooks/use_set_url_params.ts +++ b/x-pack/plugins/security_solution/public/management/components/artifact_list_page/hooks/use_set_url_params.ts @@ -10,17 +10,19 @@ import { useCallback } from 'react'; import { pickBy } from 'lodash'; import { useUrlParams } from '../../../hooks/use_url_params'; -// FIXME:PT Refactor into a more generic hooks for managing url params -export const useSetUrlParams = (): (( +type UseSetUrlParams = ( /** Any param whose value is `undefined` will be removed from the URl when in append mode */ params: Record, replace?: boolean -) => void) => { +) => void; + +// FIXME:PT Refactor into a more generic hooks for managing url params +export const useSetUrlParams = (): UseSetUrlParams => { const location = useLocation(); const history = useHistory(); const { toUrlParams, urlParams: currentUrlParams } = useUrlParams(); - return useCallback( + return useCallback( (params, replace = false) => { history.push({ ...location, diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/components/command_input_history.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/components/command_input_history.tsx index 4e192a80d5b84..6879043eb1fc0 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/components/command_input_history.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/components/command_input_history.tsx @@ -122,9 +122,12 @@ export const CommandInputHistory = memo(() => { [dispatch] ); - const handleRenderOption = useCallback((option) => { - return ; - }, []); + const handleRenderOption = useCallback>( + (option) => { + return ; + }, + [] + ); // When first loaded, clear out the current text entered, and when this component // unloads, if no option from the history was selected, then set the prior text diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/command_list.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/command_list.tsx index e6323fccb847e..d7644b60a7f7c 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/command_list.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/command_list.tsx @@ -125,7 +125,7 @@ export const CommandList = memo(({ commands, display = 'defaul }, []); const updateInputText = useCallback( - (text) => () => { + (text: string) => () => { dispatch({ type: 'updateInputTextEnteredState', payload: () => { @@ -218,7 +218,7 @@ export const CommandList = memo(({ commands, display = 'defaul ); const getTableColumns = useCallback( - (commandsByGroup) => { + (commandsByGroup: CommandDefinition[]) => { const groupLabel = commandsByGroup[0]?.helpGroupLabel ?? otherCommandsGroupLabel; const groupTestIdSuffix = convertToTestId(groupLabel); @@ -294,7 +294,7 @@ export const CommandList = memo(({ commands, display = 'defaul ); const getFilteredCommands = useCallback( - (commandsByGroup): CommandDefinition[] => + (commandsByGroup: CommandDefinition[]): CommandDefinition[] => commandsByGroup.filter( (current: CommandDefinition) => current.name !== 'help' && current.name !== 'clear' ), diff --git a/x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.tsx b/x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.tsx index 079ea01492dcc..fbfc76c77ac7d 100644 --- a/x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.tsx +++ b/x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.tsx @@ -190,7 +190,7 @@ export const EffectedPolicySelect = memo( ); const handleGlobalButtonChange = useCallback( - (selectedId) => { + (selectedId: string) => { onChange({ isGlobal: selectedId === 'globalPolicy', selected, diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/integration_tests/scan_action.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/integration_tests/scan_action.test.tsx index 4457119128e46..302a97f5aafff 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/integration_tests/scan_action.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/integration_tests/scan_action.test.tsx @@ -58,7 +58,6 @@ describe('When using scan action from response actions console', () => { beforeEach(() => { mockedContext = createAppRootMockRenderer(); - mockedContext.setExperimentalFlag({ responseActionScanEnabled: true }); apiMocks = responseActionsHttpMocks(mockedContext.coreStart.http); endpointPrivileges = { ...getEndpointAuthzInitialStateMock(), diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/lib/console_commands_definition.ts b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/lib/console_commands_definition.ts index 74c43fb535f5f..c81674bd4f7b8 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/lib/console_commands_definition.ts +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/lib/console_commands_definition.ts @@ -164,7 +164,6 @@ export const getEndpointConsoleCommands = ({ const featureFlags = ExperimentalFeaturesService.get(); const isUploadEnabled = featureFlags.responseActionUploadEnabled; - const isScanEnabled = featureFlags.responseActionScanEnabled; const doesEndpointSupportCommand = (commandName: ConsoleResponseActionCommands) => { // Agent capabilities is only validated for Endpoint agent types @@ -486,43 +485,41 @@ export const getEndpointConsoleCommands = ({ }); } - if (isScanEnabled) { - consoleCommands.push({ - name: 'scan', - about: getCommandAboutInfo({ - aboutInfo: CONSOLE_COMMANDS.scan.about, - isSupported: doesEndpointSupportCommand('scan'), - }), - RenderComponent: ScanActionResult, - meta: { - agentType, - endpointId: endpointAgentId, - capabilities: endpointCapabilities, - privileges: endpointPrivileges, - }, - exampleUsage: 'scan --path "/full/path/to/folder" --comment "Scan folder for malware"', - exampleInstruction: ENTER_OR_ADD_COMMENT_ARG_INSTRUCTION, - validate: capabilitiesAndPrivilegesValidator(agentType), - mustHaveArgs: true, - args: { - path: { - required: true, - allowMultiples: false, - mustHaveValue: 'non-empty-string', - about: CONSOLE_COMMANDS.scan.args.path.about, - }, - ...commandCommentArgument(), + consoleCommands.push({ + name: 'scan', + about: getCommandAboutInfo({ + aboutInfo: CONSOLE_COMMANDS.scan.about, + isSupported: doesEndpointSupportCommand('scan'), + }), + RenderComponent: ScanActionResult, + meta: { + agentType, + endpointId: endpointAgentId, + capabilities: endpointCapabilities, + privileges: endpointPrivileges, + }, + exampleUsage: 'scan --path "/full/path/to/folder" --comment "Scan folder for malware"', + exampleInstruction: ENTER_OR_ADD_COMMENT_ARG_INSTRUCTION, + validate: capabilitiesAndPrivilegesValidator(agentType), + mustHaveArgs: true, + args: { + path: { + required: true, + allowMultiples: false, + mustHaveValue: 'non-empty-string', + about: CONSOLE_COMMANDS.scan.args.path.about, }, - helpGroupLabel: HELP_GROUPS.responseActions.label, - helpGroupPosition: HELP_GROUPS.responseActions.position, - helpCommandPosition: 8, - helpDisabled: !doesEndpointSupportCommand('scan'), - helpHidden: !getRbacControl({ - commandName: 'scan', - privileges: endpointPrivileges, - }), - }); - } + ...commandCommentArgument(), + }, + helpGroupLabel: HELP_GROUPS.responseActions.label, + helpGroupPosition: HELP_GROUPS.responseActions.position, + helpCommandPosition: 8, + helpDisabled: !doesEndpointSupportCommand('scan'), + helpHidden: !getRbacControl({ + commandName: 'scan', + privileges: endpointPrivileges, + }), + }); switch (agentType) { case 'sentinel_one': diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/lib/integration_tests/console_commands_definition.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/lib/integration_tests/console_commands_definition.test.tsx index a20aa3bd61a2e..7c1e5cf118df0 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/lib/integration_tests/console_commands_definition.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/lib/integration_tests/console_commands_definition.test.tsx @@ -46,7 +46,6 @@ describe('When displaying Endpoint Response Actions', () => { beforeEach(() => { (ExperimentalFeaturesService.get as jest.Mock).mockReturnValue({ responseActionUploadEnabled: true, - responseActionScanEnabled: true, }); commands = getEndpointConsoleCommands({ agentType: 'endpoint', diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx index 0fe111965f463..fb2caac789451 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx @@ -55,7 +55,7 @@ export const useDateRangePicker = (isFlyout: boolean) => { }); const updateActionListDateRanges = useCallback( - ({ start, end }) => { + ({ start, end }: DurationRange) => { setDateRangePickerState((prevState) => ({ ...prevState, startDate: start, @@ -66,7 +66,7 @@ export const useDateRangePicker = (isFlyout: boolean) => { ); const updateActionListRecentlyUsedDateRanges = useCallback( - (recentlyUsedDateRanges) => { + (recentlyUsedDateRanges: DateRangePickerValues['recentlyUsedDateRanges']) => { setDateRangePickerState((prevState) => ({ ...prevState, recentlyUsedDateRanges, @@ -334,11 +334,6 @@ export const useActionsLogFilter = ({ return false; } - // `scan` - v8.15 - if (commandName === 'scan' && !featureFlags.responseActionScanEnabled) { - return false; - } - return true; }).map((commandName) => ({ key: commandName, diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/integration_tests/response_actions_log.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/integration_tests/response_actions_log.test.tsx index c15e8d1752852..17c15ca46a61b 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/integration_tests/response_actions_log.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/integration_tests/response_actions_log.test.tsx @@ -1491,7 +1491,6 @@ describe('Response actions history', () => { beforeEach(() => { featureFlags = { responseActionUploadEnabled: true, - responseActionScanEnabled: false, }; mockedContext.setExperimentalFlag(featureFlags); @@ -1511,37 +1510,7 @@ describe('Response actions history', () => { ); }); - it('should show a list of actions (without `scan`) when opened', () => { - mockedContext.setExperimentalFlag({ - ...featureFlags, - responseActionScanEnabled: false, - }); - render(); - const { getByTestId, getAllByTestId } = renderResult; - - userEvent.click(getByTestId(`${testPrefix}-${filterPrefix}-popoverButton`)); - const filterList = getByTestId(`${testPrefix}-${filterPrefix}-popoverList`); - expect(filterList).toBeTruthy(); - expect(getAllByTestId(`${filterPrefix}-option`).length).toEqual( - RESPONSE_ACTION_API_COMMANDS_NAMES.length - 1 - ); - expect(getAllByTestId(`${filterPrefix}-option`).map((option) => option.textContent)).toEqual([ - 'isolate. To check this option, press Enter.', - 'release. To check this option, press Enter.', - 'kill-process. To check this option, press Enter.', - 'suspend-process. To check this option, press Enter.', - 'processes. To check this option, press Enter.', - 'get-file. To check this option, press Enter.', - 'execute. To check this option, press Enter.', - 'upload. To check this option, press Enter.', - ]); - }); - it('should show a list of actions (with `scan`) when opened', () => { - mockedContext.setExperimentalFlag({ - ...featureFlags, - responseActionScanEnabled: true, - }); render(); const { getByTestId, getAllByTestId } = renderResult; diff --git a/x-pack/plugins/security_solution/public/management/components/search_exceptions/search_exceptions.tsx b/x-pack/plugins/security_solution/public/management/components/search_exceptions/search_exceptions.tsx index dbcdb011d28f3..51ff76158f3b8 100644 --- a/x-pack/plugins/security_solution/public/management/components/search_exceptions/search_exceptions.tsx +++ b/x-pack/plugins/security_solution/public/management/components/search_exceptions/search_exceptions.tsx @@ -6,6 +6,7 @@ */ import React, { memo, useCallback, useState } from 'react'; +import type { EuiFieldSearchProps } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiFieldSearch, EuiButton } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import type { PolicySelectionItem } from '../policies_selector'; @@ -67,7 +68,7 @@ export const SearchExceptions = memo( [onSearch, query, includedPolicies] ); - const handleOnSearchQuery = useCallback( + const handleOnSearchQuery = useCallback>( (value) => { onSearch(value, includedPolicies, false); }, diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/scan.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/scan.cy.ts index a786a0d682096..04630647ed35f 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/scan.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/scan.cy.ts @@ -25,11 +25,13 @@ describe( { env: { ftrConfig: { - kbnServerArgs: [ - `--xpack.securitySolution.enableExperimental=${JSON.stringify([ - 'responseActionScanEnabled', - ])}`, - ], + // This is not needed for this test, but it's a good example of + // how to enable experimental features in the Cypress tests. + // kbnServerArgs: [ + // `--xpack.securitySolution.enableExperimental=${JSON.stringify([ + // 'featureFlagName', + // ])}`, + // ], }, }, tags: ['@ess', '@serverless', '@skipInServerlessMKI'], diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/complete.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/complete.cy.ts index 21a7253109d4a..3ff347b320fe7 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/complete.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/complete.cy.ts @@ -18,11 +18,13 @@ describe( env: { ftrConfig: { productTypes: [{ product_line: 'security', product_tier: 'complete' }], - kbnServerArgs: [ - `--xpack.securitySolution.enableExperimental=${JSON.stringify([ - 'responseActionScanEnabled', - ])}`, - ], + // This is not needed for this test, but it's a good example of + // how to enable experimental features in the Cypress tests. + // kbnServerArgs: [ + // `--xpack.securitySolution.enableExperimental=${JSON.stringify([ + // 'featureFlagName', + // ])}`, + // ], }, }, }, diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/complete_with_endpoint.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/complete_with_endpoint.cy.ts index 54d5b688aa1d1..fa48a2589a9c9 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/complete_with_endpoint.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/complete_with_endpoint.cy.ts @@ -24,11 +24,13 @@ describe( { product_line: 'security', product_tier: 'complete' }, { product_line: 'endpoint', product_tier: 'complete' }, ], - kbnServerArgs: [ - `--xpack.securitySolution.enableExperimental=${JSON.stringify([ - 'responseActionScanEnabled', - ])}`, - ], + // This is not needed for this test, but it's a good example of + // how to enable experimental features in the Cypress tests. + // kbnServerArgs: [ + // `--xpack.securitySolution.enableExperimental=${JSON.stringify([ + // 'featureFlagName', + // ])}`, + // ], }, }, }, diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/essentials.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/essentials.cy.ts index 7be22d7e7e5b5..ad3c2a3a1bb61 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/essentials.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/essentials.cy.ts @@ -18,11 +18,13 @@ describe( env: { ftrConfig: { productTypes: [{ product_line: 'security', product_tier: 'essentials' }], - kbnServerArgs: [ - `--xpack.securitySolution.enableExperimental=${JSON.stringify([ - 'responseActionScanEnabled', - ])}`, - ], + // This is not needed for this test, but it's a good example of + // how to enable experimental features in the Cypress tests. + // kbnServerArgs: [ + // `--xpack.securitySolution.enableExperimental=${JSON.stringify([ + // 'featureFlagName', + // ])}`, + // ], }, }, }, diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/essentials_with_endpoint.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/essentials_with_endpoint.cy.ts index a57102e7a2b2c..c43acf317bf21 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/essentials_with_endpoint.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/essentials_with_endpoint.cy.ts @@ -24,11 +24,13 @@ describe( { product_line: 'security', product_tier: 'essentials' }, { product_line: 'endpoint', product_tier: 'essentials' }, ], - kbnServerArgs: [ - `--xpack.securitySolution.enableExperimental=${JSON.stringify([ - 'responseActionScanEnabled', - ])}`, - ], + // This is not needed for this test, but it's a good example of + // how to enable experimental features in the Cypress tests. + // kbnServerArgs: [ + // `--xpack.securitySolution.enableExperimental=${JSON.stringify([ + // 'featureFlagName', + // ])}`, + // ], }, }, }, diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/roles/complete_with_endpoint_roles.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/roles/complete_with_endpoint_roles.cy.ts index a31ae854aa059..17a378cb95fa8 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/roles/complete_with_endpoint_roles.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/roles/complete_with_endpoint_roles.cy.ts @@ -40,11 +40,13 @@ describe( { product_line: 'security', product_tier: 'complete' }, { product_line: 'endpoint', product_tier: 'complete' }, ], - kbnServerArgs: [ - `--xpack.securitySolution.enableExperimental=${JSON.stringify([ - 'responseActionScanEnabled', - ])}`, - ], + // This is not needed for this test, but it's a good example of + // how to enable experimental features in the Cypress tests. + // kbnServerArgs: [ + // `--xpack.securitySolution.enableExperimental=${JSON.stringify([ + // 'featureFlagName', + // ])}`, + // ], }, }, }, diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx index 3c0d08821f6e7..2ed2b20ab78a7 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx @@ -7,7 +7,7 @@ import React, { useCallback, useMemo } from 'react'; import styled from 'styled-components'; -import type { CriteriaWithPagination } from '@elastic/eui'; +import type { CriteriaWithPagination, EuiSuperDatePickerProps } from '@elastic/eui'; import { EuiBasicTable, type EuiBasicTableColumn, @@ -452,7 +452,7 @@ export const EndpointList = () => { }); }, [dispatch]); - const onRefreshChange = useCallback( + const onRefreshChange = useCallback>( (evt) => { dispatch({ type: 'userUpdatedEndpointListRefreshOptions', @@ -573,13 +573,15 @@ export const EndpointList = () => { ); } else if (!policyItemsLoading && hasPolicyData) { - const selectionOptions: EuiSelectableProps['options'] = policyItems.map((item) => { - return { - key: item.policy_id, - label: item.name, - checked: selectedPolicyId === item.policy_id ? 'on' : undefined, - }; - }); + const selectionOptions: EuiSelectableProps['options'] = policyItems + .filter((item) => item.policy_id) + .map((item) => { + return { + key: item.policy_id as string, + label: item.name, + checked: selectedPolicyId === item.policy_id ? 'on' : undefined, + }; + }); return ( ( searchableFields ); - const handleOnSearch = useCallback((query) => { + const handleOnSearch = useCallback((query: string) => { setSelectedArtifactIds([]); setCurrentFilter(query); }, []); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/artifacts/layout/policy_artifacts_layout.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/artifacts/layout/policy_artifacts_layout.tsx index 75927ece7dfde..15c347438f5a1 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/artifacts/layout/policy_artifacts_layout.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/artifacts/layout/policy_artifacts_layout.tsx @@ -28,6 +28,7 @@ import { usePolicyDetailsArtifactsNavigateCallback } from '../../policy_hooks'; import type { ExceptionsListApiClient } from '../../../../../services/exceptions_list/exceptions_list_api_client'; import { useListArtifact } from '../../../../../hooks/artifacts'; import { PolicyArtifactsEmptyUnassigned, PolicyArtifactsEmptyUnexisting } from '../empty'; +import type { PolicyArtifactsListProps } from '../list'; import { PolicyArtifactsList } from '../list'; import { PolicyArtifactsFlyout } from '../flyout'; import type { PolicyArtifactsPageLabels } from '../translations'; @@ -106,7 +107,9 @@ export const PolicyArtifactsLayout = React.memo( setExceptionItemToDelete(undefined); }, [setExceptionItemToDelete]); - const handleOnDeleteActionCallback = useCallback( + const handleOnDeleteActionCallback = useCallback< + PolicyArtifactsListProps['onDeleteActionCallback'] + >( (item) => { setExceptionItemToDelete(item); }, diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/artifacts/list/index.ts b/x-pack/plugins/security_solution/public/management/pages/policy/view/artifacts/list/index.ts index 260b580de7497..68361a01d0d1f 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/artifacts/list/index.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/artifacts/list/index.ts @@ -6,4 +6,5 @@ */ export { PolicyArtifactsList } from './policy_artifacts_list'; +export type { PolicyArtifactsListProps } from './policy_artifacts_list'; export { POLICY_ARTIFACT_LIST_LABELS } from './translations'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/artifacts/list/policy_artifacts_list.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/artifacts/list/policy_artifacts_list.tsx index 082012295b023..696e29f770645 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/artifacts/list/policy_artifacts_list.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/artifacts/list/policy_artifacts_list.tsx @@ -12,6 +12,7 @@ import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-t import type { ArtifactEntryCardDecoratorProps } from '../../../../../components/artifact_entry_card'; import { useAppUrl } from '../../../../../../common/lib/kibana'; import { APP_UI_ID } from '../../../../../../../common/constants'; +import type { SearchExceptionsProps } from '../../../../../components/search_exceptions'; import { SearchExceptions } from '../../../../../components/search_exceptions'; import { useEndpointPoliciesToArtifactPolicies } from '../../../../../components/artifact_entry_card/hooks/use_endpoint_policies_to_artifact_policies'; import { useUrlParams } from '../../../../../hooks/use_url_params'; @@ -30,7 +31,7 @@ import { useListArtifact } from '../../../../../hooks/artifacts'; import type { POLICY_ARTIFACT_LIST_LABELS } from './translations'; import type { ArtifactListPageUrlParams } from '../../../../../components/artifact_list_page'; -interface PolicyArtifactsListProps { +export interface PolicyArtifactsListProps { policy: ImmutableObject; apiClient: ExceptionsListApiClient; searchableFields: string[]; @@ -91,7 +92,7 @@ export const PolicyArtifactsList = React.memo( [artifacts?.total, pageSizeOptions, urlPagination.page, urlPagination.pageSize] ); - const handleOnSearch = useCallback( + const handleOnSearch = useCallback( (filter) => { navigateCallback({ filter }); }, @@ -123,7 +124,7 @@ export const PolicyArtifactsList = React.memo( }, [artifacts?.data.length, labels]); const artifactCardPolicies = useEndpointPoliciesToArtifactPolicies(policiesRequest.data?.items); - const provideCardProps = useCallback( + const provideCardProps = useCallback>( (artifact) => { const viewUrlPath = getArtifactPath({ filter: (artifact as ExceptionListItemSchema).item_id, diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/advanced_section.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/advanced_section.tsx index 063c3b830b7a1..2720126987117 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/advanced_section.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/advanced_section.tsx @@ -7,6 +7,7 @@ import React, { memo, useCallback, useState } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; +import type { EuiFieldTextProps } from '@elastic/eui'; import { EuiCallOut, EuiFieldText, @@ -120,7 +121,7 @@ export const AdvancedSection = memo( setShowAdvancedPolicy((prevState) => !prevState); }, []); - const handleAdvancedSettingUpdate = useCallback( + const handleAdvancedSettingUpdate = useCallback>( (event) => { const updatedPolicy = cloneDeep(policy); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/attack_surface_reduction_card.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/attack_surface_reduction_card.tsx index ecb73adfa3341..052ceffc65754 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/attack_surface_reduction_card.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/attack_surface_reduction_card.tsx @@ -7,6 +7,7 @@ import React, { memo, useCallback } from 'react'; import { OperatingSystem } from '@kbn/securitysolution-utils'; +import type { EuiSwitchProps } from '@elastic/eui'; import { EuiSwitch } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { cloneDeep } from 'lodash'; @@ -50,7 +51,7 @@ export const AttackSurfaceReductionCard = memo( const isChecked = policy.windows.attack_surface_reduction.credential_hardening.enabled; const isEditMode = mode === 'edit'; - const handleSwitchChange = useCallback( + const handleSwitchChange = useCallback( (event) => { const updatedPolicy = cloneDeep(policy); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/malware_protections_card.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/malware_protections_card.tsx index f1eda1ac0915e..634c24a1c1f51 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/malware_protections_card.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/malware_protections_card.tsx @@ -7,6 +7,7 @@ import React, { memo, useCallback } from 'react'; import { i18n } from '@kbn/i18n'; +import type { EuiSwitchProps } from '@elastic/eui'; import { EuiSpacer, EuiSwitch, EuiFlexGroup, EuiFlexItem, EuiIconTip } from '@elastic/eui'; import { OperatingSystem } from '@kbn/securitysolution-utils'; import { cloneDeep } from 'lodash'; @@ -223,7 +224,7 @@ const SubfeatureSwitch = memo( const isEditMode = mode === 'edit'; const isDisabled = policy.windows.malware.mode === 'off' || !isEditMode; - const handleBlocklistSwitchChange = useCallback( + const handleBlocklistSwitchChange = useCallback( (event) => { const value = event.target.checked; const newPayload = cloneDeep(policy); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/protection_seetings_card/components/reputation_service.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/protection_seetings_card/components/reputation_service.tsx index 2de776069f5e5..7ff4ad6b3681b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/protection_seetings_card/components/reputation_service.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/protection_seetings_card/components/reputation_service.tsx @@ -6,6 +6,7 @@ */ import React, { useCallback } from 'react'; +import type { EuiCheckboxProps } from '@elastic/eui'; import { EuiCheckbox, EuiFlexGroup, @@ -48,7 +49,7 @@ export const ReputationService = React.memo( const checkboxChecked = policy.windows.behavior_protection.reputation_service && protectionTurnedOn; - const handleChange = useCallback( + const handleChange = useCallback( (event) => { const newPayload = cloneDeep(policy); newPayload.windows.behavior_protection.reputation_service = event.target.checked; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/event_collection_card.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/event_collection_card.tsx index c74496c7512b8..a1fee2d77b01d 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/event_collection_card.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/event_collection_card.tsx @@ -20,7 +20,7 @@ import { EuiText, } from '@elastic/eui'; import { cloneDeep, get, set } from 'lodash'; -import type { EuiCheckboxProps } from '@elastic/eui/src/components/form/checkbox/checkbox'; +import type { EuiCheckboxProps } from '@elastic/eui'; import { getEmptyValue } from '../../../../../../common/components/empty_value'; import { useTestIdGenerator } from '../../../../../hooks/use_test_id_generator'; import type { PolicyFormComponentCommonProps } from '../types'; @@ -253,7 +253,7 @@ const EventCheckbox = memo( ({ policy, onChange, label, keyPath, disabled, 'data-test-subj': dataTestSubj }) => { const isChecked: boolean = get(policy, keyPath); - const checkboxOnChangeHandler = useCallback( + const checkboxOnChangeHandler = useCallback>( (ev) => { const updatedPolicy = cloneDeep(policy); set(updatedPolicy, keyPath, ev.target.checked); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/notify_user_option.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/notify_user_option.tsx index 2c05b267bb329..9181e643f393a 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/notify_user_option.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/notify_user_option.tsx @@ -9,6 +9,7 @@ import React, { useCallback, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { cloneDeep } from 'lodash'; +import type { EuiTextAreaProps, EuiCheckboxProps } from '@elastic/eui'; import { EuiSpacer, EuiFlexItem, @@ -76,7 +77,7 @@ export const NotifyUserOption = React.memo( const userNotificationSelected = policy.windows.popup[protection].enabled; const userNotificationMessage = policy.windows.popup[protection].message; - const handleUserNotificationCheckbox = useCallback( + const handleUserNotificationCheckbox = useCallback( (event) => { const newPayload = cloneDeep(policy); @@ -96,7 +97,7 @@ export const NotifyUserOption = React.memo( [policy, onChange, osList, protection] ); - const handleCustomUserNotification = useCallback( + const handleCustomUserNotification = useCallback>( (event) => { const newPayload = cloneDeep(policy); for (const os of osList) { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/protection_setting_card_switch.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/protection_setting_card_switch.tsx index d4561be6e5313..f1dfcac009211 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/protection_setting_card_switch.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/protection_setting_card_switch.tsx @@ -6,6 +6,7 @@ */ import React, { useCallback } from 'react'; +import type { EuiSwitchProps } from '@elastic/eui'; import { EuiSwitch } from '@elastic/eui'; import { cloneDeep } from 'lodash'; import { useTestIdGenerator } from '../../../../../hooks/use_test_id_generator'; @@ -51,7 +52,7 @@ export const ProtectionSettingCardSwitch = React.memo( const isPlatinumPlus = useLicense().isPlatinumPlus(); const isEditMode = mode === 'edit'; - const handleSwitchChange = useCallback( + const handleSwitchChange = useCallback( (event) => { const newPayload = cloneDeep(policy); diff --git a/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.test.tsx b/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.test.tsx index e49385ccc7eca..f6152733a2254 100644 --- a/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.test.tsx @@ -461,33 +461,7 @@ describe('Response actions history page', () => { expect(history.location.search).toEqual('?page=1&pageSize=20'); }); - // TODO: remove this test when responseActionScanEnabled is removed - it('should set selected command filter options to URL params (without `responseActionScanEnabled`)', () => { - mockedContext.setExperimentalFlag({ - responseActionScanEnabled: false, - }); - - const filterPrefix = 'actions-filter'; - render(); - const { getAllByTestId, getByTestId } = renderResult; - userEvent.click(getByTestId(`${testPrefix}-${filterPrefix}-popoverButton`)); - const allFilterOptions = getAllByTestId(`${filterPrefix}-option`); - - allFilterOptions.forEach((option) => { - option.style.pointerEvents = 'all'; - userEvent.click(option); - }); - - expect(history.location.search).toEqual( - '?commands=isolate%2Crelease%2Ckill-process%2Csuspend-process%2Cprocesses%2Cget-file%2Cexecute%2Cupload' - ); - }); - - it('should set selected command filter options to URL params (with `responseActionScanEnabled`)', () => { - mockedContext.setExperimentalFlag({ - responseActionScanEnabled: true, - }); - + it('should set selected command filter options to URL params', () => { const filterPrefix = 'actions-filter'; render(); const { getAllByTestId, getByTestId } = renderResult; @@ -631,38 +605,7 @@ describe('Response actions history page', () => { }); describe('Clear all selected options on a filter', () => { - // TODO: remove this test when responseActionScanEnabled is removed - it('should clear all selected options on `actions` filter (without `responseActionScanEnabled`)', () => { - mockedContext.setExperimentalFlag({ - responseActionScanEnabled: false, - }); - - const filterPrefix = 'actions-filter'; - render(); - const { getAllByTestId, getByTestId } = renderResult; - userEvent.click(getByTestId(`${testPrefix}-${filterPrefix}-popoverButton`)); - const allFilterOptions = getAllByTestId(`${filterPrefix}-option`); - - allFilterOptions.forEach((option) => { - option.style.pointerEvents = 'all'; - userEvent.click(option); - }); - - expect(history.location.search).toEqual( - '?commands=isolate%2Crelease%2Ckill-process%2Csuspend-process%2Cprocesses%2Cget-file%2Cexecute%2Cupload' - ); - - const clearAllButton = getByTestId(`${testPrefix}-${filterPrefix}-clearAllButton`); - clearAllButton.style.pointerEvents = 'all'; - userEvent.click(clearAllButton); - expect(history.location.search).toEqual(''); - }); - - it('should clear all selected options on `actions` filter (with `responseActionScanEnabled`)', () => { - mockedContext.setExperimentalFlag({ - responseActionScanEnabled: true, - }); - + it('should clear all selected options on `actions` filter', () => { const filterPrefix = 'actions-filter'; render(); const { getAllByTestId, getByTestId } = renderResult; diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/condition_entry_input/index.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/condition_entry_input/index.tsx index 21e183834ea79..3ce26c70d3186 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/condition_entry_input/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/condition_entry_input/index.tsx @@ -9,8 +9,9 @@ import type { ChangeEventHandler } from 'react'; import React, { memo, useCallback, useMemo, useState } from 'react'; import styled from 'styled-components'; import { i18n } from '@kbn/i18n'; -import type { EuiSuperSelectOption } from '@elastic/eui'; +import type { EuiSuperSelectOption, EuiSuperSelectProps } from '@elastic/eui'; import { EuiButtonIcon, EuiFieldText, EuiFormRow, EuiSuperSelect, EuiText } from '@elastic/eui'; +import type { TrustedAppEntryTypes } from '@kbn/securitysolution-utils'; import { ConditionEntryField, OperatingSystem } from '@kbn/securitysolution-utils'; import type { TrustedAppConditionEntry } from '../../../../../../../common/endpoint/types'; import { OperatorFieldIds } from '../../../../../../../common/endpoint/types'; @@ -73,11 +74,13 @@ const InputItem = styled.div<{ gridArea: string }>` vertical-align: baseline; `; -const operatorOptions = (Object.keys(OperatorFieldIds) as OperatorFieldIds[]).map((value) => ({ - dropdownDisplay: OPERATOR_TITLES[value], - inputDisplay: OPERATOR_TITLES[value], - value: value === 'matches' ? 'wildcard' : 'match', -})); +const operatorOptions = (Object.keys(OperatorFieldIds) as OperatorFieldIds[]).map( + (value): EuiSuperSelectOption => ({ + dropdownDisplay: OPERATOR_TITLES[value], + inputDisplay: OPERATOR_TITLES[value], + value: value === 'matches' ? 'wildcard' : 'match', + }) +); export const ConditionEntryInput = memo( ({ @@ -101,7 +104,7 @@ export const ConditionEntryInput = memo( } }, [entry, isVisited, onVisited]); - const fieldOptions = useMemo>>(() => { + const fieldOptions = useMemo>>(() => { const getDropdownDisplay = (field: ConditionEntryField) => ( <> {CONDITION_FIELD_TITLE[field]} @@ -148,7 +151,9 @@ export const ConditionEntryInput = memo( [entry, onChange] ); - const handleFieldUpdate = useCallback( + const handleFieldUpdate = useCallback< + NonNullable['onChange']> + >( (newField) => { onChange({ ...entry, field: newField }, entry); @@ -159,10 +164,9 @@ export const ConditionEntryInput = memo( [handleVisited, entry, onChange] ); - const handleOperatorUpdate = useCallback( - (newOperator) => onChange({ ...entry, type: newOperator }, entry), - [entry, onChange] - ); + const handleOperatorUpdate = useCallback< + NonNullable['onChange']> + >((newOperator) => onChange({ ...entry, type: newOperator }, entry), [entry, onChange]); const handleRemoveClick = useCallback(() => onRemove(entry), [entry, onRemove]); diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/form.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/form.tsx index ce168c5c06467..893956af34f7a 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/form.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/form.tsx @@ -7,7 +7,7 @@ import type { ChangeEventHandler } from 'react'; import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'; -import type { EuiSuperSelectOption } from '@elastic/eui'; +import type { EuiFieldTextProps, EuiSuperSelectOption } from '@elastic/eui'; import { EuiFieldText, EuiForm, @@ -332,7 +332,7 @@ export const TrustedAppsForm = memo( [item, processChanged] ); - const handleOnNameBlur = useCallback( + const handleOnNameBlur = useCallback>( ({ target: { name } }) => { processChanged(item); setVisited((prevVisited) => ({ ...prevVisited, [name]: true })); diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/cases_by_status.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/cases_by_status.tsx index 89782fa56707f..e702454d45ec5 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/cases_by_status.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/cases_by_status.tsx @@ -103,7 +103,7 @@ const CasesByStatusComponent: React.FC = () => { const caseUrl = getAppUrl({ deepLinkId: SecurityPageName.case, path: appendSearch(search) }); const goToCases = useCallback( - (ev) => { + (ev: React.SyntheticEvent) => { ev.preventDefault(); navigateTo({ url: caseUrl }); }, diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/hooks/use_navigate_to_timeline.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/hooks/use_navigate_to_timeline.tsx index ee44b775766cc..2544c8697a9d4 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/hooks/use_navigate_to_timeline.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/hooks/use_navigate_to_timeline.tsx @@ -13,7 +13,7 @@ import { sourcererActions } from '../../../../sourcerer/store'; import { getDataProvider, getDataProviderAnd, -} from '../../../../common/components/event_details/table/use_action_cell_data_provider'; +} from '../../../../common/components/event_details/use_action_cell_data_provider'; import type { DataProvider, QueryOperator } from '../../../../../common/types/timeline'; import { TimelineId } from '../../../../../common/types/timeline'; import { TimelineTypeEnum } from '../../../../../common/api/timeline'; diff --git a/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx b/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx index 4cad19444c5e7..37051c2b5c822 100644 --- a/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx @@ -105,7 +105,7 @@ const EventsByDatasetComponent: React.FC = ({ const [defaultNumberFormat] = useUiSetting$(DEFAULT_NUMBER_FORMAT); const goToHostEvents = useCallback( - (ev) => { + (ev: React.SyntheticEvent) => { ev.preventDefault(); navigateToApp(APP_UI_ID, { deepLinkId: SecurityPageName.hosts, diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_network/index.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_network/index.tsx index c7616c3c6d299..f9d4319ca2512 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_network/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_network/index.tsx @@ -72,7 +72,7 @@ const OverviewNetworkComponent: React.FC = ({ }); const goToNetwork = useCallback( - (ev) => { + (ev: React.SyntheticEvent) => { ev.preventDefault(); navigateToApp(APP_UI_ID, { deepLinkId: SecurityPageName.network, diff --git a/x-pack/plugins/security_solution/public/overview/components/recent_timelines/index.tsx b/x-pack/plugins/security_solution/public/overview/components/recent_timelines/index.tsx index 8e6ccb158bfa7..a167791a7b06c 100644 --- a/x-pack/plugins/security_solution/public/overview/components/recent_timelines/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/recent_timelines/index.tsx @@ -54,7 +54,7 @@ const StatefulRecentTimelinesComponent: React.FC = ({ filterBy }) => { ); const goToTimelines = useCallback( - (ev) => { + (ev: React.SyntheticEvent) => { ev.preventDefault(); navigateToApp(APP_UI_ID, { deepLinkId: SecurityPageName.timelines, diff --git a/x-pack/plugins/security_solution/public/resolver/view/controls/date_picker.tsx b/x-pack/plugins/security_solution/public/resolver/view/controls/date_picker.tsx index aa0c0f6031952..62d86cb37aed0 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/controls/date_picker.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/controls/date_picker.tsx @@ -8,7 +8,7 @@ import React, { useCallback, memo } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { i18n } from '@kbn/i18n'; import { EuiPopover, EuiPopoverTitle, EuiSuperDatePicker } from '@elastic/eui'; -import type { ShortDate } from '@elastic/eui'; +import type { ShortDate, EuiSuperDatePickerProps } from '@elastic/eui'; import { formatDate } from '../../../common/components/super_date_picker'; import { StyledEuiButtonIcon } from './styles'; import { useColors } from '../use_colors'; @@ -61,7 +61,7 @@ export const DateSelectionButton = memo( return selectors.currentAppliedTimeRange(state.analyzer[id]); }); - const onTimeChange = useCallback( + const onTimeChange = useCallback( ({ start, end, isInvalid }) => { if (!isInvalid) { const isQuickSelection = start.includes('now') || end.includes('now'); diff --git a/x-pack/plugins/security_solution/public/resolver/view/controls/index.tsx b/x-pack/plugins/security_solution/public/resolver/view/controls/index.tsx index 6829f9ece1fe0..a12ae2d90a7dc 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/controls/index.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/controls/index.tsx @@ -29,6 +29,8 @@ import { StyledGraphControls, StyledGraphControlsColumn, StyledEuiRange } from ' import { NodeLegend } from './legend'; import { SchemaInformation } from './schema'; +type PopoverType = null | 'schemaInfo' | 'nodeLegend' | 'sourcererSelection' | 'datePicker'; + export const GraphControls = React.memo( ({ id, @@ -51,13 +53,11 @@ export const GraphControls = React.memo( const isDatePickerAndSourcererDisabled = useIsExperimentalFeatureEnabled( 'analyzerDatePickersAndSourcererDisabled' ); - const [activePopover, setPopover] = useState< - null | 'schemaInfo' | 'nodeLegend' | 'sourcererSelection' | 'datePicker' - >(null); + const [activePopover, setPopover] = useState(null); const colorMap = useColors(); const setActivePopover = useCallback( - (value) => { + (value: PopoverType) => { if (value === activePopover) { setPopover(null); } else { diff --git a/x-pack/plugins/security_solution/public/resolver/view/process_event_dot.tsx b/x-pack/plugins/security_solution/public/resolver/view/process_event_dot.tsx index 0465f16d55b70..3846e1d7b19d1 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/process_event_dot.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/process_event_dot.tsx @@ -317,7 +317,7 @@ const UnstyledProcessEventDot = React.memo( }, [dispatch, nodeID, timestamp, id]); const handleClick = useCallback( - (clickEvent) => { + (clickEvent: React.MouseEvent) => { if (animationTarget.current?.beginElement) { animationTarget.current.beginElement(); } diff --git a/x-pack/plugins/security_solution/public/resolver/view/use_link_props.ts b/x-pack/plugins/security_solution/public/resolver/view/use_link_props.ts index f61d768a34141..494ed521c73e0 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/use_link_props.ts +++ b/x-pack/plugins/security_solution/public/resolver/view/use_link_props.ts @@ -13,8 +13,6 @@ import * as selectors from '../store/selectors'; import type { PanelViewAndParameters } from '../types'; import type { State } from '../../common/store/types'; -type EventHandlerCallback = MouseEventHandler; - /** * Get an `onClick` function and an `href` string. Use these as props for `` elements. * `onClick` will use navigate to the `panelViewAndParameters` using `history.push`. @@ -26,7 +24,7 @@ export function useLinkProps( panelViewAndParameters: PanelViewAndParameters ): { href: string; - onClick: EventHandlerCallback; + onClick: MouseEventHandler; } { const search = useSelector((state: State) => selectors.relativeHref(state.analyzer[id])(panelViewAndParameters) diff --git a/x-pack/plugins/security_solution/public/resolver/view/use_navigate_or_replace.ts b/x-pack/plugins/security_solution/public/resolver/view/use_navigate_or_replace.ts index 447bedb673523..ede554b305d30 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/use_navigate_or_replace.ts +++ b/x-pack/plugins/security_solution/public/resolver/view/use_navigate_or_replace.ts @@ -10,15 +10,13 @@ import { useCallback } from 'react'; import { useHistory } from 'react-router-dom'; import type { LocationDescriptorObject } from 'history'; -type EventHandlerCallback = MouseEventHandler; - export function useNavigateOrReplace( to: LocationDescriptorObject, /** Additional onClick callback */ - additionalOnClick?: EventHandlerCallback -): { href: string; onClick: EventHandlerCallback } { + additionalOnClick?: MouseEventHandler +): { href: string; onClick: MouseEventHandler } { const history = useHistory(); - const onClick = useCallback( + const onClick = useCallback( (event) => { try { if (additionalOnClick) { diff --git a/x-pack/plugins/security_solution/public/sourcerer/components/index.tsx b/x-pack/plugins/security_solution/public/sourcerer/components/index.tsx index 0f946bd8c247c..8b45d96669793 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/components/index.tsx +++ b/x-pack/plugins/security_solution/public/sourcerer/components/index.tsx @@ -255,7 +255,7 @@ export const Sourcerer = React.memo(({ scope: scopeId } ); const onChangeDataView = useCallback( - (newSelectedOption) => { + (newSelectedOption: string) => { setDataViewId(newSelectedOption); setIndexPatternsByDataView(newSelectedOption); }, diff --git a/x-pack/plugins/security_solution/public/sourcerer/components/use_pick_index_patterns.tsx b/x-pack/plugins/security_solution/public/sourcerer/components/use_pick_index_patterns.tsx index 397732ed4ec9f..8798a84409d13 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/components/use_pick_index_patterns.tsx +++ b/x-pack/plugins/security_solution/public/sourcerer/components/use_pick_index_patterns.tsx @@ -179,11 +179,11 @@ export const usePickIndexPatterns = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [isOnlyDetectionAlerts, selectedDataViewId, missingPatterns, scopeId, selectedPatterns]); - const onChangeCombo = useCallback((newSelectedOptions) => { + const onChangeCombo = useCallback((newSelectedOptions) => { setSelectedOptions(newSelectedOptions); }, []); - const renderOption = useCallback( + const renderOption = useCallback( ({ value }) => {value}, [] ); diff --git a/x-pack/plugins/security_solution/public/threat_intelligence/use_investigate_in_timeline.ts b/x-pack/plugins/security_solution/public/threat_intelligence/use_investigate_in_timeline.ts index 64e616d0a1ea9..85ced6d6e153d 100644 --- a/x-pack/plugins/security_solution/public/threat_intelligence/use_investigate_in_timeline.ts +++ b/x-pack/plugins/security_solution/public/threat_intelligence/use_investigate_in_timeline.ts @@ -50,7 +50,8 @@ export const useInvestigateInTimeline = ({ const { startTransaction } = useStartTransaction(); const updateTimelineIsLoading = useCallback( - (payload) => dispatch(timelineActions.updateIsLoading(payload)), + (payload: Parameters[0]) => + dispatch(timelineActions.updateIsLoading(payload)), [dispatch] ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/modal/actions/save_timeline_modal.tsx b/x-pack/plugins/security_solution/public/timelines/components/modal/actions/save_timeline_modal.tsx index 67409a91c8542..7ce0be75def61 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/modal/actions/save_timeline_modal.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/modal/actions/save_timeline_modal.tsx @@ -88,7 +88,7 @@ export const SaveTimelineModal = React.memo( }); const handleSubmit = useCallback( - (titleAndDescription, isValid) => { + (titleAndDescription: { title: string; description: string }, isValid: boolean) => { if (isValid) { dispatch( timelineActions.updateTitleAndDescription({ diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/export_timeline/export_timeline.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/export_timeline/export_timeline.tsx index 3ca9f88422a24..04493dfd9a4b8 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/export_timeline/export_timeline.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/export_timeline/export_timeline.tsx @@ -23,7 +23,7 @@ const ExportTimeline: React.FC<{ const { addSuccess } = useAppToasts(); const onExportSuccess = useCallback( - (exportCount) => { + (exportCount: number) => { if (onComplete != null) { onComplete(); } diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/types.ts b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/types.ts index 1fb75887d6a75..1a47c22d0fb61 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/types.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/types.ts @@ -240,7 +240,7 @@ export interface TimelineTab { href: string; id: TimelineType; name: string; - onClick: (ev: { preventDefault: () => void }) => void; + onClick: (ev: React.SyntheticEvent) => void; } export interface TemplateTimelineFilter { diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_status.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_status.tsx index 9e39bbf8ece34..f51334d03293b 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_status.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_status.tsx @@ -79,7 +79,7 @@ export const useTimelineStatus = ({ ); const onFilterClicked = useCallback( - (tabId) => { + (tabId: TemplateTimelineType) => { if (selectedTab === tabId) { setSelectedTab(null); } else { diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.tsx index 8002798291cc1..e08eccaf093e0 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.tsx @@ -158,7 +158,7 @@ export const useTimelineTypes = ({ data-test-subj={`open-timeline-modal-body-${TimelineTabsStyle.filter}-${tab.id}`} isSelected={tab.id === timelineType} key={`timeline-${TimelineTabsStyle.filter}-${tab.id}`} - onClick={(ev: { preventDefault: () => void }) => { + onClick={(ev: React.SyntheticEvent) => { tab.onClick(ev); onFilterClicked(tab.id, TimelineTabsStyle.filter); }} diff --git a/x-pack/plugins/security_solution/public/timelines/components/row_renderers_browser/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/row_renderers_browser/index.tsx index 776d1279ae715..4bef910848fc0 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/row_renderers_browser/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/row_renderers_browser/index.tsx @@ -24,6 +24,7 @@ import styled from 'styled-components'; import type { State } from '../../../common/store'; import { RowRendererValues } from '../../../../common/api/timeline'; +import type { RowRendererId } from '../../../../common/api/timeline'; import { useDeepEqualSelector } from '../../../common/hooks/use_selector'; import { setExcludedRowRendererIds as dispatchSetExcludedRowRendererIds } from '../../store/actions'; import { timelineSelectors } from '../../store'; @@ -79,7 +80,7 @@ const StatefulRowRenderersBrowserComponent: React.FC + (payload: RowRendererId[]) => dispatch( dispatchSetExcludedRowRendererIds({ id: timelineId, diff --git a/x-pack/plugins/security_solution/public/timelines/components/row_renderers_browser/row_renderers_browser.tsx b/x-pack/plugins/security_solution/public/timelines/components/row_renderers_browser/row_renderers_browser.tsx index 45f7090139528..4656bfb0da59f 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/row_renderers_browser/row_renderers_browser.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/row_renderers_browser/row_renderers_browser.tsx @@ -96,7 +96,7 @@ const RowRenderersBrowserComponent = ({ ); const nameColumnRenderCallback = useCallback( - (value, item) => ( + (value: string, item: RowRendererOption) => ( {value} @@ -105,7 +105,7 @@ const RowRenderersBrowserComponent = ({ ); const idColumnRenderCallback = useCallback( - (_, item) => ( + (_: unknown, item: RowRendererOption) => ( { - connectorId?: string; - subAction: string; - subActionParams?: P; - disabled?: boolean; -} - -export const useSubAction = ({ - connectorId, - subAction, - subActionParams, - disabled = false, - ...rest -}: UseSubActionParams) => { - const { http } = useKibana().services; - - return useQuery({ - queryKey: ['useSubAction', connectorId, subAction, subActionParams], - queryFn: ({ signal }) => - executeAction({ - id: connectorId as string, - params: { - subAction, - subActionParams, - }, - http, - signal, - }), - enabled: !disabled && !!connectorId && !!subAction, - ...rest, - }); -}; diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/use_sub_action_mutation.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/use_sub_action_mutation.tsx deleted file mode 100644 index 6a2c788a59c26..0000000000000 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/flyout/use_sub_action_mutation.tsx +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { executeAction } from '@kbn/triggers-actions-ui-plugin/public'; -import { useMutation } from '@tanstack/react-query'; -import { useKibana } from '../../../../../common/lib/kibana/kibana_react'; - -export interface UseSubActionParams

    { - connectorId: string; - subAction: string; - subActionParams?: P; -} - -export const useSubActionMutation = ({ - connectorId, - subAction, - subActionParams, -}: UseSubActionParams

    ) => { - const { http } = useKibana().services; - - return useMutation({ - mutationKey: ['executeSubAction', connectorId, subAction, subActionParams], - mutationFn: () => - executeAction({ - id: connectorId, - params: { - subAction, - subActionParams, - }, - http, - }), - }); -}; diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/helpers.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/helpers.tsx deleted file mode 100644 index fc1941b6824c2..0000000000000 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/helpers.tsx +++ /dev/null @@ -1,25 +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 { DEFAULT_ALERTS_INDEX, DEFAULT_PREVIEW_INDEX } from '../../../../../common/constants'; - -/* -The referenced alert _index in the flyout uses the `.internal.` such as -`.internal.alerts-security.alerts-spaceId` in the alert page flyout and -.internal.preview.alerts-security.alerts-spaceId` in the rule creation preview flyout -but we always want to use their respective aliase indices rather than accessing their backing .internal. indices. -*/ -export const getAlertIndexAlias = ( - index: string, - spaceId: string = 'default' -): string | undefined => { - if (index.startsWith(`.internal${DEFAULT_ALERTS_INDEX}`)) { - return `${DEFAULT_ALERTS_INDEX}-${spaceId}`; - } else if (index.startsWith(`.internal${DEFAULT_PREVIEW_INDEX}`)) { - return `${DEFAULT_PREVIEW_INDEX}-${spaceId}`; - } -}; diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/hooks/use_detail_panel.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/hooks/use_detail_panel.test.tsx deleted file mode 100644 index 06bce7781e0bf..0000000000000 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/hooks/use_detail_panel.test.tsx +++ /dev/null @@ -1,79 +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 { renderHook, act } from '@testing-library/react-hooks'; -import React from 'react'; -import type { UseDetailPanelConfig } from './use_detail_panel'; -import { useDetailPanel } from './use_detail_panel'; -import { useDeepEqualSelector } from '../../../../common/hooks/use_selector'; -import { SourcererScopeName } from '../../../../sourcerer/store/model'; -import { TimelineId } from '../../../../../common/types/timeline'; -import { ExpandableFlyoutProvider } from '@kbn/expandable-flyout'; -import { TestProviders } from '../../../../common/mock'; -import { createTelemetryServiceMock } from '../../../../common/lib/telemetry/telemetry_service.mock'; - -const mockedTelemetry = createTelemetryServiceMock(); -jest.mock('../../../../common/lib/kibana', () => { - const original = jest.requireActual('../../../../common/lib/kibana'); - return { - ...original, - useKibana: () => ({ - ...original.useKibana(), - services: { - ...original.useKibana().services, - telemetry: mockedTelemetry, - }, - }), - }; -}); -jest.mock('../../../../common/hooks/use_selector'); -jest.mock('../../../store'); - -jest.mock('../../../../sourcerer/containers', () => { - const mockSourcererReturn = { - browserFields: {}, - loading: true, - indexPattern: {}, - selectedPatterns: [], - missingPatterns: [], - }; - return { - useSourcererDataView: jest.fn().mockReturnValue(mockSourcererReturn), - }; -}); - -describe('useDetailPanel', () => { - const defaultProps: UseDetailPanelConfig = { - sourcererScope: SourcererScopeName.detections, - scopeId: TimelineId.test, - }; - const mockGetExpandedDetail = jest.fn().mockImplementation(() => ({})); - beforeEach(() => { - (useDeepEqualSelector as jest.Mock).mockImplementation((cb) => { - return mockGetExpandedDetail(); - }); - }); - afterEach(() => { - (useDeepEqualSelector as jest.Mock).mockClear(); - }); - - const wrapper = ({ children }: { children: React.ReactChild }) => ( - - {children} - - ); - const renderUseDetailPanel = (props = defaultProps) => - renderHook(() => useDetailPanel(props), { wrapper }); - - test('should return open fns (event, host, network, user), handleOnDetailsPanelClosed fn, shouldShowDetailsPanel, and the DetailsPanel component', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderUseDetailPanel(); - await waitForNextUpdate(); - - expect(result.current.openEventDetailsPanel).toBeDefined(); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/hooks/use_detail_panel.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/hooks/use_detail_panel.tsx deleted file mode 100644 index fde0d04b8610f..0000000000000 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/hooks/use_detail_panel.tsx +++ /dev/null @@ -1,57 +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 { useMemo, useCallback } from 'react'; -import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; -import { useKibana } from '../../../../common/lib/kibana'; -import { useSourcererDataView } from '../../../../sourcerer/containers'; -import type { SourcererScopeName } from '../../../../sourcerer/store/model'; -import { DocumentDetailsRightPanelKey } from '../../../../flyout/document_details/shared/constants/panel_keys'; - -export interface UseDetailPanelConfig { - sourcererScope: SourcererScopeName; - scopeId: string; -} -export interface UseDetailPanelReturn { - openEventDetailsPanel: (eventId?: string, onClose?: () => void) => void; -} - -export const useDetailPanel = ({ - sourcererScope, - scopeId, -}: UseDetailPanelConfig): UseDetailPanelReturn => { - const { telemetry } = useKibana().services; - const { selectedPatterns } = useSourcererDataView(sourcererScope); - - const { openFlyout } = useExpandableFlyoutApi(); - - const eventDetailsIndex = useMemo(() => selectedPatterns.join(','), [selectedPatterns]); - - const openEventDetailsPanel = useCallback( - (eventId?: string, onClose?: () => void) => { - openFlyout({ - right: { - id: DocumentDetailsRightPanelKey, - params: { - id: eventId, - indexName: eventDetailsIndex, - scopeId, - }, - }, - }); - telemetry.reportDetailsFlyoutOpened({ - location: scopeId, - panel: 'right', - }); - }, - [openFlyout, eventDetailsIndex, scopeId, telemetry] - ); - - return { - openEventDetailsPanel, - }; -}; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/column_headers/column_header.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/column_headers/column_header.tsx index 635f1a91a795d..2048cefb9bf0f 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/column_headers/column_header.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/column_headers/column_header.tsx @@ -8,6 +8,7 @@ import type { EuiContextMenuPanelDescriptor } from '@elastic/eui'; import { EuiContextMenu, EuiIcon, EuiPopover } from '@elastic/eui'; import React, { useCallback, useMemo, useRef, useState } from 'react'; +import type { DraggableChildrenFn } from '@hello-pangea/dnd'; import { Draggable } from '@hello-pangea/dnd'; import type { ResizeCallback } from 're-resizable'; import { Resizable } from 're-resizable'; @@ -215,7 +216,7 @@ const ColumnHeaderComponent: React.FC = ({ [header, onFilterChange, sort, timelineId] ); - const DraggableContent = useCallback( + const DraggableContent = useCallback( (dragProvided) => ( = ({ ); }, [dispatch, header, sort, timelineId]); - const onColumnRemoved = useCallback( + const onColumnRemoved = useCallback( (columnId) => dispatch(timelineActions.removeColumn({ id: timelineId, columnId })), [dispatch, timelineId] ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/column_headers/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/column_headers/index.tsx index d2b9a0aa7c667..f343b9af8ed97 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/column_headers/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/column_headers/index.tsx @@ -6,7 +6,7 @@ */ import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react'; -import type { DraggableChildrenFn } from '@hello-pangea/dnd'; +import type { DraggableChildrenFn, DroppableProps } from '@hello-pangea/dnd'; import { Droppable } from '@hello-pangea/dnd'; import { useDispatch } from 'react-redux'; @@ -162,7 +162,7 @@ export const ColumnHeadersComponent = ({ [columnHeaders, timelineId, draggingIndex, sort, tabType] ); - const DroppableContent = useCallback( + const DroppableContent = useCallback( (dropProvided, snapshot) => ( <> = ({ const { navigateToApp, getUrlForApp } = useKibana().services.application; const goToRuleDetails = useCallback( - (ev) => { + (ev: React.SyntheticEvent) => { ev.preventDefault(); navigateToApp(APP_UI_ID, { deepLinkId: SecurityPageName.rules, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_signature.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_signature.tsx index 55950f9a9aac6..fdb1f818f754e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_signature.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_signature.tsx @@ -9,6 +9,7 @@ import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; import styled from 'styled-components'; +import type { DraggableWrapperProps } from '../../../../../../common/components/drag_and_drop/draggable_wrapper'; import { DragEffects, DraggableWrapper, @@ -80,7 +81,7 @@ export const DraggableSignatureId = React.memo<{ [id, signatureId] ); - const render = useCallback( + const render: DraggableWrapperProps['render'] = useCallback( (dataProvider, _, snapshot) => snapshot.isDragging ? ( diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/user_name.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/user_name.tsx index 48ce6255725d3..1f070d52a8de9 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/user_name.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/user_name.tsx @@ -49,7 +49,7 @@ const UserNameComponent: React.FC = ({ const { openRightPanel } = useExpandableFlyoutApi(); const openUserDetailsSidePanel = useCallback( - (e) => { + (e: React.SyntheticEvent) => { e.preventDefault(); if (onClick) { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.tsx index 6e4b879362030..493d6d054a994 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.tsx @@ -11,6 +11,7 @@ import React, { useCallback, useMemo } from 'react'; import styled from 'styled-components'; import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; +import type { DraggableWrapperProps } from '../../../../../../common/components/drag_and_drop/draggable_wrapper'; import { DragEffects, DraggableWrapper, @@ -89,7 +90,7 @@ export const DraggableZeekElement = React.memo<{ [field, id, value] ); - const render = useCallback( + const render: DraggableWrapperProps['render'] = useCallback( (dataProvider, _, snapshot) => snapshot.isDragging ? ( diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/add_data_provider_popover.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/add_data_provider_popover.tsx index d09444edd6c99..09aef63266d2a 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/add_data_provider_popover.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/add_data_provider_popover.tsx @@ -27,6 +27,7 @@ import { StatefulEditDataProvider } from '../../edit_data_provider'; import { addContentToTimeline, getDisplayValue } from './helpers'; import { timelineSelectors } from '../../../store'; import { ADD_FIELD_LABEL, ADD_TEMPLATE_FIELD_LABEL } from './translations'; +import type { OnDataProviderEdited } from '../events'; interface AddDataProviderPopoverProps { browserFields: BrowserFields; @@ -58,7 +59,7 @@ const AddDataProviderPopoverComponent: React.FC = ( [setIsAddFilterPopoverOpen] ); - const handleDataProviderEdited = useCallback( + const handleDataProviderEdited = useCallback( ({ andProviderId, excluded, field, id, operator, providerId, value, type }) => { addContentToTimeline({ dataProviders, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/providers.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/providers.tsx index 11c13f16275f8..debb46a1f9922 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/providers.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/providers.tsx @@ -5,10 +5,11 @@ * 2.0. */ +import type { DroppableProps } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiFormHelpText, EuiSpacer } from '@elastic/eui'; import { rgba } from 'polished'; import React, { useCallback, useMemo, useRef, useState } from 'react'; -import type { DraggingStyle, NotDraggingStyle } from '@hello-pangea/dnd'; +import type { DraggableChildrenFn, DraggingStyle, NotDraggingStyle } from '@hello-pangea/dnd'; import { Draggable, Droppable } from '@hello-pangea/dnd'; import styled from 'styled-components'; import { useDispatch } from 'react-redux'; @@ -34,6 +35,7 @@ import { EMPTY_GROUP, flattenIntoAndGroups } from './helpers'; import { ProviderItemBadge } from './provider_item_badge'; import * as i18n from './translations'; +import type { OnDataProviderEdited } from '../events'; export const EMPTY_PROVIDERS_GROUP_CLASS_NAME = 'empty-providers-group'; @@ -222,7 +224,7 @@ export const DataProvidersGroupItem = React.memo( dispatch(timelineActions.updateDataProviderType(payload)); }, [dataProvider.id, dataProvider.type, dispatch, group, index, timelineId]); - const handleDataProviderEdited = useCallback( + const handleDataProviderEdited = useCallback( ({ andProviderId, excluded, field, operator, providerId, value }) => dispatch( timelineActions.dataProviderEdited({ @@ -267,7 +269,7 @@ export const DataProvidersGroupItem = React.memo( dataProvider.queryMatch.displayValue ?? dataProvider.queryMatch.value ); - const DraggableContent = useCallback( + const DraggableContent = useCallback( (provided, snapshot) => (

    ( [browserFields, group, groupIndex, timelineId] ); - const DroppableContent = useCallback( + const DroppableContent = useCallback( (droppableProvided) => ( setIsPopoverOpen(false), [setIsPopoverOpen]); const onChangeItemsPerPage = useCallback( - (itemsChangedPerPage) => + (itemsChangedPerPage: number) => dispatch(timelineActions.updateItemsPerPage({ id, itemsPerPage: itemsChangedPerPage })), [dispatch, id] ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx index 659073b3fc832..3ac5ba0cb5ac8 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx @@ -121,7 +121,7 @@ export const QueryBarTimeline = memo( const savedQueryServices = useSavedQueryServices(); const applyKqlFilterQuery = useCallback( - (expression: string, kind) => + (expression: string, kind: KueryFilterQueryKind) => dispatch( timelineActions.applyKqlFilterQuery({ id: timelineId, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_super_select/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_super_select/index.tsx index 33bbfe53bda65..246e46cfab04e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_super_select/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_super_select/index.tsx @@ -10,6 +10,7 @@ import { EuiInputPopover, EuiFieldText, htmlIdGenerator, keys } from '@elastic/e import React, { memo, useCallback, useMemo, useState } from 'react'; import type { OpenTimelineResult } from '../../open_timeline/types'; +import type { SelectableTimelineProps } from '../selectable_timeline'; import { SelectableTimeline } from '../selectable_timeline'; import * as i18n from '../translations'; import { type TimelineType, TimelineTypeEnum } from '../../../../../common/api/timeline'; @@ -52,8 +53,8 @@ const SearchTimelineSuperSelectComponent: React.FC { - setIsPopoverOpen(true); + const handlePopover = useCallback(() => { + setIsPopoverOpen((isOpen) => !isOpen); }, []); const handleKeyboardOpen: EuiFieldTextProps['onKeyDown'] = useCallback((event) => { @@ -68,7 +69,7 @@ const SearchTimelineSuperSelectComponent: React.FC ( ( ({ timelines, onlyFavorites, searchTimelineValue }) => [ ...(!onlyFavorites && searchTimelineValue === '' ? getBasicSelectableOptions(timelineId == null ? '-1' : timelineId) diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/selectable_timeline/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/selectable_timeline/index.tsx index 71c5b273d9dc1..b1672e1a7f6f4 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/selectable_timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/selectable_timeline/index.tsx @@ -25,7 +25,7 @@ import { type TimelineType, SortFieldTimelineEnum } from '../../../../../common/ import { useGetAllTimeline } from '../../../containers/all'; import { isUntitled } from '../../open_timeline/helpers'; import * as i18nTimeline from '../../open_timeline/translations'; -import type { OpenTimelineResult } from '../../open_timeline/types'; +import type { FavoriteTimelineResult, OpenTimelineResult } from '../../open_timeline/types'; import { getEmptyTagValue } from '../../../../common/components/empty_value'; import * as i18n from '../translations'; import { Direction } from '../../../../../common/search_strategy'; @@ -50,8 +50,16 @@ const TIMELINE_ITEM_HEIGHT = 50; * @param {EuiSelectableOption[]} options * @returns {EuiSelectableOption[]} modified options */ -const replaceTitleInOptions = (options: EuiSelectableOption[]): EuiSelectableOption[] => - options.map(({ title, ...props }) => ({ ...props, title: undefined, timelineTitle: title })); +const replaceTitleInOptions = ( + options: EuiSelectableOption[] +): Array< + EuiSelectableOption<{ timelineTitle: string; description?: string; graphEveId?: string }> +> => + options.map(({ title, ...props }) => ({ + ...props, + title: undefined, + timelineTitle: title ?? '', + })); export interface GetSelectableOptions { timelines: OpenTimelineResult[]; @@ -97,7 +105,7 @@ const SelectableTimelineComponent: React.FC = ({ const debouncedSetSearchTimelineValue = useMemo(() => debounce(500, setSearchTimelineValue), []); const onSearchTimeline = useCallback( - (val) => { + (val: string) => { debouncedSetSearchTimelineValue(val); }, [debouncedSetSearchTimelineValue] @@ -130,7 +138,16 @@ const SelectableTimelineComponent: React.FC = ({ [heightTrigger, pageSize] ); - const renderTimelineOption = useCallback((option, searchValue) => { + const renderTimelineOption = useCallback< + NonNullable< + EuiSelectableProps<{ + timelineTitle: string; + description?: string; + graphEventId?: string; + favorite?: FavoriteTimelineResult[]; + }>['renderOption'] + > + >((option, searchValue) => { const title: string = isUntitled({ ...option, title: option.timelineTitle }) ? i18nTimeline.UNTITLED_TIMELINE : option.timelineTitle; @@ -176,17 +193,25 @@ const SelectableTimelineComponent: React.FC = ({ ); }, []); - const handleTimelineChange = useCallback( + const handleTimelineChange = useCallback< + NonNullable< + EuiSelectableProps<{ + timelineTitle: string; + description?: string; + graphEventId?: string; + }>['onChange'] + > + >( (options) => { - const selectedTimeline = options.filter( - (option: { checked: string }) => option.checked === 'on' - ); + const selectedTimeline = options.filter((option) => option.checked === 'on'); if (selectedTimeline != null && selectedTimeline.length > 0) { onTimelineChange( isEmpty(selectedTimeline[0].timelineTitle) ? i18nTimeline.UNTITLED_TIMELINE : selectedTimeline[0].timelineTitle, - selectedTimeline[0].id === '-1' ? null : selectedTimeline[0].id, + selectedTimeline[0].id === '-1' + ? null + : (selectedTimeline[0].id as unknown as string | null), selectedTimeline[0].graphEventId ?? '' ); } @@ -195,7 +220,7 @@ const SelectableTimelineComponent: React.FC = ({ [onClosePopover, onTimelineChange] ); - const EuiSelectableContent = useCallback( + const EuiSelectableContent = useCallback>( (list, search) => ( <> {search} @@ -260,7 +285,12 @@ const SelectableTimelineComponent: React.FC = ({ }, [fetchAllTimeline, onlyFavorites, pageSize, searchTimelineValue, timelineType]); return ( - data-test-subj="selectable-input" height={POPOVER_HEIGHT} isLoading={loading && timelines == null} diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/session/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/session/index.tsx index eceb9c8dbd284..42fffc7763712 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/session/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/session/index.tsx @@ -29,7 +29,7 @@ interface Props { const SessionTabContent: React.FC = ({ timelineId }) => { const [height, setHeight] = useState(0); - const measuredRef = useCallback((node) => { + const measuredRef = useCallback((node: HTMLDivElement | HTMLSpanElement | null) => { if (node !== null) { setHeight(node.getBoundingClientRect().height); } diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/session/use_session_view.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/session/use_session_view.test.tsx index 736b23cf0232b..9c4b135b5e774 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/session/use_session_view.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/session/use_session_view.test.tsx @@ -68,18 +68,6 @@ jest.mock('../../../../../common/lib/kibana', () => { }), }; }); -const mockOpenDetailFn = jest.fn(); - -jest.mock('../../../side_panel/hooks/use_detail_panel', () => { - return { - useDetailPanel: () => ({ - openEventDetailsPanel: mockOpenDetailFn, - handleOnDetailsPanelClosed: () => {}, - DetailsPanel: () =>
    , - shouldShowDetailsPanel: false, - }), - }; -}); describe('useSessionView with active timeline and a session id and graph event id', () => { let setTimelineFullScreen: jest.Mock; @@ -155,12 +143,7 @@ describe('useSessionView with active timeline and a session id and graph event i }, { wrapper: Wrapper } ); - expect(kibana.services.sessionView.getSessionView).toHaveBeenCalledWith({ - height: 1000, - sessionEntityId: 'test', - loadAlertDetails: mockOpenDetailFn, - canReadPolicyManagement: false, - }); + expect(kibana.services.sessionView.getSessionView).toHaveBeenCalled(); }); describe('useSessionView with non active timeline and graph event id set', () => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/session/use_session_view.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/session/use_session_view.tsx index 49af740647ce1..e2aa8c42511d7 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/session/use_session_view.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/session/use_session_view.tsx @@ -11,6 +11,9 @@ import styled from 'styled-components'; import { useDispatch } from 'react-redux'; import { dataTableSelectors, tableDefaults } from '@kbn/securitysolution-data-table'; import type { TableId } from '@kbn/securitysolution-data-table'; +import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { DocumentDetailsRightPanelKey } from '../../../../../flyout/document_details/shared/constants/panel_keys'; +import { useSourcererDataView } from '../../../../../sourcerer/containers'; import { getScopedActions, isActiveTimeline, @@ -20,7 +23,6 @@ import { import { useKibana } from '../../../../../common/lib/kibana'; import * as i18n from './translations'; import { TimelineTabs } from '../../../../../../common/types/timeline'; -import { useDetailPanel } from '../../../side_panel/hooks/use_detail_panel'; import { SourcererScopeName } from '../../../../../sourcerer/store/model'; import { isFullScreen } from '../../body/column_headers'; import { SCROLLING_DISABLED_CLASS_NAME } from '../../../../../../common/constants'; @@ -242,7 +244,7 @@ export const useSessionViewNavigation = ({ scopeId }: { scopeId: string }) => { }; export const useSessionView = ({ scopeId, height }: { scopeId: string; height?: number }) => { - const { sessionView } = useKibana().services; + const { sessionView, telemetry } = useKibana().services; const getScope = useMemo(() => { if (isTimelineScope(scopeId)) { return timelineSelectors.getTimelineByIdSelector(); @@ -280,10 +282,30 @@ export const useSessionView = ({ scopeId, height }: { scopeId: string; height?: return SourcererScopeName.default; } }, [scopeId]); - const { openEventDetailsPanel } = useDetailPanel({ - sourcererScope, - scopeId, - }); + + const { selectedPatterns } = useSourcererDataView(sourcererScope); + const eventDetailsIndex = useMemo(() => selectedPatterns.join(','), [selectedPatterns]); + + const { openFlyout } = useExpandableFlyoutApi(); + const openAlertDetailsFlyout = useCallback( + (eventId?: string, onClose?: () => void) => { + openFlyout({ + right: { + id: DocumentDetailsRightPanelKey, + params: { + id: eventId, + indexName: eventDetailsIndex, + scopeId, + }, + }, + }); + telemetry.reportDetailsFlyoutOpened({ + location: scopeId, + panel: 'right', + }); + }, + [openFlyout, eventDetailsIndex, scopeId, telemetry] + ); const sessionViewComponent = useMemo(() => { const sessionViewSearchBarHeight = 118; @@ -291,7 +313,7 @@ export const useSessionView = ({ scopeId, height }: { scopeId: string; height?: return sessionViewConfig !== null ? sessionView.getSessionView({ ...sessionViewConfig, - loadAlertDetails: openEventDetailsPanel, + loadAlertDetails: openAlertDetailsFlyout, isFullScreen: fullScreen, height: heightMinusSearchBar, canReadPolicyManagement, @@ -301,13 +323,13 @@ export const useSessionView = ({ scopeId, height }: { scopeId: string; height?: height, sessionViewConfig, sessionView, - openEventDetailsPanel, + openAlertDetailsFlyout, fullScreen, canReadPolicyManagement, ]); return { - openEventDetailsPanel, + openEventDetailsPanel: openAlertDetailsFlyout, SessionView: sessionViewComponent, }; }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.tsx index 42b23945ac7b8..0b629788b7691 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.tsx @@ -208,7 +208,9 @@ export const TimelineDataTableComponent: React.FC = memo( [onColumnResize] ); - const onChangeItemsPerPage = useCallback( + const onChangeItemsPerPage = useCallback< + NonNullable + >( (itemsChangedPerPage) => { dispatch( timelineActions.updateItemsPerPage({ id: timelineId, itemsPerPage: itemsChangedPerPage }) diff --git a/x-pack/plugins/security_solution/public/timelines/hooks/use_create_timeline.tsx b/x-pack/plugins/security_solution/public/timelines/hooks/use_create_timeline.tsx index c7b5252e0897b..e0783522f5dd1 100644 --- a/x-pack/plugins/security_solution/public/timelines/hooks/use_create_timeline.tsx +++ b/x-pack/plugins/security_solution/public/timelines/hooks/use_create_timeline.tsx @@ -63,7 +63,15 @@ export const useCreateTimeline = ({ const { resetDiscoverAppState } = useDiscoverInTimelineContext(); const createTimeline = useCallback( - ({ id, show, timeRange: timeRangeParam }) => { + ({ + id, + show, + timeRange: timeRangeParam, + }: { + id: string; + show: boolean; + timeRange?: TimeRange; + }) => { const timerange = timeRangeParam ?? globalTimeRange; if (id === TimelineId.active && timelineFullScreen) { @@ -131,11 +139,11 @@ export const useCreateTimeline = ({ return useCallback( async (options?: { timeRange?: TimeRange }) => { await resetDiscoverAppState(); - createTimeline({ id: timelineId, show: true, timelineType, timeRange: options?.timeRange }); + createTimeline({ id: timelineId, show: true, timeRange: options?.timeRange }); if (typeof onClick === 'function') { onClick(); } }, - [createTimeline, timelineId, timelineType, onClick, resetDiscoverAppState] + [createTimeline, timelineId, onClick, resetDiscoverAppState] ); }; diff --git a/x-pack/plugins/security_solution/public/timelines/store/actions.ts b/x-pack/plugins/security_solution/public/timelines/store/actions.ts index fbf061529c495..e65b7273b5de7 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/actions.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/actions.ts @@ -30,6 +30,7 @@ import type { } from '../../../common/types/timeline'; import type { DataProviderType, RowRendererId } from '../../../common/api/timeline'; import type { ResolveTimelineConfig } from '../components/open_timeline/types'; +import type { PrimitiveOrArrayOfPrimitives } from '../../common/lib/kuery'; const actionCreator = actionCreatorFactory('x-pack/security_solution/local/timeline'); @@ -115,7 +116,7 @@ export const dataProviderEdited = actionCreator<{ id: string; operator: QueryOperator; providerId: string; - value: string | number | Array; + value: PrimitiveOrArrayOfPrimitives; }>('DATA_PROVIDER_EDITED'); export const updateDataProviderType = actionCreator<{ diff --git a/x-pack/plugins/security_solution/public/timelines/store/helpers.ts b/x-pack/plugins/security_solution/public/timelines/store/helpers.ts index 0342c28f28aa9..b876465449740 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/helpers.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/helpers.ts @@ -44,6 +44,7 @@ import { import { activeTimeline } from '../containers/active_timeline_context'; import type { ResolveTimelineConfig } from '../components/open_timeline/types'; import { getDisplayValue } from '../components/timeline/data_providers/helpers'; +import type { PrimitiveOrArrayOfPrimitives } from '../../common/lib/kuery'; interface AddTimelineNoteParams { id: string; @@ -841,7 +842,7 @@ const updateProviderProperties = ({ operator: QueryOperator; providerId: string; timeline: TimelineModel; - value: string | number | Array; + value: PrimitiveOrArrayOfPrimitives; }) => timeline.dataProviders.map((provider) => provider.id === providerId @@ -875,7 +876,7 @@ const updateAndProviderProperties = ({ operator: QueryOperator; providerId: string; timeline: TimelineModel; - value: string | number | Array; + value: PrimitiveOrArrayOfPrimitives; }) => timeline.dataProviders.map((provider) => provider.id === providerId @@ -909,7 +910,7 @@ interface UpdateTimelineProviderEditPropertiesParams { operator: QueryOperator; providerId: string; timelineById: TimelineById; - value: string | number | Array; + value: PrimitiveOrArrayOfPrimitives; } export const updateTimelineProviderProperties = ({ diff --git a/x-pack/plugins/security_solution/public/value_list/components/inline_edit_list_item_value.tsx b/x-pack/plugins/security_solution/public/value_list/components/inline_edit_list_item_value.tsx index d8777a8d83d00..7fe449e6cbbfc 100644 --- a/x-pack/plugins/security_solution/public/value_list/components/inline_edit_list_item_value.tsx +++ b/x-pack/plugins/security_solution/public/value_list/components/inline_edit_list_item_value.tsx @@ -33,7 +33,7 @@ export const InlineEditListItemValue = ({ listItem }: { listItem: ListItemSchema }); }, }); - const onChange = useCallback((e) => { + const onChange = useCallback>((e) => { setValue(e.target.value); }, []); const onCancel = useCallback(() => { @@ -41,7 +41,7 @@ export const InlineEditListItemValue = ({ listItem }: { listItem: ListItemSchema }, [listItem]); const onSave = useCallback( - async (newValue) => { + async (newValue: string) => { track(METRIC_TYPE.COUNT, TELEMETRY_EVENT.EDIT_VALUE_LIST_ITEM); await patchListItemMutation.mutateAsync({ id: listItem.id, diff --git a/x-pack/plugins/security_solution/public/value_list/components/value_list_modal.tsx b/x-pack/plugins/security_solution/public/value_list/components/value_list_modal.tsx index 6aa6b1b7d9b60..f2741d80bd35a 100644 --- a/x-pack/plugins/security_solution/public/value_list/components/value_list_modal.tsx +++ b/x-pack/plugins/security_solution/public/value_list/components/value_list_modal.tsx @@ -6,6 +6,7 @@ */ import React, { useState, useCallback } from 'react'; import { css } from '@emotion/css'; +import type { EuiSearchBarProps } from '@elastic/eui'; import { EuiModal, EuiModalHeader, @@ -100,7 +101,7 @@ export const ValueListModal = ({ listId, onCloseModal, canWriteIndex }: ValueLis pageSizeOptions: [5, 10, 25], }; - const onQueryChange = useCallback((params) => { + const onQueryChange: NonNullable = useCallback((params) => { setFilter(params.queryText); }, []); diff --git a/x-pack/plugins/security_solution/server/config.mock.ts b/x-pack/plugins/security_solution/server/config.mock.ts index 2db82b039484c..a5b8f404bab47 100644 --- a/x-pack/plugins/security_solution/server/config.mock.ts +++ b/x-pack/plugins/security_solution/server/config.mock.ts @@ -12,10 +12,7 @@ import { getDefaultConfigSettings } from '../common/config_settings'; import type { ConfigType } from './config'; export const createMockConfig = (): ConfigType => { - const enableExperimental: Array = [ - 'responseActionUploadEnabled', - 'responseActionScanEnabled', - ]; + const enableExperimental: Array = ['responseActionUploadEnabled']; return { [SIGNALS_INDEX_KEY]: DEFAULT_SIGNALS_INDEX, diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts index 2fdfa5143cfe2..669d3770be37d 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts @@ -78,7 +78,6 @@ import type { ActionsApiRequestHandlerContext } from '@kbn/actions-plugin/server import { sentinelOneMock } from '../../services/actions/clients/sentinelone/mocks'; import { ResponseActionsClientError } from '../../services/actions/clients/errors'; import type { EndpointAppContext } from '../../types'; -import type { ExperimentalFeatures } from '../../../../common'; jest.mock('../../services', () => { const realModule = jest.requireActual('../../services'); @@ -135,13 +134,6 @@ describe('Response actions', () => { const docGen = new EndpointDocGenerator(); - const setFeatureFlag = (ff: Partial) => { - endpointContext.experimentalFeatures = { - ...endpointContext.experimentalFeatures, - ...ff, - }; - }; - beforeEach(() => { // instantiate... everything const mockScopedClient = elasticsearchServiceMock.createScopedClusterClient(); @@ -174,8 +166,6 @@ describe('Response actions', () => { licenseService, }); - setFeatureFlag({ responseActionScanEnabled: true }); - // add the host isolation route handlers to routerMock registerResponseActionRoutes(routerMock, endpointContext); diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.ts index 9f40852fec380..16c3ea8ffd427 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.ts @@ -286,28 +286,25 @@ export function registerResponseActionRoutes( ) ); - // 8.15 route - if (endpointContext.experimentalFeatures.responseActionScanEnabled) { - router.versioned - .post({ - access: 'public', - path: SCAN_ROUTE, - options: { authRequired: true, tags: ['access:securitySolution'] }, - }) - .addVersion( - { - version: '2023-10-31', - validate: { - request: ScanActionRequestSchema, - }, + router.versioned + .post({ + access: 'public', + path: SCAN_ROUTE, + options: { authRequired: true, tags: ['access:securitySolution'] }, + }) + .addVersion( + { + version: '2023-10-31', + validate: { + request: ScanActionRequestSchema, }, - withEndpointAuthz( - { all: ['canWriteScanOperations'] }, - logger, - responseActionRequestHandler(endpointContext, 'scan') - ) - ); - } + }, + withEndpointAuthz( + { all: ['canWriteScanOperations'] }, + logger, + responseActionRequestHandler(endpointContext, 'scan') + ) + ); } function responseActionRequestHandler( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/fetch_rules_by_query_or_ids.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/fetch_rules_by_query_or_ids.ts index d59ba5676b607..d74bcc5e7f450 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/fetch_rules_by_query_or_ids.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/fetch_rules_by_query_or_ids.ts @@ -13,18 +13,19 @@ import { initPromisePool } from '../../../../../../utils/promise_pool'; import type { RuleAlertType } from '../../../../rule_schema'; import { readRules } from '../../../logic/detection_rules_client/read_rules'; import { findRules } from '../../../logic/search/find_rules'; -import { MAX_RULES_TO_PROCESS_TOTAL } from './route'; export const fetchRulesByQueryOrIds = async ({ query, ids, rulesClient, abortSignal, + maxRules, }: { query: string | undefined; ids: string[] | undefined; rulesClient: RulesClient; abortSignal: AbortSignal; + maxRules: number; }): Promise> => { if (ids) { return initPromisePool({ @@ -43,7 +44,7 @@ export const fetchRulesByQueryOrIds = async ({ const { data, total } = await findRules({ rulesClient, - perPage: MAX_RULES_TO_PROCESS_TOTAL, + perPage: maxRules, filter: query, page: undefined, sortField: undefined, @@ -51,9 +52,9 @@ export const fetchRulesByQueryOrIds = async ({ fields: undefined, }); - if (total > MAX_RULES_TO_PROCESS_TOTAL) { + if (total > maxRules) { throw new BadRequestError( - `More than ${MAX_RULES_TO_PROCESS_TOTAL} rules matched the filter query. Try to narrow it down.` + `More than ${maxRules} rules matched the filter query. Try to narrow it down.` ); } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts index 7ac96312b793d..4d31bd457a3e9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_actions/route.ts @@ -9,6 +9,7 @@ import type { IKibanaResponse, Logger } from '@kbn/core/server'; import { AbortError } from '@kbn/kibana-utils-plugin/common'; import { transformError } from '@kbn/securitysolution-es-utils'; import { buildRouteValidationWithZod } from '@kbn/zod-helpers'; +import type { BulkActionSkipResult } from '@kbn/alerting-plugin/common'; import type { ConfigType } from '../../../../../../config'; import type { PerformRulesBulkActionResponse } from '../../../../../../../common/api/detection_engine/rule_management'; import { @@ -42,8 +43,12 @@ import { buildBulkResponse } from './bulk_actions_response'; import { bulkEnableDisableRules } from './bulk_enable_disable_rules'; import { fetchRulesByQueryOrIds } from './fetch_rules_by_query_or_ids'; import { bulkScheduleBackfill } from './bulk_schedule_rule_run'; +import { createPrebuiltRuleAssetsClient } from '../../../../prebuilt_rules/logic/rule_assets/prebuilt_rule_assets_client'; -export const MAX_RULES_TO_PROCESS_TOTAL = 10000; +const MAX_RULES_TO_PROCESS_TOTAL = 10000; +// Set a lower limit for bulk edit as the rules client might fail with a "Query +// contains too many nested clauses" error +const MAX_RULES_TO_BULK_EDIT = 2000; const MAX_ROUTE_CONCURRENCY = 5; export const performBulkActionRoute = ( @@ -126,6 +131,7 @@ export const performBulkActionRoute = ( const savedObjectsClient = ctx.core.savedObjects.client; const actionsClient = ctx.actions.getActionsClient(); const detectionRulesClient = ctx.securitySolution.getDetectionRulesClient(); + const prebuiltRuleAssetClient = createPrebuiltRuleAssetsClient(savedObjectsClient); const { getExporter, getClient } = ctx.core.savedObjects; const client = getClient({ includedHiddenTypes: ['action'] }); @@ -141,31 +147,15 @@ export const performBulkActionRoute = ( const query = body.query !== '' ? body.query : undefined; - // handling this action before switch statement as bulkEditRules fetch rules within - // rulesClient method, hence there is no need to use fetchRulesByQueryOrIds utility - if (body.action === BulkActionTypeEnum.edit && !isDryRun) { - const { rules, errors, skipped } = await bulkEditRules({ - actionsClient, - rulesClient, - filter: query, - ids: body.ids, - actions: body.edit, - mlAuthz, - experimentalFeatures: config.experimentalFeatures, - }); - - return buildBulkResponse(response, { - updated: rules, - skipped, - errors, - }); - } - const fetchRulesOutcome = await fetchRulesByQueryOrIds({ rulesClient, query, ids: body.ids, abortSignal: abortController.signal, + maxRules: + body.action === BulkActionTypeEnum.edit + ? MAX_RULES_TO_BULK_EDIT + : MAX_RULES_TO_PROCESS_TOTAL, }); const rules = fetchRulesOutcome.results.map(({ result }) => result); @@ -173,6 +163,7 @@ export const performBulkActionRoute = ( let updated: RuleAlertType[] = []; let created: RuleAlertType[] = []; let deleted: RuleAlertType[] = []; + let skipped: BulkActionSkipResult[] = []; switch (body.action) { case BulkActionTypeEnum.enable: { @@ -307,25 +298,40 @@ export const performBulkActionRoute = ( // will be processed only when isDryRun === true // during dry run only validation is getting performed and rule is not saved in ES case BulkActionTypeEnum.edit: { - const bulkActionOutcome = await initPromisePool({ - concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, - items: rules, - executor: async (rule) => { - await dryRunValidateBulkEditRule({ - mlAuthz, - rule, - edit: body.edit, - experimentalFeatures: config.experimentalFeatures, - }); + if (isDryRun) { + const bulkActionOutcome = await initPromisePool({ + concurrency: MAX_RULES_TO_UPDATE_IN_PARALLEL, + items: rules, + executor: async (rule) => { + await dryRunValidateBulkEditRule({ + mlAuthz, + rule, + edit: body.edit, + experimentalFeatures: config.experimentalFeatures, + }); - return rule; - }, - abortSignal: abortController.signal, - }); - errors.push(...bulkActionOutcome.errors); - updated = bulkActionOutcome.results - .map(({ result }) => result) - .filter((rule): rule is RuleAlertType => rule !== null); + return rule; + }, + abortSignal: abortController.signal, + }); + errors.push(...bulkActionOutcome.errors); + updated = bulkActionOutcome.results + .map(({ result }) => result) + .filter((rule): rule is RuleAlertType => rule !== null); + } else { + const bulkEditResult = await bulkEditRules({ + actionsClient, + rulesClient, + prebuiltRuleAssetClient, + rules, + actions: body.edit, + mlAuthz, + experimentalFeatures: config.experimentalFeatures, + }); + updated = bulkEditResult.rules; + skipped = bulkEditResult.skipped; + errors.push(...bulkEditResult.errors); + } break; } @@ -352,6 +358,7 @@ export const performBulkActionRoute = ( updated, deleted, created, + skipped, errors, isDryRun, }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/bulk_actions/bulk_edit_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/bulk_actions/bulk_edit_rules.ts index ab3a9f486d81b..bee44a3600f97 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/bulk_actions/bulk_edit_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/bulk_actions/bulk_edit_rules.ts @@ -5,28 +5,30 @@ * 2.0. */ -import type { RulesClient } from '@kbn/alerting-plugin/server'; import type { ActionsClient } from '@kbn/actions-plugin/server'; +import type { RulesClient } from '@kbn/alerting-plugin/server'; import type { ExperimentalFeatures } from '../../../../../../common'; import type { BulkActionEditPayload } from '../../../../../../common/api/detection_engine/rule_management'; import type { MlAuthz } from '../../../../machine_learning/authz'; -import { enrichFilterWithRuleTypeMapping } from '../search/enrich_filter_with_rule_type_mappings'; -import type { RuleAlertType } from '../../../rule_schema'; +import type { RuleAlertType, RuleParams } from '../../../rule_schema'; +import type { IPrebuiltRuleAssetsClient } from '../../../prebuilt_rules/logic/rule_assets/prebuilt_rule_assets_client'; +import { convertAlertingRuleToRuleResponse } from '../detection_rules_client/converters/convert_alerting_rule_to_rule_response'; +import { calculateIsCustomized } from '../detection_rules_client/mergers/rule_source/calculate_is_customized'; +import { bulkEditActionToRulesClientOperation } from './action_to_rules_client_operation'; import { ruleParamsModifier } from './rule_params_modifier'; import { splitBulkEditActions } from './split_bulk_edit_actions'; import { validateBulkEditRule } from './validations'; -import { bulkEditActionToRulesClientOperation } from './action_to_rules_client_operation'; export interface BulkEditRulesArguments { actionsClient: ActionsClient; rulesClient: RulesClient; + prebuiltRuleAssetClient: IPrebuiltRuleAssetsClient; actions: BulkActionEditPayload[]; - filter?: string; - ids?: string[]; + rules: RuleAlertType[]; mlAuthz: MlAuthz; experimentalFeatures: ExperimentalFeatures; } @@ -41,27 +43,70 @@ export interface BulkEditRulesArguments { export const bulkEditRules = async ({ actionsClient, rulesClient, - ids, + prebuiltRuleAssetClient, + rules, actions, - filter, mlAuthz, experimentalFeatures, }: BulkEditRulesArguments) => { + // Split operations const { attributesActions, paramsActions } = splitBulkEditActions(actions); const operations = attributesActions .map((attribute) => bulkEditActionToRulesClientOperation(actionsClient, attribute)) .flat(); - const result = await rulesClient.bulkEdit({ - ...(ids ? { ids } : { filter: enrichFilterWithRuleTypeMapping(filter) }), + + // Check if there are any prebuilt rules and fetch their base versions + const prebuiltRules = rules.filter((rule) => rule.params.immutable); + const baseVersions = await prebuiltRuleAssetClient.fetchAssetsByVersion( + prebuiltRules.map((rule) => ({ + rule_id: rule.params.ruleId, + version: rule.params.version, + })) + ); + const baseVersionsMap = new Map( + baseVersions.map((baseVersion) => [baseVersion.rule_id, baseVersion]) + ); + + const result = await rulesClient.bulkEdit({ + ids: rules.map((rule) => rule.id), operations, - paramsModifier: async (ruleParams: RuleAlertType['params']) => { + paramsModifier: async (rule) => { + const ruleParams = rule.params; + await validateBulkEditRule({ mlAuthz, ruleType: ruleParams.type, edit: actions, immutable: ruleParams.immutable, + experimentalFeatures, }); - return ruleParamsModifier(ruleParams, paramsActions, experimentalFeatures); + const { modifiedParams, isParamsUpdateSkipped } = ruleParamsModifier( + ruleParams, + paramsActions, + experimentalFeatures + ); + + // Update rule source + const updatedRule = { + ...rule, + params: modifiedParams, + }; + const ruleResponse = convertAlertingRuleToRuleResponse(updatedRule); + const ruleSource = + ruleResponse.immutable === true + ? { + type: 'external' as const, + isCustomized: calculateIsCustomized( + baseVersionsMap.get(ruleResponse.rule_id), + ruleResponse + ), + } + : { + type: 'internal' as const, + }; + modifiedParams.ruleSource = ruleSource; + + return { modifiedParams, isParamsUpdateSkipped }; }, }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/bulk_actions/validations.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/bulk_actions/validations.ts index 591bcc0a18ec5..d89c78be6b846 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/bulk_actions/validations.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/bulk_actions/validations.ts @@ -32,6 +32,7 @@ interface BulkEditBulkActionsValidationArgs { mlAuthz: MlAuthz; edit: BulkActionEditPayload[]; immutable: boolean; + experimentalFeatures: ExperimentalFeatures; } interface DryRunBulkEditBulkActionsValidationArgs { @@ -110,15 +111,18 @@ export const validateBulkEditRule = async ({ mlAuthz, edit, immutable, + experimentalFeatures, }: BulkEditBulkActionsValidationArgs) => { await throwMlAuthError(mlAuthz, ruleType); - // if rule can't be edited error will be thrown - const canRuleBeEdited = !immutable || istEditApplicableToImmutableRule(edit); - await throwDryRunError( - () => invariant(canRuleBeEdited, "Elastic rule can't be edited"), - BulkActionsDryRunErrCode.IMMUTABLE - ); + if (!experimentalFeatures.prebuiltRulesCustomizationEnabled) { + // if rule can't be edited error will be thrown + const canRuleBeEdited = !immutable || istEditApplicableToImmutableRule(edit); + await throwDryRunError( + () => invariant(canRuleBeEdited, "Elastic rule can't be edited"), + BulkActionsDryRunErrCode.IMMUTABLE + ); + } }; /** @@ -140,12 +144,14 @@ export const dryRunValidateBulkEditRule = async ({ rule, edit, mlAuthz, + experimentalFeatures, }: DryRunBulkEditBulkActionsValidationArgs) => { await validateBulkEditRule({ ruleType: rule.params.type, mlAuthz, edit, immutable: rule.params.immutable, + experimentalFeatures, }); // if rule is machine_learning, index pattern action can't be applied to it diff --git a/x-pack/plugins/session_view/public/components/process_tree_alerts/index.tsx b/x-pack/plugins/session_view/public/components/process_tree_alerts/index.tsx index 6cadb836d1661..cf688abdece57 100644 --- a/x-pack/plugins/session_view/public/components/process_tree_alerts/index.tsx +++ b/x-pack/plugins/session_view/public/components/process_tree_alerts/index.tsx @@ -80,7 +80,7 @@ export function ProcessTreeAlerts({ [onAlertSelected] ); - const handleProcessEventAlertCategorySelected = useCallback((eventCategory) => { + const handleProcessEventAlertCategorySelected = useCallback((eventCategory: any) => { setSelectedProcessEventAlertCategory(eventCategory); }, []); diff --git a/x-pack/plugins/session_view/public/components/process_tree_alerts_filter/index.tsx b/x-pack/plugins/session_view/public/components/process_tree_alerts_filter/index.tsx index a52fcc09cc4ea..6f4b2b5570b4d 100644 --- a/x-pack/plugins/session_view/public/components/process_tree_alerts_filter/index.tsx +++ b/x-pack/plugins/session_view/public/components/process_tree_alerts_filter/index.tsx @@ -51,7 +51,7 @@ export const ProcessTreeAlertsFilter = ({ }; const onSelectedProcessEventAlertCategory = useCallback( - (event) => { + (event: any) => { const [_, selectedAlertEvent] = event.target.textContent.split(' '); setSelectedProcessEventAlertCategory(selectedAlertEvent); onAlertEventCategorySelected(selectedAlertEvent); diff --git a/x-pack/plugins/session_view/public/components/process_tree_node/index.tsx b/x-pack/plugins/session_view/public/components/process_tree_node/index.tsx index 3bd72837e01ed..a6201ea2ed504 100644 --- a/x-pack/plugins/session_view/public/components/process_tree_node/index.tsx +++ b/x-pack/plugins/session_view/public/components/process_tree_node/index.tsx @@ -128,7 +128,7 @@ export function ProcessTreeNode({ const nodeRef = useVisible({ viewPortEl: scrollerRef.current, visibleCallback: useCallback( - (isVisible, isAbove) => { + (isVisible: any, isAbove: any) => { onChangeJumpToEventVisibility(isVisible, isAbove); }, [onChangeJumpToEventVisibility] diff --git a/x-pack/plugins/session_view/public/components/tty_player/hooks.ts b/x-pack/plugins/session_view/public/components/tty_player/hooks.ts index 73f85b9da3783..a1f039f9caad0 100644 --- a/x-pack/plugins/session_view/public/components/tty_player/hooks.ts +++ b/x-pack/plugins/session_view/public/components/tty_player/hooks.ts @@ -335,7 +335,7 @@ export const useXtermPlayer = ({ }, [lines, currentLine, isPlaying, playSpeed, render, hasNextPage, fetchNextPage, setIsPlaying]); const seekToLine = useCallback( - (index) => { + (index: any) => { setCurrentLine(index); render(index, true); diff --git a/x-pack/plugins/session_view/public/components/tty_search_bar/index.tsx b/x-pack/plugins/session_view/public/components/tty_search_bar/index.tsx index 9ba7958cb53b6..71225b4cda939 100644 --- a/x-pack/plugins/session_view/public/components/tty_search_bar/index.tsx +++ b/x-pack/plugins/session_view/public/components/tty_search_bar/index.tsx @@ -37,7 +37,7 @@ export const TTYSearchBar = ({ const [currentMatch, setCurrentMatch] = useState(null); const jumpToMatch = useCallback( - (match) => { + (match: any) => { if (match) { setIsPlaying(false); const goToLine = lines.indexOf(match.line); @@ -103,7 +103,7 @@ export const TTYSearchBar = ({ }, [searchQuery, lines, jumpToMatch, xTermSearchFn]); const onSearch = useCallback( - (query) => { + (query: any) => { setIsPlaying(false); setSearchQuery(query); setCurrentMatch(null); @@ -112,7 +112,7 @@ export const TTYSearchBar = ({ ); const onSetCurrentMatch = useCallback( - (index) => { + (index: any) => { const match = searchResults[index]; if (match && currentMatch !== match) { diff --git a/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.test.tsx b/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.test.tsx index 3b82be30c6026..f169395688de1 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.test.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.test.tsx @@ -237,6 +237,51 @@ describe('ManageSpacePage', () => { expect(wrapper.find(EnabledFeatures)).toHaveLength(0); }); + it('hides feature visibility controls when solution view is not "classic"', async () => { + const spacesManager = spacesManagerMock.create(); + + const wrapper = mountWithIntl( + + ); + + await waitFor(async () => { + await Promise.resolve(); + + wrapper.update(); + + // default for create space: expect visible features table to exist + expect(wrapper.find(EnabledFeatures)).toHaveLength(1); + }); + + await waitFor(() => { + // switch to observability view + updateSpace(wrapper, false, 'oblt'); + // expect visible features table to not exist + expect(wrapper.find(EnabledFeatures)).toHaveLength(0); + }); + + await waitFor(() => { + // switch to classic + updateSpace(wrapper, false, 'classic'); + // expect visible features table to exist again + expect(wrapper.find(EnabledFeatures)).toHaveLength(1); + }); + }); + it('allows a space to be updated', async () => { const spaceToUpdate = { id: 'existing-space', diff --git a/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.tsx b/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.tsx index b34d2eec88e48..cb81ae9304260 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.tsx @@ -66,6 +66,7 @@ interface State { features: KibanaFeature[]; originalSpace?: Partial; showAlteringActiveSpaceDialog: boolean; + showVisibleFeaturesPicker: boolean; haveDisabledFeaturesChanged: boolean; hasSolutionViewChanged: boolean; isLoading: boolean; @@ -85,6 +86,7 @@ export class ManageSpacePage extends Component { this.state = { isLoading: true, showAlteringActiveSpaceDialog: false, + showVisibleFeaturesPicker: !!props.allowFeatureVisibility, saveInProgress: false, space: { color: getSpaceColor({}), @@ -203,7 +205,7 @@ export class ManageSpacePage extends Component { { )} - {this.props.allowFeatureVisibility && ( + {this.state.showVisibleFeaturesPicker && ( <> { return null; }; + private onSolutionViewChange = (space: Partial) => { + if (this.props.allowFeatureVisibility) { + let showVisibleFeaturesPicker = false; + if (space.solution === 'classic' || space.solution == null) { + showVisibleFeaturesPicker = true; + } + this.setState((state) => ({ ...state, showVisibleFeaturesPicker })); + } + this.onSpaceChange(space); + }; + public onSpaceChange = (updatedSpace: FormValues) => { this.setState({ space: updatedSpace, diff --git a/x-pack/plugins/spaces/public/management/management_service.test.ts b/x-pack/plugins/spaces/public/management/management_service.test.ts index e01ddd8db9ae2..5f97515171518 100644 --- a/x-pack/plugins/spaces/public/management/management_service.test.ts +++ b/x-pack/plugins/spaces/public/management/management_service.test.ts @@ -42,6 +42,7 @@ describe('ManagementService', () => { spacesManager: spacesManagerMock.create(), config, getRolesAPIClient: getRolesAPIClientMock, + getPrivilegesAPIClient: jest.fn(), eventTracker, }); @@ -63,6 +64,7 @@ describe('ManagementService', () => { spacesManager: spacesManagerMock.create(), config, getRolesAPIClient: getRolesAPIClientMock, + getPrivilegesAPIClient: jest.fn(), eventTracker, }); }); @@ -85,6 +87,7 @@ describe('ManagementService', () => { spacesManager: spacesManagerMock.create(), config, getRolesAPIClient: jest.fn(), + getPrivilegesAPIClient: jest.fn(), eventTracker, }); diff --git a/x-pack/plugins/spaces/public/management/management_service.tsx b/x-pack/plugins/spaces/public/management/management_service.tsx index 9bc94e70b83f5..b186135d88e05 100644 --- a/x-pack/plugins/spaces/public/management/management_service.tsx +++ b/x-pack/plugins/spaces/public/management/management_service.tsx @@ -7,7 +7,10 @@ import type { StartServicesAccessor } from '@kbn/core/public'; import type { ManagementApp, ManagementSetup } from '@kbn/management-plugin/public'; -import type { RolesAPIClient } from '@kbn/security-plugin-types-public'; +import type { + PrivilegesAPIClientPublicContract, + RolesAPIClient, +} from '@kbn/security-plugin-types-public'; import { spacesManagementApp } from './spaces_management_app'; import type { EventTracker } from '../analytics'; @@ -22,6 +25,7 @@ interface SetupDeps { config: ConfigType; getRolesAPIClient: () => Promise; eventTracker: EventTracker; + getPrivilegesAPIClient: () => Promise; } export class ManagementService { @@ -34,6 +38,7 @@ export class ManagementService { config, getRolesAPIClient, eventTracker, + getPrivilegesAPIClient, }: SetupDeps) { this.registeredSpacesManagementApp = management.sections.section.kibana.registerApp( spacesManagementApp.create({ @@ -42,6 +47,7 @@ export class ManagementService { config, getRolesAPIClient, eventTracker, + getPrivilegesAPIClient, }) ); } diff --git a/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx b/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx index 2415d603086e9..61619c499181c 100644 --- a/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx @@ -57,6 +57,7 @@ async function mountApp(basePath: string, pathname: string, spaceId?: string) { getStartServices: async () => [coreStart, pluginsStart as PluginsStart, {}], config, getRolesAPIClient: jest.fn(), + getPrivilegesAPIClient: jest.fn(), eventTracker, }) .mount({ @@ -79,6 +80,7 @@ describe('spacesManagementApp', () => { getStartServices: coreMock.createSetup().getStartServices as any, config, getRolesAPIClient: jest.fn(), + getPrivilegesAPIClient: jest.fn(), eventTracker, }) ).toMatchInlineSnapshot(` diff --git a/x-pack/plugins/spaces/public/management/spaces_management_app.tsx b/x-pack/plugins/spaces/public/management/spaces_management_app.tsx index 9883286122653..40532a7259521 100644 --- a/x-pack/plugins/spaces/public/management/spaces_management_app.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_management_app.tsx @@ -14,7 +14,10 @@ import { i18n } from '@kbn/i18n'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import type { RegisterManagementAppArgs } from '@kbn/management-plugin/public'; import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; -import type { RolesAPIClient } from '@kbn/security-plugin-types-public'; +import type { + PrivilegesAPIClientPublicContract, + RolesAPIClient, +} from '@kbn/security-plugin-types-public'; import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app'; import { Route, Router, Routes } from '@kbn/shared-ux-router'; @@ -30,6 +33,7 @@ interface CreateParams { config: ConfigType; getRolesAPIClient: () => Promise; eventTracker: EventTracker; + getPrivilegesAPIClient: () => Promise; } export const spacesManagementApp = Object.freeze({ diff --git a/x-pack/plugins/spaces/public/plugin.tsx b/x-pack/plugins/spaces/public/plugin.tsx index b07595618c3cc..31ba324b926f3 100644 --- a/x-pack/plugins/spaces/public/plugin.tsx +++ b/x-pack/plugins/spaces/public/plugin.tsx @@ -95,6 +95,18 @@ export class SpacesPlugin implements Plugin { + const { security } = await core.plugins.onSetup<{ security: SecurityPluginStart }>( + 'security' + ); + + if (!security.found) { + throw new Error('Security plugin is not available as runtime dependency.'); + } + + return security.contract.authz.privileges; + }; + if (plugins.home) { plugins.home.featureCatalogue.register(createSpacesFeatureCatalogueEntry()); } @@ -108,6 +120,7 @@ export class SpacesPlugin implements Plugin field.toSpec()))); }, []); - const onUpdateFilters = useCallback((newFilters) => { - dispatch({ type: 'filter', payload: mapAndFlattenFilters(newFilters) }); - }, []); + const onUpdateFilters = useCallback>( + (newFilters) => { + dispatch({ type: 'filter', payload: mapAndFlattenFilters(newFilters) }); + }, + [] + ); const onChangeQuery = useCallback( ({ query: newQuery }: { query?: Query }) => { diff --git a/x-pack/plugins/stack_connectors/common/gemini/schema.ts b/x-pack/plugins/stack_connectors/common/gemini/schema.ts index 543070c705907..43bf7337626e3 100644 --- a/x-pack/plugins/stack_connectors/common/gemini/schema.ts +++ b/x-pack/plugins/stack_connectors/common/gemini/schema.ts @@ -57,16 +57,24 @@ export const RunActionRawResponseSchema = schema.any(); export const InvokeAIActionParamsSchema = schema.object({ messages: schema.any(), + systemInstruction: schema.maybe(schema.string()), model: schema.maybe(schema.string()), temperature: schema.maybe(schema.number()), stopSequences: schema.maybe(schema.arrayOf(schema.string())), signal: schema.maybe(schema.any()), timeout: schema.maybe(schema.number()), tools: schema.maybe(schema.arrayOf(schema.any())), + toolConfig: schema.maybe( + schema.object({ + mode: schema.oneOf([schema.literal('AUTO'), schema.literal('ANY'), schema.literal('NONE')]), + allowedFunctionNames: schema.maybe(schema.arrayOf(schema.string())), + }) + ), }); export const InvokeAIRawActionParamsSchema = schema.object({ messages: schema.any(), + systemInstruction: schema.maybe(schema.string()), model: schema.maybe(schema.string()), temperature: schema.maybe(schema.number()), stopSequences: schema.maybe(schema.arrayOf(schema.string())), diff --git a/x-pack/plugins/stack_connectors/common/openai/constants.ts b/x-pack/plugins/stack_connectors/common/openai/constants.ts index 1b1bd09618ebc..c57720d9847af 100644 --- a/x-pack/plugins/stack_connectors/common/openai/constants.ts +++ b/x-pack/plugins/stack_connectors/common/openai/constants.ts @@ -36,8 +36,8 @@ export const DEFAULT_OPENAI_MODEL = 'gpt-4o'; export const OPENAI_CHAT_URL = 'https://api.openai.com/v1/chat/completions' as const; export const OPENAI_LEGACY_COMPLETION_URL = 'https://api.openai.com/v1/completions' as const; export const AZURE_OPENAI_CHAT_URL = - 'https://{your-resource-name}.openai.azure.com/openai/deployments/{deployment-id}/chat/completions?api-version={api-version}' as const; + '/openai/deployments/{deployment-id}/chat/completions?api-version={api-version}' as const; export const AZURE_OPENAI_COMPLETIONS_URL = - 'https://{your-resource-name}.openai.azure.com/openai/deployments/{deployment-id}/completions?api-version={api-version}' as const; + '/openai/deployments/{deployment-id}/completions?api-version={api-version}' as const; export const AZURE_OPENAI_COMPLETIONS_EXTENSIONS_URL = - 'https://{your-resource-name}.openai.azure.com/openai/deployments/{deployment-id}/extensions/chat/completions?api-version={api-version}' as const; + '/openai/deployments/{deployment-id}/extensions/chat/completions?api-version={api-version}' as const; diff --git a/x-pack/plugins/stack_connectors/public/connector_types/bedrock/dashboard_link.tsx b/x-pack/plugins/stack_connectors/public/connector_types/bedrock/dashboard_link.tsx index e9541c3f6759c..9074f2ae2b618 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/bedrock/dashboard_link.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/bedrock/dashboard_link.tsx @@ -29,7 +29,7 @@ export const DashboardLink: React.FC = ({ }, } = useKibana(); const onClick = useCallback( - (e) => { + (e: React.SyntheticEvent) => { e.preventDefault(); if (dashboardUrl) { navigateToUrl(dashboardUrl); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/webhook_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/webhook_params.tsx index 8e6a7c587e9cc..0e2491304bd9e 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/webhook_params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/webhook_params.tsx @@ -73,7 +73,7 @@ const WebhookParamsFields: React.FunctionComponent { + (key: string, value: string) => { return editAction( 'subActionParams', { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/jira/jira_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/jira/jira_params.tsx index 7ae1efbe13f38..b5c029282b9ca 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/jira/jira_params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/jira/jira_params.tsx @@ -97,7 +97,7 @@ const JiraParamsFields: React.FunctionComponent { + (key: string, value: string) => { editSubActionProperty(key, [{ commentId: '1', comment: value }]); }, [editSubActionProperty] diff --git a/x-pack/plugins/stack_connectors/public/connector_types/jira/search_issues.tsx b/x-pack/plugins/stack_connectors/public/connector_types/jira/search_issues.tsx index f12a848de9a54..35af5e6a8a0fd 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/jira/search_issues.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/jira/search_issues.tsx @@ -69,9 +69,11 @@ const SearchIssuesComponent: React.FC = ({ }, []); const onChangeComboBox = useCallback( - (changedOptions) => { + (changedOptions: Array>) => { setSelectedOptions(changedOptions); - onChange(changedOptions[0].value); + if (changedOptions[0].value) { + onChange(changedOptions[0].value); + } }, [onChange] ); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/lib/servicenow/use_get_app_info.tsx b/x-pack/plugins/stack_connectors/public/connector_types/lib/servicenow/use_get_app_info.tsx index b0b295c9b7269..5a619dd557fc6 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/lib/servicenow/use_get_app_info.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/lib/servicenow/use_get_app_info.tsx @@ -30,7 +30,7 @@ export const useGetAppInfo = ({ actionTypeId, http }: UseGetAppInfoProps): UseGe const abortCtrl = useRef(new AbortController()); const fetchAppInfo = useCallback( - async (connector) => { + async (connector: ServiceNowActionConnector) => { try { if (!actionTypeId || isEmpty(actionTypeId)) { return; diff --git a/x-pack/plugins/stack_connectors/public/connector_types/openai/dashboard_link.tsx b/x-pack/plugins/stack_connectors/public/connector_types/openai/dashboard_link.tsx index 85c1a9a1955b6..86b5298172a84 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/openai/dashboard_link.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/openai/dashboard_link.tsx @@ -29,7 +29,7 @@ export const DashboardLink: React.FC = ({ }, } = useKibana(); const onClick = useCallback( - (e) => { + (e: React.SyntheticEvent) => { e.preventDefault(); if (dashboardUrl) { navigateToUrl(dashboardUrl); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/opsgenie/create_alert/index.tsx b/x-pack/plugins/stack_connectors/public/connector_types/opsgenie/create_alert/index.tsx index ff67e51cad805..5e4cb6787e391 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/opsgenie/create_alert/index.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/opsgenie/create_alert/index.tsx @@ -19,6 +19,7 @@ import { EuiFormRow, EuiSpacer, EuiSwitch, + EuiSwitchEvent, EuiText, } from '@elastic/eui'; import type { @@ -143,7 +144,7 @@ const CreateAlertComponent: React.FC = ({ const [showJsonEditor, setShowJsonEditor] = useState(false); const toggleShowJsonEditor = useCallback( - (event) => { + (event: EuiSwitchEvent) => { if (!event.target.checked) { // when the user switches back remove the json editor error if there was one // must mark as undefined to remove the field so it is not sent to the server side diff --git a/x-pack/plugins/stack_connectors/public/connector_types/opsgenie/params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/opsgenie/params.tsx index 3ae86b1e7f9ad..e4e288623f206 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/opsgenie/params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/opsgenie/params.tsx @@ -22,6 +22,7 @@ import type { OpsgenieActionParams, OpsgenieCreateAlertSubActionParams, } from '../../../server/connector_types'; +import { EditActionCallback } from './types'; const actionOptions = [ { @@ -55,7 +56,7 @@ const OpsgenieParamFields: React.FC> = ( [editAction, index] ); - const editOptionalSubAction = useCallback( + const editOptionalSubAction: EditActionCallback = useCallback( (key, value) => { if (isEmpty(value)) { const paramsCopy = cloneDeep(subActionParams); @@ -69,7 +70,7 @@ const OpsgenieParamFields: React.FC> = ( [editAction, index, subActionParams] ); - const editSubAction = useCallback( + const editSubAction: EditActionCallback = useCallback( (key, value) => { editAction('subActionParams', { ...subActionParams, [key]: value }, index); }, diff --git a/x-pack/plugins/stack_connectors/public/connector_types/resilient/resilient_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/resilient/resilient_params.tsx index 7cba015493d30..a1c202c36ef8a 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/resilient/resilient_params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/resilient/resilient_params.tsx @@ -109,7 +109,7 @@ const ResilientParamsFields: React.FunctionComponent { + (key: string, value: string) => { editSubActionProperty(key, [{ commentId: '1', comment: value }]); }, [editSubActionProperty] diff --git a/x-pack/plugins/stack_connectors/public/connector_types/servicenow_itsm/servicenow_itsm_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/servicenow_itsm/servicenow_itsm_params.tsx index 51cbd8f46fc92..67de15909ded5 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/servicenow_itsm/servicenow_itsm_params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/servicenow_itsm/servicenow_itsm_params.tsx @@ -167,7 +167,7 @@ const ServiceNowParamsFields: React.FunctionComponent< ); const editComment = useCallback( - (key, value) => { + (key: string, value: string) => { editSubActionProperty(key, [{ commentId: '1', comment: value }]); }, [editSubActionProperty] diff --git a/x-pack/plugins/stack_connectors/public/connector_types/servicenow_sir/servicenow_sir_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/servicenow_sir/servicenow_sir_params.tsx index 19cc8407632fc..c6b207c70b3c3 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/servicenow_sir/servicenow_sir_params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/servicenow_sir/servicenow_sir_params.tsx @@ -77,7 +77,7 @@ const ServiceNowSIRParamsFields: React.FunctionComponent< ); const editComment = useCallback( - (key, value) => { + (key: string, value: string) => { editSubActionProperty(key, [{ commentId: '1', comment: value }]); }, [editSubActionProperty] diff --git a/x-pack/plugins/stack_connectors/public/connector_types/slack_api/slack_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/slack_api/slack_params.tsx index a41b6a6b73e01..5264863d6ab4e 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/slack_api/slack_params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/slack_api/slack_params.tsx @@ -225,7 +225,7 @@ const SlackParamsFields: React.FunctionComponent< }, [editAction, index, tempChannelId, text]); const onChangeTextField = useCallback( - (evt) => { + (evt: React.ChangeEvent) => { editAction('subActionParams', { channels: undefined, channelIds: [], text }, index); setTempChannelId(evt.target.value); }, @@ -323,7 +323,7 @@ const SlackParamsFields: React.FunctionComponent< {messageType === 'text' ? ( { + editAction={(_: string, value: string) => { setTextValue(value); editAction('subActionParams', { channels, channelIds, text: value }, index); }} diff --git a/x-pack/plugins/stack_connectors/public/connector_types/swimlane/swimlane_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/swimlane/swimlane_params.tsx index 1faa8c8bbabf4..1f60422adbcae 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/swimlane/swimlane_params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/swimlane/swimlane_params.tsx @@ -78,7 +78,7 @@ const SwimlaneParamsFields: React.FunctionComponent { + (key: string, value: string) => { editSubActionProperty(key, [{ commentId: '1', comment: value }]); }, [editSubActionProperty] diff --git a/x-pack/plugins/stack_connectors/public/connector_types/tines/tines_params.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/tines/tines_params.test.tsx index 495a15c6a569c..72bc2e3ae891f 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/tines/tines_params.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/tines/tines_params.test.tsx @@ -467,6 +467,50 @@ describe('TinesParamsFields renders', () => { webhookUrl ); }); + + it('should render webhook url fallback when stories request has error', () => { + const errorMessage = 'something broke'; + mockUseSubActionStories.mockReturnValueOnce({ + isLoading: false, + response: { stories: [story] }, + error: new Error(errorMessage), + }); + + const wrapper = mountWithIntl( + + ); + + expect(wrapper.find('[data-test-subj="tines-fallbackCallout"]').exists()).toBe(true); + expect(wrapper.find('[data-test-subj="tines-webhookUrlInput"]').exists()).toBe(true); + }); + + it('should render webhook url fallback when webhooks request has error', () => { + const errorMessage = 'something broke'; + mockUseSubActionWebhooks.mockReturnValueOnce({ + isLoading: false, + response: { webhooks: [webhook] }, + error: new Error(errorMessage), + }); + + const wrapper = mountWithIntl( + + ); + + expect(wrapper.find('[data-test-subj="tines-fallbackCallout"]').exists()).toBe(true); + expect(wrapper.find('[data-test-subj="tines-webhookUrlInput"]').exists()).toBe(true); + }); }); describe('subActions error', () => { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/tines/tines_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/tines/tines_params.tsx index 11249f9c8db3c..2726e0e3ec8a5 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/tines/tines_params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/tines/tines_params.tsx @@ -137,7 +137,10 @@ const TinesParamsFields: React.FunctionComponent(() => { + const showFallbackFrom = useMemo<'Story' | 'Webhook' | 'any' | 'error' | null>(() => { + if (storiesError || webhooksError) { + return 'error'; + } if (incompleteStories && !selectedStoryOption) { return 'Story'; } @@ -150,7 +153,9 @@ const TinesParamsFields: React.FunctionComponent - {showFallbackFrom !== 'any' && ( + {showFallbackFrom === 'error' && ( + <> + + {i18n.WEBHOOK_URL_ERROR_FALLBACK} + + + + )} + {(showFallbackFrom === 'Story' || showFallbackFrom === 'Webhook') && ( <> values: { entity, limit: API_MAX_RESULTS }, defaultMessage: `Not possible to retrieve more than {limit} results from the Tines {entity} API. If your {entity} does not appear in the list, please fill the Webhook URL below`, }); + +export const WEBHOOK_URL_ERROR_FALLBACK_TITLE = i18n.translate( + 'xpack.stackConnectors.security.tines.params.webhookUrlErrorFallbackTitle', + { + defaultMessage: 'Error using Tines API', + } +); +export const WEBHOOK_URL_ERROR_FALLBACK = i18n.translate( + 'xpack.stackConnectors.security.tines.params.webhookUrlErrorFallback', + { + defaultMessage: + 'There seems to be an issue retrieving Stories or Webhooks using the Tines API. Alternatively, you can set the Tines Webhook URL in the input below', + } +); export const WEBHOOK_URL_HELP = i18n.translate( 'xpack.stackConnectors.security.tines.params.webhookUrlHelp', { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/bedrock/bedrock.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/bedrock/bedrock.test.ts index ce85e27a8eb43..2a4d91a07f1d3 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/bedrock/bedrock.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/bedrock/bedrock.test.ts @@ -25,6 +25,7 @@ import { import { DEFAULT_BODY } from '../../../public/connector_types/bedrock/constants'; import { initDashboard } from '../lib/gen_ai/create_gen_ai_dashboard'; import { AxiosError } from 'axios'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; jest.mock('../lib/gen_ai/create_gen_ai_dashboard'); // @ts-ignore @@ -37,6 +38,7 @@ describe('BedrockConnector', () => { completion: mockResponseString, stop_reason: 'stop_sequence', }; + const logger = loggingSystemMock.createLogger(); const claude3Response = { id: 'compl_01E7D3vTBHdNdKWCe6zALmLH', @@ -57,12 +59,18 @@ describe('BedrockConnector', () => { headers: {}, data: claude3Response, }; + let connectorUsageCollector: ConnectorUsageCollector; + beforeEach(() => { jest.clearAllMocks(); mockRequest = jest.fn().mockResolvedValue(mockResponse); mockError = jest.fn().mockImplementation(() => { throw new Error('API Error'); }); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); const connector = new BedrockConnector({ @@ -73,7 +81,7 @@ describe('BedrockConnector', () => { defaultModel: DEFAULT_BEDROCK_MODEL, }, secrets: { accessKey: '123', secret: 'secret' }, - logger: loggingSystemMock.createLogger(), + logger, services: actionsMock.createServices(), }); @@ -85,7 +93,13 @@ describe('BedrockConnector', () => { describe('runApi', () => { it('the aws signature has non-streaming headers', async () => { - await connector.runApi({ body: DEFAULT_BODY }); + await connector.runApi( + { body: DEFAULT_BODY }, + new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }) + ); expect(mockSigner).toHaveBeenCalledWith( { body: DEFAULT_BODY, @@ -101,16 +115,19 @@ describe('BedrockConnector', () => { ); }); it('the Bedrock API call is successful with Claude 3 parameters; returns the response formatted for Claude 2 along with usage object', async () => { - const response = await connector.runApi({ body: DEFAULT_BODY }); + const response = await connector.runApi({ body: DEFAULT_BODY }, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - timeout: DEFAULT_TIMEOUT_MS, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, - method: 'post', - responseSchema: RunApiLatestResponseSchema, - data: DEFAULT_BODY, - }); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + timeout: DEFAULT_TIMEOUT_MS, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, + method: 'post', + responseSchema: RunApiLatestResponseSchema, + data: DEFAULT_BODY, + }, + connectorUsageCollector + ); expect(response).toEqual({ ...claude2Response, usage: claude3Response.usage, @@ -128,16 +145,19 @@ describe('BedrockConnector', () => { }); // @ts-ignore connector.request = mockRequest; - const response = await connector.runApi({ body: v2Body }); + const response = await connector.runApi({ body: v2Body }, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - timeout: DEFAULT_TIMEOUT_MS, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, - method: 'post', - responseSchema: RunActionResponseSchema, - data: v2Body, - }); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + timeout: DEFAULT_TIMEOUT_MS, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, + method: 'post', + responseSchema: RunActionResponseSchema, + data: v2Body, + }, + connectorUsageCollector + ); expect(response).toEqual(claude2Response); }); @@ -145,7 +165,15 @@ describe('BedrockConnector', () => { // @ts-ignore connector.request = mockError; - await expect(connector.runApi({ body: DEFAULT_BODY })).rejects.toThrow('API Error'); + await expect( + connector.runApi( + { body: DEFAULT_BODY }, + new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }) + ) + ).rejects.toThrow('API Error'); }); }); @@ -170,7 +198,7 @@ describe('BedrockConnector', () => { }; it('the aws signature has streaming headers', async () => { - await connector.invokeStream(aiAssistantBody); + await connector.invokeStream(aiAssistantBody, connectorUsageCollector); expect(mockSigner).toHaveBeenCalledWith( { @@ -189,170 +217,197 @@ describe('BedrockConnector', () => { }); it('the API call is successful with correct request parameters', async () => { - await connector.invokeStream(aiAssistantBody); + await connector.invokeStream(aiAssistantBody, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke-with-response-stream`, - method: 'post', - responseSchema: StreamingResponseSchema, - responseType: 'stream', - data: JSON.stringify({ ...JSON.parse(DEFAULT_BODY), temperature: 0 }), - }); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke-with-response-stream`, + method: 'post', + responseSchema: StreamingResponseSchema, + responseType: 'stream', + data: JSON.stringify({ ...JSON.parse(DEFAULT_BODY), temperature: 0 }), + }, + connectorUsageCollector + ); }); it('signal and timeout is properly passed to streamApi', async () => { const signal = jest.fn(); const timeout = 180000; - await connector.invokeStream({ ...aiAssistantBody, timeout, signal }); - - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke-with-response-stream`, - method: 'post', - responseSchema: StreamingResponseSchema, - responseType: 'stream', - data: JSON.stringify({ ...JSON.parse(DEFAULT_BODY), temperature: 0 }), - timeout, - signal, - }); + await connector.invokeStream( + { ...aiAssistantBody, timeout, signal }, + connectorUsageCollector + ); + + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke-with-response-stream`, + method: 'post', + responseSchema: StreamingResponseSchema, + responseType: 'stream', + data: JSON.stringify({ ...JSON.parse(DEFAULT_BODY), temperature: 0 }), + timeout, + signal, + }, + connectorUsageCollector + ); }); it('ensureMessageFormat - formats messages from user, assistant, and system', async () => { - await connector.invokeStream({ - messages: [ - { - role: 'system', - content: 'Be a good chatbot', - }, - { - role: 'user', - content: 'Hello world', - }, - { - role: 'assistant', - content: 'Hi, I am a good chatbot', - }, - { - role: 'user', - content: 'What is 2+2?', - }, - ], - }); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - responseType: 'stream', - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke-with-response-stream`, - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ - anthropic_version: 'bedrock-2023-05-31', - system: 'Be a good chatbot', + await connector.invokeStream( + { messages: [ - { content: 'Hello world', role: 'user' }, - { content: 'Hi, I am a good chatbot', role: 'assistant' }, - { content: 'What is 2+2?', role: 'user' }, + { + role: 'system', + content: 'Be a good chatbot', + }, + { + role: 'user', + content: 'Hello world', + }, + { + role: 'assistant', + content: 'Hi, I am a good chatbot', + }, + { + role: 'user', + content: 'What is 2+2?', + }, ], - max_tokens: DEFAULT_TOKEN_LIMIT, - temperature: 0, - }), - }); + }, + connectorUsageCollector + ); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + responseType: 'stream', + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke-with-response-stream`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + anthropic_version: 'bedrock-2023-05-31', + system: 'Be a good chatbot', + messages: [ + { content: 'Hello world', role: 'user' }, + { content: 'Hi, I am a good chatbot', role: 'assistant' }, + { content: 'What is 2+2?', role: 'user' }, + ], + max_tokens: DEFAULT_TOKEN_LIMIT, + temperature: 0, + }), + }, + connectorUsageCollector + ); }); it('ensureMessageFormat - formats messages from when double user/assistant occurs', async () => { - await connector.invokeStream({ - messages: [ - { - role: 'system', - content: 'Be a good chatbot', - }, - { - role: 'assistant', - content: 'Hi, I am a good chatbot', - }, - { - role: 'assistant', - content: 'But I can be naughty', - }, - { - role: 'user', - content: 'What is 2+2?', - }, - { - role: 'user', - content: 'I can be naughty too', - }, - { - role: 'system', - content: 'This is extra tricky', - }, - ], - }); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - responseType: 'stream', - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke-with-response-stream`, - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ - anthropic_version: 'bedrock-2023-05-31', - system: 'Be a good chatbot\nThis is extra tricky', + await connector.invokeStream( + { messages: [ - { content: 'Hi, I am a good chatbot\nBut I can be naughty', role: 'assistant' }, - { content: 'What is 2+2?\nI can be naughty too', role: 'user' }, + { + role: 'system', + content: 'Be a good chatbot', + }, + { + role: 'assistant', + content: 'Hi, I am a good chatbot', + }, + { + role: 'assistant', + content: 'But I can be naughty', + }, + { + role: 'user', + content: 'What is 2+2?', + }, + { + role: 'user', + content: 'I can be naughty too', + }, + { + role: 'system', + content: 'This is extra tricky', + }, ], - max_tokens: DEFAULT_TOKEN_LIMIT, - temperature: 0, - }), - }); + }, + connectorUsageCollector + ); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + responseType: 'stream', + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke-with-response-stream`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + anthropic_version: 'bedrock-2023-05-31', + system: 'Be a good chatbot\nThis is extra tricky', + messages: [ + { content: 'Hi, I am a good chatbot\nBut I can be naughty', role: 'assistant' }, + { content: 'What is 2+2?\nI can be naughty too', role: 'user' }, + ], + max_tokens: DEFAULT_TOKEN_LIMIT, + temperature: 0, + }), + }, + connectorUsageCollector + ); }); it('formats the system message as a user message for claude<2.1', async () => { const modelOverride = 'anthropic.claude-v2'; - await connector.invokeStream({ - messages: [ - { - role: 'system', - content: 'Be a good chatbot', - }, - { - role: 'user', - content: 'Hello world', - }, - { - role: 'assistant', - content: 'Hi, I am a good chatbot', - }, - { - role: 'user', - content: 'What is 2+2?', - }, - ], - model: modelOverride, - }); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - responseType: 'stream', - url: `${DEFAULT_BEDROCK_URL}/model/${modelOverride}/invoke-with-response-stream`, - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ - anthropic_version: 'bedrock-2023-05-31', - system: 'Be a good chatbot', + await connector.invokeStream( + { messages: [ - { content: 'Hello world', role: 'user' }, - { content: 'Hi, I am a good chatbot', role: 'assistant' }, - { content: 'What is 2+2?', role: 'user' }, + { + role: 'system', + content: 'Be a good chatbot', + }, + { + role: 'user', + content: 'Hello world', + }, + { + role: 'assistant', + content: 'Hi, I am a good chatbot', + }, + { + role: 'user', + content: 'What is 2+2?', + }, ], - max_tokens: DEFAULT_TOKEN_LIMIT, - temperature: 0, - }), - }); + model: modelOverride, + }, + connectorUsageCollector + ); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + responseType: 'stream', + url: `${DEFAULT_BEDROCK_URL}/model/${modelOverride}/invoke-with-response-stream`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + anthropic_version: 'bedrock-2023-05-31', + system: 'Be a good chatbot', + messages: [ + { content: 'Hello world', role: 'user' }, + { content: 'Hi, I am a good chatbot', role: 'assistant' }, + { content: 'What is 2+2?', role: 'user' }, + ], + max_tokens: DEFAULT_TOKEN_LIMIT, + temperature: 0, + }), + }, + connectorUsageCollector + ); }); it('responds with a readable stream', async () => { - const response = await connector.invokeStream(aiAssistantBody); + const response = await connector.invokeStream(aiAssistantBody, connectorUsageCollector); expect(response instanceof PassThrough).toEqual(true); }); @@ -360,7 +415,9 @@ describe('BedrockConnector', () => { // @ts-ignore connector.request = mockError; - await expect(connector.invokeStream(aiAssistantBody)).rejects.toThrow('API Error'); + await expect( + connector.invokeStream(aiAssistantBody, connectorUsageCollector) + ).rejects.toThrow('API Error'); }); }); @@ -376,175 +433,201 @@ describe('BedrockConnector', () => { }; it('the API call is successful with correct parameters', async () => { - const response = await connector.invokeAI(aiAssistantBody); + const response = await connector.invokeAI(aiAssistantBody, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - timeout: DEFAULT_TIMEOUT_MS, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, - method: 'post', - responseSchema: RunApiLatestResponseSchema, - data: JSON.stringify({ - ...JSON.parse(DEFAULT_BODY), - messages: [{ content: 'Hello world', role: 'user' }], - max_tokens: DEFAULT_TOKEN_LIMIT, - temperature: 0, - }), - }); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + timeout: DEFAULT_TIMEOUT_MS, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, + method: 'post', + responseSchema: RunApiLatestResponseSchema, + data: JSON.stringify({ + ...JSON.parse(DEFAULT_BODY), + messages: [{ content: 'Hello world', role: 'user' }], + max_tokens: DEFAULT_TOKEN_LIMIT, + temperature: 0, + }), + }, + connectorUsageCollector + ); expect(response.message).toEqual(mockResponseString); }); it('formats messages from user, assistant, and system', async () => { - const response = await connector.invokeAI({ - messages: [ - { - role: 'system', - content: 'Be a good chatbot', - }, - { - role: 'user', - content: 'Hello world', - }, - { - role: 'assistant', - content: 'Hi, I am a good chatbot', - }, - { - role: 'user', - content: 'What is 2+2?', - }, - ], - }); - expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - timeout: DEFAULT_TIMEOUT_MS, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, - method: 'post', - responseSchema: RunApiLatestResponseSchema, - data: JSON.stringify({ - anthropic_version: 'bedrock-2023-05-31', - system: 'Be a good chatbot', + const response = await connector.invokeAI( + { messages: [ - { content: 'Hello world', role: 'user' }, - { content: 'Hi, I am a good chatbot', role: 'assistant' }, - { content: 'What is 2+2?', role: 'user' }, + { + role: 'system', + content: 'Be a good chatbot', + }, + { + role: 'user', + content: 'Hello world', + }, + { + role: 'assistant', + content: 'Hi, I am a good chatbot', + }, + { + role: 'user', + content: 'What is 2+2?', + }, ], - max_tokens: DEFAULT_TOKEN_LIMIT, - temperature: 0, - }), - }); + }, + connectorUsageCollector + ); + expect(mockRequest).toBeCalledTimes(1); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + timeout: DEFAULT_TIMEOUT_MS, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, + method: 'post', + responseSchema: RunApiLatestResponseSchema, + data: JSON.stringify({ + anthropic_version: 'bedrock-2023-05-31', + system: 'Be a good chatbot', + messages: [ + { content: 'Hello world', role: 'user' }, + { content: 'Hi, I am a good chatbot', role: 'assistant' }, + { content: 'What is 2+2?', role: 'user' }, + ], + max_tokens: DEFAULT_TOKEN_LIMIT, + temperature: 0, + }), + }, + connectorUsageCollector + ); expect(response.message).toEqual(mockResponseString); }); it('adds system message from argument', async () => { - const response = await connector.invokeAI({ - messages: [ - { - role: 'user', - content: 'Hello world', - }, - { - role: 'assistant', - content: 'Hi, I am a good chatbot', - }, - { - role: 'user', - content: 'What is 2+2?', - }, - ], - system: 'This is a system message', - }); - expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - timeout: DEFAULT_TIMEOUT_MS, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, - method: 'post', - responseSchema: RunApiLatestResponseSchema, - data: JSON.stringify({ - anthropic_version: 'bedrock-2023-05-31', - system: 'This is a system message', + const response = await connector.invokeAI( + { messages: [ - { content: 'Hello world', role: 'user' }, - { content: 'Hi, I am a good chatbot', role: 'assistant' }, - { content: 'What is 2+2?', role: 'user' }, + { + role: 'user', + content: 'Hello world', + }, + { + role: 'assistant', + content: 'Hi, I am a good chatbot', + }, + { + role: 'user', + content: 'What is 2+2?', + }, ], - max_tokens: DEFAULT_TOKEN_LIMIT, - temperature: 0, - }), - }); + system: 'This is a system message', + }, + connectorUsageCollector + ); + expect(mockRequest).toBeCalledTimes(1); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + timeout: DEFAULT_TIMEOUT_MS, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, + method: 'post', + responseSchema: RunApiLatestResponseSchema, + data: JSON.stringify({ + anthropic_version: 'bedrock-2023-05-31', + system: 'This is a system message', + messages: [ + { content: 'Hello world', role: 'user' }, + { content: 'Hi, I am a good chatbot', role: 'assistant' }, + { content: 'What is 2+2?', role: 'user' }, + ], + max_tokens: DEFAULT_TOKEN_LIMIT, + temperature: 0, + }), + }, + connectorUsageCollector + ); expect(response.message).toEqual(mockResponseString); }); it('combines argument system message with conversation system message', async () => { - const response = await connector.invokeAI({ - messages: [ - { - role: 'system', - content: 'Be a good chatbot', - }, - { - role: 'user', - content: 'Hello world', - }, - { - role: 'assistant', - content: 'Hi, I am a good chatbot', - }, - { - role: 'user', - content: 'What is 2+2?', - }, - ], - system: 'This is a system message', - }); - expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - timeout: DEFAULT_TIMEOUT_MS, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, - method: 'post', - responseSchema: RunApiLatestResponseSchema, - data: JSON.stringify({ - anthropic_version: 'bedrock-2023-05-31', - system: 'This is a system message\nBe a good chatbot', + const response = await connector.invokeAI( + { messages: [ - { content: 'Hello world', role: 'user' }, - { content: 'Hi, I am a good chatbot', role: 'assistant' }, - { content: 'What is 2+2?', role: 'user' }, + { + role: 'system', + content: 'Be a good chatbot', + }, + { + role: 'user', + content: 'Hello world', + }, + { + role: 'assistant', + content: 'Hi, I am a good chatbot', + }, + { + role: 'user', + content: 'What is 2+2?', + }, ], - max_tokens: DEFAULT_TOKEN_LIMIT, - temperature: 0, - }), - }); + system: 'This is a system message', + }, + connectorUsageCollector + ); + expect(mockRequest).toBeCalledTimes(1); + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + timeout: DEFAULT_TIMEOUT_MS, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, + method: 'post', + responseSchema: RunApiLatestResponseSchema, + data: JSON.stringify({ + anthropic_version: 'bedrock-2023-05-31', + system: 'This is a system message\nBe a good chatbot', + messages: [ + { content: 'Hello world', role: 'user' }, + { content: 'Hi, I am a good chatbot', role: 'assistant' }, + { content: 'What is 2+2?', role: 'user' }, + ], + max_tokens: DEFAULT_TOKEN_LIMIT, + temperature: 0, + }), + }, + connectorUsageCollector + ); expect(response.message).toEqual(mockResponseString); }); it('signal and timeout is properly passed to runApi', async () => { const signal = jest.fn(); const timeout = 180000; - await connector.invokeAI({ ...aiAssistantBody, timeout, signal }); - - expect(mockRequest).toHaveBeenCalledWith({ - signed: true, - url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, - method: 'post', - responseSchema: RunApiLatestResponseSchema, - data: JSON.stringify({ - ...JSON.parse(DEFAULT_BODY), - messages: [{ content: 'Hello world', role: 'user' }], - max_tokens: DEFAULT_TOKEN_LIMIT, - temperature: 0, - }), - timeout, - signal, - }); + await connector.invokeAI({ ...aiAssistantBody, timeout, signal }, connectorUsageCollector); + + expect(mockRequest).toHaveBeenCalledWith( + { + signed: true, + url: `${DEFAULT_BEDROCK_URL}/model/${DEFAULT_BEDROCK_MODEL}/invoke`, + method: 'post', + responseSchema: RunApiLatestResponseSchema, + data: JSON.stringify({ + ...JSON.parse(DEFAULT_BODY), + messages: [{ content: 'Hello world', role: 'user' }], + max_tokens: DEFAULT_TOKEN_LIMIT, + temperature: 0, + }), + timeout, + signal, + }, + connectorUsageCollector + ); }); it('errors during API calls are properly handled', async () => { // @ts-ignore connector.request = mockError; - await expect(connector.invokeAI(aiAssistantBody)).rejects.toThrow('API Error'); + await expect(connector.invokeAI(aiAssistantBody, connectorUsageCollector)).rejects.toThrow( + 'API Error' + ); }); }); describe('getResponseErrorMessage', () => { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/bedrock/bedrock.ts b/x-pack/plugins/stack_connectors/server/connector_types/bedrock/bedrock.ts index 6b981a365b63a..b5ec114a9c456 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/bedrock/bedrock.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/bedrock/bedrock.ts @@ -11,6 +11,7 @@ import { AxiosError, Method } from 'axios'; import { IncomingMessage } from 'http'; import { PassThrough } from 'stream'; import { SubActionRequestParams } from '@kbn/actions-plugin/server/sub_action_framework/types'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { initDashboard } from '../lib/gen_ai/create_gen_ai_dashboard'; import { RunActionParamsSchema, @@ -194,16 +195,18 @@ The Kibana Connector in use may need to be reconfigured with an updated Amazon B } private async runApiRaw( - params: SubActionRequestParams + params: SubActionRequestParams, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - const response = await this.request(params); + const response = await this.request(params, connectorUsageCollector); return response.data; } private async runApiLatest( - params: SubActionRequestParams + params: SubActionRequestParams, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - const response = await this.request(params); + const response = await this.request(params, connectorUsageCollector); // keeping the response the same as claude 2 for our APIs // adding the usage object for better token tracking return { @@ -218,13 +221,10 @@ The Kibana Connector in use may need to be reconfigured with an updated Amazon B * @param body The stringified request body to be sent in the POST request. * @param model Optional model to be used for the API request. If not provided, the default model from the connector will be used. */ - public async runApi({ - body, - model: reqModel, - signal, - timeout, - raw, - }: RunActionParams): Promise { + public async runApi( + { body, model: reqModel, signal, timeout, raw }: RunActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { // set model on per request basis const currentModel = reqModel ?? this.model; const path = `/model/${currentModel}/invoke`; @@ -240,13 +240,22 @@ The Kibana Connector in use may need to be reconfigured with an updated Amazon B }; if (raw) { - return this.runApiRaw({ ...requestArgs, responseSchema: InvokeAIRawActionResponseSchema }); + return this.runApiRaw( + { ...requestArgs, responseSchema: InvokeAIRawActionResponseSchema }, + connectorUsageCollector + ); } // possible api received deprecated arguments, which will still work with the deprecated Claude 2 models if (usesDeprecatedArguments(body)) { - return this.runApiRaw({ ...requestArgs, responseSchema: RunActionResponseSchema }); + return this.runApiRaw( + { ...requestArgs, responseSchema: RunActionResponseSchema }, + connectorUsageCollector + ); } - return this.runApiLatest({ ...requestArgs, responseSchema: RunApiLatestResponseSchema }); + return this.runApiLatest( + { ...requestArgs, responseSchema: RunApiLatestResponseSchema }, + connectorUsageCollector + ); } /** @@ -257,26 +266,27 @@ The Kibana Connector in use may need to be reconfigured with an updated Amazon B * @param body The stringified request body to be sent in the POST request. * @param model Optional model to be used for the API request. If not provided, the default model from the connector will be used. */ - private async streamApi({ - body, - model: reqModel, - signal, - timeout, - }: RunActionParams): Promise { + private async streamApi( + { body, model: reqModel, signal, timeout }: RunActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { // set model on per request basis const path = `/model/${reqModel ?? this.model}/invoke-with-response-stream`; const signed = this.signRequest(body, path, true); - const response = await this.request({ - ...signed, - url: `${this.url}${path}`, - method: 'post', - responseSchema: StreamingResponseSchema, - data: body, - responseType: 'stream', - signal, - timeout, - }); + const response = await this.request( + { + ...signed, + url: `${this.url}${path}`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: body, + responseType: 'stream', + signal, + timeout, + }, + connectorUsageCollector + ); return response.data.pipe(new PassThrough()); } @@ -289,24 +299,30 @@ The Kibana Connector in use may need to be reconfigured with an updated Amazon B * @param messages An array of messages to be sent to the API * @param model Optional model to be used for the API request. If not provided, the default model from the connector will be used. */ - public async invokeStream({ - messages, - model, - stopSequences, - system, - temperature, - signal, - timeout, - tools, - }: InvokeAIActionParams | InvokeAIRawActionParams): Promise { - const res = (await this.streamApi({ - body: JSON.stringify( - formatBedrockBody({ messages, stopSequences, system, temperature, tools }) - ), + public async invokeStream( + { + messages, model, + stopSequences, + system, + temperature, signal, timeout, - })) as unknown as IncomingMessage; + tools, + }: InvokeAIActionParams | InvokeAIRawActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const res = (await this.streamApi( + { + body: JSON.stringify( + formatBedrockBody({ messages, stopSequences, system, temperature, tools }) + ), + model, + signal, + timeout, + }, + connectorUsageCollector + )) as unknown as IncomingMessage; return res; } @@ -318,54 +334,66 @@ The Kibana Connector in use may need to be reconfigured with an updated Amazon B * @param model Optional model to be used for the API request. If not provided, the default model from the connector will be used. * @returns an object with the response string as a property called message */ - public async invokeAI({ - messages, - model, - stopSequences, - system, - temperature, - maxTokens, - signal, - timeout, - }: InvokeAIActionParams): Promise { - const res = (await this.runApi({ - body: JSON.stringify( - formatBedrockBody({ messages, stopSequences, system, temperature, maxTokens }) - ), + public async invokeAI( + { + messages, model, + stopSequences, + system, + temperature, + maxTokens, signal, timeout, - })) as RunActionResponse; + }: InvokeAIActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const res = (await this.runApi( + { + body: JSON.stringify( + formatBedrockBody({ messages, stopSequences, system, temperature, maxTokens }) + ), + model, + signal, + timeout, + }, + connectorUsageCollector + )) as RunActionResponse; return { message: res.completion.trim() }; } - public async invokeAIRaw({ - messages, - model, - stopSequences, - system, - temperature, - maxTokens = DEFAULT_TOKEN_LIMIT, - signal, - timeout, - tools, - anthropicVersion, - }: InvokeAIRawActionParams): Promise { - const res = await this.runApi({ - body: JSON.stringify({ - messages, - stop_sequences: stopSequences, - system, - temperature, - max_tokens: maxTokens, - tools, - anthropic_version: anthropicVersion, - }), + public async invokeAIRaw( + { + messages, model, + stopSequences, + system, + temperature, + maxTokens = DEFAULT_TOKEN_LIMIT, signal, timeout, - raw: true, - }); + tools, + anthropicVersion, + }: InvokeAIRawActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const res = await this.runApi( + { + body: JSON.stringify({ + messages, + stop_sequences: stopSequences, + system, + temperature, + max_tokens: maxTokens, + tools, + anthropic_version: anthropicVersion, + }), + model, + signal, + timeout, + raw: true, + }, + connectorUsageCollector + ); return res; } } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/index.ts index 62dd881608605..ccd777634ec37 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/index.ts @@ -70,7 +70,7 @@ export async function executor( CasesWebhookActionParamsType > ): Promise> { - const { actionId, configurationUtilities, params, logger } = execOptions; + const { actionId, configurationUtilities, params, logger, connectorUsageCollector } = execOptions; const { subAction, subActionParams } = params; let data: CasesWebhookExecutorResultData | undefined; @@ -81,7 +81,8 @@ export async function executor( secrets: execOptions.secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); if (!api[subAction]) { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.test.ts index 3a8cf2895e60e..a44b34bf88fce 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.test.ts @@ -14,6 +14,7 @@ import { Logger } from '@kbn/core/server'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { getBasicAuthHeader } from '@kbn/actions-plugin/server/lib'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { AuthType, WebhookMethods, SSLCertType } from '../../../common/auth/constants'; import { CRT_FILE, KEY_FILE } from '../../../common/auth/mocks'; @@ -69,12 +70,17 @@ const sslConfig: CasesWebhookPublicConfigurationType = { hasAuth: true, }; const sslSecrets = { crt: CRT_FILE, key: KEY_FILE, password: 'foobar', user: null, pfx: null }; +let connectorUsageCollector: ConnectorUsageCollector; describe('Cases webhook service', () => { let service: ExternalService; let sslService: ExternalService; beforeAll(() => { + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); service = createExternalService( actionId, { @@ -82,7 +88,8 @@ describe('Cases webhook service', () => { secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); sslService = createExternalService( @@ -92,7 +99,8 @@ describe('Cases webhook service', () => { secrets: sslSecrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); jest.useFakeTimers(); jest.setSystemTime(mockTime); @@ -121,7 +129,8 @@ describe('Cases webhook service', () => { secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -135,7 +144,8 @@ describe('Cases webhook service', () => { secrets: { ...secrets, user: '', password: '' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -149,7 +159,8 @@ describe('Cases webhook service', () => { secrets: { ...secrets, user: '', password: '' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).not.toThrow(); }); @@ -162,7 +173,8 @@ describe('Cases webhook service', () => { secrets: { ...secrets, user: 'username', password: 'password' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); expect(axios.create).toHaveBeenCalledWith({ @@ -182,7 +194,8 @@ describe('Cases webhook service', () => { secrets: { ...secrets, user: 'username', password: 'password' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); expect(axios.create).toHaveBeenCalledWith({ @@ -225,6 +238,7 @@ describe('Cases webhook service', () => { logger, configurationUtilities, sslOverrides: defaultSSLOverrides, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }); @@ -238,6 +252,24 @@ describe('Cases webhook service', () => { expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "axios": [Function], + "connectorUsageCollector": ConnectorUsageCollector { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction], + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, "logger": Object { "context": Array [], "debug": [MockFunction], @@ -481,6 +513,7 @@ describe('Cases webhook service', () => { configurationUtilities, sslOverrides: defaultSSLOverrides, data: `{"fields":{"title":"title","description":"desc","tags":["hello","world"],"project":{"key":"ROC"},"issuetype":{"id":"10024"}}}`, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }); @@ -510,6 +543,36 @@ describe('Cases webhook service', () => { expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "axios": [Function], + "connectorUsageCollector": ConnectorUsageCollector { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction] { + "calls": Array [ + Array [ + "response from webhook action \\"1234\\": [HTTP 200] OK", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], + }, + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, "data": "{\\"fields\\":{\\"title\\":\\"title\\",\\"description\\":\\"desc\\",\\"tags\\":[\\"hello\\",\\"world\\"],\\"project\\":{\\"key\\":\\"ROC\\"},\\"issuetype\\":{\\"id\\":\\"10024\\"}}}", "logger": Object { "context": Array [], @@ -756,6 +819,7 @@ describe('Cases webhook service', () => { issuetype: { id: '10024' }, }, }), + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }); @@ -776,6 +840,24 @@ describe('Cases webhook service', () => { expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "axios": [Function], + "connectorUsageCollector": ConnectorUsageCollector { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction], + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, "data": "{\\"fields\\":{\\"title\\":\\"title\\",\\"description\\":\\"desc\\",\\"tags\\":[\\"hello\\",\\"world\\"],\\"project\\":{\\"key\\":\\"ROC\\"},\\"issuetype\\":{\\"id\\":\\"10024\\"}}}", "logger": Object { "context": Array [], @@ -984,6 +1066,7 @@ describe('Cases webhook service', () => { sslOverrides: defaultSSLOverrides, url: 'https://coolsite.net/issue/1/comment', data: `{"body":"comment"}`, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }); @@ -1004,6 +1087,24 @@ describe('Cases webhook service', () => { expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "axios": [Function], + "connectorUsageCollector": ConnectorUsageCollector { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction], + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, "data": "{\\"body\\":\\"comment\\"}", "logger": Object { "context": Array [], @@ -1176,7 +1277,8 @@ describe('Cases webhook service', () => { secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); const res = await service.createComment(commentReq); expect(requestMock).not.toHaveBeenCalled(); @@ -1191,7 +1293,8 @@ describe('Cases webhook service', () => { secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); const res = await service.createComment(commentReq); expect(requestMock).not.toHaveBeenCalled(); @@ -1217,7 +1320,8 @@ describe('Cases webhook service', () => { secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); await service.createComment(commentReq); expect(requestMock).toHaveBeenCalledWith({ @@ -1228,6 +1332,7 @@ describe('Cases webhook service', () => { url: 'https://coolsite.net/issue/1/comment', data: `{"body":"comment","id":"1"}`, sslOverrides: defaultSSLOverrides, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }); @@ -1257,7 +1362,8 @@ describe('Cases webhook service', () => { secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); await service.createComment(commentReq2); expect(requestMock).toHaveBeenCalledWith({ @@ -1268,6 +1374,7 @@ describe('Cases webhook service', () => { url: 'https://coolsite.net/issue/1/comment', data: `{"body":"comment","id":1}`, sslOverrides: defaultSSLOverrides, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }); }); @@ -1286,7 +1393,8 @@ describe('Cases webhook service', () => { ensureUriAllowed: jest.fn().mockImplementation(() => { throw new Error('Uri not allowed'); }), - } + }, + connectorUsageCollector ); }); @@ -1360,7 +1468,8 @@ describe('Cases webhook service', () => { secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); }); @@ -1430,7 +1539,8 @@ describe('Cases webhook service', () => { logger, { ...configurationUtilities, - } + }, + connectorUsageCollector ); requestMock.mockImplementation(() => createAxiosResponse({ diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.ts index 424fe9b394517..170c63a1d4e5b 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.ts @@ -12,6 +12,7 @@ import { renderMustacheStringNoEscape } from '@kbn/actions-plugin/server/lib/mus import { request } from '@kbn/actions-plugin/server/lib/axios_utils'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; import { combineHeadersWithBasicAuthHeader } from '@kbn/actions-plugin/server/lib'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { buildConnectorAuth, validateConnectorAuthConfiguration } from '../../../common/auth/utils'; import { validateAndNormalizeUrl, validateJson } from './validators'; import { @@ -38,7 +39,8 @@ export const createExternalService = ( actionId: string, { config, secrets }: ExternalServiceCredentials, logger: Logger, - configurationUtilities: ActionsConfigurationUtilities + configurationUtilities: ActionsConfigurationUtilities, + connectorUsageCollector: ConnectorUsageCollector ): ExternalService => { const { createCommentJson, @@ -117,6 +119,7 @@ export const createExternalService = ( logger, configurationUtilities, sslOverrides, + connectorUsageCollector, }); throwDescriptiveErrorIfResponseIsNotValid({ @@ -162,6 +165,7 @@ export const createExternalService = ( data: json, configurationUtilities, sslOverrides, + connectorUsageCollector, }); const { status, statusText, data } = res; @@ -246,6 +250,7 @@ export const createExternalService = ( data: json, configurationUtilities, sslOverrides, + connectorUsageCollector, }); throwDescriptiveErrorIfResponseIsNotValid({ @@ -319,6 +324,7 @@ export const createExternalService = ( data: json, configurationUtilities, sslOverrides, + connectorUsageCollector, }); throwDescriptiveErrorIfResponseIsNotValid({ diff --git a/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.test.ts index d53881cae1272..0c3d851981fde 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.test.ts @@ -10,27 +10,34 @@ import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.moc import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { CROWDSTRIKE_CONNECTOR_ID } from '../../../public/common'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const tokenPath = 'https://api.crowdstrike.com/oauth2/token'; const hostPath = 'https://api.crowdstrike.com/devices/entities/devices/v2'; const onlineStatusPath = 'https://api.crowdstrike.com/devices/entities/online-state/v1'; const actionsPath = 'https://api.crowdstrike.com/devices/entities/devices-actions/v2'; describe('CrowdstrikeConnector', () => { + const logger = loggingSystemMock.createLogger(); const connector = new CrowdstrikeConnector({ configurationUtilities: actionsConfigMock.create(), connector: { id: '1', type: CROWDSTRIKE_CONNECTOR_ID }, config: { url: 'https://api.crowdstrike.com' }, secrets: { clientId: '123', clientSecret: 'secret' }, - logger: loggingSystemMock.createLogger(), + logger, services: actionsMock.createServices(), }); let mockedRequest: jest.Mock; + let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { // @ts-expect-error private static - but I still want to reset it CrowdstrikeConnector.token = null; // @ts-expect-error mockedRequest = connector.request = jest.fn() as jest.Mock; + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); afterEach(() => { jest.clearAllMocks(); @@ -43,10 +50,13 @@ describe('CrowdstrikeConnector', () => { mockedRequest.mockResolvedValueOnce({ data: { access_token: 'testToken' } }); mockedRequest.mockResolvedValueOnce(mockResponse); - const result = await connector.executeHostActions({ - command: 'contain', - ids: ['id1', 'id2'], - }); + const result = await connector.executeHostActions( + { + command: 'contain', + ids: ['id1', 'id2'], + }, + connectorUsageCollector + ); expect(mockedRequest).toHaveBeenNthCalledWith( 1, expect.objectContaining({ @@ -58,7 +68,8 @@ describe('CrowdstrikeConnector', () => { method: 'post', responseSchema: expect.any(Object), url: tokenPath, - }) + }), + connectorUsageCollector ); expect(mockedRequest).toHaveBeenNthCalledWith( 2, @@ -69,7 +80,8 @@ describe('CrowdstrikeConnector', () => { data: { ids: ['id1', 'id2'] }, paramsSerializer: expect.any(Function), responseSchema: expect.any(Object), - }) + }), + connectorUsageCollector ); expect(result).toEqual({ id: 'testid', path: 'testpath' }); }); @@ -82,7 +94,10 @@ describe('CrowdstrikeConnector', () => { mockedRequest.mockResolvedValueOnce({ data: { access_token: 'testToken' } }); mockedRequest.mockResolvedValueOnce(mockResponse); - const result = await connector.getAgentDetails({ ids: ['id1', 'id2'] }); + const result = await connector.getAgentDetails( + { ids: ['id1', 'id2'] }, + connectorUsageCollector + ); expect(mockedRequest).toHaveBeenNthCalledWith( 1, @@ -95,7 +110,8 @@ describe('CrowdstrikeConnector', () => { method: 'post', responseSchema: expect.any(Object), url: tokenPath, - }) + }), + connectorUsageCollector ); expect(mockedRequest).toHaveBeenNthCalledWith( 2, @@ -108,7 +124,8 @@ describe('CrowdstrikeConnector', () => { paramsSerializer: expect.any(Function), responseSchema: expect.any(Object), url: hostPath, - }) + }), + connectorUsageCollector ); expect(result).toEqual({ resources: [{}] }); }); @@ -121,7 +138,10 @@ describe('CrowdstrikeConnector', () => { mockedRequest.mockResolvedValueOnce({ data: { access_token: 'testToken' } }); mockedRequest.mockResolvedValueOnce(mockResponse); - const result = await connector.getAgentOnlineStatus({ ids: ['id1', 'id2'] }); + const result = await connector.getAgentOnlineStatus( + { ids: ['id1', 'id2'] }, + connectorUsageCollector + ); expect(mockedRequest).toHaveBeenNthCalledWith( 1, @@ -134,7 +154,8 @@ describe('CrowdstrikeConnector', () => { method: 'post', responseSchema: expect.any(Object), url: tokenPath, - }) + }), + connectorUsageCollector ); expect(mockedRequest).toHaveBeenNthCalledWith( 2, @@ -147,7 +168,8 @@ describe('CrowdstrikeConnector', () => { paramsSerializer: expect.any(Function), responseSchema: expect.any(Object), url: onlineStatusPath, - }) + }), + connectorUsageCollector ); expect(result).toEqual({ resources: [{}] }); }); @@ -226,7 +248,7 @@ describe('CrowdstrikeConnector', () => { mockedRequest.mockResolvedValueOnce(mockResponse); // @ts-expect-error private method - but I still want to - const result = await connector.getTokenRequest(); + const result = await connector.getTokenRequest(connectorUsageCollector); expect(mockedRequest).toHaveBeenCalledWith( expect.objectContaining({ @@ -237,7 +259,8 @@ describe('CrowdstrikeConnector', () => { 'Content-Type': 'application/x-www-form-urlencoded', authorization: expect.stringContaining('Basic'), }, - }) + }), + connectorUsageCollector ); expect(result).toEqual('testToken'); }); @@ -247,7 +270,7 @@ describe('CrowdstrikeConnector', () => { mockedRequest.mockResolvedValueOnce({ data: { access_token: 'testToken' } }); mockedRequest.mockResolvedValue(mockResponse); - await connector.getAgentDetails({ ids: ['id1', 'id2'] }); + await connector.getAgentDetails({ ids: ['id1', 'id2'] }, connectorUsageCollector); expect(mockedRequest).toHaveBeenNthCalledWith( 1, @@ -260,7 +283,8 @@ describe('CrowdstrikeConnector', () => { method: 'post', responseSchema: expect.any(Object), url: tokenPath, - }) + }), + connectorUsageCollector ); expect(mockedRequest).toHaveBeenNthCalledWith( 2, @@ -273,10 +297,11 @@ describe('CrowdstrikeConnector', () => { paramsSerializer: expect.any(Function), responseSchema: expect.any(Object), url: hostPath, - }) + }), + connectorUsageCollector ); expect(mockedRequest).toHaveBeenCalledTimes(2); - await connector.getAgentDetails({ ids: ['id1', 'id2'] }); + await connector.getAgentDetails({ ids: ['id1', 'id2'] }, connectorUsageCollector); expect(mockedRequest).toHaveBeenNthCalledWith( 3, expect.objectContaining({ @@ -288,7 +313,8 @@ describe('CrowdstrikeConnector', () => { paramsSerializer: expect.any(Function), responseSchema: expect.any(Object), url: hostPath, - }) + }), + connectorUsageCollector ); expect(mockedRequest).toHaveBeenCalledTimes(3); }); @@ -298,9 +324,9 @@ describe('CrowdstrikeConnector', () => { mockedRequest.mockResolvedValueOnce({ data: { access_token: 'testToken' } }); mockedRequest.mockRejectedValueOnce(mockResponse); - await expect(() => connector.getAgentDetails({ ids: ['id1', 'id2'] })).rejects.toThrowError( - 'something goes wrong' - ); + await expect(() => + connector.getAgentDetails({ ids: ['id1', 'id2'] }, connectorUsageCollector) + ).rejects.toThrowError('something goes wrong'); expect(mockedRequest).toHaveBeenCalledTimes(2); }); it('should repeat the call one time if theres 401 error ', async () => { @@ -309,7 +335,9 @@ describe('CrowdstrikeConnector', () => { mockedRequest.mockResolvedValueOnce({ data: { access_token: 'testToken' } }); mockedRequest.mockRejectedValueOnce(mockResponse); - await expect(() => connector.getAgentDetails({ ids: ['id1', 'id2'] })).rejects.toThrowError(); + await expect(() => + connector.getAgentDetails({ ids: ['id1', 'id2'] }, connectorUsageCollector) + ).rejects.toThrowError(); expect(mockedRequest).toHaveBeenCalledTimes(3); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.ts b/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.ts index 3d14ae62924c4..a4fc84ae6a49a 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.ts @@ -9,6 +9,7 @@ import { ServiceParams, SubActionConnector } from '@kbn/actions-plugin/server'; import type { AxiosError } from 'axios'; import { SubActionRequestParams } from '@kbn/actions-plugin/server/sub_action_framework/types'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { isAggregateError, NodeSystemError } from './types'; import type { CrowdstrikeConfig, @@ -96,68 +97,87 @@ export class CrowdstrikeConnector extends SubActionConnector< }); } - public async executeHostActions({ alertIds, ...payload }: CrowdstrikeHostActionsParams) { - return this.crowdstrikeApiRequest({ - url: this.urls.hostAction, - method: 'post', - params: { - action_name: payload.command, - }, - data: { - ids: payload.ids, - ...(payload.actionParameters - ? { - action_parameters: Object.entries(payload.actionParameters).map(([name, value]) => ({ - name, - value, - })), - } - : {}), + public async executeHostActions( + { alertIds, ...payload }: CrowdstrikeHostActionsParams, + connectorUsageCollector: ConnectorUsageCollector + ) { + return this.crowdstrikeApiRequest( + { + url: this.urls.hostAction, + method: 'post', + params: { + action_name: payload.command, + }, + data: { + ids: payload.ids, + ...(payload.actionParameters + ? { + action_parameters: Object.entries(payload.actionParameters).map( + ([name, value]) => ({ + name, + value, + }) + ), + } + : {}), + }, + paramsSerializer, + responseSchema: CrowdstrikeHostActionsResponseSchema, }, - paramsSerializer, - responseSchema: CrowdstrikeHostActionsResponseSchema, - }); + connectorUsageCollector + ); } public async getAgentDetails( - payload: CrowdstrikeGetAgentsParams + payload: CrowdstrikeGetAgentsParams, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - return this.crowdstrikeApiRequest({ - url: this.urls.agents, - method: 'GET', - params: { - ids: payload.ids, + return this.crowdstrikeApiRequest( + { + url: this.urls.agents, + method: 'GET', + params: { + ids: payload.ids, + }, + paramsSerializer, + responseSchema: RelaxedCrowdstrikeBaseApiResponseSchema, }, - paramsSerializer, - responseSchema: RelaxedCrowdstrikeBaseApiResponseSchema, - }) as Promise; + connectorUsageCollector + ) as Promise; } public async getAgentOnlineStatus( - payload: CrowdstrikeGetAgentsParams + payload: CrowdstrikeGetAgentsParams, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - return this.crowdstrikeApiRequest({ - url: this.urls.agentStatus, - method: 'GET', - params: { - ids: payload.ids, + return this.crowdstrikeApiRequest( + { + url: this.urls.agentStatus, + method: 'GET', + params: { + ids: payload.ids, + }, + paramsSerializer, + responseSchema: RelaxedCrowdstrikeBaseApiResponseSchema, }, - paramsSerializer, - responseSchema: RelaxedCrowdstrikeBaseApiResponseSchema, - }) as Promise; + connectorUsageCollector + ) as Promise; } - private async getTokenRequest() { - const response = await this.request({ - url: this.urls.getToken, - method: 'post', - headers: { - accept: 'application/json', - 'Content-Type': 'application/x-www-form-urlencoded', - authorization: 'Basic ' + CrowdstrikeConnector.base64encodedToken, + private async getTokenRequest(connectorUsageCollector: ConnectorUsageCollector) { + const response = await this.request( + { + url: this.urls.getToken, + method: 'post', + headers: { + accept: 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded', + authorization: 'Basic ' + CrowdstrikeConnector.base64encodedToken, + }, + responseSchema: CrowdstrikeGetTokenResponseSchema, }, - responseSchema: CrowdstrikeGetTokenResponseSchema, - }); + connectorUsageCollector + ); const token = response.data?.access_token; if (token) { // Clear any existing timeout @@ -173,28 +193,33 @@ export class CrowdstrikeConnector extends SubActionConnector< private async crowdstrikeApiRequest( req: SubActionRequestParams, + connectorUsageCollector: ConnectorUsageCollector, retried?: boolean ): Promise { try { if (!CrowdstrikeConnector.token) { - CrowdstrikeConnector.token = (await this.getTokenRequest()) as string; + CrowdstrikeConnector.token = (await this.getTokenRequest( + connectorUsageCollector + )) as string; } - const response = await this.request({ - ...req, - headers: { - ...req.headers, - Authorization: `Bearer ${CrowdstrikeConnector.token}`, + const response = await this.request( + { + ...req, + headers: { + ...req.headers, + Authorization: `Bearer ${CrowdstrikeConnector.token}`, + }, }, - }); + connectorUsageCollector + ); return response.data; } catch (error) { if (error.code === 401 && !retried) { CrowdstrikeConnector.token = null; - return this.crowdstrikeApiRequest(req, true); + return this.crowdstrikeApiRequest(req, connectorUsageCollector, true); } - throw new CrowdstrikeError(error.message); } } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/d3security/d3security.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/d3security/d3security.test.ts index 6f1a002cdf1d0..055a7fe7a7dba 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/d3security/d3security.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/d3security/d3security.test.ts @@ -11,6 +11,7 @@ import { D3_SECURITY_CONNECTOR_ID } from '../../../common/d3security/constants'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { D3SecurityRunActionResponseSchema } from '../../../common/d3security/schema'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; describe('D3SecurityConnector', () => { const sampleBody = JSON.stringify({ @@ -28,6 +29,7 @@ describe('D3SecurityConnector', () => { const mockError = jest.fn().mockImplementation(() => { throw new Error('API Error'); }); + const logger = loggingSystemMock.createLogger(); describe('D3 Security', () => { const connector = new D3SecurityConnector({ @@ -35,26 +37,35 @@ describe('D3SecurityConnector', () => { connector: { id: '1', type: D3_SECURITY_CONNECTOR_ID }, config: { url: 'https://example.com/api' }, secrets: { token: '123' }, - logger: loggingSystemMock.createLogger(), + logger, services: actionsMock.createServices(), }); + let connectorUsageCollector: ConnectorUsageCollector; + beforeEach(() => { // @ts-ignore connector.request = mockRequest; jest.clearAllMocks(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); it('the D3 Security API call is successful with correct parameters', async () => { - const response = await connector.runApi({ body: sampleBody }); + const response = await connector.runApi({ body: sampleBody }, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://example.com/api', - method: 'post', - responseSchema: D3SecurityRunActionResponseSchema, - data: sampleBodyFormatted, - headers: { - d3key: '123', + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://example.com/api', + method: 'post', + responseSchema: D3SecurityRunActionResponseSchema, + data: sampleBodyFormatted, + headers: { + d3key: '123', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual({ result: 'success' }); }); @@ -62,7 +73,9 @@ describe('D3SecurityConnector', () => { // @ts-ignore connector.request = mockError; - await expect(connector.runApi({ body: sampleBody })).rejects.toThrow('API Error'); + await expect(connector.runApi({ body: sampleBody }, connectorUsageCollector)).rejects.toThrow( + 'API Error' + ); }); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/d3security/d3security.ts b/x-pack/plugins/stack_connectors/server/connector_types/d3security/d3security.ts index 804590c01b284..0c35766a3ddf3 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/d3security/d3security.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/d3security/d3security.ts @@ -7,6 +7,7 @@ import { ServiceParams, SubActionConnector } from '@kbn/actions-plugin/server'; import type { AxiosError } from 'axios'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { addSeverityAndEventTypeInBody } from './helpers'; import { D3SecurityRunActionParamsSchema, @@ -57,22 +58,24 @@ export class D3SecurityConnector extends SubActionConnector { - const response = await this.request({ - url: this.url, - method: 'post', - responseSchema: D3SecurityRunActionResponseSchema, - data: addSeverityAndEventTypeInBody( - body ?? '', - severity ?? D3SecuritySeverity.EMPTY, - eventType ?? '' - ), - headers: { d3key: this.token || '' }, - }); + public async runApi( + { body, severity, eventType }: D3SecurityRunActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const response = await this.request( + { + url: this.url, + method: 'post', + responseSchema: D3SecurityRunActionResponseSchema, + data: addSeverityAndEventTypeInBody( + body ?? '', + severity ?? D3SecuritySeverity.EMPTY, + eventType ?? '' + ), + headers: { d3key: this.token || '' }, + }, + connectorUsageCollector + ); return response.data; } } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/index.test.ts index f3787e8d367d9..4ee4b3e4890b7 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/index.test.ts @@ -20,6 +20,8 @@ import { validateParams, validateSecrets, } from '@kbn/actions-plugin/server/lib'; + +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { sendEmail } from './send_email'; import { ActionParamsType, @@ -514,6 +516,10 @@ describe('execute()', () => { text: 'Go to Elastic', }, }; + const connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); const actionId = 'some-id'; const executorOptions: EmailConnectorTypeExecutorOptions = { @@ -524,6 +530,7 @@ describe('execute()', () => { services, configurationUtilities: actionsConfigMock.create(), logger: mockedLogger, + connectorUsageCollector, }; beforeEach(() => { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts index 785ace370323f..3a1d01732eb7d 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/index.ts @@ -274,8 +274,16 @@ async function executor( }, execOptions: EmailConnectorTypeExecutorOptions ): Promise> { - const { actionId, config, secrets, params, configurationUtilities, services, logger } = - execOptions; + const { + actionId, + config, + secrets, + params, + configurationUtilities, + services, + logger, + connectorUsageCollector, + } = execOptions; const connectorTokenClient = services.connectorTokenClient; const emails = params.to.concat(params.cc).concat(params.bcc); @@ -366,7 +374,12 @@ async function executor( let result; try { - result = await sendEmail(logger, sendEmailOptions, connectorTokenClient); + result = await sendEmail( + logger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); } catch (err) { const message = i18n.translate('xpack.stackConnectors.email.errorSendingErrorMessage', { defaultMessage: 'error sending email', diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email.test.ts index 535c3932c04e7..77de60660a975 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email.test.ts @@ -10,7 +10,7 @@ import { Logger } from '@kbn/core/server'; import { sendEmail } from './send_email'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import nodemailer from 'nodemailer'; -import { ProxySettings } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, ProxySettings } from '@kbn/actions-plugin/server/types'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { CustomHostSettings } from '@kbn/actions-plugin/server/config'; import { sendEmailGraphApi } from './send_email_graph_api'; @@ -39,6 +39,7 @@ const sendMailMock = jest.fn(); const mockLogger = loggingSystemMock.create().get() as jest.Mocked; const connectorTokenClient = connectorTokenClientMock.create(); +let connectorUsageCollector: ConnectorUsageCollector; describe('send_email module', () => { beforeEach(() => { @@ -53,11 +54,21 @@ describe('send_email module', () => { interceptors: mockAxiosInstanceInterceptor, }; }); + + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockLogger, + connectorId: 'test-connector-id', + }); }); test('handles authenticated email using service', async () => { const sendEmailOptions = getSendEmailOptions({ transport: { service: 'other' } }); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -101,7 +112,12 @@ describe('send_email module', () => { content: { hasHTMLMessage: true }, transport: { service: 'other' }, }); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -159,7 +175,7 @@ describe('send_email module', () => { status: 202, }); - await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient, connectorUsageCollector); expect(getOAuthClientCredentialsAccessTokenMock).toHaveBeenCalledWith({ configurationUtilities: sendEmailOptions.configurationUtilities, connectorId: '1', @@ -176,6 +192,7 @@ describe('send_email module', () => { delete sendEmailGraphApiMock.mock.calls[0][0].options.configurationUtilities; sendEmailGraphApiMock.mock.calls[0].pop(); sendEmailGraphApiMock.mock.calls[0].pop(); + sendEmailGraphApiMock.mock.calls[0].pop(); expect(sendEmailGraphApiMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ Object { @@ -254,7 +271,7 @@ describe('send_email module', () => { status: 202, }); - await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient, connectorUsageCollector); expect(getOAuthClientCredentialsAccessTokenMock).toHaveBeenCalledWith({ configurationUtilities: sendEmailOptions.configurationUtilities, connectorId: '1', @@ -292,7 +309,7 @@ describe('send_email module', () => { status: 202, }); - await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient, connectorUsageCollector); expect(getOAuthClientCredentialsAccessTokenMock).toHaveBeenCalledWith({ configurationUtilities: sendEmailOptions.configurationUtilities, connectorId: '1', @@ -322,7 +339,7 @@ describe('send_email module', () => { getOAuthClientCredentialsAccessTokenMock.mockReturnValueOnce(null); await expect(() => - sendEmail(mockLogger, sendEmailOptions, connectorTokenClient) + sendEmail(mockLogger, sendEmailOptions, connectorTokenClient, connectorUsageCollector) ).rejects.toThrowErrorMatchingInlineSnapshot( `"Unable to retrieve access token for connectorId: 1"` ); @@ -362,7 +379,12 @@ describe('send_email module', () => { } ); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -412,7 +434,12 @@ describe('send_email module', () => { delete sendEmailOptions.transport.user; // @ts-expect-error delete sendEmailOptions.transport.password; - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -462,7 +489,12 @@ describe('send_email module', () => { // @ts-expect-error delete sendEmailOptions.transport.password; - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -503,9 +535,9 @@ describe('send_email module', () => { sendMailMock.mockReset(); sendMailMock.mockRejectedValue(new Error('wops')); - await expect(sendEmail(mockLogger, sendEmailOptions, connectorTokenClient)).rejects.toThrow( - 'wops' - ); + await expect( + sendEmail(mockLogger, sendEmailOptions, connectorTokenClient, connectorUsageCollector) + ).rejects.toThrow('wops'); }); test('it bypasses with proxyBypassHosts when expected', async () => { @@ -526,7 +558,12 @@ describe('send_email module', () => { } ); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -560,7 +597,12 @@ describe('send_email module', () => { } ); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -596,7 +638,12 @@ describe('send_email module', () => { } ); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -630,7 +677,12 @@ describe('send_email module', () => { } ); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -667,7 +719,12 @@ describe('send_email module', () => { } ); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); // note in the object below, the rejectUnauthenticated got set to false, @@ -710,7 +767,12 @@ describe('send_email module', () => { } ); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); // in this case, rejectUnauthorized is true, as the custom host settings @@ -757,7 +819,12 @@ describe('send_email module', () => { } ); - const result = await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + const result = await sendEmail( + mockLogger, + sendEmailOptions, + connectorTokenClient, + connectorUsageCollector + ); expect(result).toBe(sendMailMockResult); expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -791,7 +858,7 @@ describe('send_email module', () => { 'Bearer clienttokentokentoken' ); - await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient, connectorUsageCollector); expect(createAxiosInstanceMock).toHaveBeenCalledTimes(1); expect(createAxiosInstanceMock).toHaveBeenCalledWith(); expect(mockAxiosInstanceInterceptor.response.use).toHaveBeenCalledTimes(1); @@ -834,7 +901,7 @@ describe('send_email module', () => { 'Bearer clienttokentokentoken' ); - await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient); + await sendEmail(mockLogger, sendEmailOptions, connectorTokenClient, connectorUsageCollector); expect(createAxiosInstanceMock).toHaveBeenCalledTimes(1); expect(createAxiosInstanceMock).toHaveBeenCalledWith(); expect(mockAxiosInstanceInterceptor.response.use).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email.ts index f3ab3bfa22c55..199d96f352389 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email.ts @@ -17,7 +17,11 @@ import { getNodeSSLOptions, getSSLSettingsFromConfig, } from '@kbn/actions-plugin/server/lib/get_node_ssl_options'; -import { ConnectorTokenClientContract, ProxySettings } from '@kbn/actions-plugin/server/types'; +import { + ConnectorUsageCollector, + ConnectorTokenClientContract, + ProxySettings, +} from '@kbn/actions-plugin/server/types'; import { getOAuthClientCredentialsAccessToken } from '@kbn/actions-plugin/server/lib/get_oauth_client_credentials_access_token'; import { AdditionalEmailServices } from '../../../common'; import { sendEmailGraphApi } from './send_email_graph_api'; @@ -66,7 +70,8 @@ export interface Content { export async function sendEmail( logger: Logger, options: SendEmailOptions, - connectorTokenClient: ConnectorTokenClientContract + connectorTokenClient: ConnectorTokenClientContract, + connectorUsageCollector: ConnectorUsageCollector ): Promise { const { transport, content } = options; const { message, messageHTML } = content; @@ -74,9 +79,15 @@ export async function sendEmail( const renderedMessage = messageHTML ?? htmlFromMarkdown(logger, message); if (transport.service === AdditionalEmailServices.EXCHANGE) { - return await sendEmailWithExchange(logger, options, renderedMessage, connectorTokenClient); + return await sendEmailWithExchange( + logger, + options, + renderedMessage, + connectorTokenClient, + connectorUsageCollector + ); } else { - return await sendEmailWithNodemailer(logger, options, renderedMessage); + return await sendEmailWithNodemailer(logger, options, renderedMessage, connectorUsageCollector); } } @@ -85,7 +96,8 @@ export async function sendEmailWithExchange( logger: Logger, options: SendEmailOptions, messageHTML: string, - connectorTokenClient: ConnectorTokenClientContract + connectorTokenClient: ConnectorTokenClientContract, + connectorUsageCollector: ConnectorUsageCollector ): Promise { const { transport, configurationUtilities, connectorId } = options; const { clientId, clientSecret, tenantId, oauthTokenUrl } = transport; @@ -155,6 +167,7 @@ export async function sendEmailWithExchange( }, logger, configurationUtilities, + connectorUsageCollector, axiosInstance ); } @@ -163,7 +176,8 @@ export async function sendEmailWithExchange( async function sendEmailWithNodemailer( logger: Logger, options: SendEmailOptions, - messageHTML: string + messageHTML: string, + connectorUsageCollector: ConnectorUsageCollector ): Promise { const { transport, routing, content, configurationUtilities, hasAuth } = options; const { service } = transport; @@ -186,6 +200,7 @@ async function sendEmailWithNodemailer( // some deep properties, so need to use any here. const transportConfig = getTransportConfig(configurationUtilities, logger, transport, hasAuth); const nodemailerTransport = nodemailer.createTransport(transportConfig); + connectorUsageCollector.addRequestBodyBytes(undefined, email); const result = await nodemailerTransport.sendMail(email); if (service === JSON_TRANSPORT_SERVICE) { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.test.ts index 03289b79c3004..6166082345243 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.test.ts @@ -14,7 +14,7 @@ import { Logger } from '@kbn/core/server'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { CustomHostSettings } from '@kbn/actions-plugin/server/config'; -import { ProxySettings } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, ProxySettings } from '@kbn/actions-plugin/server/types'; import { sendEmailGraphApi } from './send_email_graph_api'; const createAxiosInstanceMock = axios.create as jest.Mock; @@ -28,6 +28,11 @@ describe('sendEmailGraphApi', () => { const configurationUtilities = actionsConfigMock.create(); test('email contains the proper message', async () => { + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); + axiosInstanceMock.mockReturnValueOnce({ status: 202, }); @@ -38,7 +43,8 @@ describe('sendEmailGraphApi', () => { headers: {}, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); expect(axiosInstanceMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -118,6 +124,10 @@ describe('sendEmailGraphApi', () => { }); test('email was sent on behalf of the user "from" mailbox', async () => { + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); axiosInstanceMock.mockReturnValueOnce({ status: 202, }); @@ -128,7 +138,8 @@ describe('sendEmailGraphApi', () => { headers: { Authorization: 'Bearer 1234567' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); expect(axiosInstanceMock.mock.calls[1]).toMatchInlineSnapshot(` Array [ @@ -210,6 +221,10 @@ describe('sendEmailGraphApi', () => { }); test('sendMail request was sent to the custom configured Graph API URL', async () => { + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); axiosInstanceMock.mockReturnValueOnce({ status: 202, }); @@ -221,7 +236,8 @@ describe('sendEmailGraphApi', () => { headers: {}, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); expect(axiosInstanceMock.mock.calls[2]).toMatchInlineSnapshot(` Array [ @@ -301,6 +317,10 @@ describe('sendEmailGraphApi', () => { }); test('throw the exception and log the proper error if message was not sent successfuly', async () => { + const connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); axiosInstanceMock.mockReturnValueOnce({ status: 400, data: { @@ -315,7 +335,8 @@ describe('sendEmailGraphApi', () => { sendEmailGraphApi( { options: getSendEmailOptions(), messageHTML: 'test1', headers: {} }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).rejects.toThrowErrorMatchingInlineSnapshot( '"{\\"error\\":{\\"code\\":\\"ErrorMimeContentInvalidBase64String\\",\\"message\\":\\"Invalid base64 string for MIME content.\\"}}"' diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.ts index 79d7af05e041e..ed624299b3535 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.ts @@ -11,18 +11,14 @@ import axios, { AxiosInstance, AxiosResponse } from 'axios'; import { Logger } from '@kbn/core/server'; import { request } from '@kbn/actions-plugin/server/lib/axios_utils'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { SendEmailOptions } from './send_email'; -interface SendEmailGraphApiOptions { - options: SendEmailOptions; - headers: Record; - messageHTML: string; -} - export async function sendEmailGraphApi( sendEmailOptions: SendEmailGraphApiOptions, logger: Logger, configurationUtilities: ActionsConfigurationUtilities, + connectorUsageCollector: ConnectorUsageCollector, axiosInstance?: AxiosInstance ): Promise { const { options, headers, messageHTML } = sendEmailOptions; @@ -42,6 +38,7 @@ export async function sendEmailGraphApi( headers, configurationUtilities, validateStatus: () => true, + connectorUsageCollector, }); if (res.status === 202) { return res.data; @@ -53,6 +50,12 @@ export async function sendEmailGraphApi( throw new Error(errString); } +interface SendEmailGraphApiOptions { + options: SendEmailOptions; + headers: Record; + messageHTML: string; +} + function getMessage(emailOptions: SendEmailOptions, messageHTML: string) { const { routing, content } = emailOptions; const { to, cc, bcc } = routing; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/es_index/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/es_index/index.test.ts index 2b3fab30432fa..5b7353ef58291 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/es_index/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/es_index/index.test.ts @@ -7,6 +7,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { validateConfig, validateParams } from '@kbn/actions-plugin/server/lib'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { ActionParamsType, @@ -27,11 +28,16 @@ const mockedLogger: jest.Mocked = loggerMock.create(); let connectorType: ESIndexConnectorType; let configurationUtilities: ActionsConfigurationUtilities; +let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { jest.resetAllMocks(); configurationUtilities = actionsConfigMock.create(); connectorType = getConnectorType(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); }); describe('connector registration', () => { @@ -185,6 +191,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const scopedClusterClient = elasticsearchClientMock .createClusterClient() @@ -230,6 +237,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; scopedClusterClient.bulk.mockClear(); await connectorType.executor({ @@ -280,6 +288,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; scopedClusterClient.bulk.mockClear(); @@ -324,6 +333,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; scopedClusterClient.bulk.mockClear(); await connectorType.executor({ @@ -656,6 +666,7 @@ describe('execute()', () => { services: { ...services, scopedClusterClient }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }) ).toMatchInlineSnapshot(` Object { @@ -695,6 +706,7 @@ describe('execute()', () => { services: { ...services, scopedClusterClient }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }) ).toMatchInlineSnapshot(` Object { @@ -757,6 +769,7 @@ describe('execute()', () => { services: { ...services, scopedClusterClient }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }) ).toMatchInlineSnapshot(` Object { @@ -824,6 +837,7 @@ describe('execute()', () => { services: { ...services, scopedClusterClient }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }) ).toMatchInlineSnapshot(` Object { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.test.ts index d58cefe12f839..94dd7aa0d153c 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.test.ts @@ -15,6 +15,7 @@ import { RunApiResponseSchema, StreamingResponseSchema } from '../../../common/g import { DEFAULT_GEMINI_MODEL } from '../../../common/gemini/constants'; import { AxiosError } from 'axios'; import { Transform } from 'stream'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; jest.mock('../lib/gen_ai/create_gen_ai_dashboard'); jest.mock('@kbn/actions-plugin/server/sub_action_framework/helpers/validators', () => ({ @@ -61,6 +62,7 @@ describe('GeminiConnector', () => { mockRequest = connector.request = jest.fn().mockResolvedValue(defaultResponse); }); + const logger = loggingSystemMock.createLogger(); const connector = new GeminiConnector({ connector: { id: '1', type: '.gemini' }, configurationUtilities: actionsConfigMock.create(), @@ -84,14 +86,19 @@ describe('GeminiConnector', () => { client_x509_cert_url: '', }), }, - logger: loggingSystemMock.createLogger(), + logger, services: actionsMock.createServices(), }); + let connectorUsageCollector: ConnectorUsageCollector; describe('Gemini', () => { beforeEach(() => { // @ts-ignore connector.request = mockRequest; + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); describe('runApi', () => { @@ -101,33 +108,36 @@ describe('GeminiConnector', () => { model: DEFAULT_GEMINI_MODEL, }; - const response = await connector.runApi(runActionParams); + const response = await connector.runApi(runActionParams, connectorUsageCollector); // Assertions expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:generateContent`, - method: 'post', - data: JSON.stringify({ - messages: [ - { - contents: [ - { - role: 'user', - parts: [{ text: 'What is the capital of France?' }], - }, - ], - }, - ], - }), - headers: { - Authorization: 'Bearer mock_access_token', - 'Content-Type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:generateContent`, + method: 'post', + data: JSON.stringify({ + messages: [ + { + contents: [ + { + role: 'user', + parts: [{ text: 'What is the capital of France?' }], + }, + ], + }, + ], + }), + headers: { + Authorization: 'Bearer mock_access_token', + 'Content-Type': 'application/json', + }, + timeout: 60000, + responseSchema: RunApiResponseSchema, + signal: undefined, }, - timeout: 60000, - responseSchema: RunApiResponseSchema, - signal: undefined, - }); + connectorUsageCollector + ); expect(response).toEqual(connectorResponse); }); @@ -144,66 +154,72 @@ describe('GeminiConnector', () => { }; it('the API call is successful with correct parameters', async () => { - await connector.invokeAI(aiAssistantBody); + await connector.invokeAI(aiAssistantBody, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:generateContent`, - method: 'post', - responseSchema: RunApiResponseSchema, - data: JSON.stringify({ - contents: [ - { - role: 'user', - parts: [{ text: 'What is the capital of France?' }], + expect(mockRequest).toHaveBeenCalledWith( + { + url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:generateContent`, + method: 'post', + responseSchema: RunApiResponseSchema, + data: JSON.stringify({ + contents: [ + { + role: 'user', + parts: [{ text: 'What is the capital of France?' }], + }, + ], + generation_config: { + temperature: 0, + maxOutputTokens: 8192, }, - ], - generation_config: { - temperature: 0, - maxOutputTokens: 8192, + safety_settings: [ + { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' }, + ], + }), + headers: { + Authorization: 'Bearer mock_access_token', + 'Content-Type': 'application/json', }, - safety_settings: [ - { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' }, - ], - }), - headers: { - Authorization: 'Bearer mock_access_token', - 'Content-Type': 'application/json', + signal: undefined, + timeout: 60000, }, - signal: undefined, - timeout: 60000, - }); + connectorUsageCollector + ); }); it('signal and timeout is properly passed to runApi', async () => { const signal = jest.fn(); const timeout = 60000; - await connector.invokeAI({ ...aiAssistantBody, timeout, signal }); - expect(mockRequest).toHaveBeenCalledWith({ - url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:generateContent`, - method: 'post', - responseSchema: RunApiResponseSchema, - data: JSON.stringify({ - contents: [ - { - role: 'user', - parts: [{ text: 'What is the capital of France?' }], + await connector.invokeAI({ ...aiAssistantBody, timeout, signal }, connectorUsageCollector); + expect(mockRequest).toHaveBeenCalledWith( + { + url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:generateContent`, + method: 'post', + responseSchema: RunApiResponseSchema, + data: JSON.stringify({ + contents: [ + { + role: 'user', + parts: [{ text: 'What is the capital of France?' }], + }, + ], + generation_config: { + temperature: 0, + maxOutputTokens: 8192, }, - ], - generation_config: { - temperature: 0, - maxOutputTokens: 8192, + safety_settings: [ + { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' }, + ], + }), + headers: { + Authorization: 'Bearer mock_access_token', + 'Content-Type': 'application/json', }, - safety_settings: [ - { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' }, - ], - }), - headers: { - Authorization: 'Bearer mock_access_token', - 'Content-Type': 'application/json', + signal, + timeout: 60000, }, - signal, - timeout: 60000, - }); + connectorUsageCollector + ); }); }); @@ -223,71 +239,96 @@ describe('GeminiConnector', () => { content: 'What is the capital of France?', }, ], + toolConfig: { + mode: 'ANY' as const, + allowedFunctionNames: ['foo', 'bar'], + }, }; it('the API call is successful with correct request parameters', async () => { - await connector.invokeStream(aiAssistantBody); + await connector.invokeStream(aiAssistantBody, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:streamGenerateContent?alt=sse`, - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ - contents: [ - { - role: 'user', - parts: [{ text: 'What is the capital of France?' }], + expect(mockRequest).toHaveBeenCalledWith( + { + url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:streamGenerateContent?alt=sse`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + contents: [ + { + role: 'user', + parts: [{ text: 'What is the capital of France?' }], + }, + ], + generation_config: { + temperature: 0, + maxOutputTokens: 8192, }, - ], - generation_config: { - temperature: 0, - maxOutputTokens: 8192, + tool_config: { + function_calling_config: { + mode: 'ANY', + allowed_function_names: ['foo', 'bar'], + }, + }, + safety_settings: [ + { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' }, + ], + }), + responseType: 'stream', + headers: { + Authorization: 'Bearer mock_access_token', + 'Content-Type': 'application/json', }, - safety_settings: [ - { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' }, - ], - }), - responseType: 'stream', - headers: { - Authorization: 'Bearer mock_access_token', - 'Content-Type': 'application/json', + signal: undefined, + timeout: 60000, }, - signal: undefined, - timeout: 60000, - }); + connectorUsageCollector + ); }); it('signal and timeout is properly passed to streamApi', async () => { const signal = jest.fn(); const timeout = 60000; - await connector.invokeStream({ ...aiAssistantBody, timeout, signal }); - expect(mockRequest).toHaveBeenCalledWith({ - url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:streamGenerateContent?alt=sse`, - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ - contents: [ - { - role: 'user', - parts: [{ text: 'What is the capital of France?' }], + await connector.invokeStream( + { ...aiAssistantBody, timeout, signal }, + connectorUsageCollector + ); + expect(mockRequest).toHaveBeenCalledWith( + { + url: `https://api.gemini.com/v1/projects/my-project-12345/locations/us-central1/publishers/google/models/${DEFAULT_GEMINI_MODEL}:streamGenerateContent?alt=sse`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + contents: [ + { + role: 'user', + parts: [{ text: 'What is the capital of France?' }], + }, + ], + generation_config: { + temperature: 0, + maxOutputTokens: 8192, }, - ], - generation_config: { - temperature: 0, - maxOutputTokens: 8192, + tool_config: { + function_calling_config: { + mode: 'ANY', + allowed_function_names: ['foo', 'bar'], + }, + }, + safety_settings: [ + { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' }, + ], + }), + responseType: 'stream', + headers: { + Authorization: 'Bearer mock_access_token', + 'Content-Type': 'application/json', }, - safety_settings: [ - { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_ONLY_HIGH' }, - ], - }), - responseType: 'stream', - headers: { - Authorization: 'Bearer mock_access_token', - 'Content-Type': 'application/json', + signal, + timeout: 60000, }, - signal, - timeout: 60000, - }); + connectorUsageCollector + ); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.ts b/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.ts index 6cb4671b7aeeb..895dfe66d6de4 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/gemini/gemini.ts @@ -11,7 +11,10 @@ import { PassThrough } from 'stream'; import { IncomingMessage } from 'http'; import { SubActionRequestParams } from '@kbn/actions-plugin/server/sub_action_framework/types'; import { getGoogleOAuthJwtAccessToken } from '@kbn/actions-plugin/server/lib/get_gcp_oauth_access_token'; -import { ConnectorTokenClientContract } from '@kbn/actions-plugin/server/types'; +import { + ConnectorUsageCollector, + ConnectorTokenClientContract, +} from '@kbn/actions-plugin/server/types'; import { HarmBlockThreshold, HarmCategory } from '@google/generative-ai'; import { @@ -61,6 +64,12 @@ interface Payload { temperature: number; maxOutputTokens: number; }; + tool_config?: { + function_calling_config: { + mode: 'AUTO' | 'ANY' | 'NONE'; + allowed_function_names?: string[]; + }; + }; safety_settings: Array<{ category: string; threshold: string }>; } @@ -211,13 +220,10 @@ export class GeminiConnector extends SubActionConnector { * @param body The stringified request body to be sent in the POST request. * @param model Optional model to be used for the API request. If not provided, the default model from the connector will be used. */ - public async runApi({ - body, - model: reqModel, - signal, - timeout, - raw, - }: RunActionParams): Promise { + public async runApi( + { body, model: reqModel, signal, timeout, raw }: RunActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { // set model on per request basis const currentModel = reqModel ?? this.model; const path = `/v1/projects/${this.gcpProjectID}/locations/${this.gcpRegion}/publishers/google/models/${currentModel}:generateContent`; @@ -236,7 +242,7 @@ export class GeminiConnector extends SubActionConnector { responseSchema: raw ? RunActionRawResponseSchema : RunApiResponseSchema, } as SubActionRequestParams; - const response = await this.request(requestArgs); + const response = await this.request(requestArgs, connectorUsageCollector); if (raw) { return response.data; @@ -249,65 +255,86 @@ export class GeminiConnector extends SubActionConnector { return { completion: completionText, usageMetadata }; } - private async streamAPI({ - body, - model: reqModel, - signal, - timeout, - }: RunActionParams): Promise { + private async streamAPI( + { body, model: reqModel, signal, timeout }: RunActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { const currentModel = reqModel ?? this.model; const path = `/v1/projects/${this.gcpProjectID}/locations/${this.gcpRegion}/publishers/google/models/${currentModel}:streamGenerateContent?alt=sse`; const token = await this.getAccessToken(); - const response = await this.request({ - url: `${this.url}${path}`, - method: 'post', - responseSchema: StreamingResponseSchema, - data: body, - responseType: 'stream', - headers: { - Authorization: `Bearer ${token}`, - 'Content-Type': 'application/json', + const response = await this.request( + { + url: `${this.url}${path}`, + method: 'post', + responseSchema: StreamingResponseSchema, + data: body, + responseType: 'stream', + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + signal, + timeout: timeout ?? DEFAULT_TIMEOUT_MS, }, - signal, - timeout: timeout ?? DEFAULT_TIMEOUT_MS, - }); + connectorUsageCollector + ); return response.data.pipe(new PassThrough()); } - public async invokeAI({ - messages, - model, - temperature = 0, - signal, - timeout, - }: InvokeAIActionParams): Promise { - const res = await this.runApi({ - body: JSON.stringify(formatGeminiPayload(messages, temperature)), + public async invokeAI( + { + messages, + systemInstruction, model, + temperature = 0, signal, timeout, - }); + toolConfig, + }: InvokeAIActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const res = await this.runApi( + { + body: JSON.stringify( + formatGeminiPayload({ messages, temperature, toolConfig, systemInstruction }) + ), + model, + signal, + timeout, + }, + connectorUsageCollector + ); return { message: res.completion, usageMetadata: res.usageMetadata }; } - public async invokeAIRaw({ - messages, - model, - temperature = 0, - signal, - timeout, - tools, - }: InvokeAIRawActionParams): Promise { - const res = await this.runApi({ - body: JSON.stringify({ ...formatGeminiPayload(messages, temperature), tools }), + public async invokeAIRaw( + { + messages, model, + temperature = 0, signal, timeout, - raw: true, - }); + tools, + systemInstruction, + }: InvokeAIRawActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const res = await this.runApi( + { + body: JSON.stringify({ + ...formatGeminiPayload({ messages, temperature, systemInstruction }), + tools, + }), + model, + signal, + timeout, + raw: true, + }, + connectorUsageCollector + ); return res; } @@ -320,36 +347,67 @@ export class GeminiConnector extends SubActionConnector { * @param messages An array of messages to be sent to the API * @param model Optional model to be used for the API request. If not provided, the default model from the connector will be used. */ - public async invokeStream({ - messages, - model, - stopSequences, - temperature = 0, - signal, - timeout, - tools, - }: InvokeAIActionParams): Promise { - return (await this.streamAPI({ - body: JSON.stringify({ ...formatGeminiPayload(messages, temperature), tools }), + public async invokeStream( + { + messages, + systemInstruction, model, stopSequences, + temperature = 0, signal, timeout, - })) as unknown as IncomingMessage; + tools, + toolConfig, + }: InvokeAIActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + return (await this.streamAPI( + { + body: JSON.stringify({ + ...formatGeminiPayload({ messages, temperature, toolConfig, systemInstruction }), + tools, + }), + model, + stopSequences, + signal, + timeout, + }, + connectorUsageCollector + )) as unknown as IncomingMessage; } } /** Format the json body to meet Gemini payload requirements */ -const formatGeminiPayload = ( - data: Array<{ role: string; content: string; parts: MessagePart[] }>, - temperature: number -): Payload => { +const formatGeminiPayload = ({ + messages, + systemInstruction, + temperature, + toolConfig, +}: { + messages: Array<{ role: string; content: string; parts: MessagePart[] }>; + systemInstruction?: string; + toolConfig?: InvokeAIActionParams['toolConfig']; + temperature: number; +}): Payload => { const payload: Payload = { contents: [], generation_config: { temperature, maxOutputTokens: DEFAULT_TOKEN_LIMIT, }, + ...(systemInstruction + ? { system_instruction: { role: 'user', parts: [{ text: systemInstruction }] } } + : {}), + ...(toolConfig + ? { + tool_config: { + function_calling_config: { + mode: toolConfig.mode, + allowed_function_names: toolConfig.allowedFunctionNames, + }, + }, + } + : {}), safety_settings: [ { category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, @@ -360,7 +418,7 @@ const formatGeminiPayload = ( }; let previousRole: string | null = null; - for (const row of data) { + for (const row of messages) { const correctRole = row.role === 'assistant' ? 'model' : 'user'; // if data is already preformatted by ActionsClientGeminiChatModel if (row.parts) { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/jira/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/jira/index.ts index 630c0973935cd..1481ab8601fa6 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/jira/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/jira/index.ts @@ -95,7 +95,15 @@ async function executor( ExecutorParams > ): Promise> { - const { actionId, config, params, secrets, configurationUtilities, logger } = execOptions; + const { + actionId, + config, + params, + secrets, + configurationUtilities, + logger, + connectorUsageCollector, + } = execOptions; const { subAction, subActionParams } = params as ExecutorParams; let data: JiraExecutorResultData | null = null; @@ -105,7 +113,8 @@ async function executor( secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); if (!api[subAction]) { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/jira/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/jira/service.test.ts index 34e0f1f799ce5..5e98bdc96c0ee 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/jira/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/jira/service.test.ts @@ -14,6 +14,7 @@ import { Logger } from '@kbn/core/server'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { getBasicAuthHeader } from '@kbn/actions-plugin/server'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const logger = loggingSystemMock.create().get() as jest.Mocked; interface ResponseError extends Error { @@ -135,8 +136,13 @@ const mockOldAPI = () => describe('Jira service', () => { let service: ExternalService; + let connectorUsageCollector: ConnectorUsageCollector; beforeAll(() => { + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); service = createExternalService( { // The trailing slash at the end of the url is intended. @@ -145,7 +151,8 @@ describe('Jira service', () => { secrets: { apiToken: 'token', email: 'elastic@elastic.com' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); }); @@ -162,7 +169,8 @@ describe('Jira service', () => { secrets: { apiToken: 'token', email: 'elastic@elastic.com' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -175,7 +183,8 @@ describe('Jira service', () => { secrets: { apiToken: 'token', email: 'elastic@elastic.com' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -188,7 +197,8 @@ describe('Jira service', () => { secrets: { apiToken: 'token' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -201,7 +211,8 @@ describe('Jira service', () => { secrets: { email: 'elastic@elastic.com' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -213,7 +224,8 @@ describe('Jira service', () => { secrets: { apiToken: 'token', email: 'elastic@elastic.com' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); expect(axios.create).toHaveBeenCalledWith({ @@ -258,6 +270,7 @@ describe('Jira service', () => { url: 'https://coolsite.net/rest/api/2/issue/1', logger, configurationUtilities, + connectorUsageCollector, }); }); @@ -401,6 +414,7 @@ describe('Jira service', () => { priority: { name: 'High' }, }, }, + connectorUsageCollector, }); }); @@ -459,6 +473,7 @@ describe('Jira service', () => { priority: { name: 'High' }, }, }, + connectorUsageCollector, }); }); @@ -492,6 +507,7 @@ describe('Jira service', () => { parent: { key: 'RJ-107' }, }, }, + connectorUsageCollector, }); }); @@ -561,6 +577,7 @@ describe('Jira service', () => { ...otherFields, }, }, + connectorUsageCollector, }); }); }); @@ -631,6 +648,7 @@ describe('Jira service', () => { parent: { key: 'RJ-107' }, }, }, + connectorUsageCollector, }); }); @@ -693,6 +711,7 @@ describe('Jira service', () => { ...otherFields, }, }, + connectorUsageCollector, }); }); }); @@ -746,6 +765,7 @@ describe('Jira service', () => { configurationUtilities, url: 'https://coolsite.net/rest/api/2/issue/1/comment', data: { body: 'comment' }, + connectorUsageCollector, }); }); @@ -802,6 +822,7 @@ describe('Jira service', () => { method: 'get', configurationUtilities, url: 'https://coolsite.net/rest/capabilities', + connectorUsageCollector, }); }); @@ -883,6 +904,7 @@ describe('Jira service', () => { method: 'get', configurationUtilities, url: 'https://coolsite.net/rest/api/2/issue/createmeta?projectKeys=CK&expand=projects.issuetypes.fields', + connectorUsageCollector, }); }); @@ -957,6 +979,7 @@ describe('Jira service', () => { method: 'get', configurationUtilities, url: 'https://coolsite.net/rest/api/2/issue/createmeta/CK/issuetypes', + connectorUsageCollector, }); }); @@ -1032,6 +1055,7 @@ describe('Jira service', () => { method: 'get', configurationUtilities, url: 'https://coolsite.net/rest/api/2/issue/createmeta?projectKeys=CK&issuetypeIds=10006&expand=projects.issuetypes.fields', + connectorUsageCollector, }); }); @@ -1240,6 +1264,7 @@ describe('Jira service', () => { method: 'get', configurationUtilities, url: `https://coolsite.net/rest/api/2/search?jql=project%3D%22CK%22%20and%20summary%20~%22Test%20title%22`, + connectorUsageCollector, }); }); @@ -1266,6 +1291,7 @@ describe('Jira service', () => { method: 'get', configurationUtilities, url: `https://coolsite.net/rest/api/2/search?jql=project%3D%22CK%22%20and%20summary%20~%22%5C%5C%5Bth%5C%5C!s%5C%5C%5Eis%5C%5C(%5C%5C)a%5C%5C-te%5C%5C%2Bst%5C%5C-%5C%5C%7B%5C%5C~is%5C%5C*s%5C%5C%26ue%5C%5C%3For%5C%5C%7Cand%5C%5Cbye%5C%5C%3A%5C%5C%7D%5C%5C%5D%5C%5C%7D%5C%5C%5D%22`, + connectorUsageCollector, }); }); @@ -1344,6 +1370,7 @@ describe('Jira service', () => { method: 'get', configurationUtilities, url: `https://coolsite.net/rest/api/2/issue/RJ-107`, + connectorUsageCollector, }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/jira/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/jira/service.ts index 3cd5115234da1..064667558b37e 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/jira/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/jira/service.ts @@ -16,6 +16,7 @@ import { } from '@kbn/actions-plugin/server/lib/axios_utils'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; import { getBasicAuthHeader } from '@kbn/actions-plugin/server'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { CreateCommentParams, CreateIncidentParams, @@ -47,7 +48,8 @@ const createMetaCapabilities = ['list-project-issuetypes', 'list-issuetype-field export const createExternalService = ( { config, secrets }: ExternalServiceCredentials, logger: Logger, - configurationUtilities: ActionsConfigurationUtilities + configurationUtilities: ActionsConfigurationUtilities, + connectorUsageCollector: ConnectorUsageCollector ): ExternalService => { const { apiUrl: url, projectKey } = config as JiraPublicConfigurationType; const { apiToken, email } = secrets as JiraSecretConfigurationType; @@ -189,6 +191,7 @@ export const createExternalService = ( url: `${incidentUrl}/${id}`, logger, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -242,6 +245,7 @@ export const createExternalService = ( fields, }, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -288,6 +292,7 @@ export const createExternalService = ( logger, data: { fields }, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -326,6 +331,7 @@ export const createExternalService = ( logger, data: { body: comment.comment }, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -358,6 +364,7 @@ export const createExternalService = ( url: capabilitiesUrl, logger, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -389,6 +396,7 @@ export const createExternalService = ( url: getIssueTypesOldAPIURL, logger, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -404,6 +412,7 @@ export const createExternalService = ( url: getIssueTypesUrl, logger, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -436,6 +445,7 @@ export const createExternalService = ( url: createGetIssueTypeFieldsUrl(getIssueTypeFieldsOldAPIURL, issueTypeId), logger, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -515,6 +525,7 @@ export const createExternalService = ( url: query, logger, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -543,6 +554,7 @@ export const createExternalService = ( url: getIssueUrl, logger, configurationUtilities, + connectorUsageCollector, }); throwIfResponseIsNotValid({ diff --git a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/create_service_wrapper.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/create_service_wrapper.test.ts index 311de65eb4abe..4f6133891c431 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/create_service_wrapper.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/create_service_wrapper.test.ts @@ -12,6 +12,7 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { connectorTokenClientMock } from '@kbn/actions-plugin/server/lib/connector_token_client.mock'; import { snExternalServiceConfig } from './config'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const logger = loggingSystemMock.create().get() as jest.Mocked; const connectorTokenClient = connectorTokenClientMock.create(); @@ -19,10 +20,15 @@ const configurationUtilities = actionsConfigMock.create(); jest.mock('axios'); axios.create = jest.fn(() => axios); +let connectorUsageCollector: ConnectorUsageCollector; describe('createServiceWrapper', () => { beforeEach(() => { jest.clearAllMocks(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); test('creates axios instance with apiUrl', () => { @@ -45,6 +51,7 @@ describe('createServiceWrapper', () => { serviceConfig, connectorTokenClient, createServiceFn, + connectorUsageCollector, }); expect(createServiceFn).toHaveBeenCalledWith({ @@ -53,6 +60,7 @@ describe('createServiceWrapper', () => { configurationUtilities, serviceConfig, axiosInstance: axios, + connectorUsageCollector, }); }); @@ -76,6 +84,7 @@ describe('createServiceWrapper', () => { serviceConfig, connectorTokenClient, createServiceFn, + connectorUsageCollector, }); expect(createServiceFn).toHaveBeenCalledWith({ @@ -84,6 +93,7 @@ describe('createServiceWrapper', () => { configurationUtilities, serviceConfig, axiosInstance: axios, + connectorUsageCollector, }); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/create_service_wrapper.ts b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/create_service_wrapper.ts index f2de6e3787f70..dbadbf66f8d5f 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/create_service_wrapper.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/create_service_wrapper.ts @@ -6,7 +6,10 @@ */ import { Logger } from '@kbn/core/server'; -import type { ConnectorTokenClientContract } from '@kbn/actions-plugin/server/types'; +import { + ConnectorUsageCollector, + ConnectorTokenClientContract, +} from '@kbn/actions-plugin/server/types'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; import { ExternalService, ExternalServiceCredentials, SNProductsConfigValue } from './types'; @@ -21,6 +24,7 @@ interface CreateServiceWrapperOpts { serviceConfig: SNProductsConfigValue; connectorTokenClient: ConnectorTokenClientContract; createServiceFn: ServiceFactory; + connectorUsageCollector: ConnectorUsageCollector; } export function createServiceWrapper({ @@ -31,6 +35,7 @@ export function createServiceWrapper({ serviceConfig, connectorTokenClient, createServiceFn, + connectorUsageCollector, }: CreateServiceWrapperOpts): T { const { config } = credentials; const { apiUrl: url } = config as ServiceNowPublicConfigurationType; @@ -50,5 +55,6 @@ export function createServiceWrapper({ configurationUtilities, serviceConfig, axiosInstance, + connectorUsageCollector, }); } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/service.test.ts index ce6f33e1cc0d1..aa8d248566d9a 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/service.test.ts @@ -15,6 +15,7 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { serviceNowCommonFields, serviceNowChoices } from './mocks'; import { snExternalServiceConfig } from './config'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const logger = loggingSystemMock.create().get() as jest.Mocked; jest.mock('axios', () => ({ @@ -178,6 +179,7 @@ const expectImportedIncident = (update: boolean) => { configurationUtilities, url: 'https://example.com/api/x_elas2_inc_int/elastic_api/health', method: 'get', + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -191,6 +193,7 @@ const expectImportedIncident = (update: boolean) => { u_description: 'desc', ...(update ? { elastic_incident_id: '1' } : {}), }, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -199,14 +202,21 @@ const expectImportedIncident = (update: boolean) => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident/1', method: 'get', + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }; describe('ServiceNow service', () => { let service: ExternalService; + let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { jest.clearAllMocks(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); + service = createExternalService({ credentials: { // The trailing slash at the end of the url is intended. @@ -218,6 +228,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow'], axiosInstance: axios, + connectorUsageCollector, }); }); @@ -233,6 +244,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow'], axiosInstance: axios, + connectorUsageCollector, }) ).toThrow(); }); @@ -273,6 +285,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow'], axiosInstance: axios, + connectorUsageCollector, }) ).toThrow(); }); @@ -437,6 +450,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow'], axiosInstance: axios, + connectorUsageCollector, }) ).toThrow(); }); @@ -464,6 +478,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident/1', method: 'get', + connectorUsageCollector, }); }); @@ -477,6 +492,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], table: 'sn_si_incident' }, axiosInstance: axios, + connectorUsageCollector, }); requestMock.mockImplementation(() => ({ @@ -490,6 +506,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'get', + connectorUsageCollector, }); }); @@ -535,6 +552,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident?sysparm_query=ORDERBYDESCsys_created_on^correlation_id=custom_correlation_id', method: 'get', + connectorUsageCollector, }); }); @@ -559,6 +577,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], table: 'sn_si_incident' }, axiosInstance: axios, + connectorUsageCollector, }); requestMock.mockImplementation(() => ({ @@ -572,6 +591,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident?sysparm_query=ORDERBYDESCsys_created_on^correlation_id=custom_correlation_id', method: 'get', + connectorUsageCollector, }); }); @@ -625,6 +645,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow-sir'], axiosInstance: axios, + connectorUsageCollector, }); const res = await createIncident(service); @@ -635,6 +656,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/x_elas2_sir_int/elastic_api/health', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -644,6 +666,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/import/x_elas2_sir_int_elastic_si_incident', method: 'post', data: { u_short_description: 'title', u_description: 'desc' }, + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -652,6 +675,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'get', + connectorUsageCollector, }); expect(res.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -707,6 +731,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/import/x_elas2_inc_int_elastic_incident', method: 'post', data: { u_short_description: 'title', u_description: 'desc', foo: 'test' }, + connectorUsageCollector, }); }); }); @@ -723,6 +748,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); }); @@ -749,6 +775,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/v2/table/incident', method: 'post', data: { short_description: 'title', description: 'desc' }, + connectorUsageCollector, }); }); @@ -762,6 +789,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow-sir'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); mockIncidentResponse(false); @@ -778,6 +806,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/v2/table/sn_si_incident', method: 'post', data: { short_description: 'title', description: 'desc' }, + connectorUsageCollector, }); expect(res.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -826,6 +855,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow-sir'], axiosInstance: axios, + connectorUsageCollector, }); const res = await updateIncident(service); @@ -835,6 +865,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/x_elas2_sir_int/elastic_api/health', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -844,6 +875,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/import/x_elas2_sir_int_elastic_si_incident', method: 'post', data: { u_short_description: 'title', u_description: 'desc', elastic_incident_id: '1' }, + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -852,6 +884,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'get', + connectorUsageCollector, }); expect(res.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -915,6 +948,7 @@ describe('ServiceNow service', () => { elastic_incident_id: '1', foo: 'test', }, + connectorUsageCollector, }); }); }); @@ -931,6 +965,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); }); @@ -958,6 +993,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/v2/table/incident/1', method: 'patch', data: { short_description: 'title', description: 'desc' }, + connectorUsageCollector, }); }); @@ -971,6 +1007,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow-sir'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); mockIncidentResponse(false); @@ -988,6 +1025,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'patch', data: { short_description: 'title', description: 'desc' }, + connectorUsageCollector, }); expect(res.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -1032,6 +1070,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident/1', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -1040,6 +1079,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/x_elas2_inc_int/elastic_api/health', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -1054,6 +1094,7 @@ describe('ServiceNow service', () => { u_state: '7', u_close_notes: 'Closed by Caller', }, + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(4, { @@ -1062,6 +1103,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident/1', method: 'get', + connectorUsageCollector, }); expect(res?.url).toEqual('https://example.com/nav_to.do?uri=incident.do?sys_id=1'); @@ -1097,6 +1139,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident?sysparm_query=ORDERBYDESCsys_created_on^correlation_id=custom_correlation_id', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -1105,6 +1148,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/x_elas2_inc_int/elastic_api/health', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -1119,6 +1163,7 @@ describe('ServiceNow service', () => { u_state: '7', u_close_notes: 'Closed by Caller', }, + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(4, { @@ -1127,6 +1172,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident/1', method: 'get', + connectorUsageCollector, }); expect(res?.url).toEqual('https://example.com/nav_to.do?uri=incident.do?sys_id=1'); @@ -1237,6 +1283,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); }); @@ -1268,6 +1315,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow-sir'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); mockIncidentResponse(false); @@ -1285,6 +1333,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -1298,6 +1347,7 @@ describe('ServiceNow service', () => { state: '7', close_notes: 'Closed by Caller', }, + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -1306,6 +1356,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'get', + connectorUsageCollector, }); expect(res?.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -1325,6 +1376,7 @@ describe('ServiceNow service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_dictionary?sysparm_query=name=task^ORname=incident^internal_type=string&active=true&array=false&read_only=false&sysparm_fields=max_length,element,column_label,mandatory', + connectorUsageCollector, }); }); @@ -1346,6 +1398,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], table: 'sn_si_incident' }, axiosInstance: axios, + connectorUsageCollector, }); requestMock.mockImplementation(() => ({ @@ -1358,6 +1411,7 @@ describe('ServiceNow service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_dictionary?sysparm_query=name=task^ORname=sn_si_incident^internal_type=string&active=true&array=false&read_only=false&sysparm_fields=max_length,element,column_label,mandatory', + connectorUsageCollector, }); }); @@ -1394,6 +1448,7 @@ describe('ServiceNow service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_choice?sysparm_query=name=task^ORname=incident^element=priority^ORelement=category^language=en&sysparm_fields=label,value,dependent_value,element', + connectorUsageCollector, }); }); @@ -1415,6 +1470,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], table: 'sn_si_incident' }, axiosInstance: axios, + connectorUsageCollector, }); requestMock.mockImplementation(() => ({ @@ -1428,6 +1484,7 @@ describe('ServiceNow service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_choice?sysparm_query=name=task^ORname=sn_si_incident^element=priority^ORelement=category^language=en&sysparm_fields=label,value,dependent_value,element', + connectorUsageCollector, }); }); @@ -1520,6 +1577,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); await service.checkIfApplicationIsInstalled(); expect(requestMock).not.toHaveBeenCalled(); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/service.ts index 42aed9dcf8466..84a8592aaa832 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/service.ts @@ -37,6 +37,7 @@ export const createExternalService: ServiceFactory = ({ configurationUtilities, serviceConfig, axiosInstance, + connectorUsageCollector, }): ExternalService => { const { config, secrets } = credentials; const { table, importSetTable, useImportAPI, appScope } = serviceConfig; @@ -132,6 +133,7 @@ export const createExternalService: ServiceFactory = ({ logger, configurationUtilities, method: 'get', + connectorUsageCollector, // TODO check if this is internal }); checkInstance(res); @@ -160,6 +162,7 @@ export const createExternalService: ServiceFactory = ({ logger, configurationUtilities, method: 'get', + connectorUsageCollector, }); checkInstance(res); @@ -178,6 +181,7 @@ export const createExternalService: ServiceFactory = ({ logger, params, configurationUtilities, + connectorUsageCollector, }); checkInstance(res); @@ -201,6 +205,7 @@ export const createExternalService: ServiceFactory = ({ method: 'post', data: prepareIncident(useTableApi, incident), configurationUtilities, + connectorUsageCollector, }); checkInstance(res); @@ -240,6 +245,7 @@ export const createExternalService: ServiceFactory = ({ ...(useTableApi ? {} : { elastic_incident_id: incidentId }), }, configurationUtilities, + connectorUsageCollector, }); checkInstance(res); @@ -272,6 +278,7 @@ export const createExternalService: ServiceFactory = ({ method: 'get', logger, configurationUtilities, + connectorUsageCollector, }); checkInstance(res); @@ -350,6 +357,7 @@ export const createExternalService: ServiceFactory = ({ url: fieldsUrl, logger, configurationUtilities, + connectorUsageCollector, }); checkInstance(res); @@ -367,6 +375,7 @@ export const createExternalService: ServiceFactory = ({ url: getChoicesURL(fields), logger, configurationUtilities, + connectorUsageCollector, }); checkInstance(res); return res.data.result; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/types.ts b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/types.ts index 86d037c324e41..7cecf0bcddb46 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/types.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/types.ts @@ -11,7 +11,7 @@ import { AxiosError, AxiosInstance, AxiosResponse } from 'axios'; import { TypeOf } from '@kbn/config-schema'; import { Logger } from '@kbn/core/server'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; -import { ValidatorServices } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, ValidatorServices } from '@kbn/actions-plugin/server/types'; import { ExecutorParamsSchemaITSM, ExecutorSubActionCommonFieldsParamsSchema, @@ -305,6 +305,7 @@ interface ServiceFactoryOpts { configurationUtilities: ActionsConfigurationUtilities; serviceConfig: SNProductsConfigValue; axiosInstance: AxiosInstance; + connectorUsageCollector: ConnectorUsageCollector; } export type ServiceFactory = ({ @@ -313,6 +314,7 @@ export type ServiceFactory = ({ configurationUtilities, serviceConfig, axiosInstance, + connectorUsageCollector, }: ServiceFactoryOpts) => T; /** diff --git a/x-pack/plugins/stack_connectors/server/connector_types/openai/lib/azure_openai_utils.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/openai/lib/azure_openai_utils.test.ts index e9ad87a35ab7c..6023d7715f4ed 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/openai/lib/azure_openai_utils.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/openai/lib/azure_openai_utils.test.ts @@ -146,18 +146,14 @@ describe('Azure Open AI Utils', () => { const regex = transformApiUrlToRegex(AZURE_OPENAI_CHAT_URL); const match = chatUrl.match(regex); expect(match).not.toBeNull(); - expect(match![0]).toEqual( - 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions' - ); + expect(match![0]).toEqual('/openai/deployments/NEW-DEPLOYMENT-321/chat/completions'); }); it('should match valid completion url', () => { const regex = transformApiUrlToRegex(AZURE_OPENAI_COMPLETIONS_URL); const match = completionUrl.match(regex); expect(match).not.toBeNull(); - expect(match![0]).toEqual( - 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/completions' - ); + expect(match![0]).toEqual('/openai/deployments/NEW-DEPLOYMENT-321/completions'); }); it('should match valid completion extensions url', () => { @@ -165,19 +161,14 @@ describe('Azure Open AI Utils', () => { const match = completionExtensionsUrl.match(regex); expect(match).not.toBeNull(); expect(match![0]).toEqual( - 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/extensions/chat/completions' + '/openai/deployments/NEW-DEPLOYMENT-321/extensions/chat/completions' ); }); it('should not match invalid chat url', () => { const regex = transformApiUrlToRegex(AZURE_OPENAI_CHAT_URL); [ - 'https://openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', - 'https://My-test-resource-123.openaiazure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', - 'https://My-test-resource-123.openaiaazure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', - 'https://My-test-resource-123openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', - 'https://My-test-resource-123.openai.azure.com//openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', - 'https:///My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', + 'https://openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/not-completions?api-version=2023-05-15', ].forEach((url) => { const match = url.match(regex); expect(match).toBeNull(); @@ -187,12 +178,7 @@ describe('Azure Open AI Utils', () => { it('should not match invalid completion url', () => { const regex = transformApiUrlToRegex(AZURE_OPENAI_COMPLETIONS_URL); [ - 'https://fooai.com/completions?api-version=2023-05-15', - 'https://My-test-resource-123.openaiazure.com/openai/deployments/NEW-DEPLOYMENT-321/completions?api-version=2023-05-15', - 'https://My-test-resource-123.openaiaazure.com/openai/deployments/NEW-DEPLOYMENT-321/completions?api-version=2023-05-15', - 'https://My-test-resource-123openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/completions?api-version=2023-05-15', - 'https://My-test-resource-123.openai.azure.com//openai/deployments/NEW-DEPLOYMENT-321/completions?api-version=2023-05-15', - 'https:///My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/completions?api-version=2023-05-15', + 'https://My-test-resource-123.openaiazure.com/openai/deployments/NEW-DEPLOYMENT-321/not-completions?api-version=2023-05-15', ].forEach((url) => { const match = url.match(regex); expect(match).toBeNull(); @@ -202,12 +188,7 @@ describe('Azure Open AI Utils', () => { it('should not match invalid completion extensions url', () => { const regex = transformApiUrlToRegex(AZURE_OPENAI_COMPLETIONS_EXTENSIONS_URL); [ - 'https://My-test-resource-123.openai.azure.com/openai/deployments/extensions/chat/completions?api-version=2023-05-15', - 'https://My-test-resource-123.openaiazure.com/openai/deployments/NEW-DEPLOYMENT-321/extensions/chat/completions?api-version=2023-05-15', - 'https://My-test-resource-123.openaiaazure.com/openai/deployments/NEW-DEPLOYMENT-321/extensions/chat/completions?api-version=2023-05-15', - 'https://My-test-resource-123openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/extensions/chat/completions?api-version=2023-05-15', - 'https:///My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/extensions/chat/completions?api-version=2023-05-15', - 'https://My-test-resource-123.openai.azure.com/openai//deployments/NEW-DEPLOYMENT-321/extensions/chat/completions?api-version=2023-05-15', + 'https://My-test-resource-123.openai.azure.com/openai/deployments/extensions/chat/not-completions?api-version=2023-05-15', ].forEach((url) => { const match = url.match(regex); expect(match).toBeNull(); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.test.ts index 6f0974fe1796d..87dacaf4e6f17 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.test.ts @@ -19,6 +19,7 @@ import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { RunActionResponseSchema, StreamingResponseSchema } from '../../../common/openai/schema'; import { initDashboard } from '../lib/gen_ai/create_gen_ai_dashboard'; import { PassThrough, Transform } from 'stream'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; jest.mock('../lib/gen_ai/create_gen_ai_dashboard'); const mockTee = jest.fn(); @@ -46,6 +47,9 @@ jest.mock('openai', () => ({ describe('OpenAIConnector', () => { let mockRequest: jest.Mock; let mockError: jest.Mock; + let connectorUsageCollector: ConnectorUsageCollector; + + const logger = loggingSystemMock.createLogger(); const mockResponseString = 'Hello! How can I assist you today?'; const mockResponse = { headers: {}, @@ -72,6 +76,10 @@ describe('OpenAIConnector', () => { }, }; beforeEach(() => { + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); mockRequest = jest.fn().mockResolvedValue(mockResponse); mockError = jest.fn().mockImplementation(() => { throw new Error('API Error'); @@ -92,7 +100,7 @@ describe('OpenAIConnector', () => { }, }, secrets: { apiKey: '123' }, - logger: loggingSystemMock.createLogger(), + logger, services: actionsMock.createServices(), }); @@ -113,48 +121,74 @@ describe('OpenAIConnector', () => { describe('runApi', () => { it('uses the default model if none is supplied', async () => { - const response = await connector.runApi({ body: JSON.stringify(sampleOpenAiBody) }); + const response = await connector.runApi( + { body: JSON.stringify(sampleOpenAiBody) }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - data: JSON.stringify({ ...sampleOpenAiBody, stream: false, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: false, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); it('overrides the default model with the default model specified in the body', async () => { const requestBody = { model: 'gpt-3.5-turbo', ...sampleOpenAiBody }; - const response = await connector.runApi({ body: JSON.stringify(requestBody) }); + const response = await connector.runApi( + { body: JSON.stringify(requestBody) }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - data: JSON.stringify({ ...requestBody, stream: false }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + data: JSON.stringify({ ...requestBody, stream: false }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); it('the OpenAI API call is successful with correct parameters', async () => { - const response = await connector.runApi({ body: JSON.stringify(sampleOpenAiBody) }); + const response = await connector.runApi( + { body: JSON.stringify(sampleOpenAiBody) }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - data: JSON.stringify({ ...sampleOpenAiBody, stream: false, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: false, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); @@ -168,25 +202,31 @@ describe('OpenAIConnector', () => { }, ], }; - const response = await connector.runApi({ - body: JSON.stringify({ - ...body, - stream: true, - }), - }); + const response = await connector.runApi( + { + body: JSON.stringify({ + ...body, + stream: true, + }), + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - data: JSON.stringify({ - ...body, - stream: false, - }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + data: JSON.stringify({ + ...body, + stream: false, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); @@ -194,51 +234,71 @@ describe('OpenAIConnector', () => { // @ts-ignore connector.request = mockError; - await expect(connector.runApi({ body: JSON.stringify(sampleOpenAiBody) })).rejects.toThrow( - 'API Error' - ); + await expect( + connector.runApi({ body: JSON.stringify(sampleOpenAiBody) }, connectorUsageCollector) + ).rejects.toThrow('API Error'); }); }); describe('streamApi', () => { it('the OpenAI API call is successful with correct parameters when stream = false', async () => { - const response = await connector.streamApi({ - body: JSON.stringify(sampleOpenAiBody), - stream: false, - }); + const response = await connector.streamApi( + { + body: JSON.stringify(sampleOpenAiBody), + stream: false, + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://api.openai.com/v1/chat/completions', - method: 'post', - responseSchema: RunActionResponseSchema, - data: JSON.stringify({ ...sampleOpenAiBody, stream: false, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://api.openai.com/v1/chat/completions', + method: 'post', + responseSchema: RunActionResponseSchema, + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: false, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); it('the OpenAI API call is successful with correct parameters when stream = true', async () => { - const response = await connector.streamApi({ - body: JSON.stringify(sampleOpenAiBody), - stream: true, - }); + const response = await connector.streamApi( + { + body: JSON.stringify(sampleOpenAiBody), + stream: true, + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - responseType: 'stream', - url: 'https://api.openai.com/v1/chat/completions', - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ ...sampleOpenAiBody, stream: true, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + responseType: 'stream', + url: 'https://api.openai.com/v1/chat/completions', + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: true, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual({ headers: { 'Content-Type': 'dont-compress-this' }, ...mockResponse.data, @@ -255,29 +315,35 @@ describe('OpenAIConnector', () => { }, ], }; - const response = await connector.streamApi({ - body: JSON.stringify({ - ...body, - stream: false, - }), - stream: true, - }); - expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - responseType: 'stream', - url: 'https://api.openai.com/v1/chat/completions', - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ - ...body, + const response = await connector.streamApi( + { + body: JSON.stringify({ + ...body, + stream: false, + }), stream: true, - }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', }, - }); + connectorUsageCollector + ); + expect(mockRequest).toBeCalledTimes(1); + expect(mockRequest).toHaveBeenCalledWith( + { + responseType: 'stream', + url: 'https://api.openai.com/v1/chat/completions', + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + ...body, + stream: true, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, + }, + connectorUsageCollector + ); expect(response).toEqual({ headers: { 'Content-Type': 'dont-compress-this' }, ...mockResponse.data, @@ -289,7 +355,10 @@ describe('OpenAIConnector', () => { connector.request = mockError; await expect( - connector.streamApi({ body: JSON.stringify(sampleOpenAiBody), stream: true }) + connector.streamApi( + { body: JSON.stringify(sampleOpenAiBody), stream: true }, + connectorUsageCollector + ) ).rejects.toThrow('API Error'); }); }); @@ -314,135 +383,181 @@ describe('OpenAIConnector', () => { }); it('the API call is successful with correct request parameters', async () => { - await connector.invokeStream(sampleOpenAiBody); + await connector.invokeStream(sampleOpenAiBody, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://api.openai.com/v1/chat/completions', - method: 'post', - responseSchema: StreamingResponseSchema, - responseType: 'stream', - data: JSON.stringify({ ...sampleOpenAiBody, stream: true, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://api.openai.com/v1/chat/completions', + method: 'post', + responseSchema: StreamingResponseSchema, + responseType: 'stream', + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: true, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); }); it('signal is properly passed to streamApi', async () => { const signal = jest.fn(); - await connector.invokeStream({ ...sampleOpenAiBody, signal }); - - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://api.openai.com/v1/chat/completions', - method: 'post', - responseSchema: StreamingResponseSchema, - responseType: 'stream', - data: JSON.stringify({ ...sampleOpenAiBody, stream: true, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', - }, - signal, - }); + await connector.invokeStream({ ...sampleOpenAiBody, signal }, connectorUsageCollector); + + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://api.openai.com/v1/chat/completions', + method: 'post', + responseSchema: StreamingResponseSchema, + responseType: 'stream', + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: true, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, + signal, + }, + connectorUsageCollector + ); }); it('timeout is properly passed to streamApi', async () => { const timeout = 180000; - await connector.invokeStream({ ...sampleOpenAiBody, timeout }); - - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://api.openai.com/v1/chat/completions', - method: 'post', - responseSchema: StreamingResponseSchema, - responseType: 'stream', - data: JSON.stringify({ ...sampleOpenAiBody, stream: true, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', - }, - timeout, - }); + await connector.invokeStream({ ...sampleOpenAiBody, timeout }, connectorUsageCollector); + + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://api.openai.com/v1/chat/completions', + method: 'post', + responseSchema: StreamingResponseSchema, + responseType: 'stream', + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: true, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, + timeout, + }, + connectorUsageCollector + ); }); it('errors during API calls are properly handled', async () => { // @ts-ignore connector.request = mockError; - await expect(connector.invokeStream(sampleOpenAiBody)).rejects.toThrow('API Error'); + await expect( + connector.invokeStream(sampleOpenAiBody, connectorUsageCollector) + ).rejects.toThrow('API Error'); }); it('responds with a readable stream', async () => { // @ts-ignore connector.request = mockStream(); - const response = await connector.invokeStream(sampleOpenAiBody); + const response = await connector.invokeStream(sampleOpenAiBody, connectorUsageCollector); expect(response instanceof PassThrough).toEqual(true); }); }); describe('invokeAI', () => { it('the API call is successful with correct parameters', async () => { - const response = await connector.invokeAI(sampleOpenAiBody); + const response = await connector.invokeAI(sampleOpenAiBody, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - data: JSON.stringify({ ...sampleOpenAiBody, stream: false, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: false, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response.message).toEqual(mockResponseString); expect(response.usage.total_tokens).toEqual(9); }); it('signal is properly passed to runApi', async () => { const signal = jest.fn(); - await connector.invokeAI({ ...sampleOpenAiBody, signal }); + await connector.invokeAI({ ...sampleOpenAiBody, signal }, connectorUsageCollector); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - data: JSON.stringify({ ...sampleOpenAiBody, stream: false, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: false, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, + signal, }, - signal, - }); + connectorUsageCollector + ); }); it('timeout is properly passed to runApi', async () => { const timeout = 180000; - await connector.invokeAI({ ...sampleOpenAiBody, timeout }); + await connector.invokeAI({ ...sampleOpenAiBody, timeout }, connectorUsageCollector); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - data: JSON.stringify({ ...sampleOpenAiBody, stream: false, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'X-My-Custom-Header': 'foo', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: false, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'X-My-Custom-Header': 'foo', + 'content-type': 'application/json', + }, + timeout, }, - timeout, - }); + connectorUsageCollector + ); }); it('errors during API calls are properly handled', async () => { // @ts-ignore connector.request = mockError; - await expect(connector.invokeAI(sampleOpenAiBody)).rejects.toThrow('API Error'); + await expect(connector.invokeAI(sampleOpenAiBody, connectorUsageCollector)).rejects.toThrow( + 'API Error' + ); }); }); describe('invokeAsyncIterator', () => { it('the API call is successful with correct request parameters', async () => { - await connector.invokeAsyncIterator(sampleOpenAiBody); + await connector.invokeAsyncIterator(sampleOpenAiBody, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(0); expect(mockCreate).toHaveBeenCalledWith( { @@ -457,7 +572,10 @@ describe('OpenAIConnector', () => { it('signal and timeout is properly passed', async () => { const timeout = 180000; const signal = jest.fn(); - await connector.invokeAsyncIterator({ ...sampleOpenAiBody, signal, timeout }); + await connector.invokeAsyncIterator( + { ...sampleOpenAiBody, signal, timeout }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(0); expect(mockCreate).toHaveBeenCalledWith( { @@ -478,7 +596,9 @@ describe('OpenAIConnector', () => { throw new Error('API Error'); }); - await expect(connector.invokeAsyncIterator(sampleOpenAiBody)).rejects.toThrow('API Error'); + await expect( + connector.invokeAsyncIterator(sampleOpenAiBody, connectorUsageCollector) + ).rejects.toThrow('API Error'); }); }); describe('getResponseErrorMessage', () => { @@ -568,16 +688,26 @@ describe('OpenAIConnector', () => { describe('runApi', () => { it('uses the default model if none is supplied', async () => { - const response = await connector.runApi({ body: JSON.stringify(sampleOpenAiBody) }); + const response = await connector.runApi( + { body: JSON.stringify(sampleOpenAiBody) }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - data: JSON.stringify({ ...sampleOpenAiBody, stream: false, model: DEFAULT_OPENAI_MODEL }), - headers: { - Authorization: 'Bearer 123', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + data: JSON.stringify({ + ...sampleOpenAiBody, + stream: false, + model: DEFAULT_OPENAI_MODEL, + }), + headers: { + Authorization: 'Bearer 123', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); }); @@ -614,17 +744,23 @@ describe('OpenAIConnector', () => { describe('runApi', () => { it('test the AzureAI API call is successful with correct parameters', async () => { - const response = await connector.runApi({ body: JSON.stringify(sampleAzureAiBody) }); + const response = await connector.runApi( + { body: JSON.stringify(sampleAzureAiBody) }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', - data: JSON.stringify({ ...sampleAzureAiBody, stream: false }), - headers: { - 'api-key': '123', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', + data: JSON.stringify({ ...sampleAzureAiBody, stream: false }), + headers: { + 'api-key': '123', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); @@ -637,19 +773,25 @@ describe('OpenAIConnector', () => { }, ], }; - const response = await connector.runApi({ - body: JSON.stringify({ ...body, stream: true }), - }); + const response = await connector.runApi( + { + body: JSON.stringify({ ...body, stream: true }), + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - ...mockDefaults, - url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', - data: JSON.stringify({ ...sampleAzureAiBody, stream: false }), - headers: { - 'api-key': '123', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + ...mockDefaults, + url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', + data: JSON.stringify({ ...sampleAzureAiBody, stream: false }), + headers: { + 'api-key': '123', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); @@ -657,49 +799,61 @@ describe('OpenAIConnector', () => { // @ts-ignore connector.request = mockError; - await expect(connector.runApi({ body: JSON.stringify(sampleAzureAiBody) })).rejects.toThrow( - 'API Error' - ); + await expect( + connector.runApi({ body: JSON.stringify(sampleAzureAiBody) }, connectorUsageCollector) + ).rejects.toThrow('API Error'); }); }); describe('streamApi', () => { it('the AzureAI API call is successful with correct parameters when stream = false', async () => { - const response = await connector.streamApi({ - body: JSON.stringify(sampleAzureAiBody), - stream: false, - }); + const response = await connector.streamApi( + { + body: JSON.stringify(sampleAzureAiBody), + stream: false, + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', - method: 'post', - responseSchema: RunActionResponseSchema, - data: JSON.stringify({ ...sampleAzureAiBody, stream: false }), - headers: { - 'api-key': '123', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', + method: 'post', + responseSchema: RunActionResponseSchema, + data: JSON.stringify({ ...sampleAzureAiBody, stream: false }), + headers: { + 'api-key': '123', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); it('the AzureAI API call is successful with correct parameters when stream = true', async () => { - const response = await connector.streamApi({ - body: JSON.stringify(sampleAzureAiBody), - stream: true, - }); + const response = await connector.streamApi( + { + body: JSON.stringify(sampleAzureAiBody), + stream: true, + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - responseType: 'stream', - url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ ...sampleAzureAiBody, stream: true }), - headers: { - 'api-key': '123', - 'content-type': 'application/json', + expect(mockRequest).toHaveBeenCalledWith( + { + responseType: 'stream', + url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ ...sampleAzureAiBody, stream: true }), + headers: { + 'api-key': '123', + 'content-type': 'application/json', + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual({ headers: { 'Content-Type': 'dont-compress-this' }, ...mockResponse.data, @@ -715,25 +869,31 @@ describe('OpenAIConnector', () => { }, ], }; - const response = await connector.streamApi({ - body: JSON.stringify({ ...body, stream: false }), - stream: true, - }); - expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - responseType: 'stream', - url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', - method: 'post', - responseSchema: StreamingResponseSchema, - data: JSON.stringify({ - ...body, + const response = await connector.streamApi( + { + body: JSON.stringify({ ...body, stream: false }), stream: true, - }), - headers: { - 'api-key': '123', - 'content-type': 'application/json', }, - }); + connectorUsageCollector + ); + expect(mockRequest).toBeCalledTimes(1); + expect(mockRequest).toHaveBeenCalledWith( + { + responseType: 'stream', + url: 'https://My-test-resource-123.openai.azure.com/openai/deployments/NEW-DEPLOYMENT-321/chat/completions?api-version=2023-05-15', + method: 'post', + responseSchema: StreamingResponseSchema, + data: JSON.stringify({ + ...body, + stream: true, + }), + headers: { + 'api-key': '123', + 'content-type': 'application/json', + }, + }, + connectorUsageCollector + ); expect(response).toEqual({ headers: { 'Content-Type': 'dont-compress-this' }, ...mockResponse.data, @@ -745,7 +905,10 @@ describe('OpenAIConnector', () => { connector.request = mockError; await expect( - connector.streamApi({ body: JSON.stringify(sampleAzureAiBody), stream: true }) + connector.streamApi( + { body: JSON.stringify(sampleAzureAiBody), stream: true }, + connectorUsageCollector + ) ).rejects.toThrow('API Error'); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.ts b/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.ts index 544b6bf7092c2..6cadc322a3d78 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.ts @@ -16,6 +16,7 @@ import { ChatCompletionMessageParam, } from 'openai/resources/chat/completions'; import { Stream } from 'openai/streaming'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { removeEndpointFromUrl } from './lib/openai_utils'; import { RunActionParamsSchema, @@ -156,7 +157,11 @@ export class OpenAIConnector extends SubActionConnector { * responsible for making a POST request to the external API endpoint and returning the response data * @param body The stringified request body to be sent in the POST request. */ - public async runApi({ body, signal, timeout }: RunActionParams): Promise { + + public async runApi( + { body, signal, timeout }: RunActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { const sanitizedBody = sanitizeRequest( this.provider, this.url, @@ -164,20 +169,23 @@ export class OpenAIConnector extends SubActionConnector { ...('defaultModel' in this.config ? [this.config.defaultModel] : []) ); const axiosOptions = getAxiosOptions(this.provider, this.key, false); - const response = await this.request({ - url: this.url, - method: 'post', - responseSchema: RunActionResponseSchema, - data: sanitizedBody, - signal, - // give up to 2 minutes for response - timeout: timeout ?? DEFAULT_TIMEOUT_MS, - ...axiosOptions, - headers: { - ...this.config.headers, - ...axiosOptions.headers, + const response = await this.request( + { + url: this.url, + method: 'post', + responseSchema: RunActionResponseSchema, + data: sanitizedBody, + signal, + // give up to 2 minutes for response + timeout: timeout ?? DEFAULT_TIMEOUT_MS, + ...axiosOptions, + headers: { + ...this.config.headers, + ...axiosOptions.headers, + }, }, - }); + connectorUsageCollector + ); return response.data; } @@ -189,12 +197,10 @@ export class OpenAIConnector extends SubActionConnector { * @param body request body for the API request * @param stream flag indicating whether it is a streaming request or not */ - public async streamApi({ - body, - stream, - signal, - timeout, - }: StreamActionParams): Promise { + public async streamApi( + { body, stream, signal, timeout }: StreamActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { const executeBody = getRequestWithStreamOption( this.provider, this.url, @@ -205,19 +211,22 @@ export class OpenAIConnector extends SubActionConnector { const axiosOptions = getAxiosOptions(this.provider, this.key, stream); - const response = await this.request({ - url: this.url, - method: 'post', - responseSchema: stream ? StreamingResponseSchema : RunActionResponseSchema, - data: executeBody, - signal, - ...axiosOptions, - headers: { - ...this.config.headers, - ...axiosOptions.headers, + const response = await this.request( + { + url: this.url, + method: 'post', + responseSchema: stream ? StreamingResponseSchema : RunActionResponseSchema, + data: executeBody, + signal, + ...axiosOptions, + headers: { + ...this.config.headers, + ...axiosOptions.headers, + }, + timeout, }, - timeout, - }); + connectorUsageCollector + ); return stream ? pipeStreamingResponse(response) : response.data; } @@ -264,15 +273,21 @@ export class OpenAIConnector extends SubActionConnector { * returned directly to the client for streaming * @param body - the OpenAI Invoke request body */ - public async invokeStream(body: InvokeAIActionParams): Promise { + public async invokeStream( + body: InvokeAIActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { const { signal, timeout, ...rest } = body; - const res = (await this.streamApi({ - body: JSON.stringify(rest), - stream: true, - signal, - timeout, // do not default if not provided - })) as unknown as IncomingMessage; + const res = (await this.streamApi( + { + body: JSON.stringify(rest), + stream: true, + signal, + timeout, // do not default if not provided + }, + connectorUsageCollector + )) as unknown as IncomingMessage; return res.pipe(new PassThrough()); } @@ -286,7 +301,10 @@ export class OpenAIConnector extends SubActionConnector { * tokenCountStream: Stream; the result for token counting stream * } */ - public async invokeAsyncIterator(body: InvokeAIActionParams): Promise<{ + public async invokeAsyncIterator( + body: InvokeAIActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise<{ consumerStream: Stream; tokenCountStream: Stream; }> { @@ -301,6 +319,8 @@ export class OpenAIConnector extends SubActionConnector { rest.model ?? ('defaultModel' in this.config ? this.config.defaultModel : DEFAULT_OPENAI_MODEL), }; + + connectorUsageCollector.addRequestBodyBytes(undefined, requestBody); const stream = await this.openAI.chat.completions.create(requestBody, { signal, timeout, // do not default if not provided @@ -323,9 +343,15 @@ export class OpenAIConnector extends SubActionConnector { * @param body - the OpenAI chat completion request body * @returns an object with the response string and the usage object */ - public async invokeAI(body: InvokeAIActionParams): Promise { + public async invokeAI( + body: InvokeAIActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { const { signal, timeout, ...rest } = body; - const res = await this.runApi({ body: JSON.stringify(rest), signal, timeout }); + const res = await this.runApi( + { body: JSON.stringify(rest), signal, timeout }, + connectorUsageCollector + ); if (res.choices && res.choices.length > 0 && res.choices[0].message?.content) { const result = res.choices[0].message.content.trim(); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/opsgenie/connector.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/opsgenie/connector.test.ts index fb11174e20ba5..821f2b3032661 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/opsgenie/connector.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/opsgenie/connector.test.ts @@ -15,6 +15,7 @@ import { MockedLogger } from '@kbn/logging-mocks'; import { OpsgenieConnectorTypeId } from '../../../common'; import { OpsgenieConnector } from './connector'; import * as utils from '@kbn/actions-plugin/server/lib/axios_utils'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; jest.mock('axios'); @@ -36,6 +37,7 @@ describe('OpsgenieConnector', () => { let mockedActionsConfig: jest.Mocked; let logger: MockedLogger; let services: ReturnType; + let connectorUsageCollector: ConnectorUsageCollector; const defaultCreateAlertExpect = { method: 'post', @@ -75,36 +77,43 @@ describe('OpsgenieConnector', () => { logger, services, }); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); it('calls request with the correct arguments for creating an alert', async () => { - await connector.createAlert({ message: 'hello' }); + await connector.createAlert({ message: 'hello' }, connectorUsageCollector); expect(requestMock.mock.calls[0][0]).toEqual({ data: { message: 'hello' }, ...ignoredRequestFields, ...defaultCreateAlertExpect, + connectorUsageCollector, }); }); it('calls request without modifying the alias when it is less than 512 characters when creating an alert', async () => { - await connector.createAlert({ message: 'hello', alias: '111' }); + await connector.createAlert({ message: 'hello', alias: '111' }, connectorUsageCollector); expect(requestMock.mock.calls[0][0]).toEqual({ ...ignoredRequestFields, ...defaultCreateAlertExpect, data: { message: 'hello', alias: '111' }, + connectorUsageCollector, }); }); it('calls request without modifying the alias when it is equal to 512 characters when creating an alert', async () => { const alias = 'a'.repeat(512); - await connector.createAlert({ message: 'hello', alias }); + await connector.createAlert({ message: 'hello', alias }, connectorUsageCollector); expect(requestMock.mock.calls[0][0]).toEqual({ ...ignoredRequestFields, ...defaultCreateAlertExpect, data: { message: 'hello', alias }, + connectorUsageCollector, }); }); @@ -114,12 +123,13 @@ describe('OpsgenieConnector', () => { const hasher = crypto.createHash('sha256'); const sha256Hash = hasher.update(alias); - await connector.createAlert({ message: 'hello', alias }); + await connector.createAlert({ message: 'hello', alias }, connectorUsageCollector); expect(requestMock.mock.calls[0][0]).toEqual({ ...ignoredRequestFields, ...defaultCreateAlertExpect, data: { message: 'hello', alias: `sha-${sha256Hash.digest('hex')}` }, + connectorUsageCollector, }); }); @@ -129,22 +139,24 @@ describe('OpsgenieConnector', () => { const hasher = crypto.createHash('sha256'); const sha256Hash = hasher.update(alias); - await connector.closeAlert({ alias }); + await connector.closeAlert({ alias }, connectorUsageCollector); expect(requestMock.mock.calls[0][0]).toEqual({ ...ignoredRequestFields, ...createCloseAlertExpect(`sha-${sha256Hash.digest('hex')}`), data: {}, + connectorUsageCollector, }); }); it('calls request with the correct arguments for closing an alert', async () => { - await connector.closeAlert({ user: 'sam', alias: '111' }); + await connector.closeAlert({ user: 'sam', alias: '111' }, connectorUsageCollector); expect(requestMock.mock.calls[0][0]).toEqual({ ...ignoredRequestFields, ...createCloseAlertExpect('111'), data: { user: 'sam' }, + connectorUsageCollector, }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/opsgenie/connector.ts b/x-pack/plugins/stack_connectors/server/connector_types/opsgenie/connector.ts index cd86a8ac7542a..0963ac720c80a 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/opsgenie/connector.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/opsgenie/connector.ts @@ -9,6 +9,7 @@ import crypto from 'crypto'; import { ServiceParams, SubActionConnector } from '@kbn/actions-plugin/server'; import { AxiosError } from 'axios'; import { isEmpty } from 'lodash'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { OpsgenieSubActions } from '../../../common'; import { CreateAlertParamsSchema, CloseAlertParamsSchema, Response } from './schema'; import { CloseAlertParams, Config, CreateAlertParams, FailureResponseType, Secrets } from './types'; @@ -67,14 +68,20 @@ export class OpsgenieConnector extends SubActionConnector { } } - public async createAlert(params: CreateAlertParams) { - const res = await this.request({ - method: 'post', - url: this.concatPathToURL('v2/alerts').toString(), - data: { ...params, ...OpsgenieConnector.createAliasObj(params.alias) }, - headers: this.createHeaders(), - responseSchema: Response, - }); + public async createAlert( + params: CreateAlertParams, + connectorUsageCollector: ConnectorUsageCollector + ) { + const res = await this.request( + { + method: 'post', + url: this.concatPathToURL('v2/alerts').toString(), + data: { ...params, ...OpsgenieConnector.createAliasObj(params.alias) }, + headers: this.createHeaders(), + responseSchema: Response, + }, + connectorUsageCollector + ); return res.data; } @@ -107,7 +114,10 @@ export class OpsgenieConnector extends SubActionConnector { return { Authorization: `GenieKey ${this.secrets.apiKey}` }; } - public async closeAlert(params: CloseAlertParams) { + public async closeAlert( + params: CloseAlertParams, + connectorUsageCollector: ConnectorUsageCollector + ) { const newAlias = OpsgenieConnector.createAlias(params.alias); const fullURL = this.concatPathToURL(`v2/alerts/${newAlias}/close`); @@ -115,13 +125,16 @@ export class OpsgenieConnector extends SubActionConnector { const { alias, ...paramsWithoutAlias } = params; - const res = await this.request({ - method: 'post', - url: fullURL.toString(), - data: paramsWithoutAlias, - headers: this.createHeaders(), - responseSchema: Response, - }); + const res = await this.request( + { + method: 'post', + url: fullURL.toString(), + data: paramsWithoutAlias, + headers: this.createHeaders(), + responseSchema: Response, + }, + connectorUsageCollector + ); return res.data; } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/index.test.ts index 86cdca4740f6d..38446eefe44f1 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/index.test.ts @@ -10,7 +10,7 @@ import moment from 'moment'; jest.mock('./post_pagerduty', () => ({ postPagerduty: jest.fn(), })); -import { Services } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, Services } from '@kbn/actions-plugin/server/types'; import { validateConfig, validateSecrets, validateParams } from '@kbn/actions-plugin/server/lib'; import { postPagerduty } from './post_pagerduty'; import { Logger } from '@kbn/core/server'; @@ -31,10 +31,15 @@ const mockedLogger: jest.Mocked = loggerMock.create(); let connectorType: PagerDutyConnectorType; let configurationUtilities: jest.Mocked; +let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); connectorType = getConnectorType(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); }); describe('get()', () => { @@ -269,6 +274,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -350,6 +356,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -458,6 +465,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -535,6 +543,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -578,6 +587,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); expect(actionResponse).toMatchInlineSnapshot(` @@ -608,6 +618,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); expect(actionResponse).toMatchInlineSnapshot(` @@ -638,6 +649,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); expect(actionResponse).toMatchInlineSnapshot(` @@ -668,6 +680,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); expect(actionResponse).toMatchInlineSnapshot(` @@ -708,6 +721,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -771,6 +785,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -837,6 +852,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -902,6 +918,7 @@ describe('execute()', () => { services, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/index.ts index cfd11d6803df8..c4d2444540cad 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/index.ts @@ -198,8 +198,16 @@ function getPagerDutyApiUrl(config: ConnectorTypeConfigType): string { async function executor( execOptions: PagerDutyConnectorTypeExecutorOptions ): Promise> { - const { actionId, config, secrets, params, services, configurationUtilities, logger } = - execOptions; + const { + actionId, + config, + secrets, + params, + services, + configurationUtilities, + logger, + connectorUsageCollector, + } = execOptions; const apiUrl = getPagerDutyApiUrl(config); const headers = { @@ -213,7 +221,8 @@ async function executor( response = await postPagerduty( { apiUrl, data, headers, services }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); } catch (err) { const message = i18n.translate('xpack.stackConnectors.pagerduty.postingErrorMessage', { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/post_pagerduty.ts b/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/post_pagerduty.ts index 0ef41637967d2..8b0937f9d857b 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/post_pagerduty.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/pagerduty/post_pagerduty.ts @@ -7,7 +7,7 @@ import axios, { AxiosResponse } from 'axios'; import { Logger } from '@kbn/core/server'; -import { Services } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, Services } from '@kbn/actions-plugin/server/types'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; import { request } from '@kbn/actions-plugin/server/lib/axios_utils'; @@ -22,7 +22,8 @@ interface PostPagerdutyOptions { export async function postPagerduty( options: PostPagerdutyOptions, logger: Logger, - configurationUtilities: ActionsConfigurationUtilities + configurationUtilities: ActionsConfigurationUtilities, + connectorUsageCollector: ConnectorUsageCollector ): Promise { const { apiUrl, data, headers } = options; const axiosInstance = axios.create(); @@ -36,5 +37,6 @@ export async function postPagerduty( headers, configurationUtilities, validateStatus: () => true, + connectorUsageCollector, }); } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.test.ts index 4e031bdaafeea..6f3999dc70df7 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.test.ts @@ -13,6 +13,7 @@ import { ResilientConnector } from './resilient'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { RESILIENT_CONNECTOR_ID } from './constants'; import { PushToServiceIncidentSchema } from './schema'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; jest.mock('axios'); jest.mock('@kbn/actions-plugin/server/lib/axios_utils', () => { @@ -83,13 +84,15 @@ const mockIncidentUpdate = (withUpdateError = false) => { }) ); }; +let connectorUsageCollector: ConnectorUsageCollector; describe('IBM Resilient connector', () => { + const logger = loggingSystemMock.createLogger(); const connector = new ResilientConnector( { connector: { id: '1', type: RESILIENT_CONNECTOR_ID }, configurationUtilities: actionsConfigMock.create(), - logger: loggingSystemMock.createLogger(), + logger, services: actionsMock.createServices(), config: { orgId, apiUrl }, secrets: { apiKeyId, apiKeySecret }, @@ -107,6 +110,10 @@ describe('IBM Resilient connector', () => { beforeEach(() => { jest.resetAllMocks(); jest.setSystemTime(TIMESTAMP); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); describe('getIncident', () => { @@ -129,12 +136,12 @@ describe('IBM Resilient connector', () => { }); it('returns the incident correctly', async () => { - const res = await connector.getIncident({ id: '1' }); + const res = await connector.getIncident({ id: '1' }, connectorUsageCollector); expect(res).toEqual(incidentMock); }); it('should call request with correct arguments', async () => { - await connector.getIncident({ id: '1' }); + await connector.getIncident({ id: '1' }, connectorUsageCollector); expect(requestMock).toHaveBeenCalledWith({ ...ignoredRequestFields, method: 'GET', @@ -147,6 +154,7 @@ describe('IBM Resilient connector', () => { params: { text_content_output_format: 'objects_convert', }, + connectorUsageCollector, }); }); @@ -154,7 +162,7 @@ describe('IBM Resilient connector', () => { requestMock.mockImplementation(() => { throw new Error('An error has occurred'); }); - await expect(connector.getIncident({ id: '1' })).rejects.toThrow( + await expect(connector.getIncident({ id: '1' }, connectorUsageCollector)).rejects.toThrow( 'Unable to get incident with id 1. Error: An error has occurred' ); }); @@ -183,7 +191,7 @@ describe('IBM Resilient connector', () => { }); it('creates the incident correctly', async () => { - const res = await connector.createIncident(incidentMock); + const res = await connector.createIncident(incidentMock, connectorUsageCollector); expect(res).toEqual({ title: '1', @@ -194,7 +202,7 @@ describe('IBM Resilient connector', () => { }); it('should call request with correct arguments', async () => { - await connector.createIncident(incidentMock); + await connector.createIncident(incidentMock, connectorUsageCollector); expect(requestMock).toHaveBeenCalledWith({ ...ignoredRequestFields, @@ -214,6 +222,7 @@ describe('IBM Resilient connector', () => { Authorization: `Basic ${token}`, 'Content-Type': 'application/json', }, + connectorUsageCollector, }); }); @@ -223,12 +232,15 @@ describe('IBM Resilient connector', () => { }); await expect( - connector.createIncident({ - name: 'title', - description: 'desc', - incidentTypes: [1001], - severityCode: 6, - }) + connector.createIncident( + { + name: 'title', + description: 'desc', + incidentTypes: [1001], + severityCode: 6, + }, + connectorUsageCollector + ) ).rejects.toThrow( '[Action][IBM Resilient]: Unable to create incident. Error: An error has occurred' ); @@ -237,7 +249,7 @@ describe('IBM Resilient connector', () => { it('should throw if the required attributes are not received in response', async () => { requestMock.mockImplementation(() => createAxiosResponse({ data: { notRequired: 'test' } })); - await expect(connector.createIncident(incidentMock)).rejects.toThrow( + await expect(connector.createIncident(incidentMock, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to create incident. Error: Response validation failed (Error: [id]: expected value of type [number] but got [undefined]).' ); }); @@ -255,7 +267,7 @@ describe('IBM Resilient connector', () => { }; it('updates the incident correctly', async () => { mockIncidentUpdate(); - const res = await connector.updateIncident(req); + const res = await connector.updateIncident(req, connectorUsageCollector); expect(res).toEqual({ title: '1', @@ -268,15 +280,18 @@ describe('IBM Resilient connector', () => { it('should call request with correct arguments', async () => { mockIncidentUpdate(); - await connector.updateIncident({ - incidentId: '1', - incident: { - name: 'title_updated', - description: 'desc_updated', - incidentTypes: [1001], - severityCode: 5, + await connector.updateIncident( + { + incidentId: '1', + incident: { + name: 'title_updated', + description: 'desc_updated', + incidentTypes: [1001], + severityCode: 5, + }, }, - }); + connectorUsageCollector + ); expect(requestMock.mock.calls[1][0]).toEqual({ ...ignoredRequestFields, @@ -332,13 +347,14 @@ describe('IBM Resilient connector', () => { }, ], }, + connectorUsageCollector, }); }); it('it should throw an error', async () => { mockIncidentUpdate(true); - await expect(connector.updateIncident(req)).rejects.toThrow( + await expect(connector.updateIncident(req, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to update incident with id 1. Error: An error has occurred' ); }); @@ -361,7 +377,7 @@ describe('IBM Resilient connector', () => { ); requestMock.mockImplementation(() => createAxiosResponse({ data: { notRequired: 'test' } })); - await expect(connector.updateIncident(req)).rejects.toThrow( + await expect(connector.updateIncident(req, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to update incident with id 1. Error: Response validation failed (Error: [success]: expected value of type [boolean] but got [undefined]).' ); }); @@ -388,7 +404,7 @@ describe('IBM Resilient connector', () => { }); it('should call request with correct arguments', async () => { - await connector.addComment(req); + await connector.addComment(req, connectorUsageCollector); expect(requestMock).toHaveBeenCalledWith({ ...ignoredRequestFields, @@ -404,6 +420,7 @@ describe('IBM Resilient connector', () => { format: 'text', }, }, + connectorUsageCollector, }); }); @@ -412,7 +429,7 @@ describe('IBM Resilient connector', () => { throw new Error('An error has occurred'); }); - await expect(connector.addComment(req)).rejects.toThrow( + await expect(connector.addComment(req, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to create comment at incident with id 1. Error: An error has occurred.' ); }); @@ -428,7 +445,7 @@ describe('IBM Resilient connector', () => { }); it('should call request with correct arguments', async () => { - await connector.getIncidentTypes(); + await connector.getIncidentTypes(undefined, connectorUsageCollector); expect(requestMock).toBeCalledTimes(1); expect(requestMock).toHaveBeenCalledWith({ ...ignoredRequestFields, @@ -439,11 +456,12 @@ describe('IBM Resilient connector', () => { Authorization: `Basic ${token}`, 'Content-Type': 'application/json', }, + connectorUsageCollector, }); }); it('returns incident types correctly', async () => { - const res = await connector.getIncidentTypes(); + const res = await connector.getIncidentTypes(undefined, connectorUsageCollector); expect(res).toEqual([ { id: '17', name: 'Communication error (fax; email)' }, @@ -456,7 +474,7 @@ describe('IBM Resilient connector', () => { throw new Error('An error has occurred'); }); - await expect(connector.getIncidentTypes()).rejects.toThrow( + await expect(connector.getIncidentTypes(undefined, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to get incident types. Error: An error has occurred.' ); }); @@ -466,7 +484,7 @@ describe('IBM Resilient connector', () => { createAxiosResponse({ data: { id: '1001', name: 'Custom type' } }) ); - await expect(connector.getIncidentTypes()).rejects.toThrow( + await expect(connector.getIncidentTypes(undefined, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to get incident types. Error: Response validation failed (Error: [values]: expected value of type [array] but got [undefined]).' ); }); @@ -484,7 +502,7 @@ describe('IBM Resilient connector', () => { }); it('should call request with correct arguments', async () => { - await connector.getSeverity(); + await connector.getSeverity(undefined, connectorUsageCollector); expect(requestMock).toBeCalledTimes(1); expect(requestMock).toHaveBeenCalledWith({ ...ignoredRequestFields, @@ -495,11 +513,12 @@ describe('IBM Resilient connector', () => { Authorization: `Basic ${token}`, 'Content-Type': 'application/json', }, + connectorUsageCollector, }); }); it('returns severity correctly', async () => { - const res = await connector.getSeverity(); + const res = await connector.getSeverity(undefined, connectorUsageCollector); expect(res).toEqual([ { @@ -522,7 +541,7 @@ describe('IBM Resilient connector', () => { throw new Error('An error has occurred'); }); - await expect(connector.getSeverity()).rejects.toThrow( + await expect(connector.getSeverity(undefined, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to get severity. Error: An error has occurred.' ); }); @@ -532,7 +551,7 @@ describe('IBM Resilient connector', () => { createAxiosResponse({ data: { id: '10', name: 'Critical' } }) ); - await expect(connector.getSeverity()).rejects.toThrow( + await expect(connector.getSeverity(undefined, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to get severity. Error: Response validation failed (Error: [values]: expected value of type [array] but got [undefined]).' ); }); @@ -547,7 +566,7 @@ describe('IBM Resilient connector', () => { ); }); it('should call request with correct arguments', async () => { - await connector.getFields(); + await connector.getFields(undefined, connectorUsageCollector); expect(requestMock).toBeCalledTimes(1); expect(requestMock).toHaveBeenCalledWith({ @@ -559,11 +578,12 @@ describe('IBM Resilient connector', () => { Authorization: `Basic ${token}`, 'Content-Type': 'application/json', }, + connectorUsageCollector, }); }); it('returns common fields correctly', async () => { - const res = await connector.getFields(); + const res = await connector.getFields(undefined, connectorUsageCollector); expect(res).toEqual(resilientFields); }); @@ -571,7 +591,7 @@ describe('IBM Resilient connector', () => { requestMock.mockImplementation(() => { throw new Error('An error has occurred'); }); - await expect(connector.getFields()).rejects.toThrow( + await expect(connector.getFields(undefined, connectorUsageCollector)).rejects.toThrow( 'Unable to get fields. Error: An error has occurred' ); }); @@ -579,7 +599,7 @@ describe('IBM Resilient connector', () => { it('should throw if the required attributes are not received in response', async () => { requestMock.mockImplementation(() => createAxiosResponse({ data: { someField: 'test' } })); - await expect(connector.getFields()).rejects.toThrow( + await expect(connector.getFields(undefined, connectorUsageCollector)).rejects.toThrow( '[Action][IBM Resilient]: Unable to get fields. Error: Response validation failed (Error: expected value of type [array] but got [Object]).' ); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.ts b/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.ts index 1351488dbf892..da297369ae024 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.ts @@ -10,6 +10,7 @@ import { omitBy, isNil } from 'lodash/fp'; import { CaseConnector, getBasicAuthHeader, ServiceParams } from '@kbn/actions-plugin/server'; import { schema, Type } from '@kbn/config-schema'; import { getErrorMessage } from '@kbn/actions-plugin/server/lib/axios_utils'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { CreateIncidentData, ExternalServiceIncidentResponse, @@ -117,7 +118,10 @@ export class ResilientConnector extends CaseConnector< return `${urlWithoutTrailingSlash}/${VIEW_INCIDENT_URL}/${key}`; } - public async createIncident(incident: Incident): Promise { + public async createIncident( + incident: Incident, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { try { let data: CreateIncidentData = { name: incident.name, @@ -150,19 +154,22 @@ export class ResilientConnector extends CaseConnector< }; } - const res = await this.request({ - url: `${this.urls.incident}?text_content_output_format=objects_convert`, - method: 'POST', - data, - headers: this.getAuthHeaders(), - responseSchema: schema.object( - { - id: schema.number(), - create_date: schema.number(), - }, - { unknowns: 'allow' } - ), - }); + const res = await this.request( + { + url: `${this.urls.incident}?text_content_output_format=objects_convert`, + method: 'POST', + data, + headers: this.getAuthHeaders(), + responseSchema: schema.object( + { + id: schema.number(), + create_date: schema.number(), + }, + { unknowns: 'allow' } + ), + }, + connectorUsageCollector + ); const { id, create_date: createDate } = res.data; @@ -179,30 +186,33 @@ export class ResilientConnector extends CaseConnector< } } - public async updateIncident({ - incidentId, - incident, - }: UpdateIncidentParams): Promise { + public async updateIncident( + { incidentId, incident }: UpdateIncidentParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { try { - const latestIncident = await this.getIncident({ id: incidentId }); + const latestIncident = await this.getIncident({ id: incidentId }, connectorUsageCollector); // Remove null or undefined values. Allowing null values sets the field in IBM Resilient to empty. const newIncident = omitBy(isNil, incident); const data = formatUpdateRequest({ oldIncident: latestIncident, newIncident }); - const res = await this.request({ - method: 'PATCH', - url: `${this.urls.incident}/${incidentId}`, - data, - headers: this.getAuthHeaders(), - responseSchema: schema.object({ success: schema.boolean() }, { unknowns: 'allow' }), - }); + const res = await this.request( + { + method: 'PATCH', + url: `${this.urls.incident}/${incidentId}`, + data, + headers: this.getAuthHeaders(), + responseSchema: schema.object({ success: schema.boolean() }, { unknowns: 'allow' }), + }, + connectorUsageCollector + ); if (!res.data.success) { throw new Error('Error while updating incident'); } - const updatedIncident = await this.getIncident({ id: incidentId }); + const updatedIncident = await this.getIncident({ id: incidentId }, connectorUsageCollector); return { title: `${updatedIncident.id}`, @@ -220,15 +230,21 @@ export class ResilientConnector extends CaseConnector< } } - public async addComment({ incidentId, comment }: { incidentId: string; comment: string }) { + public async addComment( + { incidentId, comment }: { incidentId: string; comment: string }, + connectorUsageCollector: ConnectorUsageCollector + ) { try { - await this.request({ - method: 'POST', - url: this.urls.comment.replace('{inc_id}', incidentId), - data: { text: { format: 'text', content: comment } }, - headers: this.getAuthHeaders(), - responseSchema: schema.object({}, { unknowns: 'allow' }), - }); + await this.request( + { + method: 'POST', + url: this.urls.comment.replace('{inc_id}', incidentId), + data: { text: { format: 'text', content: comment } }, + headers: this.getAuthHeaders(), + responseSchema: schema.object({}, { unknowns: 'allow' }), + }, + connectorUsageCollector + ); } catch (error) { throw new Error( getErrorMessage( @@ -239,17 +255,23 @@ export class ResilientConnector extends CaseConnector< } } - public async getIncident({ id }: { id: string }): Promise { + public async getIncident( + { id }: { id: string }, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { try { - const res = await this.request({ - method: 'GET', - url: `${this.urls.incident}/${id}`, - params: { - text_content_output_format: 'objects_convert', + const res = await this.request( + { + method: 'GET', + url: `${this.urls.incident}/${id}`, + params: { + text_content_output_format: 'objects_convert', + }, + headers: this.getAuthHeaders(), + responseSchema: GetIncidentResponseSchema, }, - headers: this.getAuthHeaders(), - responseSchema: GetIncidentResponseSchema, - }); + connectorUsageCollector + ); return res.data; } catch (error) { @@ -259,14 +281,20 @@ export class ResilientConnector extends CaseConnector< } } - public async getIncidentTypes(): Promise { + public async getIncidentTypes( + params: unknown, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { try { - const res = await this.request({ - method: 'GET', - url: this.urls.incidentTypes, - headers: this.getAuthHeaders(), - responseSchema: GetIncidentTypesResponseSchema, - }); + const res = await this.request( + { + method: 'GET', + url: this.urls.incidentTypes, + headers: this.getAuthHeaders(), + responseSchema: GetIncidentTypesResponseSchema, + }, + connectorUsageCollector + ); const incidentTypes = res.data?.values ?? []; @@ -281,14 +309,20 @@ export class ResilientConnector extends CaseConnector< } } - public async getSeverity(): Promise { + public async getSeverity( + params: unknown, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { try { - const res = await this.request({ - method: 'GET', - url: this.urls.severity, - headers: this.getAuthHeaders(), - responseSchema: GetSeverityResponseSchema, - }); + const res = await this.request( + { + method: 'GET', + url: this.urls.severity, + headers: this.getAuthHeaders(), + responseSchema: GetSeverityResponseSchema, + }, + connectorUsageCollector + ); const severities = res.data?.values ?? []; return severities.map((type: { value: number; label: string }) => ({ @@ -302,14 +336,17 @@ export class ResilientConnector extends CaseConnector< } } - public async getFields() { + public async getFields(params: unknown, connectorUsageCollector: ConnectorUsageCollector) { try { - const res = await this.request({ - method: 'GET', - url: this.getIncidentFieldsUrl(), - headers: this.getAuthHeaders(), - responseSchema: GetCommonFieldsResponseSchema, - }); + const res = await this.request( + { + method: 'GET', + url: this.getIncidentFieldsUrl(), + headers: this.getAuthHeaders(), + responseSchema: GetCommonFieldsResponseSchema, + }, + connectorUsageCollector + ); const fields = res.data.map((field) => { return { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/sentinelone.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/sentinelone.test.ts index ced2784f057a6..8a13a48e47be1 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/sentinelone.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/sentinelone.test.ts @@ -13,12 +13,20 @@ import { } from '../../../common/sentinelone/types'; import { API_PATH } from './sentinelone'; import { SentinelOneGetActivitiesResponseSchema } from '../../../common/sentinelone/schema'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; +import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; describe('SentinelOne Connector', () => { let connectorInstance: ReturnType; + let connectorUsageCollector: ConnectorUsageCollector; + const logger = loggingSystemMock.createLogger(); beforeEach(() => { connectorInstance = sentinelOneConnectorMocks.create(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); describe('#fetchAgentFiles()', () => { @@ -35,15 +43,17 @@ describe('SentinelOne Connector', () => { it('should error if no agent id provided', async () => { fetchAgentFilesParams.agentId = ''; - await expect(connectorInstance.fetchAgentFiles(fetchAgentFilesParams)).rejects.toHaveProperty( - 'message', - "'agentId' parameter is required" - ); + await expect( + connectorInstance.fetchAgentFiles(fetchAgentFilesParams, connectorUsageCollector) + ).rejects.toHaveProperty('message', "'agentId' parameter is required"); }); it('should call SentinelOne fetch-files API with expected data', async () => { const fetchFilesUrl = `${connectorInstance.constructorParams.config.url}${API_PATH}/agents/${fetchAgentFilesParams.agentId}/actions/fetch-files`; - const response = await connectorInstance.fetchAgentFiles(fetchAgentFilesParams); + const response = await connectorInstance.fetchAgentFiles( + fetchAgentFilesParams, + connectorUsageCollector + ); expect(response).toEqual({ data: { success: true }, errors: null }); expect(connectorInstance.requestSpy).toHaveBeenLastCalledWith({ @@ -76,14 +86,14 @@ describe('SentinelOne Connector', () => { it('should error if called with invalid agent id', async () => { downloadAgentFileParams.agentId = ''; await expect( - connectorInstance.downloadAgentFile(downloadAgentFileParams) + connectorInstance.downloadAgentFile(downloadAgentFileParams, connectorUsageCollector) ).rejects.toHaveProperty('message', "'agentId' parameter is required"); }); it('should call SentinelOne api with expected url', async () => { - await expect(connectorInstance.downloadAgentFile(downloadAgentFileParams)).resolves.toEqual( - connectorInstance.mockResponses.downloadAgentFileApiResponse - ); + await expect( + connectorInstance.downloadAgentFile(downloadAgentFileParams, connectorUsageCollector) + ).resolves.toEqual(connectorInstance.mockResponses.downloadAgentFileApiResponse); }); }); @@ -122,7 +132,10 @@ describe('SentinelOne Connector', () => { describe('#downloadRemoteScriptResults()', () => { it('should call SentinelOne api to retrieve task results', async () => { - await connectorInstance.downloadRemoteScriptResults({ taskId: 'task-123' }); + await connectorInstance.downloadRemoteScriptResults( + { taskId: 'task-123' }, + connectorUsageCollector + ); expect(connectorInstance.requestSpy).toHaveBeenCalledWith( expect.objectContaining({ @@ -136,13 +149,19 @@ describe('SentinelOne Connector', () => { connectorInstance.mockResponses.getRemoteScriptResults.data.download_links = []; await expect( - connectorInstance.downloadRemoteScriptResults({ taskId: 'task-123' }) + connectorInstance.downloadRemoteScriptResults( + { taskId: 'task-123' }, + connectorUsageCollector + ) ).rejects.toThrow('Download URL for script results of task id [task-123] not found'); }); it('should return a Stream for downloading the file', async () => { await expect( - connectorInstance.downloadRemoteScriptResults({ taskId: 'task-123' }) + connectorInstance.downloadRemoteScriptResults( + { taskId: 'task-123' }, + connectorUsageCollector + ) ).resolves.toEqual(connectorInstance.mockResponses.downloadRemoteScriptResults); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/sentinelone.ts b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/sentinelone.ts index 99f486b44a087..dd73bafae8d2f 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/sentinelone.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/sentinelone/sentinelone.ts @@ -8,6 +8,7 @@ import { ServiceParams, SubActionConnector } from '@kbn/actions-plugin/server'; import type { AxiosError } from 'axios'; import { SubActionRequestParams } from '@kbn/actions-plugin/server/sub_action_framework/types'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { Stream } from 'stream'; import type { SentinelOneConfig, @@ -157,67 +158,94 @@ export class SentinelOneConnector extends SubActionConnector< }); } - public async fetchAgentFiles({ files, agentId, zipPassCode }: SentinelOneFetchAgentFilesParams) { + public async fetchAgentFiles( + { files, agentId, zipPassCode }: SentinelOneFetchAgentFilesParams, + connectorUsageCollector: ConnectorUsageCollector + ) { if (!agentId) { throw new Error(`'agentId' parameter is required`); } - return this.sentinelOneApiRequest({ - url: `${this.urls.agents}/${agentId}/actions/fetch-files`, - method: 'post', - data: { + return this.sentinelOneApiRequest( + { + url: `${this.urls.agents}/${agentId}/actions/fetch-files`, + method: 'post', data: { - password: zipPassCode, - files, + data: { + password: zipPassCode, + files, + }, }, + responseSchema: SentinelOneFetchAgentFilesResponseSchema, }, - responseSchema: SentinelOneFetchAgentFilesResponseSchema, - }); + connectorUsageCollector + ); } - public async downloadAgentFile({ agentId, activityId }: SentinelOneDownloadAgentFileParams) { + public async downloadAgentFile( + { agentId, activityId }: SentinelOneDownloadAgentFileParams, + connectorUsageCollector: ConnectorUsageCollector + ) { if (!agentId) { throw new Error(`'agentId' parameter is required`); } - return this.sentinelOneApiRequest({ - url: `${this.urls.agents}/${agentId}/uploads/${activityId}`, - method: 'get', - responseType: 'stream', - responseSchema: SentinelOneDownloadAgentFileResponseSchema, - }); + return this.sentinelOneApiRequest( + { + url: `${this.urls.agents}/${agentId}/uploads/${activityId}`, + method: 'get', + responseType: 'stream', + responseSchema: SentinelOneDownloadAgentFileResponseSchema, + }, + connectorUsageCollector + ); } - public async getActivities(queryParams?: SentinelOneGetActivitiesParams) { - return this.sentinelOneApiRequest({ - url: this.urls.activities, - method: 'get', - params: queryParams, - responseSchema: SentinelOneGetActivitiesResponseSchema, - }); + public async getActivities( + queryParams?: SentinelOneGetActivitiesParams, + connectorUsageCollector?: ConnectorUsageCollector + ) { + return this.sentinelOneApiRequest( + { + url: this.urls.activities, + method: 'get', + params: queryParams, + responseSchema: SentinelOneGetActivitiesResponseSchema, + }, + connectorUsageCollector! + ); } - public async executeScript({ filter, script }: SentinelOneExecuteScriptParams) { + public async executeScript( + { filter, script }: SentinelOneExecuteScriptParams, + connectorUsageCollector: ConnectorUsageCollector + ) { if (!filter.ids && !filter.uuids) { throw new Error(`A filter must be defined; either 'ids' or 'uuids'`); } - return this.sentinelOneApiRequest({ - url: this.urls.remoteScriptsExecute, - method: 'post', - data: { + return this.sentinelOneApiRequest( + { + url: this.urls.remoteScriptsExecute, + method: 'post', data: { - outputDestination: 'SentinelCloud', - ...script, + data: { + outputDestination: 'SentinelCloud', + ...script, + }, + filter, }, - filter, + responseSchema: SentinelOneExecuteScriptResponseSchema, }, - responseSchema: SentinelOneExecuteScriptResponseSchema, - }); + connectorUsageCollector + ); } - public async isolateHost({ alertIds, ...payload }: SentinelOneIsolateHostParams) { - const response = await this.getAgents(payload); + public async isolateHost( + { alertIds, ...payload }: SentinelOneIsolateHostParams, + connectorUsageCollector: ConnectorUsageCollector + ) { + const response = await this.getAgents(payload, connectorUsageCollector); if (response.data.length === 0) { const errorMessage = 'No agents found'; @@ -233,20 +261,26 @@ export class SentinelOneConnector extends SubActionConnector< const agentId = response.data[0].id; - return this.sentinelOneApiRequest({ - url: this.urls.isolateHost, - method: 'post', - data: { - filter: { - ids: agentId, + return this.sentinelOneApiRequest( + { + url: this.urls.isolateHost, + method: 'post', + data: { + filter: { + ids: agentId, + }, }, + responseSchema: SentinelOneIsolateHostResponseSchema, }, - responseSchema: SentinelOneIsolateHostResponseSchema, - }); + connectorUsageCollector + ); } - public async releaseHost({ alertIds, ...payload }: SentinelOneIsolateHostParams) { - const response = await this.getAgents(payload); + public async releaseHost( + { alertIds, ...payload }: SentinelOneIsolateHostParams, + connectorUsageCollector: ConnectorUsageCollector + ) { + const response = await this.getAgents(payload, connectorUsageCollector); if (response.data.length === 0) { throw new Error('No agents found'); @@ -258,57 +292,76 @@ export class SentinelOneConnector extends SubActionConnector< const agentId = response.data[0].id; - return this.sentinelOneApiRequest({ - url: this.urls.releaseHost, - method: 'post', - data: { - filter: { - ids: agentId, + return this.sentinelOneApiRequest( + { + url: this.urls.releaseHost, + method: 'post', + data: { + filter: { + ids: agentId, + }, }, + responseSchema: SentinelOneIsolateHostResponseSchema, }, - responseSchema: SentinelOneIsolateHostResponseSchema, - }); + connectorUsageCollector + ); } public async getAgents( - payload: SentinelOneGetAgentsParams + payload: SentinelOneGetAgentsParams, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - return this.sentinelOneApiRequest({ - url: this.urls.agents, - params: { - ...payload, + return this.sentinelOneApiRequest( + { + url: this.urls.agents, + params: { + ...payload, + }, + responseSchema: SentinelOneGetAgentsResponseSchema, }, - responseSchema: SentinelOneGetAgentsResponseSchema, - }); + connectorUsageCollector + ); } public async getRemoteScriptStatus( - payload: SentinelOneGetRemoteScriptStatusParams + payload: SentinelOneGetRemoteScriptStatusParams, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - return this.sentinelOneApiRequest({ - url: this.urls.remoteScriptStatus, - params: { - parent_task_id: payload.parentTaskId, + return this.sentinelOneApiRequest( + { + url: this.urls.remoteScriptStatus, + params: { + parent_task_id: payload.parentTaskId, + }, + responseSchema: SentinelOneGetRemoteScriptStatusResponseSchema, }, - responseSchema: SentinelOneGetRemoteScriptStatusResponseSchema, - }) as unknown as SentinelOneGetRemoteScriptStatusApiResponse; + connectorUsageCollector + ) as unknown as SentinelOneGetRemoteScriptStatusApiResponse; } - public async getRemoteScriptResults({ - taskIds, - }: SentinelOneGetRemoteScriptResultsParams): Promise { - return this.sentinelOneApiRequest({ - url: this.urls.remoteScriptsResults, - method: 'post', - data: { data: { taskIds } }, - responseSchema: SentinelOneGetRemoteScriptResultsResponseSchema, - }) as unknown as SentinelOneGetRemoteScriptResultsApiResponse; + public async getRemoteScriptResults( + { taskIds }: SentinelOneGetRemoteScriptResultsParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + return this.sentinelOneApiRequest( + { + url: this.urls.remoteScriptsResults, + method: 'post', + data: { data: { taskIds } }, + responseSchema: SentinelOneGetRemoteScriptResultsResponseSchema, + }, + connectorUsageCollector + ) as unknown as SentinelOneGetRemoteScriptResultsApiResponse; } - public async downloadRemoteScriptResults({ - taskId, - }: SentinelOneDownloadRemoteScriptResultsParams): Promise { - const scriptResultsInfo = await this.getRemoteScriptResults({ taskIds: [taskId] }); + public async downloadRemoteScriptResults( + { taskId }: SentinelOneDownloadRemoteScriptResultsParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const scriptResultsInfo = await this.getRemoteScriptResults( + { taskIds: [taskId] }, + connectorUsageCollector + ); this.logger.debug( () => `script results for taskId [${taskId}]:\n${JSON.stringify(scriptResultsInfo)}` @@ -327,26 +380,33 @@ export class SentinelOneConnector extends SubActionConnector< throw new Error(`Download URL for script results of task id [${taskId}] not found`); } - const downloadConnection = await this.request({ - url: fileUrl, - method: 'get', - responseType: 'stream', - responseSchema: SentinelOneDownloadRemoteScriptResultsResponseSchema, - }); + const downloadConnection = await this.request( + { + url: fileUrl, + method: 'get', + responseType: 'stream', + responseSchema: SentinelOneDownloadRemoteScriptResultsResponseSchema, + }, + connectorUsageCollector + ); return downloadConnection.data; } private async sentinelOneApiRequest( - req: SubActionRequestParams + req: SubActionRequestParams, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - const response = await this.request({ - ...req, - params: { - ...req.params, - APIToken: this.secrets.token, + const response = await this.request( + { + ...req, + params: { + ...req.params, + APIToken: this.secrets.token, + }, }, - }); + connectorUsageCollector + ); return response.data; } @@ -374,15 +434,19 @@ export class SentinelOneConnector extends SubActionConnector< } public async getRemoteScripts( - payload: SentinelOneGetRemoteScriptsParams + payload: SentinelOneGetRemoteScriptsParams, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - return this.sentinelOneApiRequest({ - url: this.urls.remoteScripts, - params: { - limit: API_MAX_RESULTS, - ...payload, + return this.sentinelOneApiRequest( + { + url: this.urls.remoteScripts, + params: { + limit: API_MAX_RESULTS, + ...payload, + }, + responseSchema: SentinelOneGetRemoteScriptsResponseSchema, }, - responseSchema: SentinelOneGetRemoteScriptsResponseSchema, - }); + connectorUsageCollector + ); } } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/server_log/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/server_log/index.test.ts index 082098023fc3f..29fd5d41adc26 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/server_log/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/server_log/index.test.ts @@ -6,6 +6,7 @@ */ import { validateParams } from '@kbn/actions-plugin/server/lib'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { Logger } from '@kbn/core/server'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { getConnectorType, ServerLogConnectorType, ServerLogConnectorTypeExecutorOptions } from '.'; @@ -107,6 +108,10 @@ describe('execute()', () => { secrets: {}, configurationUtilities, logger: mockedLogger, + connectorUsageCollector: new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }), }; await connectorType.executor(executorOptions); expect(mockedLogger.info).toHaveBeenCalledWith('Server log: message text here'); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/index.ts index bbfaf902ba671..d32f52cd698ee 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/index.ts @@ -102,7 +102,15 @@ async function executorITOM( ExecutorParamsITOM > ): Promise> { - const { actionId, config, params, secrets, configurationUtilities, logger } = execOptions; + const { + actionId, + config, + params, + secrets, + configurationUtilities, + logger, + connectorUsageCollector, + } = execOptions; const { subAction, subActionParams } = params; const connectorTokenClient = execOptions.services.connectorTokenClient; const externalServiceConfig = snExternalServiceConfig[actionTypeId]; @@ -119,6 +127,7 @@ async function executorITOM( serviceConfig: externalServiceConfig, connectorTokenClient, createServiceFn: createService, + connectorUsageCollector, }); const apiAsRecord = api as unknown as Record; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/service.test.ts index 01d8ed53478ca..951c2731b526d 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/service.test.ts @@ -15,6 +15,7 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { snExternalServiceConfig } from '../lib/servicenow/config'; import { itomEventParams, serviceNowChoices } from '../lib/servicenow/mocks'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const logger = loggingSystemMock.create().get() as jest.Mocked; @@ -33,8 +34,13 @@ const configurationUtilities = actionsConfigMock.create(); describe('ServiceNow SIR service', () => { let service: ExternalServiceITOM; + let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); service = createExternalService({ credentials: { config: { apiUrl: 'https://example.com/', isOAuth: false }, @@ -44,6 +50,7 @@ describe('ServiceNow SIR service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow-itom'], axiosInstance: axios, + connectorUsageCollector, }) as ExternalServiceITOM; }); @@ -69,6 +76,7 @@ describe('ServiceNow SIR service', () => { url: 'https://example.com/api/global/em/jsonv2', method: 'post', data: { records: [itomEventParams] }, + connectorUsageCollector, }); }); }); @@ -85,6 +93,7 @@ describe('ServiceNow SIR service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_choice?sysparm_query=name=task^ORname=em_event^element=severity^language=en&sysparm_fields=label,value,dependent_value,element', + connectorUsageCollector, }); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/service.ts index e096b67de7ef4..a6ed020461194 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itom/service.ts @@ -23,6 +23,7 @@ export const createExternalService: ServiceFactory = ({ configurationUtilities, serviceConfig, axiosInstance, + connectorUsageCollector, }): ExternalServiceITOM => { const snService = createExternalServiceCommon({ credentials, @@ -30,6 +31,7 @@ export const createExternalService: ServiceFactory = ({ configurationUtilities, serviceConfig, axiosInstance, + connectorUsageCollector, }); const addEvent = async (params: ExecutorSubActionAddEventParams) => { @@ -41,6 +43,7 @@ export const createExternalService: ServiceFactory = ({ method: 'post', data: { records: [params] }, configurationUtilities, + connectorUsageCollector, }); snService.checkInstance(res); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itsm/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itsm/index.ts index 0322b0e341844..6ab6bc389ac7a 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itsm/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itsm/index.ts @@ -125,8 +125,16 @@ async function executor( ExecutorParams > ): Promise> { - const { actionId, config, params, secrets, services, configurationUtilities, logger } = - execOptions; + const { + actionId, + config, + params, + secrets, + services, + configurationUtilities, + logger, + connectorUsageCollector, + } = execOptions; const { subAction, subActionParams } = params; const connectorTokenClient = services.connectorTokenClient; const externalServiceConfig = snExternalServiceConfig[actionTypeId]; @@ -143,6 +151,7 @@ async function executor( serviceConfig: externalServiceConfig, connectorTokenClient, createServiceFn: createService, + connectorUsageCollector, }); const apiAsRecord = api as unknown as Record; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itsm/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itsm/service.test.ts index 1c068dc60489d..5590da4cbfbd6 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itsm/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_itsm/service.test.ts @@ -15,6 +15,7 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { serviceNowCommonFields, serviceNowChoices } from '../lib/servicenow/mocks'; import { snExternalServiceConfig } from '../lib/servicenow/config'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const logger = loggingSystemMock.create().get() as jest.Mocked; jest.mock('axios', () => ({ @@ -122,6 +123,7 @@ const expectImportedIncident = (update: boolean) => { configurationUtilities, url: 'https://example.com/api/x_elas2_inc_int/elastic_api/health', method: 'get', + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -135,6 +137,7 @@ const expectImportedIncident = (update: boolean) => { u_description: 'desc', ...(update ? { elastic_incident_id: '1' } : {}), }, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -143,14 +146,20 @@ const expectImportedIncident = (update: boolean) => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident/1', method: 'get', + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }; describe('ServiceNow service', () => { let service: ExternalService; + let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { jest.clearAllMocks(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); service = createExternalService({ credentials: { // The trailing slash at the end of the url is intended. @@ -162,6 +171,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow'], axiosInstance: axios, + connectorUsageCollector, }); }); @@ -177,6 +187,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow'], axiosInstance: axios, + connectorUsageCollector, }) ).toThrow(); }); @@ -217,6 +228,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow'], axiosInstance: axios, + connectorUsageCollector, }) ).toThrow(); }); @@ -381,6 +393,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow'], axiosInstance: axios, + connectorUsageCollector, }) ).toThrow(); }); @@ -408,6 +421,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/incident/1', method: 'get', + connectorUsageCollector, }); }); @@ -421,6 +435,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], table: 'sn_si_incident' }, axiosInstance: axios, + connectorUsageCollector, }); requestMock.mockImplementation(() => ({ @@ -434,6 +449,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'get', + connectorUsageCollector, }); }); @@ -487,6 +503,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow-sir'], axiosInstance: axios, + connectorUsageCollector, }); const res = await createIncident(service); @@ -497,6 +514,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/x_elas2_sir_int/elastic_api/health', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -506,6 +524,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/import/x_elas2_sir_int_elastic_si_incident', method: 'post', data: { u_short_description: 'title', u_description: 'desc' }, + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -514,6 +533,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'get', + connectorUsageCollector, }); expect(res.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -572,6 +592,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); }); @@ -596,6 +617,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/v2/table/incident', method: 'post', data: { short_description: 'title', description: 'desc' }, + connectorUsageCollector, }); }); @@ -609,6 +631,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow-sir'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); mockIncidentResponse(false); @@ -624,6 +647,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/v2/table/sn_si_incident', method: 'post', data: { short_description: 'title', description: 'desc' }, + connectorUsageCollector, }); expect(res.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -660,6 +684,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow-sir'], axiosInstance: axios, + connectorUsageCollector, }); const res = await updateIncident(service); @@ -669,6 +694,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/x_elas2_sir_int/elastic_api/health', method: 'get', + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(2, { @@ -678,6 +704,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/import/x_elas2_sir_int_elastic_si_incident', method: 'post', data: { u_short_description: 'title', u_description: 'desc', elastic_incident_id: '1' }, + connectorUsageCollector, }); expect(requestMock).toHaveBeenNthCalledWith(3, { @@ -686,6 +713,7 @@ describe('ServiceNow service', () => { configurationUtilities, url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'get', + connectorUsageCollector, }); expect(res.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -747,6 +775,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); }); @@ -772,6 +801,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/v2/table/incident/1', method: 'patch', data: { short_description: 'title', description: 'desc' }, + connectorUsageCollector, }); }); @@ -785,6 +815,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow-sir'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); mockIncidentResponse(false); @@ -801,6 +832,7 @@ describe('ServiceNow service', () => { url: 'https://example.com/api/now/v2/table/sn_si_incident/1', method: 'patch', data: { short_description: 'title', description: 'desc' }, + connectorUsageCollector, }); expect(res.url).toEqual('https://example.com/nav_to.do?uri=sn_si_incident.do?sys_id=1'); @@ -820,6 +852,7 @@ describe('ServiceNow service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_dictionary?sysparm_query=name=task^ORname=incident^internal_type=string&active=true&array=false&read_only=false&sysparm_fields=max_length,element,column_label,mandatory', + connectorUsageCollector, }); }); @@ -841,6 +874,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], table: 'sn_si_incident' }, axiosInstance: axios, + connectorUsageCollector, }); requestMock.mockImplementation(() => ({ @@ -853,6 +887,7 @@ describe('ServiceNow service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_dictionary?sysparm_query=name=task^ORname=sn_si_incident^internal_type=string&active=true&array=false&read_only=false&sysparm_fields=max_length,element,column_label,mandatory', + connectorUsageCollector, }); }); @@ -889,6 +924,7 @@ describe('ServiceNow service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_choice?sysparm_query=name=task^ORname=incident^element=priority^ORelement=category^language=en&sysparm_fields=label,value,dependent_value,element', + connectorUsageCollector, }); }); @@ -910,6 +946,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], table: 'sn_si_incident' }, axiosInstance: axios, + connectorUsageCollector, }); requestMock.mockImplementation(() => ({ @@ -923,6 +960,7 @@ describe('ServiceNow service', () => { logger, configurationUtilities, url: 'https://example.com/api/now/table/sys_choice?sysparm_query=name=task^ORname=sn_si_incident^element=priority^ORelement=category^language=en&sysparm_fields=label,value,dependent_value,element', + connectorUsageCollector, }); }); @@ -1015,6 +1053,7 @@ describe('ServiceNow service', () => { configurationUtilities, serviceConfig: { ...snExternalServiceConfig['.servicenow'], useImportAPI: false }, axiosInstance: axios, + connectorUsageCollector, }); await service.checkIfApplicationIsInstalled(); expect(requestMock).not.toHaveBeenCalled(); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/index.ts index d564d6bc79d62..8d842c6e6fccf 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/index.ts @@ -116,8 +116,16 @@ async function executor( ExecutorParams > ): Promise> { - const { actionId, config, params, secrets, services, configurationUtilities, logger } = - execOptions; + const { + actionId, + config, + params, + secrets, + services, + configurationUtilities, + logger, + connectorUsageCollector, + } = execOptions; const { subAction, subActionParams } = params; const connectorTokenClient = services.connectorTokenClient; const externalServiceConfig = snExternalServiceConfig[actionTypeId]; @@ -134,6 +142,7 @@ async function executor( serviceConfig: externalServiceConfig, connectorTokenClient, createServiceFn: createService, + connectorUsageCollector, }); const apiAsRecord = api as unknown as Record; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/service.test.ts index 97a0570eb50db..91eb7e4dcd7af 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/service.test.ts @@ -15,6 +15,7 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { observables } from '../lib/servicenow/mocks'; import { snExternalServiceConfig } from '../lib/servicenow/config'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const logger = loggingSystemMock.create().get() as jest.Mocked; @@ -31,6 +32,7 @@ jest.mock('@kbn/actions-plugin/server/lib/axios_utils', () => { axios.create = jest.fn(() => axios); const requestMock = utils.request as jest.Mock; const configurationUtilities = actionsConfigMock.create(); +let connectorUsageCollector: ConnectorUsageCollector; const mockApplicationVersion = () => requestMock.mockImplementationOnce(() => ({ @@ -70,6 +72,7 @@ const expectAddObservables = (single: boolean) => { configurationUtilities, url: 'https://example.com/api/x_elas2_sir_int/elastic_api/health', method: 'get', + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); const url = single @@ -85,6 +88,7 @@ const expectAddObservables = (single: boolean) => { url, method: 'post', data, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }); }; @@ -92,6 +96,10 @@ describe('ServiceNow SIR service', () => { let service: ExternalServiceSIR; beforeEach(() => { + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); service = createExternalService({ credentials: { config: { apiUrl: 'https://example.com/', isOAuth: false }, @@ -101,6 +109,7 @@ describe('ServiceNow SIR service', () => { configurationUtilities, serviceConfig: snExternalServiceConfig['.servicenow-sir'], axiosInstance: axios, + connectorUsageCollector, }) as ExternalServiceSIR; }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/service.ts index 69836a5b95e29..8fc7249c1d6a1 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/servicenow_sir/service.ts @@ -28,6 +28,7 @@ export const createExternalService: ServiceFactory = ({ configurationUtilities, serviceConfig, axiosInstance, + connectorUsageCollector, }): ExternalServiceSIR => { const snService = createExternalServiceCommon({ credentials, @@ -35,6 +36,7 @@ export const createExternalService: ServiceFactory = ({ configurationUtilities, serviceConfig, axiosInstance, + connectorUsageCollector, }); const _addObservable = async (data: Observable | Observable[], url: string) => { @@ -47,6 +49,7 @@ export const createExternalService: ServiceFactory = ({ method: 'post', data, configurationUtilities, + connectorUsageCollector, }); snService.checkInstance(res); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/slack/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/slack/index.test.ts index 3f6203b725913..7d897ce5a3b77 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/slack/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/slack/index.test.ts @@ -9,6 +9,7 @@ import { Logger } from '@kbn/core/server'; import { Services, ActionTypeExecutorResult as ConnectorTypeExecutorResult, + ConnectorUsageCollector, } from '@kbn/actions-plugin/server/types'; import { validateParams, validateSecrets } from '@kbn/actions-plugin/server/lib'; import { @@ -35,6 +36,7 @@ const mockedLogger: jest.Mocked = loggerMock.create(); let connectorType: SlackConnectorType; let configurationUtilities: jest.Mocked; +let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); @@ -43,6 +45,10 @@ beforeEach(() => { return { status: 'ok', actionId: options.actionId }; }, }); + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); }); describe('connector registration', () => { @@ -181,6 +187,7 @@ describe('execute()', () => { params: { message: 'this invocation should succeed' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); expect(response).toMatchInlineSnapshot(` Object { @@ -201,6 +208,7 @@ describe('execute()', () => { params: { message: 'failure: this invocation should fail' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }) ).rejects.toThrowErrorMatchingInlineSnapshot( `"slack mockExecutor failure: this invocation should fail"` @@ -226,6 +234,7 @@ describe('execute()', () => { params: { message: 'this invocation should succeed' }, configurationUtilities: configUtils, logger: mockedLogger, + connectorUsageCollector, }); expect(mockedLogger.debug).toHaveBeenCalledWith( 'IncomingWebhook was called with proxyUrl https://someproxyhost' @@ -252,6 +261,7 @@ describe('execute()', () => { params: { message: 'this invocation should succeed' }, configurationUtilities: configUtils, logger: mockedLogger, + connectorUsageCollector, }); expect(mockedLogger.debug).not.toHaveBeenCalledWith( 'IncomingWebhook was called with proxyUrl https://someproxyhost' @@ -278,6 +288,7 @@ describe('execute()', () => { params: { message: 'this invocation should succeed' }, configurationUtilities: configUtils, logger: mockedLogger, + connectorUsageCollector, }); expect(mockedLogger.debug).toHaveBeenCalledWith( 'IncomingWebhook was called with proxyUrl https://someproxyhost' @@ -304,6 +315,7 @@ describe('execute()', () => { params: { message: 'this invocation should succeed' }, configurationUtilities: configUtils, logger: mockedLogger, + connectorUsageCollector, }); expect(mockedLogger.debug).toHaveBeenCalledWith( 'IncomingWebhook was called with proxyUrl https://someproxyhost' @@ -330,6 +342,7 @@ describe('execute()', () => { params: { message: 'this invocation should succeed' }, configurationUtilities: configUtils, logger: mockedLogger, + connectorUsageCollector, }); expect(mockedLogger.debug).not.toHaveBeenCalledWith( 'IncomingWebhook was called with proxyUrl https://someproxyhost' diff --git a/x-pack/plugins/stack_connectors/server/connector_types/slack/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/slack/index.ts index 98573f98f2aa8..489d7c22b0286 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/slack/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/slack/index.ts @@ -139,7 +139,8 @@ function validateConnectorTypeConfig( async function slackExecutor( execOptions: SlackConnectorTypeExecutorOptions ): Promise> { - const { actionId, secrets, params, configurationUtilities, logger } = execOptions; + const { actionId, secrets, params, configurationUtilities, logger, connectorUsageCollector } = + execOptions; let result: IncomingWebhookResult; const { webhookUrl } = secrets; @@ -163,6 +164,7 @@ async function slackExecutor( const webhook = new IncomingWebhook(webhookUrl, { agent, }); + connectorUsageCollector.addRequestBodyBytes(undefined, { text: message }); result = await webhook.send(message); } catch (err) { if (err.original == null || err.original.response == null) { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/slack_api/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/slack_api/index.test.ts index 59030a71aaa05..84e5b68a41c7e 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/slack_api/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/slack_api/index.test.ts @@ -7,7 +7,7 @@ import axios from 'axios'; import { Logger } from '@kbn/core/server'; -import { Services } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, Services } from '@kbn/actions-plugin/server/types'; import { validateConfig, validateParams, validateSecrets } from '@kbn/actions-plugin/server/lib'; import { getConnectorType } from '.'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; @@ -39,10 +39,15 @@ const headers = { let connectorType: SlackApiConnectorType; let configurationUtilities: jest.Mocked; +let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); connectorType = getConnectorType(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); }); describe('connector registration', () => { @@ -198,6 +203,7 @@ describe('execute', () => { params: {} as PostMessageParams, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }) ).rejects.toThrowErrorMatchingInlineSnapshot( `"[Action][ExternalService] -> [Slack API] Unsupported subAction type undefined."` @@ -296,6 +302,7 @@ describe('execute', () => { }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); expect(requestMock).toHaveBeenCalledWith({ @@ -306,6 +313,7 @@ describe('execute', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'general', text: 'some text' }, + connectorUsageCollector, }); expect(response).toEqual({ @@ -386,6 +394,7 @@ describe('execute', () => { }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); expect(requestMock).toHaveBeenCalledWith({ @@ -396,6 +405,7 @@ describe('execute', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'LKJHGF345', text: 'some text' }, + connectorUsageCollector, }); expect(response).toEqual({ @@ -476,6 +486,7 @@ describe('execute', () => { }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); expect(requestMock).toHaveBeenCalledWith({ @@ -486,6 +497,7 @@ describe('execute', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'LKJHGF345', blocks: testBlock.blocks }, + connectorUsageCollector, }); expect(response).toEqual({ @@ -525,6 +537,7 @@ describe('execute', () => { }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); expect(requestMock).toHaveBeenCalledWith({ @@ -534,6 +547,7 @@ describe('execute', () => { logger: mockedLogger, method: 'get', url: 'https://slack.com/api/conversations.info?channel=ZXCVBNM567', + connectorUsageCollector, }); expect(response).toEqual({ diff --git a/x-pack/plugins/stack_connectors/server/connector_types/slack_api/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/slack_api/index.ts index 35e85e98e6645..b816a1b014678 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/slack_api/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/slack_api/index.ts @@ -107,6 +107,7 @@ const slackApiExecutor = async ({ secrets, configurationUtilities, logger, + connectorUsageCollector, }: SlackApiExecutorOptions): Promise> => { const subAction = params.subAction; @@ -128,7 +129,8 @@ const slackApiExecutor = async ({ secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); if (subAction === 'validChannelId') { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/slack_api/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/slack_api/service.test.ts index 1389d4a98e9ec..936d4006006d1 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/slack_api/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/slack_api/service.test.ts @@ -13,6 +13,7 @@ import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.moc import { createExternalService } from './service'; import { SlackApiService } from '../../../common/slack_api/types'; import { SLACK_API_CONNECTOR_ID } from '../../../common/slack_api/constants'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const logger = loggingSystemMock.create().get() as jest.Mocked; @@ -28,6 +29,7 @@ jest.mock('@kbn/actions-plugin/server/lib/axios_utils', () => { axios.create = jest.fn(() => axios); const requestMock = request as jest.Mock; const configurationUtilities = actionsConfigMock.create(); +let connectorUsageCollector: ConnectorUsageCollector; const channel = { id: 'channel_id_1', @@ -117,12 +119,17 @@ describe('Slack API service', () => { let service: SlackApiService; beforeAll(() => { + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); service = createExternalService( { secrets: { token: 'token' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); }); @@ -138,7 +145,8 @@ describe('Slack API service', () => { secrets: { token: '' }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrowErrorMatchingInlineSnapshot(`"[Action][Slack API]: Wrong configuration."`); }); @@ -172,6 +180,7 @@ describe('Slack API service', () => { configurationUtilities, method: 'get', url: 'https://slack.com/api/conversations.info?channel=channel_id_1', + connectorUsageCollector, }); }); @@ -207,6 +216,7 @@ describe('Slack API service', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'general', text: 'a message' }, + connectorUsageCollector, }); }); @@ -231,6 +241,7 @@ describe('Slack API service', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'QWEERTYU987', text: 'a message' }, + connectorUsageCollector, }); }); @@ -251,6 +262,7 @@ describe('Slack API service', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'QWEERTYU987', text: 'a message' }, + connectorUsageCollector, }); }); @@ -291,6 +303,7 @@ describe('Slack API service', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'general', blocks: testBlock.blocks }, + connectorUsageCollector, }); }); @@ -315,6 +328,7 @@ describe('Slack API service', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'QWEERTYU987', blocks: testBlock.blocks }, + connectorUsageCollector, }); }); @@ -338,6 +352,7 @@ describe('Slack API service', () => { method: 'post', url: 'https://slack.com/api/chat.postMessage', data: { channel: 'QWEERTYU987', blocks: testBlock.blocks }, + connectorUsageCollector, }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/slack_api/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/slack_api/service.ts index 28e9ee8be4b5d..7180b0982d92c 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/slack_api/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/slack_api/service.ts @@ -13,6 +13,7 @@ import { request } from '@kbn/actions-plugin/server/lib/axios_utils'; import { pipe } from 'fp-ts/lib/pipeable'; import { map, getOrElse } from 'fp-ts/lib/Option'; import type { ActionTypeExecutorResult as ConnectorTypeExecutorResult } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { SLACK_CONNECTOR_NAME } from './translations'; import type { PostMessageSubActionParams, @@ -111,7 +112,8 @@ export const createExternalService = ( secrets: { token: string }; }, logger: Logger, - configurationUtilities: ActionsConfigurationUtilities + configurationUtilities: ActionsConfigurationUtilities, + connectorUsageCollector: ConnectorUsageCollector ): SlackApiService => { const { token } = secrets; const { allowedChannels } = config || { allowedChannels: [] }; @@ -139,6 +141,7 @@ export const createExternalService = ( method: 'get', headers, url: `${SLACK_URL}conversations.info?channel=${channelId}`, + connectorUsageCollector, }); }; if (channelId.length === 0) { @@ -207,6 +210,7 @@ export const createExternalService = ( data: { channel: channelToUse, text }, headers, configurationUtilities, + connectorUsageCollector, }); return buildSlackExecutorSuccessResponse({ slackApiResponseData: result.data }); @@ -232,6 +236,7 @@ export const createExternalService = ( data: { channel: channelToUse, blocks: blockJson.blocks }, headers, configurationUtilities, + connectorUsageCollector, }); return buildSlackExecutorSuccessResponse({ slackApiResponseData: result.data }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/swimlane/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/swimlane/index.ts index d24febcccaad3..bbe53e86e068e 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/swimlane/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/swimlane/index.ts @@ -76,7 +76,15 @@ async function executor( ExecutorParams > ): Promise> { - const { actionId, config, params, secrets, configurationUtilities, logger } = execOptions; + const { + actionId, + config, + params, + secrets, + configurationUtilities, + logger, + connectorUsageCollector, + } = execOptions; const { subAction, subActionParams } = params as ExecutorParams; let data: SwimlaneExecutorResultData | null = null; @@ -86,7 +94,8 @@ async function executor( secrets, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); if (!api[subAction]) { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/swimlane/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/swimlane/service.test.ts index 1aeee9c586fd5..5c04d60bed9c1 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/swimlane/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/swimlane/service.test.ts @@ -14,6 +14,7 @@ import { request, createAxiosResponse } from '@kbn/actions-plugin/server/lib/axi import { createExternalService } from './service'; import { mappings } from './mocks'; import { ExternalService } from './types'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const logger = loggingSystemMock.create().get() as jest.Mocked; @@ -56,8 +57,13 @@ describe('Swimlane Service', () => { }; const url = config.apiUrl.slice(0, -1); + let connectorUsageCollector: ConnectorUsageCollector; beforeAll(() => { + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); service = createExternalService( { // The trailing slash at the end of the url is intended. @@ -66,7 +72,8 @@ describe('Swimlane Service', () => { secrets: { apiToken }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); }); beforeEach(() => { @@ -87,7 +94,8 @@ describe('Swimlane Service', () => { secrets: { apiToken }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -104,7 +112,8 @@ describe('Swimlane Service', () => { secrets: { apiToken }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -122,7 +131,8 @@ describe('Swimlane Service', () => { secrets: { apiToken }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ) ).toThrow(); }); @@ -138,7 +148,8 @@ describe('Swimlane Service', () => { }, }, logger, - configurationUtilities + configurationUtilities, + connectorUsageCollector ); }).toThrow(); }); @@ -191,6 +202,7 @@ describe('Swimlane Service', () => { url: `${url}/api/app/${config.appId}/record`, method: 'post', configurationUtilities, + connectorUsageCollector, }); }); @@ -274,6 +286,7 @@ describe('Swimlane Service', () => { url: `${url}/api/app/${config.appId}/record/${incidentId}`, method: 'patch', configurationUtilities, + connectorUsageCollector, }); }); @@ -353,6 +366,7 @@ describe('Swimlane Service', () => { url: `${url}/api/app/${config.appId}/record/${incidentId}/${mappings.commentsConfig.id}/comment`, method: 'post', configurationUtilities, + connectorUsageCollector, }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/swimlane/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/swimlane/service.ts index 42c4b65408f21..4abe7f08de5c5 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/swimlane/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/swimlane/service.ts @@ -14,6 +14,7 @@ import { throwIfResponseIsNotValid, } from '@kbn/actions-plugin/server/lib/axios_utils'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { getBodyForEventAction } from './helpers'; import { CreateCommentParams, @@ -42,7 +43,8 @@ const createErrorMessage = (errorResponse: ResponseError | null | undefined): st export const createExternalService = ( { config, secrets }: ExternalServiceCredentials, logger: Logger, - configurationUtilities: ActionsConfigurationUtilities + configurationUtilities: ActionsConfigurationUtilities, + connectorUsageCollector: ConnectorUsageCollector ): ExternalService => { const { apiUrl: url, appId, mappings } = config as SwimlanePublicConfigurationType; const { apiToken } = secrets as SwimlaneSecretConfigurationType; @@ -92,6 +94,7 @@ export const createExternalService = ( logger, method: 'post', url: getPostRecordUrl(appId), + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -132,6 +135,7 @@ export const createExternalService = ( logger, method: 'patch', url: getPostRecordIdUrl(appId, params.incidentId), + connectorUsageCollector, }); throwIfResponseIsNotValid({ @@ -181,6 +185,7 @@ export const createExternalService = ( logger, method: 'post', url: getPostCommentUrl(appId, incidentId, fieldId), + connectorUsageCollector, }); /** diff --git a/x-pack/plugins/stack_connectors/server/connector_types/teams/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/teams/index.test.ts index 0b144bceb05c7..6b1b0cf105d9d 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/teams/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/teams/index.test.ts @@ -6,7 +6,7 @@ */ import { Logger } from '@kbn/core/server'; -import { Services } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, Services } from '@kbn/actions-plugin/server/types'; import { validateParams, validateSecrets } from '@kbn/actions-plugin/server/lib'; import axios from 'axios'; import { getConnectorType, TeamsConnectorType, ConnectorTypeId } from '.'; @@ -34,10 +34,15 @@ const mockedLogger: jest.Mocked = loggerMock.create(); let connectorType: TeamsConnectorType; let configurationUtilities: jest.Mocked; +let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); connectorType = getConnectorType(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); }); describe('connector registration', () => { @@ -167,11 +172,42 @@ describe('execute()', () => { params: { message: 'this invocation should succeed' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); delete requestMock.mock.calls[0][0].configurationUtilities; expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "axios": undefined, + "connectorUsageCollector": ConnectorUsageCollector { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction] { + "calls": Array [ + Array [ + "response from teams action \\"some-id\\": [HTTP 200] ", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], + }, + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, "data": Object { "text": "this invocation should succeed", }, @@ -223,11 +259,42 @@ describe('execute()', () => { params: { message: 'this invocation should succeed' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); delete requestMock.mock.calls[0][0].configurationUtilities; expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "axios": undefined, + "connectorUsageCollector": ConnectorUsageCollector { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction] { + "calls": Array [ + Array [ + "response from teams action \\"some-id\\": [HTTP 200] ", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], + }, + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, "data": Object { "text": "this invocation should succeed", }, diff --git a/x-pack/plugins/stack_connectors/server/connector_types/teams/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/teams/index.ts index 84aa7449725c8..9ab0fe4d428d7 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/teams/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/teams/index.ts @@ -119,7 +119,8 @@ function validateConnectorTypeConfig( async function teamsExecutor( execOptions: TeamsConnectorTypeExecutorOptions ): Promise> { - const { actionId, secrets, params, configurationUtilities, logger } = execOptions; + const { actionId, secrets, params, configurationUtilities, logger, connectorUsageCollector } = + execOptions; const { webhookUrl } = secrets; const { message } = params; const data = { text: message }; @@ -134,6 +135,7 @@ async function teamsExecutor( logger, data, configurationUtilities, + connectorUsageCollector, }) ); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/thehive/thehive.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/thehive/thehive.test.ts index 6218d48ae33fa..5972d5da570ef 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/thehive/thehive.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/thehive/thehive.test.ts @@ -18,17 +18,20 @@ import { PushToServiceIncidentSchema, } from '../../../common/thehive/schema'; import type { ExecutorSubActionCreateAlertParams, Incident } from '../../../common/thehive/types'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const mockTime = new Date('2024-04-03T09:10:30.000'); describe('TheHiveConnector', () => { + const logger = loggingSystemMock.createLogger(); + const connector = new TheHiveConnector( { configurationUtilities: actionsConfigMock.create(), connector: { id: '1', type: THEHIVE_CONNECTOR_ID }, config: { url: 'https://example.com', organisation: null }, secrets: { apiKey: 'test123' }, - logger: loggingSystemMock.createLogger(), + logger, services: actionsMock.createServices(), }, PushToServiceIncidentSchema @@ -36,6 +39,7 @@ describe('TheHiveConnector', () => { let mockRequest: jest.Mock; let mockError: jest.Mock; + let connectorUsageCollector: ConnectorUsageCollector; beforeAll(() => { jest.useFakeTimers(); @@ -51,6 +55,10 @@ describe('TheHiveConnector', () => { throw new Error('API Error'); }); jest.clearAllMocks(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); describe('createIncident', () => { @@ -124,18 +132,21 @@ describe('TheHiveConnector', () => { }; it('TheHive API call is successful with correct parameters', async () => { - const response = await connector.createIncident(incident); + const response = await connector.createIncident(incident, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://example.com/api/v1/case', - method: 'post', - responseSchema: TheHiveIncidentResponseSchema, - data: incident, - headers: { - Authorization: 'Bearer test123', - 'X-Organisation': null, + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://example.com/api/v1/case', + method: 'post', + responseSchema: TheHiveIncidentResponseSchema, + data: incident, + headers: { + Authorization: 'Bearer test123', + 'X-Organisation': null, + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual({ id: '~172064', url: 'https://example.com/cases/~172064/details', @@ -148,7 +159,9 @@ describe('TheHiveConnector', () => { // @ts-ignore connector.request = mockError; - await expect(connector.createIncident(incident)).rejects.toThrow('API Error'); + await expect(connector.createIncident(incident, connectorUsageCollector)).rejects.toThrow( + 'API Error' + ); }); }); @@ -173,18 +186,24 @@ describe('TheHiveConnector', () => { }; it('TheHive API call is successful with correct parameters', async () => { - const response = await connector.updateIncident({ incidentId: '~172064', incident }); + const response = await connector.updateIncident( + { incidentId: '~172064', incident }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://example.com/api/v1/case/~172064', - method: 'patch', - responseSchema: TheHiveUpdateIncidentResponseSchema, - data: incident, - headers: { - Authorization: 'Bearer test123', - 'X-Organisation': null, + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://example.com/api/v1/case/~172064', + method: 'patch', + responseSchema: TheHiveUpdateIncidentResponseSchema, + data: incident, + headers: { + Authorization: 'Bearer test123', + 'X-Organisation': null, + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual({ id: '~172064', url: 'https://example.com/cases/~172064/details', @@ -197,9 +216,9 @@ describe('TheHiveConnector', () => { // @ts-ignore connector.request = mockError; - await expect(connector.updateIncident({ incidentId: '~172064', incident })).rejects.toThrow( - 'API Error' - ); + await expect( + connector.updateIncident({ incidentId: '~172064', incident }, connectorUsageCollector) + ).rejects.toThrow('API Error'); }); }); @@ -224,21 +243,27 @@ describe('TheHiveConnector', () => { }); it('TheHive API call is successful with correct parameters', async () => { - await connector.addComment({ - incidentId: '~172064', - comment: 'test comment', - }); + await connector.addComment( + { + incidentId: '~172064', + comment: 'test comment', + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://example.com/api/v1/case/~172064/comment', - method: 'post', - responseSchema: TheHiveAddCommentResponseSchema, - data: { message: 'test comment' }, - headers: { - Authorization: 'Bearer test123', - 'X-Organisation': null, + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://example.com/api/v1/case/~172064/comment', + method: 'post', + responseSchema: TheHiveAddCommentResponseSchema, + data: { message: 'test comment' }, + headers: { + Authorization: 'Bearer test123', + 'X-Organisation': null, + }, }, - }); + connectorUsageCollector + ); }); it('errors during API calls are properly handled', async () => { @@ -246,7 +271,10 @@ describe('TheHiveConnector', () => { connector.request = mockError; await expect( - connector.addComment({ incidentId: '~172064', comment: 'test comment' }) + connector.addComment( + { incidentId: '~172064', comment: 'test comment' }, + connectorUsageCollector + ) ).rejects.toThrow('API Error'); }); }); @@ -314,16 +342,19 @@ describe('TheHiveConnector', () => { }); it('TheHive API call is successful with correct parameters', async () => { - const response = await connector.getIncident({ id: '~172064' }); + const response = await connector.getIncident({ id: '~172064' }, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://example.com/api/v1/case/~172064', - responseSchema: TheHiveIncidentResponseSchema, - headers: { - Authorization: 'Bearer test123', - 'X-Organisation': null, + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://example.com/api/v1/case/~172064', + responseSchema: TheHiveIncidentResponseSchema, + headers: { + Authorization: 'Bearer test123', + 'X-Organisation': null, + }, }, - }); + connectorUsageCollector + ); expect(response).toEqual(mockResponse.data); }); @@ -331,7 +362,9 @@ describe('TheHiveConnector', () => { // @ts-ignore connector.request = mockError; - await expect(connector.getIncident({ id: '~172064' })).rejects.toThrow('API Error'); + await expect( + connector.getIncident({ id: '~172064' }, connectorUsageCollector) + ).rejects.toThrow('API Error'); }); }); @@ -385,25 +418,30 @@ describe('TheHiveConnector', () => { }; it('TheHive API call is successful with correct parameters', async () => { - await connector.createAlert(alert); + await connector.createAlert(alert, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); - expect(mockRequest).toHaveBeenCalledWith({ - url: 'https://example.com/api/v1/alert', - method: 'post', - responseSchema: TheHiveCreateAlertResponseSchema, - data: alert, - headers: { - Authorization: 'Bearer test123', - 'X-Organisation': null, + expect(mockRequest).toHaveBeenCalledWith( + { + url: 'https://example.com/api/v1/alert', + method: 'post', + responseSchema: TheHiveCreateAlertResponseSchema, + data: alert, + headers: { + Authorization: 'Bearer test123', + 'X-Organisation': null, + }, }, - }); + connectorUsageCollector + ); }); it('errors during API calls are properly handled', async () => { // @ts-ignore connector.request = mockError; - await expect(connector.createAlert(alert)).rejects.toThrow('API Error'); + await expect(connector.createAlert(alert, connectorUsageCollector)).rejects.toThrow( + 'API Error' + ); }); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/thehive/thehive.ts b/x-pack/plugins/stack_connectors/server/connector_types/thehive/thehive.ts index fe0caf8788f28..623a9b8ee73d7 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/thehive/thehive.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/thehive/thehive.ts @@ -8,6 +8,7 @@ import { ServiceParams, CaseConnector } from '@kbn/actions-plugin/server'; import type { AxiosError } from 'axios'; import { Type } from '@kbn/config-schema'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { SUB_ACTION } from '../../../common/thehive/constants'; import { TheHiveIncidentResponseSchema, @@ -68,14 +69,20 @@ export class TheHiveConnector extends CaseConnector< return `API Error: ${error.response?.data?.type} - ${error.response?.data?.message}`; } - public async createIncident(incident: Incident): Promise { - const res = await this.request({ - method: 'post', - url: `${this.url}/api/${API_VERSION}/case`, - data: incident, - headers: this.getAuthHeaders(), - responseSchema: TheHiveIncidentResponseSchema, - }); + public async createIncident( + incident: Incident, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const res = await this.request( + { + method: 'post', + url: `${this.url}/api/${API_VERSION}/case`, + data: incident, + headers: this.getAuthHeaders(), + responseSchema: TheHiveIncidentResponseSchema, + }, + connectorUsageCollector + ); return { id: res.data._id, @@ -85,30 +92,42 @@ export class TheHiveConnector extends CaseConnector< }; } - public async addComment({ incidentId, comment }: { incidentId: string; comment: string }) { - await this.request({ - method: 'post', - url: `${this.url}/api/${API_VERSION}/case/${incidentId}/comment`, - data: { message: comment }, - headers: this.getAuthHeaders(), - responseSchema: TheHiveAddCommentResponseSchema, - }); + public async addComment( + { incidentId, comment }: { incidentId: string; comment: string }, + connectorUsageCollector: ConnectorUsageCollector + ) { + await this.request( + { + method: 'post', + url: `${this.url}/api/${API_VERSION}/case/${incidentId}/comment`, + data: { message: comment }, + headers: this.getAuthHeaders(), + responseSchema: TheHiveAddCommentResponseSchema, + }, + connectorUsageCollector + ); } - public async updateIncident({ - incidentId, - incident, - }: { - incidentId: string; - incident: Incident; - }): Promise { - await this.request({ - method: 'patch', - url: `${this.url}/api/${API_VERSION}/case/${incidentId}`, - data: incident, - headers: this.getAuthHeaders(), - responseSchema: TheHiveUpdateIncidentResponseSchema, - }); + public async updateIncident( + { + incidentId, + incident, + }: { + incidentId: string; + incident: Incident; + }, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + await this.request( + { + method: 'patch', + url: `${this.url}/api/${API_VERSION}/case/${incidentId}`, + data: incident, + headers: this.getAuthHeaders(), + responseSchema: TheHiveUpdateIncidentResponseSchema, + }, + connectorUsageCollector + ); return { id: incidentId, @@ -118,23 +137,35 @@ export class TheHiveConnector extends CaseConnector< }; } - public async getIncident({ id }: { id: string }): Promise { - const res = await this.request({ - url: `${this.url}/api/${API_VERSION}/case/${id}`, - headers: this.getAuthHeaders(), - responseSchema: TheHiveIncidentResponseSchema, - }); + public async getIncident( + { id }: { id: string }, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + const res = await this.request( + { + url: `${this.url}/api/${API_VERSION}/case/${id}`, + headers: this.getAuthHeaders(), + responseSchema: TheHiveIncidentResponseSchema, + }, + connectorUsageCollector + ); return res.data; } - public async createAlert(alert: ExecutorSubActionCreateAlertParams) { - await this.request({ - method: 'post', - url: `${this.url}/api/${API_VERSION}/alert`, - data: alert, - headers: this.getAuthHeaders(), - responseSchema: TheHiveCreateAlertResponseSchema, - }); + public async createAlert( + alert: ExecutorSubActionCreateAlertParams, + connectorUsageCollector: ConnectorUsageCollector + ) { + await this.request( + { + method: 'post', + url: `${this.url}/api/${API_VERSION}/alert`, + data: alert, + headers: this.getAuthHeaders(), + responseSchema: TheHiveCreateAlertResponseSchema, + }, + connectorUsageCollector + ); } } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.test.ts index b30a888f27998..299ac1c55bfc5 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.test.ts @@ -5,13 +5,14 @@ * 2.0. */ -import axios, { AxiosInstance } from 'axios'; +import axios, { AxiosError, AxiosInstance, AxiosResponse } from 'axios'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { TinesConnector } from './tines'; import { request } from '@kbn/actions-plugin/server/lib/axios_utils'; import { API_MAX_RESULTS, TINES_CONNECTOR_ID } from '../../../common/tines/constants'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; jest.mock('axios'); (axios as jest.Mocked).create.mockImplementation( @@ -78,6 +79,7 @@ const storiesGetRequestExpected = { 'Content-Type': 'application/json', }, params: { per_page: API_MAX_RESULTS }, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }; const agentsGetRequestExpected = { @@ -91,20 +93,28 @@ const agentsGetRequestExpected = { 'Content-Type': 'application/json', }, params: { story_id: story.id, per_page: API_MAX_RESULTS }, + connectorUsageCollector: expect.any(ConnectorUsageCollector), }; +let connectorUsageCollector: ConnectorUsageCollector; + describe('TinesConnector', () => { + const logger = loggingSystemMock.createLogger(); const connector = new TinesConnector({ configurationUtilities: actionsConfigMock.create(), config: { url }, connector: { id: '1', type: TINES_CONNECTOR_ID }, secrets: { email, token }, - logger: loggingSystemMock.createLogger(), + logger, services: actionsMock.createServices(), }); beforeEach(() => { jest.clearAllMocks(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger, + connectorId: 'test-connector-id', + }); }); describe('getStories', () => { @@ -113,13 +123,13 @@ describe('TinesConnector', () => { }); it('should request Tines stories', async () => { - await connector.getStories(); + await connector.getStories(undefined, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); expect(mockRequest).toHaveBeenCalledWith(storiesGetRequestExpected); }); it('should return the Tines stories reduced array', async () => { - const { stories } = await connector.getStories(); + const { stories } = await connector.getStories(undefined, connectorUsageCollector); expect(stories).toEqual([storyResult]); }); @@ -127,7 +137,7 @@ describe('TinesConnector', () => { mockRequest.mockReturnValueOnce({ data: { stories: [story], meta: { pages: 1 } }, }); - const response = await connector.getStories(); + const response = await connector.getStories(undefined, connectorUsageCollector); expect(response.incompleteResponse).toEqual(false); }); @@ -135,25 +145,50 @@ describe('TinesConnector', () => { mockRequest.mockReturnValueOnce({ data: { stories: [story], meta: { pages: 2 } }, }); - const response = await connector.getStories(); + const response = await connector.getStories(undefined, connectorUsageCollector); expect(response.incompleteResponse).toEqual(true); }); }); + describe('Error handling', () => { + let error: AxiosError; + + beforeEach(() => { + error = new AxiosError(); + }); + + it('should return status text api error', () => { + error.response = { status: 401, statusText: 'Unauthorized' } as AxiosResponse; + // @ts-expect-error protected method + const errorMessage = connector.getResponseErrorMessage(error); + expect(errorMessage).toEqual('API Error: Unauthorized'); + }); + + it('should return original error', () => { + error.toString = () => 'Network Error'; + // @ts-expect-error protected method + const errorMessage = connector.getResponseErrorMessage(error); + expect(errorMessage).toEqual('Network Error'); + }); + }); + describe('getWebhooks', () => { beforeAll(() => { mockRequest.mockReturnValue({ data: { agents: [webhookAgent], meta: { pages: 1 } } }); }); it('should request Tines webhook actions', async () => { - await connector.getWebhooks({ storyId: story.id }); + await connector.getWebhooks({ storyId: story.id }, connectorUsageCollector); expect(mockRequest).toBeCalledTimes(1); expect(mockRequest).toHaveBeenCalledWith(agentsGetRequestExpected); }); it('should return the Tines webhooks reduced array', async () => { - const { webhooks } = await connector.getWebhooks({ storyId: story.id }); + const { webhooks } = await connector.getWebhooks( + { storyId: story.id }, + connectorUsageCollector + ); expect(webhooks).toEqual([webhookResult]); }); @@ -161,7 +196,7 @@ describe('TinesConnector', () => { mockRequest.mockReturnValueOnce({ data: { agents: [webhookAgent], meta: { pages: 1 } }, }); - const response = await connector.getWebhooks({ storyId: story.id }); + const response = await connector.getWebhooks({ storyId: story.id }, connectorUsageCollector); expect(response.incompleteResponse).toEqual(false); }); @@ -169,7 +204,7 @@ describe('TinesConnector', () => { mockRequest.mockReturnValueOnce({ data: { agents: [webhookAgent], meta: { pages: 2 } }, }); - const response = await connector.getWebhooks({ storyId: story.id }); + const response = await connector.getWebhooks({ storyId: story.id }, connectorUsageCollector); expect(response.incompleteResponse).toEqual(true); }); }); @@ -180,10 +215,13 @@ describe('TinesConnector', () => { }); it('should send data to Tines webhook using selected webhook parameter', async () => { - await connector.runWebhook({ - webhook: webhookResult, - body: '[]', - }); + await connector.runWebhook( + { + webhook: webhookResult, + body: '[]', + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); expect(mockRequest).toHaveBeenCalledWith({ @@ -194,14 +232,18 @@ describe('TinesConnector', () => { headers: { 'Content-Type': 'application/json', }, + connectorUsageCollector, }); }); it('should send data to Tines webhook using webhook url parameter', async () => { - await connector.runWebhook({ - webhookUrl, - body: '[]', - }); + await connector.runWebhook( + { + webhookUrl, + body: '[]', + }, + connectorUsageCollector + ); expect(mockRequest).toBeCalledTimes(1); expect(mockRequest).toHaveBeenCalledWith({ @@ -212,6 +254,7 @@ describe('TinesConnector', () => { headers: { 'Content-Type': 'application/json', }, + connectorUsageCollector, }); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.ts b/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.ts index cb46a9abea3cc..f7e3f4bea1444 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/tines/tines.ts @@ -6,6 +6,7 @@ */ import { ServiceParams, SubActionConnector } from '@kbn/actions-plugin/server'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import type { AxiosError } from 'axios'; import { SubActionRequestParams } from '@kbn/actions-plugin/server/sub_action_framework/types'; import { @@ -108,12 +109,16 @@ export class TinesConnector extends SubActionConnector( req: SubActionRequestParams, - reducer: (response: R) => T + reducer: (response: R) => T, + connectorUsageCollector: ConnectorUsageCollector ): Promise { - const response = await this.request({ - ...req, - params: { ...req.params, per_page: API_MAX_RESULTS }, - }); + const response = await this.request( + { + ...req, + params: { ...req.params, per_page: API_MAX_RESULTS }, + }, + connectorUsageCollector + ); return { ...reducer(response.data), incompleteResponse: response.data.meta.pages > 1, @@ -121,29 +126,31 @@ export class TinesConnector extends SubActionConnector { + public async getStories( + params: unknown, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { return this.tinesApiRequest( { url: this.urls.stories, headers: this.getAuthHeaders(), responseSchema: TinesStoriesApiResponseSchema, }, - storiesReducer + storiesReducer, + connectorUsageCollector ); } - public async getWebhooks({ - storyId, - }: TinesWebhooksActionParams): Promise { + public async getWebhooks( + { storyId }: TinesWebhooksActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { return this.tinesApiRequest( { url: this.urls.agents, @@ -151,24 +158,27 @@ export class TinesConnector extends SubActionConnector { + public async runWebhook( + { webhook, webhookUrl, body }: TinesRunActionParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { if (!webhook && !webhookUrl) { throw Error('Invalid subActionsParams: [webhook] or [webhookUrl] expected but got none'); } - const response = await this.request({ - url: webhookUrl ? webhookUrl : this.urls.getRunWebhookURL(webhook!), - method: 'post', - responseSchema: TinesRunApiResponseSchema, - data: body, - }); + const response = await this.request( + { + url: webhookUrl ? webhookUrl : this.urls.getRunWebhookURL(webhook!), + method: 'post', + responseSchema: TinesRunApiResponseSchema, + data: body, + }, + connectorUsageCollector + ); return response.data; } } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/torq/__snapshots__/index.test.ts.snap b/x-pack/plugins/stack_connectors/server/connector_types/torq/__snapshots__/index.test.ts.snap new file mode 100644 index 0000000000000..e8260c86f3e00 --- /dev/null +++ b/x-pack/plugins/stack_connectors/server/connector_types/torq/__snapshots__/index.test.ts.snap @@ -0,0 +1,48 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`execute Torq action execute with token happy flow 1`] = ` +Object { + "axios": Any, + "connectorUsageCollector": Object { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction] { + "calls": Array [ + Array [ + "response from Torq action \\"some-id\\": [HTTP 200] ", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], + }, + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, + "data": Object { + "msg": "some data", + }, + "headers": Object { + "Content-Type": "application/json", + "X-Torq-Token": "1234", + }, + "logger": Any, + "method": "post", + "url": "https://hooks.torq.io/v1/test", + "validateStatus": Any, +} +`; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/torq/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/torq/index.test.ts index 4bf60d10eb789..39bbdd44a918d 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/torq/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/torq/index.test.ts @@ -12,6 +12,7 @@ import { ActionTypeConfigType, getActionType, TorqActionType } from '.'; import * as utils from '@kbn/actions-plugin/server/lib/axios_utils'; import { validateConfig, validateParams, validateSecrets } from '@kbn/actions-plugin/server/lib'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; import { Services } from '@kbn/actions-plugin/server/types'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; @@ -37,10 +38,15 @@ const services: Services = actionsMock.createServices(); let actionType: TorqActionType; const mockedLogger: jest.Mocked = loggerMock.create(); let configurationUtilities: jest.Mocked; +let connectorUsageCollector: ConnectorUsageCollector; beforeAll(() => { actionType = getActionType(); configurationUtilities = actionsConfigMock.create(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); }); describe('actionType', () => { @@ -171,48 +177,29 @@ describe('execute Torq action', () => { params: { body: '{"msg": "some data"}' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); delete requestMock.mock.calls[0][0].configurationUtilities; - expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` - Object { - "axios": [MockFunction], - "data": Object { - "msg": "some data", - }, - "headers": Object { - "Content-Type": "application/json", - "X-Torq-Token": "1234", + expect(requestMock.mock.calls[0][0]).toMatchSnapshot({ + axios: expect.any(Function), + connectorUsageCollector: { + usage: { + requestBodyBytes: 0, }, - "logger": Object { - "context": Array [], - "debug": [MockFunction] { - "calls": Array [ - Array [ - "response from Torq action \\"some-id\\": [HTTP 200] ", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], - }, - "error": [MockFunction], - "fatal": [MockFunction], - "get": [MockFunction], - "info": [MockFunction], - "isLevelEnabled": [MockFunction], - "log": [MockFunction], - "trace": [MockFunction], - "warn": [MockFunction], - }, - "method": "post", - "url": "https://hooks.torq.io/v1/test", - "validateStatus": [Function], - } - `); + }, + data: { + msg: 'some data', + }, + headers: { + 'Content-Type': 'application/json', + 'X-Torq-Token': '1234', + }, + logger: expect.any(Object), + method: 'post', + url: 'https://hooks.torq.io/v1/test', + validateStatus: expect.any(Function), + }); }); test('renders parameter templates as expected', async () => { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/torq/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/torq/index.ts index c3e7dc4f1533c..b60237dd7991e 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/torq/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/torq/index.ts @@ -146,6 +146,7 @@ export async function executor( const { webhookIntegrationUrl } = execOptions.config; const { body: data } = execOptions.params; const configurationUtilities = execOptions.configurationUtilities; + const connectorUsageCollector = execOptions.connectorUsageCollector; const secrets: ActionTypeSecretsType = execOptions.secrets; const token = secrets.token; @@ -171,6 +172,7 @@ export async function executor( configurationUtilities, logger: execOptions.logger, validateStatus: (status: number) => status >= 200 && status < 300, + connectorUsageCollector, }) ); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/webhook/__snapshots__/index.test.ts.snap b/x-pack/plugins/stack_connectors/server/connector_types/webhook/__snapshots__/index.test.ts.snap new file mode 100644 index 0000000000000..f52e34d90dbf0 --- /dev/null +++ b/x-pack/plugins/stack_connectors/server/connector_types/webhook/__snapshots__/index.test.ts.snap @@ -0,0 +1,46 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`execute() execute with username/password sends request with basic auth 1`] = ` +Object { + "axios": undefined, + "connectorUsageCollector": Object { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction] { + "calls": Array [ + Array [ + "response from webhook action \\"some-id\\": [HTTP 200] ", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], + }, + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, + "data": "some data", + "headers": Object { + "Authorization": "Basic YWJjOjEyMw==", + "aheader": "a value", + }, + "logger": Any, + "method": "post", + "sslOverrides": Object {}, + "url": "https://abc.def/my-webhook", +} +`; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.test.ts index 6c51fe11e97de..724daa852019f 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Services } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, Services } from '@kbn/actions-plugin/server/types'; import { validateConfig, validateParams, validateSecrets } from '@kbn/actions-plugin/server/lib'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; @@ -41,10 +41,15 @@ const mockedLogger: jest.Mocked = loggerMock.create(); let connectorType: WebhookConnectorType; let configurationUtilities: jest.Mocked; +let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); connectorType = getConnectorType(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); }); describe('connectorType', () => { @@ -339,46 +344,27 @@ describe('execute()', () => { params: { body: 'some data' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); delete requestMock.mock.calls[0][0].configurationUtilities; - expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` - Object { - "axios": undefined, - "data": "some data", - "headers": Object { - "Authorization": "Basic YWJjOjEyMw==", - "aheader": "a value", - }, - "logger": Object { - "context": Array [], - "debug": [MockFunction] { - "calls": Array [ - Array [ - "response from webhook action \\"some-id\\": [HTTP 200] ", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], - }, - "error": [MockFunction], - "fatal": [MockFunction], - "get": [MockFunction], - "info": [MockFunction], - "isLevelEnabled": [MockFunction], - "log": [MockFunction], - "trace": [MockFunction], - "warn": [MockFunction], + expect(requestMock.mock.calls[0][0]).toMatchSnapshot({ + axios: undefined, + connectorUsageCollector: { + usage: { + requestBodyBytes: 0, }, - "method": "post", - "sslOverrides": Object {}, - "url": "https://abc.def/my-webhook", - } - `); + }, + data: 'some data', + headers: { + Authorization: 'Basic YWJjOjEyMw==', + aheader: 'a value', + }, + logger: expect.any(Object), + method: 'post', + sslOverrides: {}, + url: 'https://abc.def/my-webhook', + }); }); test('execute with ssl adds ssl settings to sslOverrides', async () => { @@ -400,6 +386,7 @@ describe('execute()', () => { params: { body: 'some data' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); delete requestMock.mock.calls[0][0].configurationUtilities; @@ -407,6 +394,36 @@ describe('execute()', () => { expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "axios": undefined, + "connectorUsageCollector": ConnectorUsageCollector { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction] { + "calls": Array [ + Array [ + "response from webhook action \\"some-id\\": [HTTP 200] ", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], + }, + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, "data": "some data", "headers": Object { "aheader": "a value", @@ -588,6 +605,7 @@ describe('execute()', () => { params: { body: 'some data' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); expect(mockedLogger.error).toBeCalledWith( 'error on some-id webhook event: maxContentLength size of 1000000 exceeded' @@ -618,12 +636,43 @@ describe('execute()', () => { params: { body: 'some data' }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); delete requestMock.mock.calls[0][0].configurationUtilities; expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "axios": undefined, + "connectorUsageCollector": ConnectorUsageCollector { + "connectorId": "test-connector-id", + "logger": Object { + "context": Array [], + "debug": [MockFunction] { + "calls": Array [ + Array [ + "response from webhook action \\"some-id\\": [HTTP 200] ", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], + }, + "error": [MockFunction], + "fatal": [MockFunction], + "get": [MockFunction], + "info": [MockFunction], + "isLevelEnabled": [MockFunction], + "log": [MockFunction], + "trace": [MockFunction], + "warn": [MockFunction], + }, + "usage": Object { + "requestBodyBytes": 0, + }, + }, "data": "some data", "headers": Object { "aheader": "a value", diff --git a/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts index 78f02d24b9b87..f7c7fd4f6d61e 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts @@ -128,7 +128,8 @@ function validateConnectorTypeConfig( export async function executor( execOptions: WebhookConnectorTypeExecutorOptions ): Promise> { - const { actionId, config, params, configurationUtilities, logger } = execOptions; + const { actionId, config, params, configurationUtilities, logger, connectorUsageCollector } = + execOptions; const { method, url, headers = {}, hasAuth, authType, ca, verificationMode } = config; const { body: data } = params; @@ -159,6 +160,7 @@ export async function executor( data, configurationUtilities, sslOverrides, + connectorUsageCollector, }) ); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.test.ts index 9205c3fef91c9..b357faffc8a0b 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.test.ts @@ -14,7 +14,7 @@ import { XmattersConnectorType, } from '.'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; -import { Services } from '@kbn/actions-plugin/server/types'; +import { ConnectorUsageCollector, Services } from '@kbn/actions-plugin/server/types'; import { validateConfig, validateConnector, @@ -45,10 +45,15 @@ const mockedLogger: jest.Mocked = loggerMock.create(); let connectorType: XmattersConnectorType; let configurationUtilities: jest.Mocked; +let connectorUsageCollector: ConnectorUsageCollector; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); connectorType = getConnectorType(); + connectorUsageCollector = new ConnectorUsageCollector({ + logger: mockedLogger, + connectorId: 'test-connector-id', + }); }); describe('connectorType', () => { @@ -423,6 +428,7 @@ describe('execute()', () => { }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); const { method, url, headers, data } = requestMock.mock.calls[0][0]; @@ -472,6 +478,7 @@ describe('execute()', () => { }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); expect(mockedLogger.warn).toBeCalledWith( 'Error thrown triggering xMatters workflow: maxContentLength size of 1000000 exceeded' @@ -504,6 +511,7 @@ describe('execute()', () => { }, configurationUtilities, logger: mockedLogger, + connectorUsageCollector, }); const { method, url, headers, data } = requestMock.mock.calls[0][0]; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.ts index 880c2278ca923..ad189bda9defb 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.ts @@ -8,7 +8,7 @@ import { isString } from 'lodash'; import { i18n } from '@kbn/i18n'; import { schema, TypeOf } from '@kbn/config-schema'; -import type { +import { ActionType as ConnectorType, ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, ActionTypeExecutorResult as ConnectorTypeExecutorResult, @@ -247,7 +247,8 @@ function validateConnectorTypeSecrets( export async function executor( execOptions: XmattersConnectorTypeExecutorOptions ): Promise> { - const { actionId, configurationUtilities, config, params, logger } = execOptions; + const { actionId, configurationUtilities, config, params, logger, connectorUsageCollector } = + execOptions; const { configUrl, usesBasic } = config; const data = getPayloadForRequest(params); @@ -263,7 +264,12 @@ export async function executor( if (!url) { throw new Error('Error: no url provided'); } - result = await postXmatters({ url, data, basicAuth }, logger, configurationUtilities); + result = await postXmatters( + { url, data, basicAuth }, + logger, + configurationUtilities, + connectorUsageCollector + ); } catch (err) { const message = i18n.translate('xpack.stackConnectors.xmatters.postingErrorMessage', { defaultMessage: 'Error triggering xMatters workflow', diff --git a/x-pack/plugins/stack_connectors/server/connector_types/xmatters/post_xmatters.ts b/x-pack/plugins/stack_connectors/server/connector_types/xmatters/post_xmatters.ts index 2c2a08901cec3..215d1942c6e8a 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/xmatters/post_xmatters.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/xmatters/post_xmatters.ts @@ -10,6 +10,7 @@ import { Logger } from '@kbn/core/server'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; import { request } from '@kbn/actions-plugin/server/lib/axios_utils'; import { combineHeadersWithBasicAuthHeader } from '@kbn/actions-plugin/server/lib'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; interface PostXmattersOptions { url: string; @@ -34,7 +35,8 @@ interface PostXmattersOptions { export async function postXmatters( options: PostXmattersOptions, logger: Logger, - configurationUtilities: ActionsConfigurationUtilities + configurationUtilities: ActionsConfigurationUtilities, + connectorUsageCollector: ConnectorUsageCollector ): Promise { const { url, data, basicAuth } = options; const axiosInstance = axios.create(); @@ -50,5 +52,6 @@ export async function postXmatters( data, configurationUtilities, validateStatus: () => true, + connectorUsageCollector, }); } diff --git a/x-pack/plugins/task_manager/server/task_running/task_runner.test.ts b/x-pack/plugins/task_manager/server/task_running/task_runner.test.ts index 9274e0583547e..899586abcc9f7 100644 --- a/x-pack/plugins/task_manager/server/task_running/task_runner.test.ts +++ b/x-pack/plugins/task_manager/server/task_running/task_runner.test.ts @@ -2061,6 +2061,97 @@ describe('TaskManagerRunner', () => { ); expect(onTaskEvent).toHaveBeenCalledTimes(2); }); + + test('emits TaskEvent when failing to update a recurring task', async () => { + const id = _.random(1, 20).toString(); + const runAt = minutesFromNow(_.random(5)); + const onTaskEvent = jest.fn(); + const { runner, instance, store } = await readyToRunStageSetup({ + onTaskEvent, + instance: { + id, + schedule: { interval: '1m' }, + }, + definitions: { + bar: { + title: 'Bar!', + createTaskRunner: () => ({ + async run() { + return { runAt, state: {} }; + }, + }), + }, + }, + }); + + const error = new Error('fail'); + + store.update.mockImplementation(() => { + throw error; + }); + + await expect(runner.run()).rejects.toThrowError('fail'); + + expect(onTaskEvent).toHaveBeenCalledWith( + withAnyTiming( + asTaskRunEvent( + id, + asErr({ + task: instance, + persistence: TaskPersistence.Recurring, + result: TaskRunResult.Failed, + isExpired: false, + error, + }) + ) + ) + ); + }); + + test('emits TaskEvent when failing to update a non-recurring task', async () => { + const id = _.random(1, 20).toString(); + const runAt = minutesFromNow(_.random(5)); + const onTaskEvent = jest.fn(); + const { runner, instance, store } = await readyToRunStageSetup({ + onTaskEvent, + instance: { + id, + }, + definitions: { + bar: { + title: 'Bar!', + createTaskRunner: () => ({ + async run() { + return { runAt, state: {} }; + }, + }), + }, + }, + }); + + const error = new Error('fail'); + + store.update.mockImplementation(() => { + throw error; + }); + + await expect(runner.run()).rejects.toThrowError('fail'); + + expect(onTaskEvent).toHaveBeenCalledWith( + withAnyTiming( + asTaskRunEvent( + id, + asErr({ + task: instance, + persistence: TaskPersistence.NonRecurring, + result: TaskRunResult.Failed, + isExpired: false, + error, + }) + ) + ) + ); + }); }); test('does not update saved object if task expires', async () => { diff --git a/x-pack/plugins/task_manager/server/task_running/task_runner.ts b/x-pack/plugins/task_manager/server/task_running/task_runner.ts index 6eaaf2cd2881f..bfcabed9f6e45 100644 --- a/x-pack/plugins/task_manager/server/task_running/task_runner.ts +++ b/x-pack/plugins/task_manager/server/task_running/task_runner.ts @@ -719,40 +719,54 @@ export class TaskManagerRunner implements TaskRunner { await eitherAsync( result, async ({ runAt, schedule, taskRunError }: SuccessfulRunResult) => { - const processedResult = { - task, - persistence: - schedule || task.schedule ? TaskPersistence.Recurring : TaskPersistence.NonRecurring, - result: await (runAt || schedule || task.schedule - ? this.processResultForRecurringTask(result) - : this.processResultWhenDone()), - }; - - // Alerting task runner returns SuccessfulRunResult with taskRunError - // when the alerting task fails, so we check for this condition in order - // to emit the correct task run event for metrics collection - // taskRunError contains the "source" (TaskErrorSource) data - if (!!taskRunError) { - debugLogger.debug(`Emitting task run failed event for task ${this.taskType}`); + const taskPersistence = + schedule || task.schedule ? TaskPersistence.Recurring : TaskPersistence.NonRecurring; + try { + const processedResult = { + task, + persistence: taskPersistence, + result: await (runAt || schedule || task.schedule + ? this.processResultForRecurringTask(result) + : this.processResultWhenDone()), + }; + + // Alerting task runner returns SuccessfulRunResult with taskRunError + // when the alerting task fails, so we check for this condition in order + // to emit the correct task run event for metrics collection + // taskRunError contains the "source" (TaskErrorSource) data + if (!!taskRunError) { + debugLogger.debug(`Emitting task run failed event for task ${this.taskType}`); + this.onTaskEvent( + asTaskRunEvent( + this.id, + asErr({ ...processedResult, isExpired: taskHasExpired, error: taskRunError }), + taskTiming + ) + ); + } else { + this.onTaskEvent( + asTaskRunEvent( + this.id, + asOk({ ...processedResult, isExpired: taskHasExpired }), + taskTiming + ) + ); + } + } catch (err) { this.onTaskEvent( asTaskRunEvent( this.id, asErr({ - ...processedResult, + task, + persistence: taskPersistence, + result: TaskRunResult.Failed, isExpired: taskHasExpired, - error: taskRunError, + error: err, }), taskTiming ) ); - } else { - this.onTaskEvent( - asTaskRunEvent( - this.id, - asOk({ ...processedResult, isExpired: taskHasExpired }), - taskTiming - ) - ); + throw err; } }, async ({ error }: FailedRunResult) => { diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.ts b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.ts index dd8c83fd4f249..d9285fac81c81 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.ts @@ -68,7 +68,7 @@ export const useIndicators = ({ const { inspectorAdapters } = useInspector(); const onChangeItemsPerPage = useCallback( - (pageSize) => + (pageSize: any) => setPagination((currentPagination) => ({ ...currentPagination, pageSize, @@ -78,7 +78,7 @@ export const useIndicators = ({ ); const onChangePage = useCallback( - (pageIndex) => setPagination((currentPagination) => ({ ...currentPagination, pageIndex })), + (pageIndex: any) => setPagination((currentPagination) => ({ ...currentPagination, pageIndex })), [] ); diff --git a/x-pack/plugins/timelines/common/utils/accessibility/helpers.ts b/x-pack/plugins/timelines/common/utils/accessibility/helpers.ts index e877edd28458b..f1bedd4fc42eb 100644 --- a/x-pack/plugins/timelines/common/utils/accessibility/helpers.ts +++ b/x-pack/plugins/timelines/common/utils/accessibility/helpers.ts @@ -638,13 +638,6 @@ export const onKeyDownFocusHandler = ({ } }; -/** - * An `onFocus` event handler that focuses the first child draggable - * keyboard handler - */ -export const onFocusReFocusDraggable = (event: React.FocusEvent) => - event.target.querySelector(`.${DRAGGABLE_KEYBOARD_WRAPPER_CLASS_NAME}`)?.focus(); - /** Returns `true` when the element, or one of it's children has focus */ export const elementOrChildrenHasFocus = (element: HTMLElement | null | undefined): boolean => element === document.activeElement || element?.querySelector(':focus-within') != null; @@ -661,18 +654,6 @@ export type FocusableElement = | HTMLTextAreaElement | HTMLVideoElement; -/** - * This function has a side effect. It focuses the first element with a - * matching `className` in the `containerElement`. - */ -export const skipFocusInContainerTo = ({ - containerElement, - className, -}: { - containerElement: HTMLElement | null; - className: string; -}) => containerElement?.querySelector(`.${className}`)?.focus(); - /** * Returns a table cell's focusable children, which may be one of the following * a) a `HTMLButtonElement` that does NOT have the `disabled` attribute diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_range_form.tsx b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_range_form.tsx index 1c0cb4d35030a..ec4520ef87fd7 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_range_form.tsx +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_range_form.tsx @@ -31,7 +31,7 @@ export const FilterRangeForm: FilterAggConfigRange['aggTypeConfig']['FilterAggFo const includeTo = config?.includeTo ?? false; const updateConfig = useCallback( - (update) => { + (update: any) => { onChange({ config: { ...config, diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx index 46ecd77961617..2e52eb67ac49a 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx @@ -51,7 +51,7 @@ export const FilterTermForm: FilterAggConfigTerm['aggTypeConfig']['FilterAggForm }, []); const updateConfig = useCallback( - (update) => { + (update: any) => { onChange({ config: { ...config, diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_latest_function_config.ts b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_latest_function_config.ts index a56191f660f42..72a858231c7b3 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_latest_function_config.ts +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_latest_function_config.ts @@ -161,7 +161,7 @@ export function useLatestFunctionConfig( }, [dataView, data.search.aggs, runtimeMappings]); const updateLatestFunctionConfig = useCallback( - (update) => + (update: any) => setLatestFunctionConfig({ ...config, ...update, diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 53dcc0869d477..d34c2e6f98c5e 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -6851,13 +6851,7 @@ "securitySolutionPackages.ecsDataQualityDashboard.errors.read": "lire", "securitySolutionPackages.ecsDataQualityDashboard.errors.theFollowingPrivilegesLabel": "Les privilèges suivants sont requis pour vérifier un index :", "securitySolutionPackages.ecsDataQualityDashboard.errors.viewIndexMetadata": "view_index_metadata", - "securitySolutionPackages.ecsDataQualityDashboard.errorsPopover.copyToClipboardButton": "Copier dans le presse-papiers", - "securitySolutionPackages.ecsDataQualityDashboard.errorsPopover.errorsCalloutSummary": "La qualité des données n'a pas été vérifiée pour certains index", - "securitySolutionPackages.ecsDataQualityDashboard.errorsPopover.errorsTitle": "Erreurs", "securitySolutionPackages.ecsDataQualityDashboard.errorsPopover.viewErrorsButton": "Afficher les erreurs", - "securitySolutionPackages.ecsDataQualityDashboard.errorsViewerTable.errorColumn": "Erreur", - "securitySolutionPackages.ecsDataQualityDashboard.errorsViewerTable.indexColumn": "Index", - "securitySolutionPackages.ecsDataQualityDashboard.errorsViewerTable.patternColumn": "Modèle", "securitySolutionPackages.ecsDataQualityDashboard.fieldsLabel": "Champs", "securitySolutionPackages.ecsDataQualityDashboard.frozenDescription": "L'index n'est plus mis à jour et il est rarement interrogé. Les informations doivent toujours être interrogeables, mais il est acceptable que ces requêtes soient extrêmement lentes.", "securitySolutionPackages.ecsDataQualityDashboard.frozenPatternTooltip": "{indices} {indices, plural, =1 {L'index correspondant} other {Les index correspondants}} au modèle {pattern} {indices, plural, =1 {est} other {sont}} \"frozen\". Les index gelés ne sont plus mis à jour et sont rarement interrogés. Les informations doivent toujours être interrogeables, mais il est acceptable que ces requêtes soient extrêmement lentes.", @@ -6869,15 +6863,10 @@ "securitySolutionPackages.ecsDataQualityDashboard.ilmPhaseHot": "hot", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhaseLabel": "Phase ILM", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptBody": "La qualité des données sera vérifiée pour les index comprenant ces phases de gestion du cycle de vie des index (ILM, Index Lifecycle Management)", - "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptColdLabel": "froid", - "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptFrozenLabel": "frozen", - "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptHotLabel": "hot", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptIlmPhasesThatCanBeCheckedSubtitle": "Phases ILM dans lesquelles la qualité des données peut être vérifiée", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptIlmPhasesThatCannotBeCheckedSubtitle": "Phases ILM dans lesquelles la vérification ne peut pas être effectuée", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptITheFollowingIlmPhasesLabel": "Les phases ILM suivantes ne sont pas disponibles pour la vérification de la qualité des données, car leur accès est plus lent", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptTitle": "Sélectionner une ou plusieurs phases ILM", - "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptUnmanagedLabel": "non géré", - "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptWarmLabel": "warm", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhaseUnmanaged": "non géré", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhaseWarm": "warm", "securitySolutionPackages.ecsDataQualityDashboard.incompatibleTab.incompatibleFieldMappingsTableTitle": "Mappings de champ incompatibles – {indexName}", @@ -6899,7 +6888,6 @@ "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.custonDetectionEngineRulesWorkMessage": "✅ Les règles de moteur de détection personnalisées fonctionnent", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.detectionEngineRulesWillWorkMessage": "✅ Les règles de moteur de détection fonctionneront pour ces champs", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.detectionEngineRulesWontWorkMessage": "❌ Les règles de moteur de détection référençant ces champs ne leur correspondront peut-être pas correctement", - "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.docsLabel": "Documents", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.ecsCompliantCallout": "{fieldCount, plural, =1 {Le type de mapping d'index et les valeurs de document de ce champ sont conformes} other {Les types de mapping d'index et les valeurs de document de ces champs sont conformes}} à la version {version} d'Elastic Common Schema (ECS)", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.ecsCompliantCalloutTitle": "{fieldCount} {fieldCount, plural, =1 {Champ conforme} other {Champs conformes}} à ECS", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.ecsCompliantEmptyContent": "Aucun mapping de champ de cet index n'est conforme à Elastic Common Schema (ECS). L'index doit (au moins) contenir un champ de date @timestamp.", @@ -6914,7 +6902,6 @@ "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.incompatibleCalloutTitle": "{fieldCount} {fieldCount, plural, =1 {Champ incompatible} other {Champs incompatibles}}", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.incompatibleEmptyContent": "Tous les mappings de champs et toutes les valeurs de documents de cet index sont conformes à Elastic Common Schema (ECS).", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.incompatibleEmptyTitle": "Toutes les valeurs et tous les mappings de champs sont conformes à ECS", - "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.incompatibleFieldsTab": "Champs incompatibles", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.indexMarkdown": "Index", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.mappingThatConflictWithEcsMessage": "❌ Les mappings ou valeurs de champs qui ne sont pas conformes à ECS ne sont pas pris en charge", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.missingTimestampCallout": "Veuillez envisager d'ajouter un mapping de champ de @timestamp (date) à cet index, comme requis par Elastic Common Schema (ECS), car :", @@ -6945,7 +6932,6 @@ "securitySolutionPackages.ecsDataQualityDashboard.sameFamilyBadgeLabel": "même famille", "securitySolutionPackages.ecsDataQualityDashboard.sameFamilyTab.sameFamilyFieldMappingsTableTitle": "Mêmes familles de mappings de champ – {indexName}", "securitySolutionPackages.ecsDataQualityDashboard.securitySolutionPackages.ecsDataQualityDashboardSubtitle": "Vérifiez la compatibilité des mappings et des valeurs d'index avec", - "securitySolutionPackages.ecsDataQualityDashboard.securitySolutionPackages.ecsDataQualityDashboardTitle": "Qualité des données", "securitySolutionPackages.ecsDataQualityDashboard.selectAnIndexPrompt": "Sélectionner un index pour le comparer à la version ECS", "securitySolutionPackages.ecsDataQualityDashboard.selectOneOrMorPhasesPlaceholder": "Sélectionner une ou plusieurs phases ILM", "securitySolutionPackages.ecsDataQualityDashboard.statLabels.checkedLabel": "vérifié", @@ -6961,21 +6947,10 @@ "securitySolutionPackages.ecsDataQualityDashboard.storageTreemap.noDataLabel": "Aucune donnée à afficher", "securitySolutionPackages.ecsDataQualityDashboard.storageTreemap.noDataReasonLabel": "Le champ {stackByField1} n'était présent dans aucun groupe", "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.collapseLabel": "Réduire", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.docsColumn": "Documents", "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.expandRowsColumn": "Développer les lignes", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.failedTooltip": "Échoué", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.ilmPhaseColumn": "Phase ILM", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.incompatibleFieldsColumn": "Champs incompatibles", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indexColumn": "Index", "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indexesNameLabel": "Nom de l'index", "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indexToolTip": "Cet index correspond au nom d'index ou de modèle : {pattern}", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indicesCheckedColumn": "Index vérifiés", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indicesColumn": "Index", "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.lastCheckColumn": "Dernière vérification", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.passedTooltip": "Approuvé", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.resultColumn": "Résultat", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.sizeColumn": "Taille", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.thisIndexHasNotBeenCheckedTooltip": "Cet index n'a pas été vérifié", "securitySolutionPackages.ecsDataQualityDashboard.timestampDescriptionLabel": "Date/heure d'origine de l'événement. Il s'agit des date et heure extraites de l'événement, représentant généralement le moment auquel l'événement a été généré par la source. Si la source de l'événement ne comporte pas d'horodatage original, cette valeur est habituellement remplie la première fois que l'événement a été reçu par le pipeline. Champs requis pour tous les événements.", "securitySolutionPackages.ecsDataQualityDashboard.toasts.copiedErrorsToastTitle": "Erreurs copiées dans le presse-papiers", "securitySolutionPackages.ecsDataQualityDashboard.toasts.copiedResultsToastTitle": "Résultats copiés dans le presse-papiers", @@ -7035,6 +7010,14 @@ "securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications": "Applications de confiance", "securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications.description": "Aide à atténuer les conflits avec d'autres logiciels, généralement d'autres applications d'antivirus ou de sécurité des points de terminaison.", "securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications.privilegesTooltip": "\"Tous les espaces\" est requis pour l'accès aux applications de confiance.", + "securitySolutionPackages.flyout.right.header.collapseDetailButtonAriaLabel": "Réduire les détails", + "securitySolutionPackages.flyout.right.header.collapseDetailButtonLabel": "Réduire les détails", + "securitySolutionPackages.flyout.right.header.expandDetailButtonAriaLabel": "Développer les détails", + "securitySolutionPackages.flyout.right.header.expandDetailButtonLabel": "Développer les détails", + "securitySolutionPackages.flyout.shared.errorDescription": "Une erreur est survenue lors de l'affichage de {message}.", + "securitySolutionPackages.flyout.shared.errorTitle": "Impossible d'afficher {title}.", + "securitySolutionPackages.flyout.shared.ExpandablePanelButtonIconAriaLabel": "Activer/Désactiver le panneau extensible", + "securitySolutionPackages.flyout.shared.expandablePanelLoadingAriaLabel": "panneau extensible", "securitySolutionPackages.markdown.insight.upsell": "Passez au niveau {requiredLicense} pour pouvoir utiliser les informations des guides d'investigation", "securitySolutionPackages.markdown.investigationGuideInteractions.upsell": "Passez au niveau {requiredLicense} pour pouvoir utiliser les interactions des guides d'investigation", "securitySolutionPackages.navigation.landingLinks": "Vues de sécurité", @@ -11106,8 +11089,8 @@ "xpack.apm.serviceIcons.service": "Service", "xpack.apm.serviceIcons.serviceDetails.cloud.architecture": "Architecture", "xpack.apm.serviceIcons.serviceDetails.cloud.availabilityZoneLabel": "{zones, plural, =0 {Zone de disponibilité} one {Zone de disponibilité} other {Zones de disponibilité}} ", - "xpack.apm.serviceIcons.serviceDetails.cloud.faasTriggerTypeLabel": "{triggerTypes, plural, =0 {Type de déclencheur} one {Type de déclencheur} other {Types de déclencheurs}} ", "xpack.apm.serviceIcons.serviceDetails.cloud.functionNameLabel": "{functionNames, plural, =0 {Nom de fonction} one {Nom de fonction} other {Noms de fonction}} ", + "xpack.apm.serviceIcons.serviceDetails.cloud.faasTriggerTypeLabel": "{triggerTypes, plural, =0 {Type de déclencheur} one {Type de déclencheur} other {Types de déclencheurs}} ", "xpack.apm.serviceIcons.serviceDetails.cloud.machineTypesLabel": "{machineTypes, plural, =0{Type de machine} one {Type de machine} other {Types de machines}} ", "xpack.apm.serviceIcons.serviceDetails.cloud.projectIdLabel": "ID de projet", "xpack.apm.serviceIcons.serviceDetails.cloud.providerLabel": "Fournisseur cloud", @@ -14608,12 +14591,10 @@ "xpack.dataQuality.Initializing": "Page Initialisation de la qualité de l'ensemble de données", "xpack.dataQuality.name": "Qualité de l’ensemble de données", "xpack.datasetQuality.actionsColumnName": "Actions", - "xpack.datasetQuality.appDescription": "Surveillez la qualité du jeu de données pour les flux de données {logsPattern} suivant le {dsNamingSchemeLink}.", "xpack.datasetQuality.appDescription.dsNamingSchemeLinkText": "Schéma de dénomination du flux de données", "xpack.datasetQuality.appTitle": "Qualité de l’ensemble de données", "xpack.datasetQuality.betaBadgeDescription": "Cette fonctionnalité est actuellement en version bêta. Nous aimerions beaucoup savoir si vous avez des commentaires ou si vous rencontrez des bugs. Veuillez ouvrir un dossier d'assistance et/ou consulter notre forum de discussion.", "xpack.datasetQuality.betaBadgeLabel": "Bêta", - "xpack.datasetQuality.collapseLabel": "Réduire", "xpack.datasetQuality.datasetQualityColumnName": "Qualité de l’ensemble de données", "xpack.datasetQuality.datasetQualityColumnTooltip": "La qualité est basée sur le pourcentage de documents dégradés dans un ensemble de données. {visualQueue}", "xpack.datasetQuality.datasetQualityIdicator": "{quality}", @@ -14624,9 +14605,6 @@ "xpack.datasetQuality.emptyState.noData.title": "Aucun ensemble de données trouvé", "xpack.datasetQuality.emptyState.noPrivileges.message": "Vous ne disposez pas des autorisations requises pour voir les données de logs. Assurez-vous d'avoir les autorisations requises pour voir {datasetPattern}.", "xpack.datasetQuality.emptyState.noPrivileges.title": "Impossible de charger les ensembles de données", - "xpack.datasetQuality.expandLabel": "Développer", - "xpack.datasetQuality.fetchDatasetDetailsFailed": "Nous n'avons pas pu obtenir les détails de votre ensemble de données.", - "xpack.datasetQuality.fetchDatasetDetailsFailed.noDatasetSelected": "Vous n'avez sélectionné aucun ensemble de données", "xpack.datasetQuality.fetchDatasetStatsFailed": "Nous n'avons pas pu obtenir vos ensembles de données.", "xpack.datasetQuality.fetchDegradedStatsFailed": "Nous n'avons pas pu obtenir d'informations sur vos documents dégradés.", "xpack.datasetQuality.fetchIntegrationsFailed": "Nous n'avons pas pu obtenir vos intégrations.", @@ -14634,9 +14612,6 @@ "xpack.datasetQuality.fewDegradedDocsTooltip": "{degradedDocsCount} documents dégradés dans cet ensemble de données.", "xpack.datasetQuality.filterBar.placeholder": "Filtrer les ensembles de données", "xpack.datasetQuality.flyout.degradedDocsTitle": "Documents dégradés", - "xpack.datasetQuality.flyout.degradedField.count": "Nombre de documents", - "xpack.datasetQuality.flyout.degradedField.field": "Champ", - "xpack.datasetQuality.flyout.degradedField.lastOccurrence": "Dernière occurrence", "xpack.datasetQuality.flyout.nonAggregatable.description": "{description}", "xpack.datasetQuality.flyout.nonAggregatable.howToFixIt": "{rolloverLink} manuellement cet ensemble de données pour empêcher des délais à l'avenir.", "xpack.datasetQuality.flyout.nonAggregatable.warning": "{dataset} est incompatible avec l'agrégation _ignored, ce qui peut entraîner des délais lors de la recherche de données. {howToFixIt}", @@ -19774,7 +19749,6 @@ "xpack.fleet.createPackagePolicy.StepSelectPolicy.errorLoadingAgentPoliciesTitle": "Erreur lors du chargement des stratégies d'agent", "xpack.fleet.createPackagePolicy.StepSelectPolicy.errorLoadingPackageTitle": "Erreur lors du chargement des informations de pack", "xpack.fleet.createPackagePolicy.StepSelectPolicy.errorLoadingSelectedAgentPolicyTitle": "Erreur lors du chargement de la stratégie d'agent sélectionnée", - "xpack.fleet.createPackagePolicy.StepSelectPolicy.noPolicySelectedError": "Une stratégie d'agent est requise.", "xpack.fleet.createPackagePolicy.transformInstallWithCurrentUserPermissionCallout": "Ce package a {count, plural, one {une ressource de transformation qui sera créée et démarrée} other {# ressources de transformation qui seront créées et démarrées}} avec les mêmes rôles que l'utilisateur responsable de l'installation du package.", "xpack.fleet.createPackagePolicyBottomBar.addAnotherIntegration": "Ajouter une autre intégration", "xpack.fleet.createPackagePolicyBottomBar.backButton": "Retour", @@ -25117,7 +25091,7 @@ "xpack.lens.collapse.min": "Min.", "xpack.lens.collapse.none": "Aucun", "xpack.lens.collapse.sum": "Somme", - "xpack.lens.colorMapping.editColorMappingSectionlabel": "Mapping des couleurs", + "xpack.lens.colorMapping.editColorMappingSectionLabel": "Mapping des couleurs", "xpack.lens.colorMapping.editColorMappingTitle": "Modifier les couleurs par mapping de terme", "xpack.lens.colorMapping.editColors": "Modifier les couleurs", "xpack.lens.colorMapping.editColorsTitle": "Modifier les couleurs", @@ -25745,9 +25719,7 @@ "xpack.lens.metric.breakdownBy": "Répartir par", "xpack.lens.metric.color": "Couleur", "xpack.lens.metric.colorMode.dynamic": "Dynamique", - "xpack.lens.metric.colorMode.label": "Mode couleur", "xpack.lens.metric.colorMode.static": "Statique", - "xpack.lens.metric.dynamicColoring.label": "Mode couleur", "xpack.lens.metric.groupLabel": "Valeur d’objectif et unique", "xpack.lens.metric.headingLabel": "Valeur", "xpack.lens.metric.icon": "Décoration de l’icône", @@ -25803,7 +25775,6 @@ "xpack.lens.paletteHeatmapGradient.label": "Couleur", "xpack.lens.paletteMetricGradient.label": "Couleur", "xpack.lens.palettePicker.label": "Palette", - "xpack.lens.paletteTableGradient.label": "Couleur", "xpack.lens.pie.addLayer": "Visualisation", "xpack.lens.pie.arrayValues": "Les dimensions suivantes contiennent des valeurs de tableau : {label}. Le rendu de votre visualisation peut ne pas se présenter comme attendu.", "xpack.lens.pie.collapsedDimensionsDontCount": "(Les dimensions réduites ne sont pas concernées par cette limite.)", @@ -26991,8 +26962,8 @@ "xpack.maps.source.esSearch.descendingLabel": "décroissant", "xpack.maps.source.esSearch.extentFilterLabel": "Filtre dynamique pour les données de la zone de carte visible", "xpack.maps.source.esSearch.fieldNotFoundMsg": "Impossible de trouver \"{fieldName}\" dans le modèle d'indexation \"{indexPatternName}\".", - "xpack.maps.source.esSearch.geofieldLabel": "Champ géospatial", "xpack.maps.source.esSearch.geoFieldLabel": "Champ géospatial", + "xpack.maps.source.esSearch.geofieldLabel": "Champ géospatial", "xpack.maps.source.esSearch.geoFieldTypeLabel": "Type de champ géospatial", "xpack.maps.source.esSearch.indexOverOneLengthEditError": "Votre vue de données pointe vers plusieurs index. Un seul index est autorisé par vue de données.", "xpack.maps.source.esSearch.indexZeroLengthEditError": "Votre vue de données ne pointe vers aucun index.", @@ -33104,13 +33075,11 @@ "xpack.observabilityAiAssistantManagement.settingsPage.logIndexPatternDescription": "Modèle d'index utilisé par l'assistant d'IA lorsqu'il recherche des logs. Les logs sont classés par catégories et utilisés pour l'analyse des causes premières", "xpack.observabilityAiAssistantManagement.settingsPage.searchConnector": "Connecteurs Search", "xpack.observabilityAiAssistantManagement.settingsPage.searchConnectorIndexPatternDescription": "Modèle d'index utilisé par l’assistant d’IA lors de l'interrogation des index des connecteurs de recherche (une partie de la base de connaissances). L'index de chaque connecteur de recherche sera interrogé par défaut", - "xpack.observabilityAiAssistantManagement.settingsPage.selectYourLanguageLabel": "Sélectionnez la langue que vous souhaitez que l'assistant utilise pour générer des réponses.", "xpack.observabilityAiAssistantManagement.settingsPage.settingsLabel": "Paramètres", "xpack.observabilityAiAssistantManagement.settingsPage.showAIAssistantButtonLabel": "Afficher le bouton de l'Assistant d'IA et les informations contextuelles dans les applications d'Observability", "xpack.observabilityAiAssistantManagement.settingsPage.showAIAssistantDescriptionLabel": "Affichez/masquez le bouton de l'Assistant d'IA et les informations contextuelles dans les applications d'Observability en cochant ou en décochant la fonctionnalité Assistant d'IA dans Espaces > > Fonctionnalités.", "xpack.observabilityAiAssistantManagement.settingsPage.simulatedFunctionCallingDescription": "[version d'évaluation technique] Utilisez l'appel de fonction simulé. L’appel de fonction simulé ne nécessite pas la prise en charge de l'API pour les fonctions ou les outils, mais il peut réduire les performances. L'appel de fonction simulé est actuellement toujours activé pour les connecteurs non-OpenAI, indépendamment de ce paramètre.", "xpack.observabilityAiAssistantManagement.settingsPage.simulatedFunctionCallingLabel": "Simuler un appel de fonction", - "xpack.observabilityAiAssistantManagement.settingsPage.userPreferencesLabel": "Langue utilisée pour les réponses", "xpack.observabilityAiAssistantManagement.settingsTab.h3.logIndexPatternLabel": "Modèle d'indexation des logs", "xpack.observabilityAiAssistantManagement.settingsTab.h3.searchConnectorIndexPatternLabel": "Modèle d'indexation de connecteur de recherche", "xpack.observabilityAiAssistantManagement.span.expandRowLabel": "Développer la ligne", @@ -35459,7 +35428,6 @@ "xpack.securitySolution.alertCountByRuleByStatus.status": "Statut", "xpack.securitySolution.alertCountByRuleByStatus.tooltipTitle": "Nom de règle", "xpack.securitySolution.alertDetails.overview.hostRiskDataTitle": "Données de risque de {riskEntity}", - "xpack.securitySolution.alertDetails.overview.insights.suppressedAlertsCountTechnicalPreview": "Version d'évaluation technique", "xpack.securitySolution.alertDetails.summary.readLess": "Lire moins", "xpack.securitySolution.alertDetails.summary.readMore": "En savoir plus", "xpack.securitySolution.alerts.badge.readOnly.tooltip": "Impossible de mettre à jour les alertes", @@ -36455,8 +36423,8 @@ "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.maxAlertsFieldLessThanWarning": "Kibana ne permet qu'un maximum de {maxNumber} {maxNumber, plural, =1 {alerte} other {alertes}} par exécution de règle.", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.nameFieldRequiredError": "Nom obligatoire.", "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.noteHelpText": "Ajouter un guide d'investigation sur les règles...", - "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "Ajouter le guide de configuration de règle...", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupHelpText": "Fournissez des instructions sur les conditions préalables à la règle, telles que les intégrations requises, les étapes de configuration et tout ce qui est nécessaire au bon fonctionnement de la règle.", + "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "Ajouter le guide de configuration de règle...", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupLabel": "Guide de configuration", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.tagFieldEmptyError": "Une balise ne doit pas être vide", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.threatIndicatorPathFieldEmptyError": "Le remplacement du préfixe d'indicateur ne peut pas être vide.", @@ -38822,15 +38790,11 @@ "xpack.securitySolution.event.summary.threat_indicator.modal.allMatches": "Toutes les correspondances d'indicateur", "xpack.securitySolution.event.summary.threat_indicator.modal.close": "Fermer", "xpack.securitySolution.event.summary.threat_indicator.showMatches": "Afficher les {count} alertes de correspondance d'indicateur", - "xpack.securitySolution.eventDetails.alertReason": "Raison d'alerte", - "xpack.securitySolution.eventDetails.description": "Description", "xpack.securitySolution.eventDetails.responseActions.endpoint.executed": "a exécuté la commande {command}", "xpack.securitySolution.eventDetails.responseActions.endpoint.failed": "n'a pas pu exécuter la commande {command}", "xpack.securitySolution.eventDetails.responseActions.endpoint.pending": "exécute la commande {command}", "xpack.securitySolution.eventDetails.responseActions.endpoint.tried": "a tenté d'exécuter la commande {command}", "xpack.securitySolution.eventDetails.summaryView": "résumé", - "xpack.securitySolution.eventDetails.table": "Tableau", - "xpack.securitySolution.eventDetails.table.actions": "Actions", "xpack.securitySolution.eventFilter.flyoutForm.confirmModal.name": "filtre d'événements", "xpack.securitySolution.eventFilter.flyoutForm.creationSuccessToastTitle": "\"{name}\" a été ajouté à la liste de filtres d'événements.", "xpack.securitySolution.eventFilter.form.description.placeholder": "Description", @@ -39268,10 +39232,6 @@ "xpack.securitySolution.flyout.right.alertPreview.ariaLabel": "Voir un aperçu de l'alerte avec l'id {id}", "xpack.securitySolution.flyout.right.eventCategoryText": "Catégorie d'événement", "xpack.securitySolution.flyout.right.header.assignedTitle": "Utilisateurs affectés", - "securitySolutionPackages.flyout.right.header.collapseDetailButtonAriaLabel": "Réduire les détails", - "securitySolutionPackages.flyout.right.header.collapseDetailButtonLabel": "Réduire les détails", - "securitySolutionPackages.flyout.right.header.expandDetailButtonAriaLabel": "Développer les détails", - "securitySolutionPackages.flyout.right.header.expandDetailButtonLabel": "Développer les détails", "xpack.securitySolution.flyout.right.header.headerTitle": "Détails des documents", "xpack.securitySolution.flyout.right.header.jsonTabLabel": "JSON", "xpack.securitySolution.flyout.right.header.overviewTabLabel": "Aperçu", @@ -39358,10 +39318,6 @@ "xpack.securitySolution.flyout.right.visualizations.sessionPreview.timeDescription": "à", "xpack.securitySolution.flyout.right.visualizations.sessionPreview.upsellDescription": "Cette fonctionnalité requiert un {subscription}", "xpack.securitySolution.flyout.right.visualizations.sessionPreview.upsellLinkText": "Abonnement Enterprise", - "securitySolutionPackages.flyout.shared.errorDescription": "Une erreur est survenue lors de l'affichage de {message}.", - "securitySolutionPackages.flyout.shared.errorTitle": "Impossible d'afficher {title}.", - "securitySolutionPackages.flyout.shared.ExpandablePanelButtonIconAriaLabel": "Activer/Désactiver le panneau extensible", - "securitySolutionPackages.flyout.shared.expandablePanelLoadingAriaLabel": "panneau extensible", "xpack.securitySolution.flyout.tour.entities.description": "Consultez la vue {entities} étendue pour en savoir plus sur les hôtes et les utilisateurs liés à l'alerte.", "xpack.securitySolution.flyout.tour.entities.text": "Entités", "xpack.securitySolution.flyout.tour.entities.title": "De nouvelles informations sur les hôtes et les utilisateurs sont disponibles", @@ -41724,7 +41680,6 @@ "xpack.slo.permissionsCallout.readIndexPermission": "Autorisations d'index 'read' ​​et 'view_index_metadata' sur tous les modèles d'index que vous souhaitez utiliser pour créer des SLO", "xpack.slo.permissionsCallout.readSloPermission": "Autorisation 'read' ​​sur le modèle d'index : .slo-*", "xpack.slo.permissionsCallout.title": "Permissions insuffisantes", - "xpack.slo.permissionsCallout.writeClusterPermission": "Autorisations de cluster 'manage_transform' et 'manage_ingest_pipelines'", "xpack.slo.permissionsCallout.writeSloPermission": "Autorisation 'all' sur le modèle d'index : .slo-*", "xpack.slo.queryBuilder.closeButtonLabel": "Fermer", "xpack.slo.queryBuilder.documentsButtonLabel": "Afficher les documents", @@ -42069,8 +42024,8 @@ "xpack.slo.sloEmbeddable.config.sloSelector.placeholder": "Sélectionner un SLO", "xpack.slo.sloEmbeddable.displayName": "Aperçu du SLO", "xpack.slo.sloEmbeddable.overview.sloNotFoundText": "Le SLO a été supprimé. Vous pouvez supprimer sans risque le widget du tableau de bord.", - "xpack.slo.sloGridItem.targetFlexItemLabel": "Cible {target}", "xpack.slo.sLOGridItem.targetFlexItemLabel": "Cible {target}", + "xpack.slo.sloGridItem.targetFlexItemLabel": "Cible {target}", "xpack.slo.sloGroupConfiguration.customFiltersLabel": "Personnaliser le filtre", "xpack.slo.sloGroupConfiguration.customFiltersOptional": "Facultatif", "xpack.slo.sloGroupConfiguration.customFilterText": "Personnaliser le filtre", @@ -43516,8 +43471,8 @@ "xpack.stackConnectors.components.casesWebhookxpack.stackConnectors.components.casesWebhook.connectorTypeTitle": "Webhook - Données de gestion des cas", "xpack.stackConnectors.components.d3security.bodyCodeEditorAriaLabel": "Éditeur de code", "xpack.stackConnectors.components.d3security.bodyFieldLabel": "Corps", - "xpack.stackConnectors.components.d3security.connectorTypeTitle": "Données D3", "xpack.stackConnectors.components.d3Security.connectorTypeTitle": "D3 Security", + "xpack.stackConnectors.components.d3security.connectorTypeTitle": "Données D3", "xpack.stackConnectors.components.d3security.eventTypeFieldLabel": "Type d'événement", "xpack.stackConnectors.components.d3security.invalidActionText": "Nom d'action non valide.", "xpack.stackConnectors.components.d3security.requiredActionText": "L'action est requise.", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index e89e452923f30..71939a6d5abac 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -6847,13 +6847,7 @@ "securitySolutionPackages.ecsDataQualityDashboard.errors.read": "読み取り", "securitySolutionPackages.ecsDataQualityDashboard.errors.theFollowingPrivilegesLabel": "インデックスを確認するには次の権限が必要です:", "securitySolutionPackages.ecsDataQualityDashboard.errors.viewIndexMetadata": "view_index_metadata", - "securitySolutionPackages.ecsDataQualityDashboard.errorsPopover.copyToClipboardButton": "クリップボードにコピー", - "securitySolutionPackages.ecsDataQualityDashboard.errorsPopover.errorsCalloutSummary": "一部のインデックスのデータ品質が確認されませんでした", - "securitySolutionPackages.ecsDataQualityDashboard.errorsPopover.errorsTitle": "エラー", "securitySolutionPackages.ecsDataQualityDashboard.errorsPopover.viewErrorsButton": "エラーを表示", - "securitySolutionPackages.ecsDataQualityDashboard.errorsViewerTable.errorColumn": "エラー", - "securitySolutionPackages.ecsDataQualityDashboard.errorsViewerTable.indexColumn": "インデックス", - "securitySolutionPackages.ecsDataQualityDashboard.errorsViewerTable.patternColumn": "パターン", "securitySolutionPackages.ecsDataQualityDashboard.fieldsLabel": "フィールド", "securitySolutionPackages.ecsDataQualityDashboard.frozenDescription": "インデックスは更新されず、ほとんど照会されません。情報はまだ検索可能でなければなりませんが、クエリーが非常に低速でも問題ありません。", "securitySolutionPackages.ecsDataQualityDashboard.frozenPatternTooltip": "{pattern}パターンと一致する{indices} {indices, plural, other {インデックス}}{indices, plural, other {は}}フローズンです。フローズンインデックスは更新されず、ほとんど照会されません。情報はまだ検索可能でなければなりませんが、クエリーが非常に低速でも問題ありません。", @@ -6865,15 +6859,10 @@ "securitySolutionPackages.ecsDataQualityDashboard.ilmPhaseHot": "ホット", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhaseLabel": "ILMフェーズ", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptBody": "これらのインデックスライフサイクル管理(ILM)フェーズのインデックスはデータ品質が確認されます", - "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptColdLabel": "コールド", - "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptFrozenLabel": "凍結", - "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptHotLabel": "ホット", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptIlmPhasesThatCanBeCheckedSubtitle": "データ品質を確認できるILMフェーズ", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptIlmPhasesThatCannotBeCheckedSubtitle": "確認できないILMフェーズ", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptITheFollowingIlmPhasesLabel": "次のILMフェーズは、アクセスが低速になるため、データ品質が確認できません", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptTitle": "1つ以上のILMフェーズを選択", - "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptUnmanagedLabel": "管理対象外", - "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptWarmLabel": "ウォーム", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhaseUnmanaged": "管理対象外", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhaseWarm": "ウォーム", "securitySolutionPackages.ecsDataQualityDashboard.incompatibleTab.incompatibleFieldMappingsTableTitle": "非互換フィールドマッピング - {indexName}", @@ -6895,7 +6884,6 @@ "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.custonDetectionEngineRulesWorkMessage": "✅ カスタム検出エンジンルールが動作する", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.detectionEngineRulesWillWorkMessage": "✅ これらのフィールドの検出エンジンルールが動作する", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.detectionEngineRulesWontWorkMessage": "❌ これらのフィールドを参照する検出エンジンルールが正常に一致しない場合がある", - "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.docsLabel": "ドキュメント", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.ecsCompliantCallout": "{fieldCount, plural, =1 {このフィールドのインデックスマッピングタイプとドキュメント値} other {これらのフィールドのインデックスマッピングタイプとドキュメント値}}は、Elastic Common Schema(ECS)バージョン{version}に準拠しています", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.ecsCompliantCalloutTitle": "{fieldCount} {fieldCount, plural, other {個のECSに準拠したフィールド}}", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.ecsCompliantEmptyContent": "このインデックスのどのフィールドマッピングもElastic Common Schema(ECS)と互換性がありません。インデックスには(1つ以上の)@timestamp日付フィールドを含める必要があります。", @@ -6910,7 +6898,6 @@ "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.incompatibleCalloutTitle": "{fieldCount} {fieldCount, plural, other {個のECSに準拠していないフィールド}}", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.incompatibleEmptyContent": "このインデックスのすべてのフィールドマッピングとドキュメント値がElastic Common Schema(ECS)と互換性があります。", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.incompatibleEmptyTitle": "すべてのフィールドマッピングと値がECSと互換性があります", - "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.incompatibleFieldsTab": "非互換フィールド", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.indexMarkdown": "インデックス", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.mappingThatConflictWithEcsMessage": "❌ ECSと互換性がないマッピングまたはフィールド値はサポートされません", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.missingTimestampCallout": "次の理由のため、Elastic Common Schema(ECS)で必要な@timestamp(日付)フィールドマッピングをこのインデックスに追加することを検討してください。", @@ -6941,7 +6928,6 @@ "securitySolutionPackages.ecsDataQualityDashboard.sameFamilyBadgeLabel": "同じファミリー", "securitySolutionPackages.ecsDataQualityDashboard.sameFamilyTab.sameFamilyFieldMappingsTableTitle": "同じファミリーフィールドマッピング - {indexName}", "securitySolutionPackages.ecsDataQualityDashboard.securitySolutionPackages.ecsDataQualityDashboardSubtitle": "互換性に関してインデックスマッピングと値を確認", - "securitySolutionPackages.ecsDataQualityDashboard.securitySolutionPackages.ecsDataQualityDashboardTitle": "データ品質", "securitySolutionPackages.ecsDataQualityDashboard.selectAnIndexPrompt": "ECSバージョンと比較するインデックスを選択", "securitySolutionPackages.ecsDataQualityDashboard.selectOneOrMorPhasesPlaceholder": "1つ以上のILMフェーズを選択", "securitySolutionPackages.ecsDataQualityDashboard.statLabels.checkedLabel": "確認済み", @@ -6957,21 +6943,10 @@ "securitySolutionPackages.ecsDataQualityDashboard.storageTreemap.noDataLabel": "表示するデータがありません", "securitySolutionPackages.ecsDataQualityDashboard.storageTreemap.noDataReasonLabel": "{stackByField1}フィールドがどのグループにも存在しませんでした", "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.collapseLabel": "縮小", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.docsColumn": "ドキュメント", "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.expandRowsColumn": "行を展開", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.failedTooltip": "失敗", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.ilmPhaseColumn": "ILMフェーズ", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.incompatibleFieldsColumn": "非互換フィールド", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indexColumn": "インデックス", "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indexesNameLabel": "インデックス名", "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indexToolTip": "このインデックスはパターンまたはインデックス名と一致します:{pattern}", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indicesCheckedColumn": "確認されたインデックス", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indicesColumn": "インデックス", "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.lastCheckColumn": "最終確認", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.passedTooltip": "合格", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.resultColumn": "結果", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.sizeColumn": "サイズ", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.thisIndexHasNotBeenCheckedTooltip": "このインデックスは確認されていません", "securitySolutionPackages.ecsDataQualityDashboard.timestampDescriptionLabel": "イベントが生成された日時これはイベントから抽出された日時で、一般的にはイベントがソースから生成された日時を表します。イベントソースに元のタイムスタンプがない場合は、通常、この値はイベントがパイプラインによって受信された最初の日時が入力されます。すべてのイベントの必須フィールドです。", "securitySolutionPackages.ecsDataQualityDashboard.toasts.copiedErrorsToastTitle": "エラーをクリップボードにコピーしました", "securitySolutionPackages.ecsDataQualityDashboard.toasts.copiedResultsToastTitle": "結果をクリップボードにコピーしました", @@ -7031,6 +7006,14 @@ "securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications": "信頼できるアプリケーション", "securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications.description": "他のソフトウェア(通常は他のウイルス対策またはエンドポイントセキュリティアプリケーション)との競合を軽減することができます。", "securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications.privilegesTooltip": "信頼できるアプリケーションのアクセスには、すべてのスペースが必要です。", + "securitySolutionPackages.flyout.right.header.collapseDetailButtonAriaLabel": "詳細を折りたたむ", + "securitySolutionPackages.flyout.right.header.collapseDetailButtonLabel": "詳細を折りたたむ", + "securitySolutionPackages.flyout.right.header.expandDetailButtonAriaLabel": "詳細を展開", + "securitySolutionPackages.flyout.right.header.expandDetailButtonLabel": "詳細を展開", + "securitySolutionPackages.flyout.shared.errorDescription": "{message}の表示中にエラーが発生しました。", + "securitySolutionPackages.flyout.shared.errorTitle": "{title}を表示できません。", + "securitySolutionPackages.flyout.shared.ExpandablePanelButtonIconAriaLabel": "展開可能なパネルトグル", + "securitySolutionPackages.flyout.shared.expandablePanelLoadingAriaLabel": "展開可能なパネル", "securitySolutionPackages.markdown.investigationGuideInteractions.upsell": "{requiredLicense}にアップグレードして、調査ガイドのインタラクションを利用", "securitySolutionPackages.navigation.landingLinks": "セキュリティビュー", "securitySolutionPackages.sideNav.betaBadge.label": "ベータ", @@ -11096,8 +11079,8 @@ "xpack.apm.serviceIcons.service": "サービス", "xpack.apm.serviceIcons.serviceDetails.cloud.architecture": "アーキテクチャー", "xpack.apm.serviceIcons.serviceDetails.cloud.availabilityZoneLabel": "{zones, plural, other {可用性ゾーン}} ", - "xpack.apm.serviceIcons.serviceDetails.cloud.faasTriggerTypeLabel": "{triggerTypes, plural, other {トリガータイプ}} ", "xpack.apm.serviceIcons.serviceDetails.cloud.functionNameLabel": "{functionNames, plural, other {関数名}} ", + "xpack.apm.serviceIcons.serviceDetails.cloud.faasTriggerTypeLabel": "{triggerTypes, plural, other {トリガータイプ}} ", "xpack.apm.serviceIcons.serviceDetails.cloud.machineTypesLabel": "{machineTypes, plural, other {コンピュータータイプ} }\n ", "xpack.apm.serviceIcons.serviceDetails.cloud.projectIdLabel": "プロジェクト ID", "xpack.apm.serviceIcons.serviceDetails.cloud.providerLabel": "クラウドプロバイダー", @@ -14597,12 +14580,10 @@ "xpack.dataQuality.Initializing": "データセット品質ページを初期化中", "xpack.dataQuality.name": "データセット品質", "xpack.datasetQuality.actionsColumnName": "アクション", - "xpack.datasetQuality.appDescription": "{dsNamingSchemeLink}に従う{logsPattern}データストリームのデータセット品質を監視します。", "xpack.datasetQuality.appDescription.dsNamingSchemeLinkText": "データストリーム命名スキーム", "xpack.datasetQuality.appTitle": "データセット品質", "xpack.datasetQuality.betaBadgeDescription": "現在、この機能はベータです。バグが発生した場合やフィードバックがある場合は、お問い合わせください。サポート問題をオープンするか、ディスカッションフォーラムをご覧ください。", "xpack.datasetQuality.betaBadgeLabel": "ベータ", - "xpack.datasetQuality.collapseLabel": "縮小", "xpack.datasetQuality.datasetQualityColumnName": "データセット品質", "xpack.datasetQuality.datasetQualityColumnTooltip": "品質は、データセットの劣化したドキュメントの割合に基づきます。{visualQueue}", "xpack.datasetQuality.datasetQualityIdicator": "{quality}", @@ -14613,9 +14594,6 @@ "xpack.datasetQuality.emptyState.noData.title": "データセットが見つかりません", "xpack.datasetQuality.emptyState.noPrivileges.message": "ログデータを表示するために必要な権限がありません。{datasetPattern}を表示するための十分な権限があることを確認してください。", "xpack.datasetQuality.emptyState.noPrivileges.title": "データセットを読み込めませんでした", - "xpack.datasetQuality.expandLabel": "拡張", - "xpack.datasetQuality.fetchDatasetDetailsFailed": "データセット詳細を取得できませんでした。", - "xpack.datasetQuality.fetchDatasetDetailsFailed.noDatasetSelected": "データセットが選択されていません", "xpack.datasetQuality.fetchDatasetStatsFailed": "データセットを取得できませんでした。", "xpack.datasetQuality.fetchDegradedStatsFailed": "劣化したドキュメント情報を取得できませんでした。", "xpack.datasetQuality.fetchIntegrationsFailed": "統合を取得できませんでした。", @@ -14623,9 +14601,6 @@ "xpack.datasetQuality.fewDegradedDocsTooltip": "このデータセットの{degradedDocsCount}個の劣化したドキュメント。", "xpack.datasetQuality.filterBar.placeholder": "データセットのフィルタリング", "xpack.datasetQuality.flyout.degradedDocsTitle": "劣化したドキュメント", - "xpack.datasetQuality.flyout.degradedField.count": "ドキュメント数", - "xpack.datasetQuality.flyout.degradedField.field": "フィールド", - "xpack.datasetQuality.flyout.degradedField.lastOccurrence": "前回の発生", "xpack.datasetQuality.flyout.nonAggregatable.description": "{description}", "xpack.datasetQuality.flyout.nonAggregatable.howToFixIt": "今後の遅れを防止するには、手動でこのデータを{rolloverLink}してください。", "xpack.datasetQuality.flyout.nonAggregatable.warning": "{dataset}は_ignored集約をサポートしていません。データのクエリを実行するときに遅延が生じる可能性があります。{howToFixIt}", @@ -19764,7 +19739,6 @@ "xpack.fleet.createPackagePolicy.StepSelectPolicy.errorLoadingAgentPoliciesTitle": "エージェントポリシーの読み込みエラー", "xpack.fleet.createPackagePolicy.StepSelectPolicy.errorLoadingPackageTitle": "パッケージ情報の読み込みエラー", "xpack.fleet.createPackagePolicy.StepSelectPolicy.errorLoadingSelectedAgentPolicyTitle": "選択したエージェントポリシーの読み込みエラー", - "xpack.fleet.createPackagePolicy.StepSelectPolicy.noPolicySelectedError": "エージェントポリシーは必須です。", "xpack.fleet.createPackagePolicy.transformInstallWithCurrentUserPermissionCallout": "このパッケージには、パッケージをインストールするユーザーと同じロールで作成、開始される{count, plural, one {1個のトランスフォームアセット} other {# トランスフォームアセット}}があります。", "xpack.fleet.createPackagePolicyBottomBar.addAnotherIntegration": "別の統合を追加", "xpack.fleet.createPackagePolicyBottomBar.backButton": "戻る", @@ -25106,7 +25080,7 @@ "xpack.lens.collapse.min": "最低", "xpack.lens.collapse.none": "なし", "xpack.lens.collapse.sum": "合計", - "xpack.lens.colorMapping.editColorMappingSectionlabel": "カラーマッピング", + "xpack.lens.colorMapping.editColorMappingSectionLabel": "カラーマッピング", "xpack.lens.colorMapping.editColorMappingTitle": "用語マッピングで色を編集", "xpack.lens.colorMapping.editColors": "色を編集", "xpack.lens.colorMapping.editColorsTitle": "色を編集", @@ -25733,9 +25707,7 @@ "xpack.lens.metric.breakdownBy": "分類する", "xpack.lens.metric.color": "色", "xpack.lens.metric.colorMode.dynamic": "動的", - "xpack.lens.metric.colorMode.label": "色モード", "xpack.lens.metric.colorMode.static": "静的", - "xpack.lens.metric.dynamicColoring.label": "色モード", "xpack.lens.metric.groupLabel": "目標値と単一の値", "xpack.lens.metric.headingLabel": "値", "xpack.lens.metric.icon": "アイコン装飾", @@ -25791,7 +25763,6 @@ "xpack.lens.paletteHeatmapGradient.label": "色", "xpack.lens.paletteMetricGradient.label": "色", "xpack.lens.palettePicker.label": "パレット", - "xpack.lens.paletteTableGradient.label": "色", "xpack.lens.pie.addLayer": "ビジュアライゼーション", "xpack.lens.pie.arrayValues": "次のディメンションには配列値があります:{label}。可視化が想定通りに表示されない場合があります。", "xpack.lens.pie.collapsedDimensionsDontCount": "(折りたたまれたディメンションはこの制限に対してカウントされません。)", @@ -26980,8 +26951,8 @@ "xpack.maps.source.esSearch.descendingLabel": "降順", "xpack.maps.source.esSearch.extentFilterLabel": "マップの表示範囲でデータを動的にフィルタリング", "xpack.maps.source.esSearch.fieldNotFoundMsg": "インデックスパターン''{indexPatternName}''に''{fieldName}''が見つかりません。", - "xpack.maps.source.esSearch.geofieldLabel": "地理空間フィールド", "xpack.maps.source.esSearch.geoFieldLabel": "地理空間フィールド", + "xpack.maps.source.esSearch.geofieldLabel": "地理空間フィールド", "xpack.maps.source.esSearch.geoFieldTypeLabel": "地理空間フィールドタイプ", "xpack.maps.source.esSearch.indexOverOneLengthEditError": "データビューは複数のインデックスを参照しています。データビューごとに1つのインデックスのみが許可されています。", "xpack.maps.source.esSearch.indexZeroLengthEditError": "データビューはどのインデックスも参照していません。", @@ -33091,13 +33062,11 @@ "xpack.observabilityAiAssistantManagement.settingsPage.logIndexPatternDescription": "ログのクエリを実行するときにAI Assistantによって使用されるインデックスパターン。ログは分類され、根本原因分析で使用されます。", "xpack.observabilityAiAssistantManagement.settingsPage.searchConnector": "検索コネクター", "xpack.observabilityAiAssistantManagement.settingsPage.searchConnectorIndexPatternDescription": "検索コネクターインデックス(ナレッジベースの一部)をクエリするときに、AI Assistantによって使用されるインデックスパターン。デフォルトでは、すべての検索コネクターのインデックスに対してクエリが実行されます。", - "xpack.observabilityAiAssistantManagement.settingsPage.selectYourLanguageLabel": "応答を生成するときにアシスタントで使用する言語を選択してください。", "xpack.observabilityAiAssistantManagement.settingsPage.settingsLabel": "設定", "xpack.observabilityAiAssistantManagement.settingsPage.showAIAssistantButtonLabel": "オブザーバビリティアプリにAI Assistantボタンと状況に応じたインサイトを表示", "xpack.observabilityAiAssistantManagement.settingsPage.showAIAssistantDescriptionLabel": "オブザーバビリティアプリでAI Assistantボタンと状況に応じたインサイトのオン/オフを切り替えるには、[スペース]>[]>[機能]でAI Assistant機能のチェックをオンまたはオフにします。", "xpack.observabilityAiAssistantManagement.settingsPage.simulatedFunctionCallingDescription": "[technical preview] シミュレートされた関数呼び出しを使用します。シミュレートされた関数呼び出しでは、関数またはツールのAPIサポートは必要ありませんが、パフォーマンスが低下する可能性があります。現在、シミュレートされた関数呼び出しは、この設定に関係なく、非OpenAIコネクターで常に有効です。", "xpack.observabilityAiAssistantManagement.settingsPage.simulatedFunctionCallingLabel": "関数呼び出しをシミュレート", - "xpack.observabilityAiAssistantManagement.settingsPage.userPreferencesLabel": "応答言語", "xpack.observabilityAiAssistantManagement.settingsTab.h3.logIndexPatternLabel": "ログインデックスパターン", "xpack.observabilityAiAssistantManagement.settingsTab.h3.searchConnectorIndexPatternLabel": "検索コネクターインデックスパターン", "xpack.observabilityAiAssistantManagement.span.expandRowLabel": "行を展開", @@ -35444,7 +35413,6 @@ "xpack.securitySolution.alertCountByRuleByStatus.status": "ステータス", "xpack.securitySolution.alertCountByRuleByStatus.tooltipTitle": "ルール名", "xpack.securitySolution.alertDetails.overview.hostRiskDataTitle": "{riskEntity}リスクデータ", - "xpack.securitySolution.alertDetails.overview.insights.suppressedAlertsCountTechnicalPreview": "テクニカルプレビュー", "xpack.securitySolution.alertDetails.summary.readLess": "表示を減らす", "xpack.securitySolution.alertDetails.summary.readMore": "続きを読む", "xpack.securitySolution.alerts.badge.readOnly.tooltip": "アラートを更新できません", @@ -36439,8 +36407,8 @@ "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.maxAlertsFieldLessThanWarning": "Kibanaで許可される最大数は、1回の実行につき、{maxNumber} {maxNumber, plural, other {アラート}}です。", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.nameFieldRequiredError": "名前が必要です。", "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.noteHelpText": "ルール調査ガイドを追加...", - "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "ルールセットアップガイドを追加...", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupHelpText": "必要な統合、構成ステップ、ルールが正常に動作するために必要な他のすべての項目といった、ルール前提条件に関する指示を入力します。", + "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "ルールセットアップガイドを追加...", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupLabel": "セットアップガイド", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.tagFieldEmptyError": "タグを空にすることはできません", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.threatIndicatorPathFieldEmptyError": "インジケータープレフィックスの無効化を空にすることはできません", @@ -38804,15 +38772,11 @@ "xpack.securitySolution.event.summary.threat_indicator.modal.allMatches": "すべてのインジケーター一致", "xpack.securitySolution.event.summary.threat_indicator.modal.close": "閉じる", "xpack.securitySolution.event.summary.threat_indicator.showMatches": "すべての{count}件のインジケーター一致アラートを表示", - "xpack.securitySolution.eventDetails.alertReason": "アラートの理由", - "xpack.securitySolution.eventDetails.description": "説明", "xpack.securitySolution.eventDetails.responseActions.endpoint.executed": "{command}コマンドを実行しました", "xpack.securitySolution.eventDetails.responseActions.endpoint.failed": "{command}コマンドを実行できませんでした", "xpack.securitySolution.eventDetails.responseActions.endpoint.pending": "{command}コマンドを実行しています", "xpack.securitySolution.eventDetails.responseActions.endpoint.tried": "{command}コマンドを実行しようとしました", "xpack.securitySolution.eventDetails.summaryView": "まとめ", - "xpack.securitySolution.eventDetails.table": "表", - "xpack.securitySolution.eventDetails.table.actions": "アクション", "xpack.securitySolution.eventFilter.flyoutForm.confirmModal.name": "イベントフィルター", "xpack.securitySolution.eventFilter.flyoutForm.creationSuccessToastTitle": "\"{name}\"がイベントフィルターリストに追加されました。", "xpack.securitySolution.eventFilter.form.description.placeholder": "説明", @@ -39251,10 +39215,6 @@ "xpack.securitySolution.flyout.right.alertPreview.ariaLabel": "ID {id}のアラートをプレビュー", "xpack.securitySolution.flyout.right.eventCategoryText": "イベントカテゴリ", "xpack.securitySolution.flyout.right.header.assignedTitle": "担当者", - "securitySolutionPackages.flyout.right.header.collapseDetailButtonAriaLabel": "詳細を折りたたむ", - "securitySolutionPackages.flyout.right.header.collapseDetailButtonLabel": "詳細を折りたたむ", - "securitySolutionPackages.flyout.right.header.expandDetailButtonAriaLabel": "詳細を展開", - "securitySolutionPackages.flyout.right.header.expandDetailButtonLabel": "詳細を展開", "xpack.securitySolution.flyout.right.header.headerTitle": "ドキュメント詳細", "xpack.securitySolution.flyout.right.header.jsonTabLabel": "JSON", "xpack.securitySolution.flyout.right.header.overviewTabLabel": "概要", @@ -39341,10 +39301,6 @@ "xpack.securitySolution.flyout.right.visualizations.sessionPreview.timeDescription": "に", "xpack.securitySolution.flyout.right.visualizations.sessionPreview.upsellDescription": "この機能には{subscription}が必要です", "xpack.securitySolution.flyout.right.visualizations.sessionPreview.upsellLinkText": "エンタープライズサブスクリプション", - "securitySolutionPackages.flyout.shared.errorDescription": "{message}の表示中にエラーが発生しました。", - "securitySolutionPackages.flyout.shared.errorTitle": "{title}を表示できません。", - "securitySolutionPackages.flyout.shared.ExpandablePanelButtonIconAriaLabel": "展開可能なパネルトグル", - "securitySolutionPackages.flyout.shared.expandablePanelLoadingAriaLabel": "展開可能なパネル", "xpack.securitySolution.flyout.tour.entities.description": "アラートに関連付けられたホストとユーザーの詳細については、展開された{entities}ビューを確認してください。", "xpack.securitySolution.flyout.tour.entities.text": "エンティティ", "xpack.securitySolution.flyout.tour.entities.title": "新しいホストとユーザーのインサイトがあります", @@ -41709,7 +41665,6 @@ "xpack.slo.permissionsCallout.readIndexPermission": "SLOの作成で使用するすべてのインデックスパターンのreadおよびview_index_metadataインデックス権限。", "xpack.slo.permissionsCallout.readSloPermission": "インデックスパターンのread権限:.slo-*", "xpack.slo.permissionsCallout.title": "不十分な権限", - "xpack.slo.permissionsCallout.writeClusterPermission": "manage_transformおよびmanage_ingest_pipelinesクラスター権限", "xpack.slo.permissionsCallout.writeSloPermission": "インデックスパターンでのall権限:.slo-*", "xpack.slo.queryBuilder.closeButtonLabel": "閉じる", "xpack.slo.queryBuilder.documentsButtonLabel": "ドキュメントを表示", @@ -42053,8 +42008,8 @@ "xpack.slo.sloEmbeddable.config.sloSelector.placeholder": "SLOを選択", "xpack.slo.sloEmbeddable.displayName": "SLO概要", "xpack.slo.sloEmbeddable.overview.sloNotFoundText": "SLOが削除されました。ウィジェットをダッシュボードから安全に削除できます。", - "xpack.slo.sloGridItem.targetFlexItemLabel": "目標{target}", "xpack.slo.sLOGridItem.targetFlexItemLabel": "目標{target}", + "xpack.slo.sloGridItem.targetFlexItemLabel": "目標{target}", "xpack.slo.sloGroupConfiguration.customFiltersLabel": "カスタムフィルター", "xpack.slo.sloGroupConfiguration.customFiltersOptional": "オプション", "xpack.slo.sloGroupConfiguration.customFilterText": "カスタムフィルター", @@ -43496,8 +43451,8 @@ "xpack.stackConnectors.components.casesWebhookxpack.stackConnectors.components.casesWebhook.connectorTypeTitle": "Webフック - ケース管理データ", "xpack.stackConnectors.components.d3security.bodyCodeEditorAriaLabel": "コードエディター", "xpack.stackConnectors.components.d3security.bodyFieldLabel": "本文", - "xpack.stackConnectors.components.d3security.connectorTypeTitle": "D3データ", "xpack.stackConnectors.components.d3Security.connectorTypeTitle": "D3セキュリティ", + "xpack.stackConnectors.components.d3security.connectorTypeTitle": "D3データ", "xpack.stackConnectors.components.d3security.eventTypeFieldLabel": "イベントタイプ", "xpack.stackConnectors.components.d3security.invalidActionText": "無効なアクション名です。", "xpack.stackConnectors.components.d3security.requiredActionText": "アクションが必要です。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 30cfd990ff4ee..8e87dc6c73fc8 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -6858,13 +6858,7 @@ "securitySolutionPackages.ecsDataQualityDashboard.errors.read": "读取", "securitySolutionPackages.ecsDataQualityDashboard.errors.theFollowingPrivilegesLabel": "检查索引需要以下权限:", "securitySolutionPackages.ecsDataQualityDashboard.errors.viewIndexMetadata": "view_index_metadata", - "securitySolutionPackages.ecsDataQualityDashboard.errorsPopover.copyToClipboardButton": "复制到剪贴板", - "securitySolutionPackages.ecsDataQualityDashboard.errorsPopover.errorsCalloutSummary": "未检查某些索引以了解数据质量", - "securitySolutionPackages.ecsDataQualityDashboard.errorsPopover.errorsTitle": "错误", "securitySolutionPackages.ecsDataQualityDashboard.errorsPopover.viewErrorsButton": "查看错误", - "securitySolutionPackages.ecsDataQualityDashboard.errorsViewerTable.errorColumn": "错误", - "securitySolutionPackages.ecsDataQualityDashboard.errorsViewerTable.indexColumn": "索引", - "securitySolutionPackages.ecsDataQualityDashboard.errorsViewerTable.patternColumn": "模式", "securitySolutionPackages.ecsDataQualityDashboard.fieldsLabel": "字段", "securitySolutionPackages.ecsDataQualityDashboard.frozenDescription": "不再更新并且极少查询该索引。仍然需要能够搜索信息,但如果那些查询速度极慢,也没有关系。", "securitySolutionPackages.ecsDataQualityDashboard.frozenPatternTooltip": "{indices} 个匹配 {pattern} 模式的{indices, plural, other {索引}}{indices, plural, other {为}}已冻结索引。不再更新并且极少会查询已冻结索引。仍然需要能够搜索信息,但如果那些查询速度极慢,也没有关系。", @@ -6876,15 +6870,10 @@ "securitySolutionPackages.ecsDataQualityDashboard.ilmPhaseHot": "热", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhaseLabel": "ILM 阶段", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptBody": "将检查具有这些索引生命周期管理 (ILM) 阶段的索引以了解数据质量", - "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptColdLabel": "冷", - "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptFrozenLabel": "冻结", - "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptHotLabel": "热", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptIlmPhasesThatCanBeCheckedSubtitle": "可进行检查以了解数据质量的 ILM 阶段", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptIlmPhasesThatCannotBeCheckedSubtitle": "无法检查的 ILM 阶段", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptITheFollowingIlmPhasesLabel": "由于访问速度较慢,无法检查以下 ILM 阶段以了解数据质量", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptTitle": "选择一个或多个 ILM 阶段", - "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptUnmanagedLabel": "未受管", - "securitySolutionPackages.ecsDataQualityDashboard.ilmPhasesEmptyPromptWarmLabel": "温", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhaseUnmanaged": "未受管", "securitySolutionPackages.ecsDataQualityDashboard.ilmPhaseWarm": "温", "securitySolutionPackages.ecsDataQualityDashboard.incompatibleTab.incompatibleFieldMappingsTableTitle": "不兼容的字段映射 - {indexName}", @@ -6906,7 +6895,6 @@ "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.custonDetectionEngineRulesWorkMessage": "✅ 定制检测引擎规则有效", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.detectionEngineRulesWillWorkMessage": "✅ 检测引擎规则将适用于这些字段", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.detectionEngineRulesWontWorkMessage": "❌ 引用这些字段的检测引擎规则可能无法与其正确匹配", - "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.docsLabel": "文档", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.ecsCompliantCallout": "{fieldCount, plural, =1 {此字段的索引映射类型和文档值} other {这些字段的索引映射类型和文档值}}遵循 Elastic Common Schema (ECS) 版本 {version}", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.ecsCompliantCalloutTitle": "{fieldCount} 个符合 ECS 规范的{fieldCount, plural, other {字段}}", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.ecsCompliantEmptyContent": "此索引中没有任何字段映射遵循 Elastic Common Schema (ECS)。此索引必须(至少)包含一个 @timestamp 日期字段。", @@ -6921,7 +6909,6 @@ "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.incompatibleCalloutTitle": "{fieldCount} 个不兼容的{fieldCount, plural, other {字段}}", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.incompatibleEmptyContent": "此索引中的所有字段映射和文档值均符合 Elastic Common Schema (ECS) 规范。", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.incompatibleEmptyTitle": "所有字段映射和值均符合 ECS 规范", - "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.incompatibleFieldsTab": "不兼容的字段", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.indexMarkdown": "索引", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.mappingThatConflictWithEcsMessage": "❌ 不支持不符合 ECS 规范的映射或字段值", "securitySolutionPackages.ecsDataQualityDashboard.indexProperties.missingTimestampCallout": "考虑根据 Elastic Common Schema (ECS) 的要求将 @timestamp(日期)字段映射添加到此索引,因为:", @@ -6952,7 +6939,6 @@ "securitySolutionPackages.ecsDataQualityDashboard.sameFamilyBadgeLabel": "同一系列", "securitySolutionPackages.ecsDataQualityDashboard.sameFamilyTab.sameFamilyFieldMappingsTableTitle": "同一系列的字段映射 - {indexName}", "securitySolutionPackages.ecsDataQualityDashboard.securitySolutionPackages.ecsDataQualityDashboardSubtitle": "检查索引映射和值以了解与以下项的兼容性", - "securitySolutionPackages.ecsDataQualityDashboard.securitySolutionPackages.ecsDataQualityDashboardTitle": "数据质量", "securitySolutionPackages.ecsDataQualityDashboard.selectAnIndexPrompt": "选择索引以将其与 ECS 版本进行比较", "securitySolutionPackages.ecsDataQualityDashboard.selectOneOrMorPhasesPlaceholder": "选择一个或多个 ILM 阶段", "securitySolutionPackages.ecsDataQualityDashboard.statLabels.checkedLabel": "已检查", @@ -6968,21 +6954,10 @@ "securitySolutionPackages.ecsDataQualityDashboard.storageTreemap.noDataLabel": "没有可显示的数据", "securitySolutionPackages.ecsDataQualityDashboard.storageTreemap.noDataReasonLabel": "任何组中都不存在 {stackByField1} 字段", "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.collapseLabel": "折叠", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.docsColumn": "文档", "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.expandRowsColumn": "展开行", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.failedTooltip": "失败", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.ilmPhaseColumn": "ILM 阶段", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.incompatibleFieldsColumn": "不兼容的字段", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indexColumn": "索引", "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indexesNameLabel": "索引名称", "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indexToolTip": "此索引与模式或索引名称相匹配:{pattern}", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indicesCheckedColumn": "已检查索引", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.indicesColumn": "索引", "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.lastCheckColumn": "上次检查", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.passedTooltip": "通过", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.resultColumn": "结果", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.sizeColumn": "大小", - "securitySolutionPackages.ecsDataQualityDashboard.summaryTable.thisIndexHasNotBeenCheckedTooltip": "尚未检查此索引", "securitySolutionPackages.ecsDataQualityDashboard.timestampDescriptionLabel": "事件发生时的日期/时间。这是从事件中提取的日期/时间,通常表示源生成事件的时间。如果事件源没有原始时间戳,通常会在管道首次收到事件时填充此值。所有事件的必填字段。", "securitySolutionPackages.ecsDataQualityDashboard.toasts.copiedErrorsToastTitle": "已将错误复制到剪贴板", "securitySolutionPackages.ecsDataQualityDashboard.toasts.copiedResultsToastTitle": "已将结果复制到剪贴板", @@ -7042,6 +7017,14 @@ "securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications": "受信任的应用程序", "securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications.description": "帮助减少与其他软件(通常指其他防病毒或终端安全应用程序)的冲突。", "securitySolutionPackages.features.featureRegistry.subFeatures.trustedApplications.privilegesTooltip": "访问受信任的应用程序需要所有工作区。", + "securitySolutionPackages.flyout.right.header.collapseDetailButtonAriaLabel": "折叠详情", + "securitySolutionPackages.flyout.right.header.collapseDetailButtonLabel": "折叠详情", + "securitySolutionPackages.flyout.right.header.expandDetailButtonAriaLabel": "展开详情", + "securitySolutionPackages.flyout.right.header.expandDetailButtonLabel": "展开详情", + "securitySolutionPackages.flyout.shared.errorDescription": "显示 {message} 时出现错误。", + "securitySolutionPackages.flyout.shared.errorTitle": "无法显示 {title}。", + "securitySolutionPackages.flyout.shared.ExpandablePanelButtonIconAriaLabel": "可展开面板切换按钮", + "securitySolutionPackages.flyout.shared.expandablePanelLoadingAriaLabel": "可展开面板", "securitySolutionPackages.markdown.insight.upsell": "升级到{requiredLicense}以利用调查指南中的洞见", "securitySolutionPackages.markdown.investigationGuideInteractions.upsell": "升级到 {requiredLicense} 以利用调查指南交互", "securitySolutionPackages.navigation.landingLinks": "安全视图", @@ -11115,8 +11098,8 @@ "xpack.apm.serviceIcons.service": "服务", "xpack.apm.serviceIcons.serviceDetails.cloud.architecture": "架构", "xpack.apm.serviceIcons.serviceDetails.cloud.availabilityZoneLabel": "{zones, plural, other {可用性区域}} ", - "xpack.apm.serviceIcons.serviceDetails.cloud.faasTriggerTypeLabel": "{triggerTypes, plural, other {触发类型}} ", "xpack.apm.serviceIcons.serviceDetails.cloud.functionNameLabel": "{functionNames, plural, other {功能名称}} ", + "xpack.apm.serviceIcons.serviceDetails.cloud.faasTriggerTypeLabel": "{triggerTypes, plural, other {触发类型}} ", "xpack.apm.serviceIcons.serviceDetails.cloud.machineTypesLabel": "{machineTypes, plural, other {机器类型}} ", "xpack.apm.serviceIcons.serviceDetails.cloud.projectIdLabel": "项目 ID", "xpack.apm.serviceIcons.serviceDetails.cloud.providerLabel": "云服务提供商", @@ -14620,12 +14603,10 @@ "xpack.dataQuality.Initializing": "正在初始化“数据集质量”页面", "xpack.dataQuality.name": "数据集质量", "xpack.datasetQuality.actionsColumnName": "操作", - "xpack.datasetQuality.appDescription": "监测跟随 {dsNamingSchemeLink} 的 {logsPattern} 数据流的数据集质量。", "xpack.datasetQuality.appDescription.dsNamingSchemeLinkText": "数据流命名方案", "xpack.datasetQuality.appTitle": "数据集质量", "xpack.datasetQuality.betaBadgeDescription": "此功能当前为公测版。如果遇到任何错误或有任何反馈,我们乐于倾听您的意见。请报告支持问题和/或访问我们的讨论论坛。", "xpack.datasetQuality.betaBadgeLabel": "公测版", - "xpack.datasetQuality.collapseLabel": "折叠", "xpack.datasetQuality.datasetQualityColumnName": "数据集质量", "xpack.datasetQuality.datasetQualityColumnTooltip": "质量基于数据集中的已降级文档的百分比。{visualQueue}", "xpack.datasetQuality.datasetQualityIdicator": "{quality}", @@ -14636,9 +14617,6 @@ "xpack.datasetQuality.emptyState.noData.title": "找不到数据集", "xpack.datasetQuality.emptyState.noPrivileges.message": "您没有查看日志数据所需的权限。请确保您具有足够的权限,可以查看 {datasetPattern}。", "xpack.datasetQuality.emptyState.noPrivileges.title": "无法加载数据集", - "xpack.datasetQuality.expandLabel": "展开", - "xpack.datasetQuality.fetchDatasetDetailsFailed": "无法获取数据集详情。", - "xpack.datasetQuality.fetchDatasetDetailsFailed.noDatasetSelected": "尚未选择任何数据集", "xpack.datasetQuality.fetchDatasetStatsFailed": "无法获取数据集。", "xpack.datasetQuality.fetchDegradedStatsFailed": "无法获取已降级文档信息。", "xpack.datasetQuality.fetchIntegrationsFailed": "无法获取集成。", @@ -14646,9 +14624,6 @@ "xpack.datasetQuality.fewDegradedDocsTooltip": "此数据集中的 {degradedDocsCount} 个已降级文档。", "xpack.datasetQuality.filterBar.placeholder": "筛选数据集", "xpack.datasetQuality.flyout.degradedDocsTitle": "已降级文档", - "xpack.datasetQuality.flyout.degradedField.count": "文档计数", - "xpack.datasetQuality.flyout.degradedField.field": "字段", - "xpack.datasetQuality.flyout.degradedField.lastOccurrence": "最后一次发生", "xpack.datasetQuality.flyout.nonAggregatable.description": "{description}", "xpack.datasetQuality.flyout.nonAggregatable.howToFixIt": "手动 {rolloverLink} 此数据集以防止未来出现延迟。", "xpack.datasetQuality.flyout.nonAggregatable.warning": "{dataset} 不支持 _ignored 聚合,在查询数据时可能会导致延迟。{howToFixIt}", @@ -19790,7 +19765,6 @@ "xpack.fleet.createPackagePolicy.StepSelectPolicy.errorLoadingAgentPoliciesTitle": "加载代理策略时出错", "xpack.fleet.createPackagePolicy.StepSelectPolicy.errorLoadingPackageTitle": "加载软件包信息时出错", "xpack.fleet.createPackagePolicy.StepSelectPolicy.errorLoadingSelectedAgentPolicyTitle": "加载选定代理策略时出错", - "xpack.fleet.createPackagePolicy.StepSelectPolicy.noPolicySelectedError": "代理策略必填。", "xpack.fleet.createPackagePolicy.transformInstallWithCurrentUserPermissionCallout": "此软件包具有 {count, plural, one {一个转换资产} other {# 个转换资产}},它们将使用与安装软件包的用户相同的角色创建并启动。", "xpack.fleet.createPackagePolicyBottomBar.addAnotherIntegration": "添加其他集成", "xpack.fleet.createPackagePolicyBottomBar.backButton": "返回", @@ -25137,7 +25111,7 @@ "xpack.lens.collapse.min": "最小值", "xpack.lens.collapse.none": "无", "xpack.lens.collapse.sum": "求和", - "xpack.lens.colorMapping.editColorMappingSectionlabel": "颜色映射", + "xpack.lens.colorMapping.editColorMappingSectionLabel": "颜色映射", "xpack.lens.colorMapping.editColorMappingTitle": "按词映射编辑颜色", "xpack.lens.colorMapping.editColors": "编辑颜色", "xpack.lens.colorMapping.editColorsTitle": "编辑颜色", @@ -25765,9 +25739,7 @@ "xpack.lens.metric.breakdownBy": "细分方式", "xpack.lens.metric.color": "颜色", "xpack.lens.metric.colorMode.dynamic": "动态", - "xpack.lens.metric.colorMode.label": "颜色模式", "xpack.lens.metric.colorMode.static": "静态", - "xpack.lens.metric.dynamicColoring.label": "颜色模式", "xpack.lens.metric.groupLabel": "目标值和单值", "xpack.lens.metric.headingLabel": "值", "xpack.lens.metric.icon": "图标装饰", @@ -25823,7 +25795,6 @@ "xpack.lens.paletteHeatmapGradient.label": "颜色", "xpack.lens.paletteMetricGradient.label": "颜色", "xpack.lens.palettePicker.label": "调色板", - "xpack.lens.paletteTableGradient.label": "颜色", "xpack.lens.pie.addLayer": "可视化", "xpack.lens.pie.arrayValues": "以下维度包含数组值:{label}。您的可视化可能无法正常渲染。", "xpack.lens.pie.collapsedDimensionsDontCount": "(折叠的维度不计入此限制。)", @@ -27012,8 +26983,8 @@ "xpack.maps.source.esSearch.descendingLabel": "降序", "xpack.maps.source.esSearch.extentFilterLabel": "在可见地图区域中动态筛留数据", "xpack.maps.source.esSearch.fieldNotFoundMsg": "在索引模式“{indexPatternName}”中找不到“{fieldName}”。", - "xpack.maps.source.esSearch.geofieldLabel": "地理空间字段", "xpack.maps.source.esSearch.geoFieldLabel": "地理空间字段", + "xpack.maps.source.esSearch.geofieldLabel": "地理空间字段", "xpack.maps.source.esSearch.geoFieldTypeLabel": "地理空间字段类型", "xpack.maps.source.esSearch.indexOverOneLengthEditError": "您的数据视图指向多个索引。每个数据视图只允许一个索引。", "xpack.maps.source.esSearch.indexZeroLengthEditError": "您的数据视图未指向任何索引。", @@ -33131,13 +33102,11 @@ "xpack.observabilityAiAssistantManagement.settingsPage.logIndexPatternDescription": "AI 助手查询日志时使用的索引模式。日志将进行归类并用于根本原因分析", "xpack.observabilityAiAssistantManagement.settingsPage.searchConnector": "搜索连接器", "xpack.observabilityAiAssistantManagement.settingsPage.searchConnectorIndexPatternDescription": "查询搜索连接器索引(知识库的一部分)时 AI 助手使用的索引模式。默认情况下,将查询每个搜索连接器的索引", - "xpack.observabilityAiAssistantManagement.settingsPage.selectYourLanguageLabel": "选择您希望助手在生成响应时使用的语言。", "xpack.observabilityAiAssistantManagement.settingsPage.settingsLabel": "设置", "xpack.observabilityAiAssistantManagement.settingsPage.showAIAssistantButtonLabel": "在 Observability 应用中显示 AI 助手按钮和上下文洞察", "xpack.observabilityAiAssistantManagement.settingsPage.showAIAssistantDescriptionLabel": "通过在“工作区 > > 功能”中选中或取消选中 AI 助手功能,在 Observability 应用中打开或关闭 AI 助手按钮和上下文洞察。", "xpack.observabilityAiAssistantManagement.settingsPage.simulatedFunctionCallingDescription": "[技术预览] 使用模拟函数调用。模拟函数调用不需要函数或工具的 API 支持,但可能会降低性能。无论此设置如何,当前会始终对非 OpenAI 连接器启用模拟函数调用。", "xpack.observabilityAiAssistantManagement.settingsPage.simulatedFunctionCallingLabel": "模拟函数调用", - "xpack.observabilityAiAssistantManagement.settingsPage.userPreferencesLabel": "响应语言", "xpack.observabilityAiAssistantManagement.settingsTab.h3.logIndexPatternLabel": "日志索引模式", "xpack.observabilityAiAssistantManagement.settingsTab.h3.searchConnectorIndexPatternLabel": "搜索连接器索引模式", "xpack.observabilityAiAssistantManagement.span.expandRowLabel": "展开行", @@ -35485,7 +35454,6 @@ "xpack.securitySolution.alertCountByRuleByStatus.status": "状态", "xpack.securitySolution.alertCountByRuleByStatus.tooltipTitle": "规则名称", "xpack.securitySolution.alertDetails.overview.hostRiskDataTitle": "{riskEntity}风险数据", - "xpack.securitySolution.alertDetails.overview.insights.suppressedAlertsCountTechnicalPreview": "技术预览", "xpack.securitySolution.alertDetails.summary.readLess": "阅读更少内容", "xpack.securitySolution.alertDetails.summary.readMore": "阅读更多内容", "xpack.securitySolution.alerts.badge.readOnly.tooltip": "无法更新告警", @@ -36481,8 +36449,8 @@ "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.maxAlertsFieldLessThanWarning": "每次规则运行时,Kibana 最多只允许 {maxNumber} 个{maxNumber, plural, other {告警}}。", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.nameFieldRequiredError": "名称必填。", "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.noteHelpText": "添加规则调查指南......", - "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "添加规则设置指南......", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupHelpText": "提供有关规则先决条件的说明,如所需集成、配置步骤,以及规则正常运行所需的任何其他内容。", + "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "添加规则设置指南......", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupLabel": "设置指南", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.tagFieldEmptyError": "标签不得为空", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.threatIndicatorPathFieldEmptyError": "指标前缀覆盖不得为空", @@ -38848,15 +38816,11 @@ "xpack.securitySolution.event.summary.threat_indicator.modal.allMatches": "所有指标匹配", "xpack.securitySolution.event.summary.threat_indicator.modal.close": "关闭", "xpack.securitySolution.event.summary.threat_indicator.showMatches": "显示所有 {count} 个指标匹配告警", - "xpack.securitySolution.eventDetails.alertReason": "告警原因", - "xpack.securitySolution.eventDetails.description": "描述", "xpack.securitySolution.eventDetails.responseActions.endpoint.executed": "已执行 {command} 命令", "xpack.securitySolution.eventDetails.responseActions.endpoint.failed": "无法执行 {command} 命令", "xpack.securitySolution.eventDetails.responseActions.endpoint.pending": "正在执行 {command} 命令", "xpack.securitySolution.eventDetails.responseActions.endpoint.tried": "已尝试执行 {command} 命令", "xpack.securitySolution.eventDetails.summaryView": "摘要", - "xpack.securitySolution.eventDetails.table": "表", - "xpack.securitySolution.eventDetails.table.actions": "操作", "xpack.securitySolution.eventFilter.flyoutForm.confirmModal.name": "事件筛选", "xpack.securitySolution.eventFilter.flyoutForm.creationSuccessToastTitle": "“{name}”已添加到事件筛选列表。", "xpack.securitySolution.eventFilter.form.description.placeholder": "描述", @@ -39295,10 +39259,6 @@ "xpack.securitySolution.flyout.right.alertPreview.ariaLabel": "预览 ID 为 {id} 的告警", "xpack.securitySolution.flyout.right.eventCategoryText": "事件类别", "xpack.securitySolution.flyout.right.header.assignedTitle": "被分配人", - "securitySolutionPackages.flyout.right.header.collapseDetailButtonAriaLabel": "折叠详情", - "securitySolutionPackages.flyout.right.header.collapseDetailButtonLabel": "折叠详情", - "securitySolutionPackages.flyout.right.header.expandDetailButtonAriaLabel": "展开详情", - "securitySolutionPackages.flyout.right.header.expandDetailButtonLabel": "展开详情", "xpack.securitySolution.flyout.right.header.headerTitle": "文档详情", "xpack.securitySolution.flyout.right.header.jsonTabLabel": "JSON", "xpack.securitySolution.flyout.right.header.overviewTabLabel": "概览", @@ -39384,10 +39344,6 @@ "xpack.securitySolution.flyout.right.visualizations.sessionPreview.timeDescription": "处于", "xpack.securitySolution.flyout.right.visualizations.sessionPreview.upsellDescription": "此功能需要{subscription}", "xpack.securitySolution.flyout.right.visualizations.sessionPreview.upsellLinkText": "企业级订阅", - "securitySolutionPackages.flyout.shared.errorDescription": "显示 {message} 时出现错误。", - "securitySolutionPackages.flyout.shared.errorTitle": "无法显示 {title}。", - "securitySolutionPackages.flyout.shared.ExpandablePanelButtonIconAriaLabel": "可展开面板切换按钮", - "securitySolutionPackages.flyout.shared.expandablePanelLoadingAriaLabel": "可展开面板", "xpack.securitySolution.flyout.tour.entities.description": "请查阅展开的 {entities} 视图以了解与该告警有关的主机和用户的更多信息。", "xpack.securitySolution.flyout.tour.entities.text": "实体", "xpack.securitySolution.flyout.tour.entities.title": "有新主机和用户洞见可用", @@ -41753,7 +41709,6 @@ "xpack.slo.permissionsCallout.readIndexPermission": "您要用于创建 SLO 的任何索引模式上的“read”和“view_index_metadata”索引权限", "xpack.slo.permissionsCallout.readSloPermission": "索引模式上的“read”权限:.slo-*", "xpack.slo.permissionsCallout.title": "权限不足", - "xpack.slo.permissionsCallout.writeClusterPermission": "“manage_transform”和“manage_ingest_pipelines”集群权限", "xpack.slo.permissionsCallout.writeSloPermission": "索引模式上的“all”权限:.slo-*", "xpack.slo.queryBuilder.closeButtonLabel": "关闭", "xpack.slo.queryBuilder.documentsButtonLabel": "查看文档", @@ -42097,8 +42052,8 @@ "xpack.slo.sloEmbeddable.config.sloSelector.placeholder": "选择 SLO", "xpack.slo.sloEmbeddable.displayName": "SLO 概览", "xpack.slo.sloEmbeddable.overview.sloNotFoundText": "SLO 已删除。您可以放心从仪表板中删除小组件。", - "xpack.slo.sloGridItem.targetFlexItemLabel": "目标 {target}", "xpack.slo.sLOGridItem.targetFlexItemLabel": "目标 {target}", + "xpack.slo.sloGridItem.targetFlexItemLabel": "目标 {target}", "xpack.slo.sloGroupConfiguration.customFiltersLabel": "定制筛选", "xpack.slo.sloGroupConfiguration.customFiltersOptional": "可选", "xpack.slo.sloGroupConfiguration.customFilterText": "定制筛选", @@ -43544,8 +43499,8 @@ "xpack.stackConnectors.components.casesWebhookxpack.stackConnectors.components.casesWebhook.connectorTypeTitle": "Webhook - 案例管理数据", "xpack.stackConnectors.components.d3security.bodyCodeEditorAriaLabel": "代码编辑器", "xpack.stackConnectors.components.d3security.bodyFieldLabel": "正文", - "xpack.stackConnectors.components.d3security.connectorTypeTitle": "D3 数据", "xpack.stackConnectors.components.d3Security.connectorTypeTitle": "D3 Security", + "xpack.stackConnectors.components.d3security.connectorTypeTitle": "D3 数据", "xpack.stackConnectors.components.d3security.eventTypeFieldLabel": "事件类型", "xpack.stackConnectors.components.d3security.invalidActionText": "操作名称无效。", "xpack.stackConnectors.components.d3security.requiredActionText": "“操作”必填。", diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_autocomplete/index.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_autocomplete/index.tsx index 53f0d7d500eed..da3b08fda8e18 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_autocomplete/index.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_autocomplete/index.tsx @@ -172,7 +172,7 @@ export const TextAreaWithAutocomplete: React.FunctionComponent { + (event: React.KeyboardEvent) => { if (selectableRef.current && isListOpen) { if (!selectableHasFocus && (event.code === 'ArrowUp' || event.code === 'ArrowDown')) { event.preventDefault(); @@ -219,7 +219,7 @@ export const TextAreaWithAutocomplete: React.FunctionComponent { + (event: any) => { const box = document .querySelector('.euiSelectableMsgAutoComplete') ?.getBoundingClientRect() || { @@ -292,7 +292,7 @@ export const TextAreaWithAutocomplete: React.FunctionComponent closeList(), [closeList]); const onScroll = useCallback( - (evt) => { + (evt: any) => { // FUTURE ENGINEER -> we need to make sure to not close the autocomplete option list if (selectableRef?.current?.listId !== evt.target?.firstElementChild?.id) { closeList(true); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_alerts_filter_query.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_alerts_filter_query.tsx index bbaf737101910..683bf29432668 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_alerts_filter_query.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_alerts_filter_query.tsx @@ -12,7 +12,7 @@ import { i18n } from '@kbn/i18n'; import { EuiSwitch, EuiSpacer } from '@elastic/eui'; import { AlertsFilter } from '@kbn/alerting-plugin/common'; import deepEqual from 'fast-deep-equal'; -import { AlertsSearchBar } from '../alerts_search_bar'; +import { AlertsSearchBar, AlertsSearchBarProps } from '../alerts_search_bar'; interface ActionAlertsFilterQueryProps { state?: AlertsFilter['query']; @@ -52,7 +52,7 @@ export const ActionAlertsFilterQuery: React.FC = ( [query, setQuery] ); - const onQueryChange = useCallback( + const onQueryChange: AlertsSearchBarProps['onQueryChange'] = useCallback( ({ query: newQuery }) => updateQuery({ kql: newQuery }), [updateQuery] ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx index 7d34fb42409d0..1a55e2990fbf7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx @@ -376,7 +376,7 @@ export const ActionTypeForm = ({ throttleUnit={actionThrottleUnit} hasAlertsMappings={hasAlertsMappings} onNotifyWhenChange={useCallback( - (notifyWhen) => { + (notifyWhen: RuleNotifyWhenType) => { setActionFrequencyProperty('notifyWhen', notifyWhen, index); }, [setActionFrequencyProperty, index] diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_event_log_list_table.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_event_log_list_table.tsx index 9cd6305b81e79..ce977ea349cbe 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_event_log_list_table.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_event_log_list_table.tsx @@ -262,7 +262,7 @@ export const ConnectorEventLogListTable = { + (e: React.ChangeEvent) => { if (e.target.value === '') { setSearchText(''); } @@ -272,7 +272,7 @@ export const ConnectorEventLogListTable = { + (e: React.KeyboardEvent) => { if (e.key === 'Enter') { setSearchText(search); } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_pagination.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_pagination.ts index bc0c14772b575..61fda55c4eb3a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_pagination.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_pagination.ts @@ -32,7 +32,7 @@ export function usePagination({ onPageChange, pageIndex, pageSize }: PaginationP }); const [flyoutAlertIndex, setFlyoutAlertIndex] = useState(-1); const onChangePageSize = useCallback( - (_pageSize) => { + (_pageSize: number) => { setPagination((state) => ({ ...state, pageSize: _pageSize, @@ -44,7 +44,7 @@ export function usePagination({ onPageChange, pageIndex, pageSize }: PaginationP [updateBulkActionsState, onPageChange] ); const onChangePageIndex = useCallback( - (_pageIndex) => { + (_pageIndex: number) => { setPagination((state) => ({ ...state, pageIndex: _pageIndex })); updateBulkActionsState({ action: BulkActionsVerbs.clear }); onPageChange({ pageIndex: _pageIndex, pageSize: pagination.pageSize }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/execution_duration_chart.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/execution_duration_chart.tsx index 4999496f669c3..c8afbb76f5910 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/execution_duration_chart.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/execution_duration_chart.tsx @@ -65,7 +65,7 @@ export const ExecutionDurationChart: React.FunctionComponent = ({ numberOfExecutions ); - const onChange = useCallback( + const onChange: React.ChangeEventHandler = useCallback( ({ target }) => onChangeDuration(Number(target.value)), [onChangeDuration] ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/field_browser/components/field_table/field_table.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/field_browser/components/field_table/field_table.tsx index c5bf664776301..7647e8c625761 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/field_browser/components/field_table/field_table.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/field_browser/components/field_table/field_table.tsx @@ -5,18 +5,24 @@ * 2.0. */ import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { EuiInMemoryTable, Pagination, Direction, useEuiTheme } from '@elastic/eui'; +import { + EuiInMemoryTable, + Pagination, + Direction, + useEuiTheme, + CriteriaWithPagination, +} from '@elastic/eui'; import { BrowserFields } from '@kbn/rule-registry-plugin/common'; import { getFieldColumns, getFieldItemsData } from '../field_items'; import { CATEGORY_TABLE_CLASS_NAME, TABLE_HEIGHT } from '../../helpers'; -import type { FieldBrowserProps, GetFieldTableColumns } from '../../types'; +import type { BrowserFieldItem, FieldBrowserProps, GetFieldTableColumns } from '../../types'; import { FieldTableHeader } from './field_table_header'; import { styles } from './field_table.styles'; -const DEFAULT_SORTING: { field: string; direction: Direction } = { - field: '', +const DEFAULT_SORTING: { field: keyof BrowserFieldItem; direction: Direction } = { + field: 'name', direction: 'asc', -} as const; +}; export interface FieldTableProps extends Pick { /** @@ -104,16 +110,19 @@ const FieldTableComponent: React.FC = ({ [sortDirection, sortField] ); - const onTableChange = useCallback(({ page, sort = DEFAULT_SORTING }) => { - const { index, size } = page; - const { field, direction } = sort; + const onTableChange = useCallback( + ({ page, sort = DEFAULT_SORTING }: CriteriaWithPagination) => { + const { index, size } = page; + const { field, direction } = sort; - setPageIndex(index); - setPageSize(size); + setPageIndex(index); + setPageSize(size); - setSortField(field); - setSortDirection(direction); - }, []); + setSortField(field); + setSortDirection(direction); + }, + [] + ); /** * Process columns diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_error_log.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_error_log.tsx index 2d33a205e6e36..34993d085425e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_error_log.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_error_log.tsx @@ -171,7 +171,7 @@ export const RuleErrorLog = (props: RuleErrorLogProps) => { ); const onSearchChange = useCallback( - (e) => { + (e: React.ChangeEvent) => { if (e.target.value === '') { setSearchText(''); } @@ -181,7 +181,7 @@ export const RuleErrorLog = (props: RuleErrorLogProps) => { ); const onKeyUp = useCallback( - (e) => { + (e: React.KeyboardEvent) => { if (e.key === 'Enter') { setSearchText(search); } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_table.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_table.tsx index 0aacada7e810c..bcaba9f511c6e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_table.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_table.tsx @@ -46,7 +46,10 @@ import { RulesListDocLink } from '../../rules_list/components/rules_list_doc_lin import { LoadExecutionLogAggregationsProps } from '../../../lib/rule_api'; import { RuleEventLogListKPIWithApi as RuleEventLogListKPI } from './rule_event_log_list_kpi'; import { useMultipleSpaces } from '../../../hooks/use_multiple_spaces'; -import { useLoadRuleEventLogs } from '../../../hooks/use_load_rule_event_logs'; +import { + useLoadRuleEventLogs, + UseLoadRuleEventLogsProps, +} from '../../../hooks/use_load_rule_event_logs'; import { RulesSettingsLink } from '../../../components/rules_setting/rules_settings_link'; import { RefreshToken } from './types'; @@ -196,7 +199,7 @@ export const RuleEventLogListTable = ( // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const onError = useCallback( + const onError = useCallback>( (e) => { if (e.body.statusCode === 413) { return; @@ -309,7 +312,7 @@ export const RuleEventLogListTable = ( }, []); const onSearchChange = useCallback( - (e) => { + (e: React.ChangeEvent) => { if (e.target.value === '') { setSearchText(''); } @@ -319,7 +322,7 @@ export const RuleEventLogListTable = ( ); const onKeyUp = useCallback( - (e) => { + (e: React.KeyboardEvent) => { if (e.key === 'Enter') { setSearchText(search); } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_status_panel.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_status_panel.tsx index 2419993f12670..0e07b73b56c4e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_status_panel.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_status_panel.tsx @@ -20,6 +20,7 @@ import { EuiTitle, EuiHorizontalRule, } from '@elastic/eui'; +import { SnoozeSchedule } from '../../../../types'; import { RuleStatusDropdown } from '../..'; import { ComponentOpts as RuleApis, @@ -60,11 +61,11 @@ export const RuleStatusPanel: React.FC = ({ const isInitialized = useRef(false); const onSnoozeRule = useCallback( - (snoozeSchedule) => snoozeRule(rule, snoozeSchedule), + (snoozeSchedule: SnoozeSchedule) => snoozeRule(rule, snoozeSchedule), [rule, snoozeRule] ); const onUnsnoozeRule = useCallback( - (scheduleIds) => unsnoozeRule(rule, scheduleIds), + (scheduleIds?: string[]) => unsnoozeRule(rule, scheduleIds), [rule, unsnoozeRule] ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_add.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_add.tsx index e3d564afaeda8..8657248a29df3 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_add.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_add.tsx @@ -78,7 +78,7 @@ const RuleAdd = < }: RuleAddProps) => { const onSaveHandler = onSave ?? reloadRules; const [metadata, setMetadata] = useState(initialMetadata); - const onChangeMetaData = useCallback((newMetadata) => setMetadata(newMetadata), []); + const onChangeMetaData = useCallback((newMetadata: any) => setMetadata(newMetadata), []); const initialRule: InitialRule = useMemo(() => { return { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_edit.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_edit.tsx index 9c0abae3eb2a3..72eab243ad0c8 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_edit.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_edit.tsx @@ -137,7 +137,7 @@ export const RuleEdit = < const [config, setConfig] = useState({ isUsingSecurity: false }); const [metadata, setMetadata] = useState(initialMetadata); - const onChangeMetaData = useCallback((newMetadata) => setMetadata(newMetadata), []); + const onChangeMetaData = useCallback((newMetadata: any) => setMetadata(newMetadata), []); const { http, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/helpers/number_field.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/helpers/number_field.tsx index 2483f6fc4a43c..3f4be5cde90c8 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/helpers/number_field.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/helpers/number_field.tsx @@ -18,9 +18,12 @@ export const NumberField: React.FC< const max = typeof props.max !== 'undefined' ? props.max : Infinity; const onChange = useCallback( - (e) => { + (e: React.ChangeEvent) => { const { value } = e.target; - const isValid = !isNaN(Number(value)) && value >= min && value <= max; + const valueAsNumber = Number(value); + + const isValid = !isNaN(valueAsNumber) && valueAsNumber >= min && valueAsNumber <= max; + if (isValid || value === '') { setDisplayValue(value); } @@ -32,7 +35,7 @@ export const NumberField: React.FC< ); const onBlur = useCallback( - (e) => { + (e: React.FocusEvent) => { if (isNaN(Number(displayValue)) || displayValue === '') { setDisplayValue(props.value); } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/panel/base_snooze_panel.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/panel/base_snooze_panel.tsx index 40d705e878165..3d6523a144e99 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/panel/base_snooze_panel.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/panel/base_snooze_panel.tsx @@ -77,11 +77,18 @@ export const BaseSnoozePanel: React.FunctionComponent = ({ const { euiTheme } = useEuiTheme(); - const onChangeValue = useCallback( - ({ target }) => setIntervalValue(target.value), + const onChangeValue: React.ChangeEventHandler = useCallback( + ({ target }) => { + const value = Number(target.value); + + if (!isNaN(value)) { + setIntervalValue(value); + } + }, [setIntervalValue] ); - const onChangeUnit = useCallback( + + const onChangeUnit: React.ChangeEventHandler = useCallback( ({ target }) => setIntervalUnit(target.value), [setIntervalUnit] ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/scheduler.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/scheduler.tsx index 97c8065c18f21..4e17bca05e4e0 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/scheduler.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/scheduler.tsx @@ -196,7 +196,7 @@ const RuleSnoozeSchedulerPanel: React.FunctionComponent = ({ }, [setSelectingEndDate]); const selectStartDT = useCallback( - (date, clearEndDT) => { + (date: Moment, clearEndDT: boolean) => { setStartDT(moment.max(date, minDate)); if (clearEndDT) { setEndDT(null); @@ -207,7 +207,7 @@ const RuleSnoozeSchedulerPanel: React.FunctionComponent = ({ [setStartDT, setSelectingEndDate, minDate] ); const selectEndDT = useCallback( - (date) => { + (date: Moment) => { setEndDT(date.add(1, 'minutes')); setSelectingEndTime(true); setSelectingEndDate(false); @@ -216,7 +216,7 @@ const RuleSnoozeSchedulerPanel: React.FunctionComponent = ({ ); const onSelectFromInline = useCallback( - (date) => { + (date: Moment) => { const dateAsMoment = moment(date); const newDateAfterStart = !startDT || dateAsMoment.isSameOrAfter(startDT); const isEndDateTimeChange = @@ -228,6 +228,7 @@ const RuleSnoozeSchedulerPanel: React.FunctionComponent = ({ const applyToEndDate = !isStartDateTimeChange && (selectingEndDate || (isEndDateTimeChange && selectingEndTime)); + if (applyToEndDate && newDateAfterStart) { selectEndDT(date); } else selectStartDT(date, !isStartDateTimeChange); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_status_dropdown.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_status_dropdown.tsx index ddd836a4f0993..6ad7d525c3507 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_status_dropdown.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_status_dropdown.tsx @@ -147,7 +147,7 @@ export const RuleStatusDropdown: React.FunctionComponent = ({ ); const onSnoozeRule = useCallback( - async (snoozeSchedule) => { + async (snoozeSchedule: SnoozeSchedule) => { try { await snoozeRule(snoozeSchedule); onRuleChanged(); @@ -159,7 +159,7 @@ export const RuleStatusDropdown: React.FunctionComponent = ({ ); const onUnsnoozeRule = useCallback( - async (scheduleIds) => { + async (scheduleIds?: string[]) => { try { await unsnoozeRule(scheduleIds); onRuleChanged(); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_auto_refresh.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_auto_refresh.tsx index 42c59667e0e39..3b5dff7052559 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_auto_refresh.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_auto_refresh.tsx @@ -9,6 +9,7 @@ import { i18n } from '@kbn/i18n'; import React, { useCallback, useEffect, useState, useRef } from 'react'; import moment from 'moment'; import { EuiFlexGroup, EuiFlexItem, EuiText, EuiAutoRefreshButton } from '@elastic/eui'; +import { OnRefreshChangeProps } from '@elastic/eui/src/components/date_picker/types'; interface RulesListAutoRefreshProps { lastUpdate: string; @@ -95,7 +96,7 @@ export const RulesListAutoRefresh = (props: RulesListAutoRefreshProps) => { }, [isPaused, refreshInterval]); const onRefreshChange = useCallback( - ({ isPaused: newIsPaused, refreshInterval: newRefreshInterval }) => { + ({ isPaused: newIsPaused, refreshInterval: newRefreshInterval }: OnRefreshChangeProps) => { setIsPaused(newIsPaused); setRefreshInterval(newRefreshInterval); }, diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx index 4a617ba61097e..7d527c27d8303 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx @@ -205,7 +205,7 @@ export const EsDeprecationsTable: React.FunctionComponent = ({ [sortConfig] ); - const handleSearch = useCallback(({ query, error }) => { + const handleSearch = useCallback(({ query, error }: any) => { if (error) { setSearchError(error); } else { diff --git a/x-pack/test/alerting_api_integration/common/plugins/alerts/server/sub_action_connector.ts b/x-pack/test/alerting_api_integration/common/plugins/alerts/server/sub_action_connector.ts index 7bd9db83dcc00..302bbf2b06668 100644 --- a/x-pack/test/alerting_api_integration/common/plugins/alerts/server/sub_action_connector.ts +++ b/x-pack/test/alerting_api_integration/common/plugins/alerts/server/sub_action_connector.ts @@ -11,6 +11,7 @@ import type { ServiceParams } from '@kbn/actions-plugin/server'; import { PluginSetupContract as ActionsPluginSetup } from '@kbn/actions-plugin/server/plugin'; import { schema, TypeOf } from '@kbn/config-schema'; import { SubActionConnectorType } from '@kbn/actions-plugin/server/sub_action_framework/types'; +import { ConnectorUsageCollector } from '@kbn/actions-plugin/server/types'; const TestConfigSchema = schema.object({ url: schema.string() }); const TestSecretsSchema = schema.object({ @@ -69,7 +70,11 @@ export const getTestSubActionConnector = ( return `Message: ${error.response?.data.errorMessage}. Code: ${error.response?.data.errorCode}`; } - public async subActionWithParams({ id }: { id: string }) { + public async subActionWithParams( + { id }: { id: string }, + connectorUsageCollector: ConnectorUsageCollector + ) { + connectorUsageCollector.addRequestBodyBytes(undefined, { id }); return { id }; } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/bedrock.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/bedrock.ts index 1b39410a7bf93..3bc7b665e2c2e 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/bedrock.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/bedrock.ts @@ -13,8 +13,9 @@ import { } from '@kbn/actions-simulators-plugin/server/bedrock_simulation'; import { DEFAULT_TOKEN_LIMIT } from '@kbn/stack-connectors-plugin/common/bedrock/constants'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; +import { IValidatedEvent } from '@kbn/event-log-plugin/generated/schemas'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; -import { getUrlPrefix, ObjectRemover } from '../../../../../common/lib'; +import { getEventLog, getUrlPrefix, ObjectRemover } from '../../../../../common/lib'; const connectorTypeId = '.bedrock'; const name = 'A bedrock action'; @@ -344,6 +345,23 @@ export default function bedrockTest({ getService }: FtrProviderContext) { }, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: bedrockActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(145); }); it('should overwrite the model when a model argument is provided', async () => { @@ -374,6 +392,23 @@ export default function bedrockTest({ getService }: FtrProviderContext) { }, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: bedrockActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 2 }], + ['execute', { gte: 2 }], + ]), + }); + }); + + const executeEvent = events[3]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(145); }); it('should invoke AI with assistant AI body argument formatted to bedrock expectations', async () => { @@ -423,6 +458,23 @@ export default function bedrockTest({ getService }: FtrProviderContext) { connector_id: bedrockActionId, data: { message: bedrockClaude2SuccessResponse.completion }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: bedrockActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 3 }], + ['execute', { gte: 3 }], + ]), + }); + }); + + const executeEvent = events[5]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(256); }); describe('Token tracking dashboard', () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/cases_webhook.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/cases_webhook.ts index f26ba86f6fa3a..1ef7b170a4f0d 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/cases_webhook.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/cases_webhook.ts @@ -14,13 +14,16 @@ import { ExternalServiceSimulator, } from '@kbn/actions-simulators-plugin/server/plugin'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; +import { IValidatedEvent } from '@kbn/event-log-plugin/generated/schemas'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function casesWebhookTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); const configService = getService('config'); + const retry = getService('retry'); const config = { createCommentJson: '{"body":{{{case.comment}}}}', createCommentMethod: 'post', @@ -398,6 +401,23 @@ export default function casesWebhookTest({ getService }: FtrProviderContext) { const { pushedDate, ...dataWithoutTime } = body.data; body.data = dataWithoutTime; + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(125); + expect(body).to.eql({ status: 'ok', connector_id: simulatedActionId, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/d3security.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/d3security.ts index 7e1f0636b3a96..72cea764d0165 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/d3security.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/d3security.ts @@ -12,7 +12,9 @@ import { d3SecuritySuccessResponse, } from '@kbn/actions-simulators-plugin/server/d3security_simulation'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; +import { IValidatedEvent } from '@kbn/event-log-plugin/generated/schemas'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; const connectorTypeId = '.d3security'; const name = 'A D3 Security action'; @@ -24,6 +26,7 @@ const secrets = { export default function d3SecurityTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); const createConnector = async (url: string) => { const { body } = await supertest @@ -248,6 +251,24 @@ export default function d3SecurityTest({ getService }: FtrProviderContext) { }, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: d3SecurityActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(99); + expect(body).to.eql({ status: 'ok', connector_id: d3SecurityActionId, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/email.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/email.ts index cfffe90126fac..6ed2c89e094f9 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/email.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/email.ts @@ -11,12 +11,15 @@ import { ExternalServiceSimulator, getExternalServiceSimulatorPath, } from '@kbn/actions-simulators-plugin/server/plugin'; +import { IValidatedEvent } from '@kbn/event-log-plugin/generated/schemas'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function emailTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); + const retry = getService('retry'); describe('create email action', () => { let createdActionId = ''; @@ -103,7 +106,7 @@ export default function emailTest({ getService }: FtrProviderContext) { }, }) .expect(200) - .then((resp: any) => { + .then(async (resp: any) => { expect(resp.body.data.message.messageId).to.be.a('string'); expect(resp.body.data.messageId).to.be.a('string'); @@ -131,6 +134,23 @@ export default function emailTest({ getService }: FtrProviderContext) { headers: {}, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: createdActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(350); }); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/es_index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/es_index.ts index 46287db208b87..8d867aea49685 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/es_index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/es_index.ts @@ -7,7 +7,9 @@ import type { Client } from '@elastic/elasticsearch'; import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/generated/schemas'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; const ES_TEST_INDEX_NAME = 'functional-test-actions-index'; @@ -16,6 +18,7 @@ export default function indexTest({ getService }: FtrProviderContext) { const es: Client = getService('es'); const supertest = getService('supertest'); const esDeleteAllIndices = getService('esDeleteAllIndices'); + const retry = getService('retry'); describe('index action', () => { beforeEach(() => esDeleteAllIndices(ES_TEST_INDEX_NAME)); @@ -214,6 +217,23 @@ export default function indexTest({ getService }: FtrProviderContext) { } expect(passed1).to.be(true); expect(passed2).to.be(true); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: createdAction.id, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(0); }); it('should execute successly with refresh false', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/jira.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/jira.ts index 054678996888f..2268e379f441a 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/jira.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/jira.ts @@ -7,6 +7,7 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/generated/schemas'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; import { @@ -16,12 +17,14 @@ import { import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { MAX_OTHER_FIELDS_LENGTH } from '@kbn/stack-connectors-plugin/common/jira/constants'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function jiraTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); const configService = getService('config'); + const retry = getService('retry'); const mockJira = { config: { @@ -517,6 +520,23 @@ export default function jiraTest({ getService }: FtrProviderContext) { url: `${jiraSimulatorURL}/browse/CK-1`, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 2 }], + ['execute', { gte: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(124); }); it('should handle creating an incident with other fields', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/openai.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/openai.ts index 716041e939e8a..05dfc61dd59e3 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/openai.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/openai.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { OpenAISimulator, @@ -14,6 +15,7 @@ import { import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; import { getUrlPrefix, ObjectRemover } from '../../../../../common/lib'; +import { getEventLog } from '../../../../../common/lib'; const connectorTypeId = '.gen-ai'; const name = 'A genAi action'; @@ -315,6 +317,23 @@ export default function genAiTest({ getService }: FtrProviderContext) { connector_id: genAiActionId, data: genAiSuccessResponse, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: genAiActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(78); }); describe('Token tracking dashboard', () => { const dashboardId = 'specific-dashboard-id-default'; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/opsgenie.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/opsgenie.ts index 48386480b00da..75913a4182bbd 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/opsgenie.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/opsgenie.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { OpsgenieSimulator, @@ -13,11 +14,13 @@ import { } from '@kbn/actions-simulators-plugin/server/opsgenie_simulation'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function opsgenieTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); describe('Opsgenie', () => { describe('action creation', () => { @@ -535,6 +538,23 @@ export default function opsgenieTest({ getService }: FtrProviderContext) { connector_id: opsgenieActionId, data: opsgenieSuccessResponse, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: opsgenieActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(21); }); it('should preserve the alias when it is 512 characters when creating an alert', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/pagerduty.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/pagerduty.ts index 7148ac962c728..2871066b6456a 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/pagerduty.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/pagerduty.ts @@ -7,6 +7,7 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; import { @@ -14,12 +15,14 @@ import { ExternalServiceSimulator, } from '@kbn/actions-simulators-plugin/server/plugin'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function pagerdutyTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); const configService = getService('config'); + const retry = getService('retry'); describe('pagerduty action', () => { let simulatedActionId = ''; @@ -173,6 +176,23 @@ export default function pagerdutyTest({ getService }: FtrProviderContext) { status: 'success', }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(142); }); it('should execute successfully with links and customDetails', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/resilient.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/resilient.ts index c9b4e7ecafa3f..6dfb420463e9f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/resilient.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/resilient.ts @@ -6,15 +6,18 @@ */ import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { ResilientSimulator } from '@kbn/actions-simulators-plugin/server/resilient_simulation'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function resilientTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); const mockResilient = { config: { @@ -409,6 +412,23 @@ export default function resilientTest({ getService }: FtrProviderContext) { url: `${simulatorUrl}/#incidents/123`, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: resilientActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(167); }); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/server_log.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/server_log.ts index a5f14e512ddb1..a3fedba5d1f69 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/server_log.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/server_log.ts @@ -6,12 +6,15 @@ */ import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function serverLogTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); + const retry = getService('retry'); describe('server-log action', () => { let serverLogActionId: string; @@ -69,6 +72,23 @@ export default function serverLogTest({ getService }: FtrProviderContext) { .expect(200); expect(result.status).to.eql('ok'); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: serverLogActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(0); }); }); } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_itom.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_itom.ts index 4702d3bbe6df7..0f1748db4f5ef 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_itom.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_itom.ts @@ -10,16 +10,19 @@ import expect from '@kbn/expect'; import { asyncForEach } from '@kbn/std'; import getPort from 'get-port'; import http from 'http'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; import { getServiceNowServer } from '@kbn/actions-simulators-plugin/server/plugin'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function serviceNowITOMTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); const mockServiceNowCommon = { params: { @@ -500,6 +503,23 @@ export default function serviceNowITOMTest({ getService }: FtrProviderContext) { }) .expect(200); expect(result.status).to.eql('ok'); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(317); }); }); @@ -548,6 +568,23 @@ export default function serviceNowITOMTest({ getService }: FtrProviderContext) { }, ], }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 2 }], + ['execute', { equal: 2 }], + ]), + }); + }); + + const executeEvent = events[3]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(0); }); }); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_itsm.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_itsm.ts index ec62e6d30f6ff..bc0f48f15caf5 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_itsm.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_itsm.ts @@ -10,17 +10,20 @@ import expect from '@kbn/expect'; import { asyncForEach } from '@kbn/std'; import getPort from 'get-port'; import http from 'http'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; import { getServiceNowServer } from '@kbn/actions-simulators-plugin/server/plugin'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { MAX_ADDITIONAL_FIELDS_LENGTH } from '@kbn/stack-connectors-plugin/common/servicenow/constants'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function serviceNowITSMTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); const mockServiceNowCommon = { params: { @@ -708,6 +711,23 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { url: `${serviceNowSimulatorURL}/nav_to.do?uri=incident.do?sys_id=123`, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(261); }); }); @@ -755,6 +775,23 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { url: `${serviceNowSimulatorURL}/nav_to.do?uri=incident.do?sys_id=123`, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(239); }); }); @@ -803,6 +840,23 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { }, ], }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 2 }], + ['execute', { gte: 2 }], + ]), + }); + }); + + const executeEvent = events[3]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(0); }); }); @@ -829,6 +883,22 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { connector_id: simulatedActionId, data: {}, }); + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 3 }], + ['execute', { gte: 3 }], + ]), + }); + }); + + const executeEvent = events[5]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(0); }); }); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_sir.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_sir.ts index fd4781f6d9e62..717a44a406712 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_sir.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/servicenow_sir.ts @@ -10,17 +10,20 @@ import expect from '@kbn/expect'; import { asyncForEach } from '@kbn/std'; import getPort from 'get-port'; import http from 'http'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; import { getServiceNowServer } from '@kbn/actions-simulators-plugin/server/plugin'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { MAX_ADDITIONAL_FIELDS_LENGTH } from '@kbn/stack-connectors-plugin/common/servicenow/constants'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function serviceNowSIRTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); const mockServiceNowCommon = { config: { @@ -721,6 +724,23 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) { url: `${serviceNowSimulatorURL}/nav_to.do?uri=sn_si_incident.do?sys_id=123`, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(645); }); }); @@ -768,6 +788,22 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) { url: `${serviceNowSimulatorURL}/nav_to.do?uri=sn_si_incident.do?sys_id=123`, }, }); + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(429); }); }); @@ -816,6 +852,23 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) { }, ], }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 2 }], + ['execute', { gte: 2 }], + ]), + }); + }); + + const executeEvent = events[3]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(0); }); }); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/slack_webhook.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/slack_webhook.ts index 4941bec1844ca..457f9edbed2fc 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/slack_webhook.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/slack_webhook.ts @@ -9,14 +9,18 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; import http from 'http'; import getPort from 'get-port'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; + import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; import { getSlackServer } from '@kbn/actions-simulators-plugin/server/plugin'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function slackTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); describe('Slack webhook action', () => { let simulatedActionId = ''; @@ -175,6 +179,23 @@ export default function slackTest({ getService }: FtrProviderContext) { .expect(200); expect(result.status).to.eql('ok'); expect(proxyHaveBeenCalled).to.equal(true); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(18); }); it('should handle an empty message error', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/swimlane.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/swimlane.ts index 859f4f952fe58..4d91fdddf80dd 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/swimlane.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/swimlane.ts @@ -9,16 +9,19 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; import getPort from 'get-port'; import http from 'http'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; import { getSwimlaneServer } from '@kbn/actions-simulators-plugin/server/plugin'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function swimlaneTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); const mockSwimlane = { name: 'A swimlane action', @@ -459,6 +462,23 @@ export default function swimlaneTest({ getService }: FtrProviderContext) { url: `${swimlaneSimulatorURL}/record/123456asdf/wowzeronza`, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(175); }); it('should handle updating an incident', async () => { @@ -490,6 +510,23 @@ export default function swimlaneTest({ getService }: FtrProviderContext) { url: `${swimlaneSimulatorURL}/record/123456asdf/wowzeronza`, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 1 }], + ['execute', { gte: 2 }], + ]), + }); + }); + + const executeEvent = events[3]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(193); }); }); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/tines.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/tines.ts index 53dd3aaaf026a..04971990f879e 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/tines.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/tines.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { TinesSimulator, @@ -16,6 +17,7 @@ import { } from '@kbn/actions-simulators-plugin/server/tines_simulation'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; const connectorTypeId = '.tines'; const name = 'A tines action'; @@ -35,6 +37,7 @@ const webhook = { export default function tinesTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const configService = getService('config'); + const retry = getService('retry'); const createConnector = async (url: string) => { const { body } = await supertest @@ -392,6 +395,23 @@ export default function tinesTest({ getService }: FtrProviderContext) { incompleteResponse: false, }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: tinesActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(2); }); it('should get webhooks', async () => { @@ -422,6 +442,22 @@ export default function tinesTest({ getService }: FtrProviderContext) { incompleteResponse: false, }, }); + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: tinesActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 2 }], + ['execute', { gte: 2 }], + ]), + }); + }); + + const executeEvent = events[3]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(2); }); it('should run the webhook', async () => { @@ -440,6 +476,22 @@ export default function tinesTest({ getService }: FtrProviderContext) { connector_id: tinesActionId, data: tinesWebhookSuccessResponse, }); + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: tinesActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 3 }], + ['execute', { gte: 3 }], + ]), + }); + }); + + const executeEvent = events[5]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(8); }); it('should run the webhook url', async () => { @@ -464,6 +516,22 @@ export default function tinesTest({ getService }: FtrProviderContext) { connector_id: tinesActionId, data: tinesWebhookSuccessResponse, }); + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: tinesActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 3 }], + ['execute', { gte: 3 }], + ]), + }); + }); + + const executeEvent = events[5]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(8); }); }); @@ -506,6 +574,22 @@ export default function tinesTest({ getService }: FtrProviderContext) { errorSource: TaskErrorSource.FRAMEWORK, service_message: 'Status code: 422. Message: API Error: Unprocessable Entity', }); + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: tinesActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 1 }], + ['execute', { gte: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(2); }); it('should return a failure when attempting to get webhooks', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/torq.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/torq.ts index 257378b406da5..b709ef837ad03 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/torq.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/torq.ts @@ -7,6 +7,7 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers/get_proxy_server'; import { @@ -14,12 +15,14 @@ import { ExternalServiceSimulator, } from '@kbn/actions-simulators-plugin/server/plugin'; import { FtrProviderContext } from '../../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function torqTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); const configService = getService('config'); + const retry = getService('retry'); describe('Torq action', () => { let simulatedActionId = ''; @@ -159,6 +162,22 @@ export default function torqTest({ getService }: FtrProviderContext) { connector_id: simulatedActionId, data: `{"msg": "test"}`, }); + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 1 }], + ['execute', { gte: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(14); }); it('should handle a 400 Torq error', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/webhook.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/webhook.ts index c7a8f1c1b2524..f05db95254c1c 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/webhook.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/webhook.ts @@ -8,6 +8,8 @@ import httpProxy from 'http-proxy'; import http from 'http'; import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; + import { URL, format as formatUrl } from 'url'; import getPort from 'get-port'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; @@ -17,6 +19,7 @@ import { getWebhookServer, } from '@kbn/actions-simulators-plugin/server/plugin'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; const defaultValues: Record = { headers: null, @@ -36,6 +39,7 @@ export default function webhookTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); const configService = getService('config'); + const retry = getService('retry'); async function createWebhookAction( webhookSimulatorURL: string, @@ -258,6 +262,23 @@ export default function webhookTest({ getService }: FtrProviderContext) { .expect(200); expect(result.status).to.eql('ok'); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: webhookActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 1 }], + ['execute', { gte: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(19); }); it('should support the PUT method against webhook target', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/xmatters.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/xmatters.ts index 4efacbf78f951..7cf2320c97933 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/xmatters.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/xmatters.ts @@ -7,6 +7,7 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; +import { IValidatedEvent } from '@kbn/event-log-plugin/server'; import { getHttpProxyServer } from '@kbn/alerting-api-integration-helpers'; import { @@ -14,12 +15,14 @@ import { ExternalServiceSimulator, } from '@kbn/actions-simulators-plugin/server/plugin'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getEventLog } from '../../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function xmattersTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); const configService = getService('config'); + const retry = getService('retry'); describe('xmatters action', () => { let simulatedActionId = ''; @@ -180,6 +183,23 @@ export default function xmattersTest({ getService }: FtrProviderContext) { spaceId: '', }, }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: simulatedActionId, + provider: 'actions', + actions: new Map([ + ['execute-start', { gte: 1 }], + ['execute', { gte: 1 }], + ]), + }); + }); + + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.be(130); }); it('should handle a 40x xmatters error', async () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/execute.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/execute.ts index acfb06e64cff6..f7b62d51d635f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/execute.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/execute.ts @@ -652,6 +652,8 @@ export default function ({ getService }: FtrProviderContext) { expect(executeEvent?.message).to.eql(message); expect(startExecuteEvent?.message).to.eql(message.replace('executed', 'started')); + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.eql(0); + if (source) { expect(executeEvent?.kibana?.action?.execution?.source).to.eql(source.toLowerCase()); } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/sub_action_framework/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/sub_action_framework/index.ts index c8fb3e4b6ce2d..b504f8204c4aa 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/sub_action_framework/index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/sub_action_framework/index.ts @@ -8,8 +8,9 @@ import type SuperTest from 'supertest'; import expect from '@kbn/expect'; import { TaskErrorSource } from '@kbn/task-manager-plugin/common'; +import { IValidatedEvent } from '@kbn/event-log-plugin/generated/schemas'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; -import { getUrlPrefix, ObjectRemover } from '../../../../../common/lib'; +import { getEventLog, getUrlPrefix, ObjectRemover } from '../../../../../common/lib'; /** * The sub action connector is defined here @@ -79,6 +80,7 @@ const executeSubAction = async ({ // eslint-disable-next-line import/no-default-export export default function createActionTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); + const retry = getService('retry'); describe('Sub action framework', () => { const objectRemover = new ObjectRemover(supertest); @@ -140,13 +142,35 @@ export default function createActionTests({ getService }: FtrProviderContext) { const res = await createSubActionConnector({ supertest }); objectRemover.add('default', res.body.id, 'action', 'actions'); + const connectorId = res.body.id as string; + const subActionParams = { id: 'test-id' }; + const execRes = await executeSubAction({ supertest, - connectorId: res.body.id as string, + connectorId, subAction: 'subActionWithParams', - subActionParams: { id: 'test-id' }, + subActionParams, + }); + + const events: IValidatedEvent[] = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: 'default', + type: 'action', + id: connectorId, + provider: 'actions', + actions: new Map([ + ['execute-start', { equal: 1 }], + ['execute', { equal: 1 }], + ]), + }); }); + const executeEvent = events[1]; + expect(executeEvent?.kibana?.action?.execution?.usage?.request_body_bytes).to.eql( + Buffer.byteLength(JSON.stringify(subActionParams)) + ); + expect(execRes.body).to.eql({ status: 'ok', data: { id: 'test-id' }, diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/find_csp_benchmark_rule.ts b/x-pack/test/api_integration/apis/cloud_security_posture/find_csp_benchmark_rule.ts index 17890737c4e3d..f2497d08de913 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/find_csp_benchmark_rule.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/find_csp_benchmark_rule.ts @@ -9,7 +9,7 @@ import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import type { CspBenchmarkRule, FindCspBenchmarkRuleResponse, -} from '@kbn/cloud-security-posture-plugin/common/types/rules/v3'; +} from '@kbn/cloud-security-posture-common/schema/rules/v3'; import { FtrProviderContext } from '../../ftr_provider_context'; import { createPackagePolicy } from './helper'; diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/rules/v1.ts b/x-pack/test/api_integration/apis/cloud_security_posture/rules/v1.ts index 9e6b10f410545..4959c8998a5b3 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/rules/v1.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/rules/v1.ts @@ -9,7 +9,7 @@ import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import type { CspBenchmarkRule, FindCspBenchmarkRuleResponse, -} from '@kbn/cloud-security-posture-plugin/common/types/rules/v3'; +} from '@kbn/cloud-security-posture-common/schema/rules/v3'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { createPackagePolicy } from '../helper'; diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/rules/v2.ts b/x-pack/test/api_integration/apis/cloud_security_posture/rules/v2.ts index 45758f93362be..747e6d1d2bd5f 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/rules/v2.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/rules/v2.ts @@ -9,7 +9,7 @@ import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import type { CspBenchmarkRule, FindCspBenchmarkRuleResponse, -} from '@kbn/cloud-security-posture-plugin/common/types/latest'; +} from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { createPackagePolicy } from '../helper'; diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_index_timeout.ts b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_index_timeout.ts index b82140727fc24..4c90ac3e4e4f2 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_index_timeout.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_index_timeout.ts @@ -13,7 +13,6 @@ import { LATEST_VULNERABILITIES_INDEX_DEFAULT_NS, VULNERABILITIES_INDEX_DEFAULT_NS, } from '@kbn/cloud-security-posture-plugin/common/constants'; -import { setupFleetAndAgents } from '../../../../fleet_api_integration/apis/agents/services'; import { generateAgent } from '../../../../fleet_api_integration/helpers'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { deleteIndex, createPackagePolicy } from '../helper'; @@ -35,12 +34,15 @@ export default function (providerContext: FtrProviderContext) { const es = getService('es'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); + const fleetAndAgents = getService('fleetAndAgents'); describe('GET /internal/cloud_security_posture/status', () => { let agentPolicyId: string; describe('STATUS = INDEX_TIMEOUT TEST', () => { - setupFleetAndAgents(providerContext); + before(async () => { + await fleetAndAgents.setup(); + }); beforeEach(async () => { await kibanaServer.savedObjects.cleanStandardList(); diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_waiting_for_results.ts b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_waiting_for_results.ts index bfb5321bdcba9..883bc4b0e745b 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_waiting_for_results.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_waiting_for_results.ts @@ -7,7 +7,6 @@ import expect from '@kbn/expect'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import type { CspSetupStatus } from '@kbn/cloud-security-posture-common'; -import { setupFleetAndAgents } from '../../../../fleet_api_integration/apis/agents/services'; import { generateAgent } from '../../../../fleet_api_integration/helpers'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { createPackagePolicy } from '../helper'; @@ -19,13 +18,15 @@ export default function (providerContext: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); + const fleetAndAgents = getService('fleetAndAgents'); describe('GET /internal/cloud_security_posture/status', () => { let agentPolicyId: string; describe('STATUS = WAITING_FOR_RESULT TEST', () => { - setupFleetAndAgents(providerContext); - + before(async () => { + await fleetAndAgents.setup(); + }); beforeEach(async () => { await kibanaServer.savedObjects.cleanStandardList(); await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); diff --git a/x-pack/test/api_integration/apis/slos/create_slo.ts b/x-pack/test/api_integration/apis/slos/create_slo.ts index 4b458558b233e..71ce8434a61f1 100644 --- a/x-pack/test/api_integration/apis/slos/create_slo.ts +++ b/x-pack/test/api_integration/apis/slos/create_slo.ts @@ -29,6 +29,7 @@ export default function ({ getService }: FtrProviderContext) { let createSLOInput: CreateSLOInput; before(async () => { + await slo.createUser(); await loadTestData(getService); await slo.deleteAllSLOs(); }); @@ -47,12 +48,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('creates a new slo and transforms', async () => { - const apiResponse = await supertestAPI - .post('/api/observability/slos') - .set('kbn-xsrf', 'true') - .set('x-elastic-internal-origin', 'foo') - .send(createSLOInput) - .expect(200); + const apiResponse = await slo.create(createSLOInput); expect(apiResponse.body).property('id'); @@ -113,7 +109,7 @@ export default function ({ getService }: FtrProviderContext) { transforms: [ { id: `slo-${id}-1`, - authorization: { roles: ['superuser'] }, + authorization: { roles: ['slo_editor', 'editor'] }, version: '10.0.0', create_time: rollUpTransformResponse.body.transforms[0].create_time, source: { @@ -193,7 +189,7 @@ export default function ({ getService }: FtrProviderContext) { transforms: [ { id: `slo-summary-${id}-1`, - authorization: { roles: ['superuser'] }, + authorization: { roles: ['slo_editor', 'editor'] }, version: '10.0.0', create_time: summaryTransform.body.transforms[0].create_time, source: { @@ -372,12 +368,7 @@ export default function ({ getService }: FtrProviderContext) { it('creates instanceId for SLOs with multi groupBy', async () => { createSLOInput.groupBy = ['system.network.name', 'event.dataset']; - const apiResponse = await supertestAPI - .post('/api/observability/slos') - .set('kbn-xsrf', 'true') - .set('x-elastic-internal-origin', 'foo') - .send(createSLOInput) - .expect(200); + const apiResponse = await slo.create(createSLOInput); expect(apiResponse.body).property('id'); @@ -396,12 +387,7 @@ export default function ({ getService }: FtrProviderContext) { it('creates instanceId for SLOs with single groupBy', async () => { createSLOInput.groupBy = 'system.network.name'; - const apiResponse = await supertestAPI - .post('/api/observability/slos') - .set('kbn-xsrf', 'true') - .set('x-elastic-internal-origin', 'foo') - .send(createSLOInput) - .expect(200); + const apiResponse = await slo.create(createSLOInput); expect(apiResponse.body).property('id'); @@ -418,12 +404,7 @@ export default function ({ getService }: FtrProviderContext) { it('creates instanceId for SLOs without groupBy ([])', async () => { createSLOInput.groupBy = []; - const apiResponse = await supertestAPI - .post('/api/observability/slos') - .set('kbn-xsrf', 'true') - .set('x-elastic-internal-origin', 'foo') - .send(createSLOInput) - .expect(200); + const apiResponse = await slo.create(createSLOInput); expect(apiResponse.body).property('id'); @@ -440,12 +421,7 @@ export default function ({ getService }: FtrProviderContext) { it('creates instanceId for SLOs without groupBy (["*"])', async () => { createSLOInput.groupBy = ['*']; - const apiResponse = await supertestAPI - .post('/api/observability/slos') - .set('kbn-xsrf', 'true') - .set('x-elastic-internal-origin', 'foo') - .send(createSLOInput) - .expect(200); + const apiResponse = await slo.create(createSLOInput); expect(apiResponse.body).property('id'); @@ -462,12 +438,7 @@ export default function ({ getService }: FtrProviderContext) { it('creates instanceId for SLOs without groupBy ("")', async () => { createSLOInput.groupBy = ''; - const apiResponse = await supertestAPI - .post('/api/observability/slos') - .set('kbn-xsrf', 'true') - .set('x-elastic-internal-origin', 'foo') - .send(createSLOInput) - .expect(200); + const apiResponse = await slo.create(createSLOInput); expect(apiResponse.body).property('id'); diff --git a/x-pack/test/api_integration/apis/slos/delete_slo.ts b/x-pack/test/api_integration/apis/slos/delete_slo.ts index b27bb49b7042f..19480d568a37c 100644 --- a/x-pack/test/api_integration/apis/slos/delete_slo.ts +++ b/x-pack/test/api_integration/apis/slos/delete_slo.ts @@ -29,6 +29,7 @@ export default function ({ getService }: FtrProviderContext) { let createSLOInput: CreateSLOInput; before(async () => { + await slo.createUser(); await slo.deleteAllSLOs(); await sloEsClient.deleteTestSourceData(); await loadTestData(getService); @@ -48,7 +49,11 @@ export default function ({ getService }: FtrProviderContext) { }); it('deletes new slo saved object and transforms', async () => { - const id = await slo.create(createSLOInput); + const response = await slo.create(createSLOInput); + + expect(response.body).property('id'); + + const { id } = response.body; const savedObject = await kibanaServer.savedObjects.find({ type: SO_SLO_TYPE, @@ -86,11 +91,7 @@ export default function ({ getService }: FtrProviderContext) { // expect summary transform to be created expect(summaryTransform.body.transforms[0].id).eql(`slo-summary-${id}-1`); - await supertestAPI - .delete(`/api/observability/slos/${id}`) - .set('kbn-xsrf', 'true') - .send() - .expect(204); + await slo.delete(id); }); // await retry.tryForTime(150 * 1000, async () => { diff --git a/x-pack/test/api_integration/apis/slos/fetch_historical_summary.ts b/x-pack/test/api_integration/apis/slos/fetch_historical_summary.ts index b8ca6a03b3d8e..96f8e21c8c593 100644 --- a/x-pack/test/api_integration/apis/slos/fetch_historical_summary.ts +++ b/x-pack/test/api_integration/apis/slos/fetch_historical_summary.ts @@ -23,6 +23,7 @@ export default function ({ getService }: FtrProviderContext) { describe('fetch historical summary', () => { before(async () => { + await sloApi.createUser(); const now = moment().startOf('minute'); const curr = now.clone().subtract(30, 'days'); const end = now.clone().add(5, 'minutes'); diff --git a/x-pack/test/api_integration/apis/slos/get_slo.ts b/x-pack/test/api_integration/apis/slos/get_slo.ts index b2cd64db05e71..274c2535a4630 100644 --- a/x-pack/test/api_integration/apis/slos/get_slo.ts +++ b/x-pack/test/api_integration/apis/slos/get_slo.ts @@ -35,6 +35,7 @@ export default function ({ getService }: FtrProviderContext) { }; before(async () => { + await slo.createUser(); await slo.deleteAllSLOs(); await sloEsClient.deleteTestSourceData(); await loadTestData(getService); @@ -55,10 +56,11 @@ export default function ({ getService }: FtrProviderContext) { await sloEsClient.deleteTestSourceData(); }); - it('gets slo by id and calculates SLI - occurances rolling', async () => { - const id = await createSLO({ + it('gets slo by id and calculates SLI - occurrences rolling', async () => { + const response = await createSLO({ groupBy: '*', }); + const id = response.body.id; await retry.tryForTime(300 * 1000, async () => { const getResponse = await supertestAPI @@ -87,7 +89,7 @@ export default function ({ getService }: FtrProviderContext) { groupBy: '*', groupings: {}, id, - settings: { syncDelay: '1m', frequency: '1m' }, + settings: { syncDelay: '1m', frequency: '1m', preventInitialBackfill: false }, revision: 1, enabled: true, createdAt: getResponse.body.createdAt, @@ -103,6 +105,9 @@ export default function ({ getService }: FtrProviderContext) { remaining: -49, isEstimated: false, }, + fiveMinuteBurnRate: 40, + oneDayBurnRate: 50, + oneHourBurnRate: 50, status: 'VIOLATED', }, }); @@ -110,13 +115,14 @@ export default function ({ getService }: FtrProviderContext) { }); it('gets slo by id and calculates SLI - occurences calendarAligned', async () => { - const id = await createSLO({ + const response = await createSLO({ groupBy: '*', timeWindow: { duration: '1w', type: 'calendarAligned', }, }); + const id = response.body.id; await retry.tryForTime(300 * 1000, async () => { const getResponse = await supertestAPI @@ -146,7 +152,7 @@ export default function ({ getService }: FtrProviderContext) { groupBy: '*', groupings: {}, id, - settings: { syncDelay: '1m', frequency: '1m' }, + settings: { syncDelay: '1m', frequency: '1m', preventInitialBackfill: false }, revision: 1, enabled: true, createdAt: getResponse.body.createdAt, @@ -162,6 +168,9 @@ export default function ({ getService }: FtrProviderContext) { remaining: -49, isEstimated: true, }, + fiveMinuteBurnRate: 40, + oneDayBurnRate: 50, + oneHourBurnRate: 50, status: 'VIOLATED', }, }); @@ -169,7 +178,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('gets slo by id and calculates SLI - timeslices rolling', async () => { - const id = await createSLO({ + const response = await createSLO({ groupBy: '*', timeWindow: { duration: '7d', @@ -182,6 +191,7 @@ export default function ({ getService }: FtrProviderContext) { timesliceWindow: '1m', }, }); + const id = response.body.id; await retry.tryForTime(300 * 1000, async () => { const getResponse = await supertestAPI @@ -215,7 +225,7 @@ export default function ({ getService }: FtrProviderContext) { groupBy: '*', groupings: {}, id, - settings: { syncDelay: '1m', frequency: '1m' }, + settings: { syncDelay: '1m', frequency: '1m', preventInitialBackfill: false }, revision: 1, enabled: true, createdAt: getResponse.body.createdAt, @@ -223,7 +233,7 @@ export default function ({ getService }: FtrProviderContext) { version: 2, instanceId: '*', meta: {}, - summary: { + summary: expect.objectContaining({ sliValue: 0.5, errorBudget: { initial: 0.01, @@ -232,13 +242,13 @@ export default function ({ getService }: FtrProviderContext) { isEstimated: false, }, status: 'VIOLATED', - }, + }), }); }); }); it('gets slo by id and calculates SLI - timeslices calendarAligned', async () => { - const id = await createSLO({ + const response = await createSLO({ groupBy: '*', timeWindow: { duration: '1w', @@ -251,6 +261,7 @@ export default function ({ getService }: FtrProviderContext) { timesliceWindow: '10m', }, }); + const id = response.body.id; await retry.tryForTime(300 * 1000, async () => { const getResponse = await supertestAPI @@ -283,7 +294,7 @@ export default function ({ getService }: FtrProviderContext) { groupBy: '*', groupings: {}, id, - settings: { syncDelay: '1m', frequency: '1m' }, + settings: { syncDelay: '1m', frequency: '1m', preventInitialBackfill: false }, revision: 1, enabled: true, createdAt: getResponse.body.createdAt, @@ -299,6 +310,9 @@ export default function ({ getService }: FtrProviderContext) { remaining: 0.801587, isEstimated: false, }, + fiveMinuteBurnRate: 40, + oneDayBurnRate: 50, + oneHourBurnRate: 50, status: 'DEGRADING', }, }); @@ -353,7 +367,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('gets slos instances', async () => { - const id = await createSLO(); + const createResponse = await createSLO(); + const id = createResponse.body.id; await retry.tryForTime(400 * 1000, async () => { const response = await supertestAPI @@ -381,13 +396,11 @@ export default function ({ getService }: FtrProviderContext) { }); it('gets slo definitions', async () => { - const id = await createSLO(); - const secondId = await createSLO({ name: 'test name int' }); - const response = await supertestAPI - .get(`/api/observability/slos/_definitions`) - .set('kbn-xsrf', 'true') - .send() - .expect(200); + const createResponse = await createSLO(); + const id = createResponse.body.id; + const secondCreateResponse = await createSLO({ name: 'test name int' }); + const secondId = secondCreateResponse.body.id; + const response = await slo.getDefinitions(); expect(response.body).toEqual({ page: 1, @@ -418,6 +431,7 @@ export default function ({ getService }: FtrProviderContext) { settings: { frequency: '1m', syncDelay: '1m', + preventInitialBackfill: false, }, tags: ['test'], timeWindow: { @@ -452,6 +466,7 @@ export default function ({ getService }: FtrProviderContext) { settings: { frequency: '1m', syncDelay: '1m', + preventInitialBackfill: false, }, tags: ['test'], timeWindow: { @@ -466,11 +481,7 @@ export default function ({ getService }: FtrProviderContext) { }); // can search by name - const searchResponse = await supertestAPI - .get(`/api/observability/slos/_definitions?search=api`) - .set('kbn-xsrf', 'true') - .send() - .expect(200); + const searchResponse = await slo.getDefinitions({ search: 'api' }); expect(searchResponse.body.total).toEqual(1); diff --git a/x-pack/test/api_integration/apis/slos/reset_slo.ts b/x-pack/test/api_integration/apis/slos/reset_slo.ts index 014e546b2b639..cccac8f1796be 100644 --- a/x-pack/test/api_integration/apis/slos/reset_slo.ts +++ b/x-pack/test/api_integration/apis/slos/reset_slo.ts @@ -16,7 +16,6 @@ export default function ({ getService }: FtrProviderContext) { describe('Reset SLOs', function () { this.tags('skipCloud'); - const supertestAPI = getService('supertest'); const kibanaServer = getService('kibanaServer'); const esClient = getService('es'); const logger = getService('log'); @@ -25,6 +24,7 @@ export default function ({ getService }: FtrProviderContext) { before(async () => { await sloEsClient.deleteTestSourceData(); + await slo.createUser(); await slo.deleteAllSLOs(); await loadTestData(getService); }); @@ -79,25 +79,13 @@ export default function ({ getService }: FtrProviderContext) { }, }); - const responseBeforeReset = await supertestAPI - .get(`/api/observability/slos/_definitions`) - .set('kbn-xsrf', 'true') - .send() - .expect(200); + const responseBeforeReset = await slo.getDefinitions(); expect(responseBeforeReset.body.results[0].version).eql(1); - await supertestAPI - .post(`/api/observability/slos/${id}/_reset`) - .set('kbn-xsrf', 'true') - .send() - .expect(200); + await slo.reset(id); - const responseAfterReset = await supertestAPI - .get(`/api/observability/slos/_definitions`) - .set('kbn-xsrf', 'true') - .send() - .expect(200); + const responseAfterReset = await slo.getDefinitions(); expect(responseAfterReset.body.results[0].version).eql(2); }); diff --git a/x-pack/test/api_integration/apis/slos/update_slo.ts b/x-pack/test/api_integration/apis/slos/update_slo.ts index 76e19d6ba20a0..7bf6967bd26a3 100644 --- a/x-pack/test/api_integration/apis/slos/update_slo.ts +++ b/x-pack/test/api_integration/apis/slos/update_slo.ts @@ -26,6 +26,7 @@ export default function ({ getService }: FtrProviderContext) { let createSLOInput: CreateSLOInput; before(async () => { + await slo.createUser(); await slo.deleteAllSLOs(); await loadTestData(getService); }); diff --git a/x-pack/test/api_integration/services/fleet_and_agents.ts b/x-pack/test/api_integration/services/fleet_and_agents.ts new file mode 100644 index 0000000000000..8a30dc35e2651 --- /dev/null +++ b/x-pack/test/api_integration/services/fleet_and_agents.ts @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; +import { FtrProviderContext } from '../ftr_provider_context'; + +export async function FleetAndAgents({ getService }: FtrProviderContext) { + // Use elastic/fleet-server service account to execute setup to verify privilege configuration + const es = getService('es'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + + return { + async setup() { + const { token } = await es.security.createServiceToken({ + namespace: 'elastic', + service: 'fleet-server', + }); + + await supertestWithoutAuth + .post(`/api/fleet/setup`) + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set('kbn-xsrf', 'xxx') + .set('Authorization', `Bearer ${token.value}`) + .send() + .expect(200); + await supertestWithoutAuth + .post(`/api/fleet/agents/setup`) + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set('kbn-xsrf', 'xxx') + .set('Authorization', `Bearer ${token.value}`) + .send({ forceRecreate: true }) + .expect(200); + }, + }; +} diff --git a/x-pack/test/api_integration/services/index.ts b/x-pack/test/api_integration/services/index.ts index cc2b3f77ca0fa..f6561446cc751 100644 --- a/x-pack/test/api_integration/services/index.ts +++ b/x-pack/test/api_integration/services/index.ts @@ -23,6 +23,7 @@ import { IndexManagementProvider } from './index_management'; import { DataViewApiProvider } from './data_view_api'; import { SloApiProvider } from './slo'; import { SecuritySolutionApiProvider } from './security_solution_api.gen'; +import { FleetAndAgents } from './fleet_and_agents'; export const services = { ...commonServices, @@ -42,4 +43,5 @@ export const services = { indexManagement: IndexManagementProvider, slo: SloApiProvider, securitySolutionApi: SecuritySolutionApiProvider, + fleetAndAgents: FleetAndAgents, }; diff --git a/x-pack/test/api_integration/services/slo.ts b/x-pack/test/api_integration/services/slo.ts index c7b765dddf613..d0d6cdc190e0e 100644 --- a/x-pack/test/api_integration/services/slo.ts +++ b/x-pack/test/api_integration/services/slo.ts @@ -4,8 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import { SLO_SUMMARY_DESTINATION_INDEX_NAME } from '@kbn/slo-plugin/common/constants'; +import { TOTAL_INDEX_PRIVILEGE_SET_EDITOR } from '@kbn/slo-plugin/server/services/get_diagnosis'; import { CreateSLOInput, fetchHistoricalSummaryParamsSchema, @@ -21,39 +21,92 @@ type FetchHistoricalSummaryParams = t.OutputOf< >; export function SloApiProvider({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); + const supertest = getService('supertestWithoutAuth'); const esClient = getService('es'); + const security = getService('security'); return { + async createUser() { + const username = 'slo_editor'; + const roleName = 'slo_editor'; + try { + await security.user.delete(username); + await security.role.delete(roleName); + } catch (error) { + const status = error.response.status; + if (status !== 404) { + throw error; + } + } + const password = 'changeme'; + + await security.role.create(roleName, { + elasticsearch: { + indices: [ + { + names: ['.slo-observability.*'], + privileges: TOTAL_INDEX_PRIVILEGE_SET_EDITOR, + }, + ], + }, + }); + + await security.user.create(username, { + password, + roles: [roleName, 'editor'], + }); + }, async create(params: CreateSLOInput) { const slo = await supertest .post('/api/observability/slos') .set('kbn-xsrf', 'true') + .auth('slo_editor', 'changeme') .send(params) .expect(200); - const { id } = slo.body; + return slo; + }, + async reset(id: string) { + const response = supertest + .post(`/api/observability/slos/${id}/_reset`) + .auth('slo_editor', 'changeme') + .set('kbn-xsrf', 'true') + .send() + .expect(200); - const reqBody = [{ id: `slo-${id}-1` }, { id: `slo-summary-${id}-1` }]; - await supertest - .post(`/internal/transform/schedule_now_transforms`) + return response; + }, + async getDefinitions({ search }: { search?: string } = {}) { + const url = `/api/observability/slos/_definitions${search ? `?search=${search}` : ''}`; + const response = await supertest + .get(url) .set('kbn-xsrf', 'true') - .set('elastic-api-version', '1') - .send(reqBody) + .auth('slo_editor', 'changeme') + .send() .expect(200); - return id; + return response; + }, + async delete(id: string) { + await supertest + .delete(`/api/observability/slos/${id}`) + .set('kbn-xsrf', 'true') + .auth('slo_editor', 'changeme') + .send() + .expect(204); }, async deleteAllSLOs() { const response = await supertest .get(`/api/observability/slos/_definitions`) .set('kbn-xsrf', 'true') + .auth('slo_editor', 'changeme') .send() .expect(200); for (const { id } of (response.body as FindSLODefinitionsResponse).results) { await supertest .delete(`/api/observability/slos/${id}`) .set('kbn-xsrf', 'true') + .auth('slo_editor', 'changeme') .send() .expect(204); } @@ -65,6 +118,7 @@ export function SloApiProvider({ getService }: FtrProviderContext) { const { body } = await supertest .post(`/internal/observability/slos/_historical_summary`) .set('kbn-xsrf', 'foo') + .auth('slo_editor', 'changeme') .set('elastic-api-version', '1') .send(params); diff --git a/x-pack/test/cloud_security_posture_api/routes/benchmarks.ts b/x-pack/test/cloud_security_posture_api/routes/benchmarks.ts index a8b94a9f36799..93ee947cef4a5 100644 --- a/x-pack/test/cloud_security_posture_api/routes/benchmarks.ts +++ b/x-pack/test/cloud_security_posture_api/routes/benchmarks.ts @@ -15,7 +15,7 @@ import { } from '@kbn/cloud-security-posture-plugin/common/constants'; import expect from '@kbn/expect'; import Chance from 'chance'; -import { CspBenchmarkRule } from '@kbn/cloud-security-posture-plugin/common/types/latest'; +import { CspBenchmarkRule } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { FtrProviderContext } from '../ftr_provider_context'; import { CspSecurityCommonProvider } from './helper/user_roles_utilites'; diff --git a/x-pack/test/cloud_security_posture_api/routes/csp_benchmark_rules_bulk_update.ts b/x-pack/test/cloud_security_posture_api/routes/csp_benchmark_rules_bulk_update.ts index 5b80b5c7bc99d..b46ecd1ef2943 100644 --- a/x-pack/test/cloud_security_posture_api/routes/csp_benchmark_rules_bulk_update.ts +++ b/x-pack/test/cloud_security_posture_api/routes/csp_benchmark_rules_bulk_update.ts @@ -17,7 +17,7 @@ import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE, DETECTION_RULE_RULES_API_CURRENT_VERSION, } from '@kbn/cloud-security-posture-plugin/common/constants'; -import type { CspBenchmarkRule } from '@kbn/cloud-security-posture-plugin/common/types/latest'; +import type { CspBenchmarkRule } from '@kbn/cloud-security-posture-common/schema/rules/latest'; // eslint-disable @kbn/imports/no_boundary_crossing import { generateBenchmarkRuleTags } from '@kbn/cloud-security-posture-plugin/common/utils/detection_rules'; import type { FtrProviderContext } from '../ftr_provider_context'; diff --git a/x-pack/test/cloud_security_posture_api/routes/csp_benchmark_rules_get_states.ts b/x-pack/test/cloud_security_posture_api/routes/csp_benchmark_rules_get_states.ts index 3b023ca4d352b..61a22a234b6d0 100644 --- a/x-pack/test/cloud_security_posture_api/routes/csp_benchmark_rules_get_states.ts +++ b/x-pack/test/cloud_security_posture_api/routes/csp_benchmark_rules_get_states.ts @@ -13,7 +13,7 @@ import { X_ELASTIC_INTERNAL_ORIGIN_REQUEST, } from '@kbn/core-http-common'; import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '@kbn/cloud-security-posture-plugin/common/constants'; -import type { CspBenchmarkRule } from '@kbn/cloud-security-posture-plugin/common/types/latest'; +import type { CspBenchmarkRule } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import type { FtrProviderContext } from '../ftr_provider_context'; import { CspSecurityCommonProvider } from './helper/user_roles_utilites'; diff --git a/x-pack/test/cloud_security_posture_functional/pages/findings.ts b/x-pack/test/cloud_security_posture_functional/pages/findings.ts index 35f1f0b5cbff4..9b5460f3141d6 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/findings.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/findings.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import Chance from 'chance'; -import { CspBenchmarkRule } from '@kbn/cloud-security-posture-plugin/common/types/latest'; +import { CspBenchmarkRule } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '@kbn/cloud-security-posture-plugin/common/constants'; import { ELASTIC_HTTP_VERSION_HEADER, diff --git a/x-pack/test/cloud_security_posture_functional/pages/findings_grouping.ts b/x-pack/test/cloud_security_posture_functional/pages/findings_grouping.ts index acfd5918afe9f..1f3a95b81bd6f 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/findings_grouping.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/findings_grouping.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import Chance from 'chance'; import { asyncForEach } from '@kbn/std'; -import { CspBenchmarkRule } from '@kbn/cloud-security-posture-plugin/common/types/latest'; +import { CspBenchmarkRule } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '@kbn/cloud-security-posture-plugin/common/constants'; import { ELASTIC_HTTP_VERSION_HEADER, diff --git a/x-pack/test/dataset_quality_api_integration/tests/data_streams/stats.spec.ts b/x-pack/test/dataset_quality_api_integration/tests/data_streams/stats.spec.ts index b01dc1f2375aa..25a7f419f2746 100644 --- a/x-pack/test/dataset_quality_api_integration/tests/data_streams/stats.spec.ts +++ b/x-pack/test/dataset_quality_api_integration/tests/data_streams/stats.spec.ts @@ -22,8 +22,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { endpoint: 'GET /internal/dataset_quality/data_streams/stats', params: { query: { - type: 'logs', - datasetQuery: '-', + types: ['logs'], }, }, }); diff --git a/x-pack/test/dataset_quality_api_integration/tests/integrations/integrations.spec.ts b/x-pack/test/dataset_quality_api_integration/tests/integrations/integrations.spec.ts index 13011410a0317..2176dbd1fa95d 100644 --- a/x-pack/test/dataset_quality_api_integration/tests/integrations/integrations.spec.ts +++ b/x-pack/test/dataset_quality_api_integration/tests/integrations/integrations.spec.ts @@ -39,11 +39,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { return await datasetQualityApiClient[user]({ endpoint: 'GET /internal/dataset_quality/integrations', - params: { - query: { - type: 'logs', - }, - }, }); } @@ -53,12 +48,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { await Promise.all(integrationPackages.map((pkg) => installPackage({ supertest, pkg }))); }); - it('returns only log based integrations and its datasets map', async () => { + it('returns all installed integrations and its datasets map', async () => { const resp = await callApiAs(); expect(resp.body.integrations.map((integration) => integration.name)).to.eql([ 'apm', 'endpoint', + 'synthetics', 'system', ]); diff --git a/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy.ts b/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy.ts index 80309b8909363..b51e135ba9c3e 100644 --- a/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy.ts +++ b/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy.ts @@ -9,7 +9,6 @@ import expect from '@kbn/expect'; import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common'; import { FLEET_AGENT_POLICIES_SCHEMA_VERSION } from '@kbn/fleet-plugin/server/constants'; import { skipIfNoDockerRegistry, generateAgent } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; export default function (providerContext: FtrProviderContext) { @@ -18,6 +17,7 @@ export default function (providerContext: FtrProviderContext) { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const es = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); const getPackage = async (pkgName: string) => { const getPkgRes = await supertest @@ -42,9 +42,8 @@ export default function (providerContext: FtrProviderContext) { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); await kibanaServer.savedObjects.cleanStandardList(); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); - it('should get list agent policies', async () => { await supertest.get(`/api/fleet/agent_policies`).expect(200); }); @@ -102,8 +101,8 @@ export default function (providerContext: FtrProviderContext) { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); await kibanaServer.savedObjects.cleanStandardList(); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); let packagePoliciesToDeleteIds: string[] = []; after(async () => { if (systemPkgVersion) { @@ -476,8 +475,8 @@ export default function (providerContext: FtrProviderContext) { describe('POST /api/fleet/agent_policies/{agentPolicyId}/copy', () => { before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/fleet/agents'); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); const createdPolicyIds: string[] = []; after(async () => { const deletedPromises = createdPolicyIds.map((agentPolicyId) => @@ -1460,8 +1459,8 @@ export default function (providerContext: FtrProviderContext) { let policyId: string; before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); before(async () => { const getPkRes = await getPackage('system'); diff --git a/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy_datastream_permissions.ts b/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy_datastream_permissions.ts index c786b806b1b14..2b0d4e3a2f361 100644 --- a/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy_datastream_permissions.ts +++ b/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy_datastream_permissions.ts @@ -8,20 +8,20 @@ import expect from '@kbn/expect'; import { v4 as uuidv4 } from 'uuid'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -import { setupFleetAndAgents } from '../agents/services'; import { skipIfNoDockerRegistry } from '../../helpers'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const fleetAndAgents = getService('fleetAndAgents'); describe('datastream privileges', () => { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); after(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); diff --git a/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy_root_integrations.ts b/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy_root_integrations.ts index 1de66d530d184..f5ce7dada17e2 100644 --- a/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy_root_integrations.ts +++ b/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy_root_integrations.ts @@ -8,20 +8,20 @@ import expect from '@kbn/expect'; import { v4 as uuidv4 } from 'uuid'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -import { setupFleetAndAgents } from '../agents/services'; import { skipIfNoDockerRegistry } from '../../helpers'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const fleetAndAgents = getService('fleetAndAgents'); describe('agent policy with root integrations', () => { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); after(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); diff --git a/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy_with_agents_setup.ts b/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy_with_agents_setup.ts index 72fd2d855130d..33e76b11d7791 100644 --- a/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy_with_agents_setup.ts +++ b/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy_with_agents_setup.ts @@ -13,7 +13,6 @@ import { import { ENROLLMENT_API_KEYS_INDEX } from '@kbn/fleet-plugin/common/constants'; import { skipIfNoDockerRegistry } from '../../helpers'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; @@ -21,6 +20,7 @@ export default function (providerContext: FtrProviderContext) { const esArchiver = getService('esArchiver'); const esClient = getService('es'); const kibanaServer = getService('kibanaServer'); + const fleetAndAgents = getService('fleetAndAgents'); async function getEnrollmentKeyForPolicyId(policyId: string) { const listRes = await supertest.get(`/api/fleet/enrollment_api_keys`).expect(200); @@ -89,6 +89,7 @@ export default function (providerContext: FtrProviderContext) { before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/fleet/agents'); + await fleetAndAgents.setup(); }); after(async () => { // Wait before agent status is updated @@ -98,8 +99,6 @@ export default function (providerContext: FtrProviderContext) { await esArchiver.unload('x-pack/test/functional/es_archives/fleet/agents'); }); - setupFleetAndAgents(providerContext); - describe('In default space', () => { describe('POST /api/fleet/agent_policies', () => { it('should create an enrollment key for the policy', async () => { diff --git a/x-pack/test/fleet_api_integration/apis/agents/action_status.ts b/x-pack/test/fleet_api_integration/apis/agents/action_status.ts index 184b1ea8d203e..772aa3eaf4eb9 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/action_status.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/action_status.ts @@ -12,7 +12,6 @@ import { AGENT_POLICY_INDEX, } from '@kbn/fleet-plugin/common'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -import { setupFleetAndAgents } from './services'; import { skipIfNoDockerRegistry } from '../../helpers'; const ES_INDEX_OPTIONS = { headers: { 'X-elastic-product-origin': 'fleet' } }; @@ -22,13 +21,14 @@ export default function (providerContext: FtrProviderContext) { const supertest = getService('supertest'); const es = getService('es'); const esArchiver = getService('esArchiver'); + const fleetAndAgents = getService('fleetAndAgents'); describe('action_status_api', () => { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/agents'); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); after(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/fleet/agents'); diff --git a/x-pack/test/fleet_api_integration/apis/agents/reassign.ts b/x-pack/test/fleet_api_integration/apis/agents/reassign.ts index 1bbc9eb29ceb2..48a29d2a7190d 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/reassign.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/reassign.ts @@ -7,7 +7,6 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -import { setupFleetAndAgents } from './services'; import { testUsers } from '../test_users'; export default function (providerContext: FtrProviderContext) { @@ -15,17 +14,18 @@ export default function (providerContext: FtrProviderContext) { const esArchiver = getService('esArchiver'); const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); + const fleetAndAgents = getService('fleetAndAgents'); describe('fleet_reassign_agent', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); + await fleetAndAgents.setup(); }); beforeEach(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); await esArchiver.load('x-pack/test/functional/es_archives/fleet/agents'); await getService('supertest').post(`/api/fleet/setup`).set('kbn-xsrf', 'xxx').send(); }); - setupFleetAndAgents(providerContext); afterEach(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/fleet/agents'); await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); diff --git a/x-pack/test/fleet_api_integration/apis/agents/request_diagnostics.ts b/x-pack/test/fleet_api_integration/apis/agents/request_diagnostics.ts index 45cca59da5e8e..782104e907dc9 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/request_diagnostics.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/request_diagnostics.ts @@ -9,7 +9,6 @@ import expect from '@kbn/expect'; import moment from 'moment'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -import { setupFleetAndAgents } from './services'; import { skipIfNoDockerRegistry } from '../../helpers'; import { testUsers } from '../test_users'; @@ -19,10 +18,14 @@ export default function (providerContext: FtrProviderContext) { const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); const es = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); describe('fleet_request_diagnostics', () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); beforeEach(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); await esArchiver.load('x-pack/test/functional/es_archives/fleet/agents'); diff --git a/x-pack/test/fleet_api_integration/apis/agents/services.ts b/x-pack/test/fleet_api_integration/apis/agents/services.ts index 7cb04d895ce7c..171744631c1cb 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/services.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/services.ts @@ -5,23 +5,11 @@ * 2.0. */ -import supertest from 'supertest'; import { Client, HttpConnection } from '@elastic/elasticsearch'; import { format as formatUrl } from 'url'; -import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; - import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -export function getSupertestWithoutAuth({ getService }: FtrProviderContext) { - const config = getService('config'); - const kibanaUrl = config.get('servers.kibana'); - kibanaUrl.auth = null; - kibanaUrl.password = null; - - return supertest(formatUrl(kibanaUrl)); -} - export function getEsClientForAPIKey({ getService }: FtrProviderContext, esApiKey: string) { const config = getService('config'); const url = formatUrl({ ...config.get('servers.elasticsearch'), auth: false }); @@ -34,30 +22,3 @@ export function getEsClientForAPIKey({ getService }: FtrProviderContext, esApiKe Connection: HttpConnection, }); } - -export function setupFleetAndAgents(providerContext: FtrProviderContext) { - before(async () => { - // Use elastic/fleet-server service account to execute setup to verify privilege configuration - const es = providerContext.getService('es'); - const { token } = await es.security.createServiceToken({ - namespace: 'elastic', - service: 'fleet-server', - }); - const supetestWithoutAuth = getSupertestWithoutAuth(providerContext); - - await supetestWithoutAuth - .post(`/api/fleet/setup`) - .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') - .set('kbn-xsrf', 'xxx') - .set('Authorization', `Bearer ${token.value}`) - .send() - .expect(200); - await supetestWithoutAuth - .post(`/api/fleet/agents/setup`) - .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') - .set('kbn-xsrf', 'xxx') - .set('Authorization', `Bearer ${token.value}`) - .send({ forceRecreate: true }) - .expect(200); - }); -} diff --git a/x-pack/test/fleet_api_integration/apis/agents/unenroll.ts b/x-pack/test/fleet_api_integration/apis/agents/unenroll.ts index 120bd026ec3f1..68ef8f242b505 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/unenroll.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/unenroll.ts @@ -10,7 +10,6 @@ import { v4 as uuidv4 } from 'uuid'; import { AGENTS_INDEX } from '@kbn/fleet-plugin/common'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -import { setupFleetAndAgents } from './services'; import { skipIfNoDockerRegistry } from '../../helpers'; export default function (providerContext: FtrProviderContext) { @@ -18,6 +17,7 @@ export default function (providerContext: FtrProviderContext) { const esArchiver = getService('esArchiver'); const supertest = getService('supertest'); const esClient = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); describe('fleet_unenroll_agent', () => { skipIfNoDockerRegistry(providerContext); @@ -25,8 +25,8 @@ export default function (providerContext: FtrProviderContext) { let outputAPIKeyId: string; before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); beforeEach(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); await esArchiver.load('x-pack/test/functional/es_archives/fleet/agents'); diff --git a/x-pack/test/fleet_api_integration/apis/agents/update_agent_tags.ts b/x-pack/test/fleet_api_integration/apis/agents/update_agent_tags.ts index 92e0500f5e365..497e82ea6abc4 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/update_agent_tags.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/update_agent_tags.ts @@ -7,23 +7,23 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -import { setupFleetAndAgents } from './services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const esArchiver = getService('esArchiver'); const supertest = getService('supertest'); + const fleetAndAgents = getService('fleetAndAgents'); describe('fleet_update_agent_tags', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); + await fleetAndAgents.setup(); }); beforeEach(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); await esArchiver.load('x-pack/test/functional/es_archives/fleet/agents'); await getService('supertest').post(`/api/fleet/setup`).set('kbn-xsrf', 'xxx').send(); }); - setupFleetAndAgents(providerContext); afterEach(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/fleet/agents'); await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); diff --git a/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts b/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts index 22f548e119129..27ba9377a37a8 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts @@ -11,7 +11,6 @@ import moment from 'moment'; import { AGENTS_INDEX, PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -import { setupFleetAndAgents } from './services'; import { skipIfNoDockerRegistry, generateAgent, makeSnapshotVersion } from '../../helpers'; import { testUsers } from '../test_users'; @@ -22,13 +21,14 @@ export default function (providerContext: FtrProviderContext) { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const supertestWithoutAuth = getService('supertestWithoutAuth'); + const fleetAndAgents = getService('fleetAndAgents'); describe('fleet_upgrade_agent', () => { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/agents'); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); beforeEach(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/agents'); diff --git a/x-pack/test/fleet_api_integration/apis/agents/uploads.ts b/x-pack/test/fleet_api_integration/apis/agents/uploads.ts index 8ea34cc8c17de..6ffc84c79bc9d 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/uploads.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/uploads.ts @@ -12,7 +12,6 @@ import { FILE_STORAGE_METADATA_AGENT_INDEX, } from '@kbn/fleet-plugin/server/constants'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -import { setupFleetAndAgents } from './services'; import { skipIfNoDockerRegistry } from '../../helpers'; export default function (providerContext: FtrProviderContext) { @@ -20,6 +19,7 @@ export default function (providerContext: FtrProviderContext) { const esArchiver = getService('esArchiver'); const supertest = getService('supertest'); const esClient = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); const ES_INDEX_OPTIONS = { headers: { 'X-elastic-product-origin': 'fleet' } }; @@ -155,9 +155,9 @@ export default function (providerContext: FtrProviderContext) { describe('fleet_uploads', () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); before(async () => { + await fleetAndAgents.setup(); await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); await getService('supertest').post(`/api/fleet/setup`).set('kbn-xsrf', 'xxx').send(); await cleanupFiles(); diff --git a/x-pack/test/fleet_api_integration/apis/download_sources/crud.ts b/x-pack/test/fleet_api_integration/apis/download_sources/crud.ts index 0a7ab7b8bcf9e..578641515aab7 100644 --- a/x-pack/test/fleet_api_integration/apis/download_sources/crud.ts +++ b/x-pack/test/fleet_api_integration/apis/download_sources/crud.ts @@ -8,7 +8,6 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; import { testUsers } from '../test_users'; export default function (providerContext: FtrProviderContext) { @@ -18,14 +17,15 @@ export default function (providerContext: FtrProviderContext) { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); + const fleetAndAgents = getService('fleetAndAgents'); - describe('fleet_download_sources_crud', async function () { + describe('fleet_download_sources_crud', function () { skipIfNoDockerRegistry(providerContext); before(async () => { await kibanaServer.savedObjects.cleanStandardList(); await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); let defaultDownloadSourceId: string; diff --git a/x-pack/test/fleet_api_integration/apis/enrollment_api_keys/crud.ts b/x-pack/test/fleet_api_integration/apis/enrollment_api_keys/crud.ts index d5e59733a008b..58922bd0f3cad 100644 --- a/x-pack/test/fleet_api_integration/apis/enrollment_api_keys/crud.ts +++ b/x-pack/test/fleet_api_integration/apis/enrollment_api_keys/crud.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -import { setupFleetAndAgents, getEsClientForAPIKey } from '../agents/services'; +import { getEsClientForAPIKey } from '../agents/services'; import { skipIfNoDockerRegistry } from '../../helpers'; import { testUsers } from '../test_users'; @@ -21,10 +21,12 @@ export default function (providerContext: FtrProviderContext) { const es = getService('es'); const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); + const fleetAndAgents = getService('fleetAndAgents'); describe('fleet_enrollment_api_keys_crud', () => { before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/fleet/agents'); + await fleetAndAgents.setup(); }); after(async () => { @@ -32,7 +34,6 @@ export default function (providerContext: FtrProviderContext) { }); skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); describe('GET /fleet/enrollment_api_keys', async () => { it('should list existing api keys', async () => { diff --git a/x-pack/test/fleet_api_integration/apis/enrollment_api_keys/privileges.ts b/x-pack/test/fleet_api_integration/apis/enrollment_api_keys/privileges.ts index 187fcacab570d..6b681cdff3f95 100644 --- a/x-pack/test/fleet_api_integration/apis/enrollment_api_keys/privileges.ts +++ b/x-pack/test/fleet_api_integration/apis/enrollment_api_keys/privileges.ts @@ -8,7 +8,6 @@ import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; import { runPrivilegeTests } from '../../privileges_helpers'; -import { setupFleetAndAgents } from '../agents/services'; import { testUsers } from '../test_users'; export default function (providerContext: FtrProviderContext) { @@ -16,10 +15,12 @@ export default function (providerContext: FtrProviderContext) { const esArchiver = getService('esArchiver'); const supertestWithoutAuth = getService('supertestWithoutAuth'); const supertest = getService('supertest'); + const fleetAndAgents = getService('fleetAndAgents'); describe('fleet_enrollment_api_keys_privileges', () => { before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/fleet/agents'); + await fleetAndAgents.setup(); }); after(async () => { @@ -27,7 +28,6 @@ export default function (providerContext: FtrProviderContext) { }); skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); const SCENARIOS = [ { diff --git a/x-pack/test/fleet_api_integration/apis/epm/bulk_get_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/bulk_get_assets.ts index 07b871dd18032..0d8bac87fa83e 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/bulk_get_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/bulk_get_assets.ts @@ -8,11 +8,12 @@ import { GetBulkAssetsResponse } from '@kbn/fleet-plugin/common'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry, isDockerRegistryEnabledOrSkipped } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); + const fleetAndAgents = getService('fleetAndAgents'); + const pkgName = 'all_assets'; const pkgVersion = '0.1.0'; @@ -28,7 +29,10 @@ export default function (providerContext: FtrProviderContext) { describe('Bulk get assets', async () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); describe('installs all assets when installing a package for the first time', async () => { before(async () => { diff --git a/x-pack/test/fleet_api_integration/apis/epm/bulk_install.ts b/x-pack/test/fleet_api_integration/apis/epm/bulk_install.ts index 790fcd13873ea..547f066e43c00 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/bulk_install.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/bulk_install.ts @@ -8,11 +8,11 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); + const fleetAndAgents = getService('fleetAndAgents'); const pkgName = 'multiple_versions'; const pkgOlderVersion = '0.1.0'; @@ -24,7 +24,10 @@ export default function (providerContext: FtrProviderContext) { describe('bulk package install api', async () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); it('should install the latest version by default', async () => { const response = await supertest diff --git a/x-pack/test/fleet_api_integration/apis/epm/bulk_upgrade.ts b/x-pack/test/fleet_api_integration/apis/epm/bulk_upgrade.ts index ad9c1eec519c4..e644f9b1296b9 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/bulk_upgrade.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/bulk_upgrade.ts @@ -13,13 +13,13 @@ import { } from '@kbn/fleet-plugin/common'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; import { testUsers } from '../test_users'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); + const fleetAndAgents = getService('fleetAndAgents'); const deletePackage = async (name: string, version: string) => { await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx'); @@ -27,7 +27,10 @@ export default function (providerContext: FtrProviderContext) { describe('bulk package upgrade api', async () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); describe('bulk package upgrade with a package already installed', async () => { beforeEach(async () => { diff --git a/x-pack/test/fleet_api_integration/apis/epm/custom_ingest_pipeline.ts b/x-pack/test/fleet_api_integration/apis/epm/custom_ingest_pipeline.ts index 93476c0d252fc..78de2c34dbeb1 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/custom_ingest_pipeline.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/custom_ingest_pipeline.ts @@ -7,7 +7,6 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -import { setupFleetAndAgents } from '../agents/services'; import { skipIfNoDockerRegistry } from '../../helpers'; const TEST_INDEX = 'logs-log.log-test'; @@ -19,6 +18,7 @@ export default function (providerContext: FtrProviderContext) { const supertest = getService('supertest'); const es = getService('es'); const esArchiver = getService('esArchiver'); + const fleetAndAgents = getService('fleetAndAgents'); // TODO: Use test package or move to input package version github.com/elastic/kibana/issues/154243 const LOG_INTEGRATION_VERSION = '1.1.2'; @@ -26,8 +26,8 @@ export default function (providerContext: FtrProviderContext) { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); before(async () => { await supertest diff --git a/x-pack/test/fleet_api_integration/apis/epm/data_stream.ts b/x-pack/test/fleet_api_integration/apis/epm/data_stream.ts index a257ff97933d9..fbbb623354340 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/data_stream.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/data_stream.ts @@ -10,12 +10,12 @@ import { v4 as uuidv4 } from 'uuid'; import { asyncForEach } from '@kbn/std'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const es = getService('es'); const supertest = getService('supertest'); + const fleetAndAgents = getService('fleetAndAgents'); const uninstallPackage = async (name: string, version: string) => { await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx'); @@ -29,7 +29,7 @@ export default function (providerContext: FtrProviderContext) { .expect(200); }; - describe('datastreams', async () => { + describe('datastreams', () => { describe('standard integration', () => { const pkgName = 'datastreams'; const pkgVersion = '0.1.0'; @@ -39,7 +39,10 @@ export default function (providerContext: FtrProviderContext) { const namespaces = ['default', 'foo', 'bar']; skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); const writeMetricsDoc = (namespace: string) => es.transport.request( @@ -310,7 +313,10 @@ export default function (providerContext: FtrProviderContext) { const namespace = 'default'; skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); const writeMetricDoc = (body: any = {}) => es.transport.request( diff --git a/x-pack/test/fleet_api_integration/apis/epm/data_views.ts b/x-pack/test/fleet_api_integration/apis/epm/data_views.ts index 5a0753fb321b4..be1335e171c02 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/data_views.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/data_views.ts @@ -8,11 +8,10 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; - + const fleetAndAgents = getService('fleetAndAgents'); const supertest = getService('supertest'); const testPkgs = [ @@ -45,7 +44,10 @@ export default function (providerContext: FtrProviderContext) { describe('EPM - data views', () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); afterEach(async () => { await Promise.all(testPkgs.map((pkg) => uninstallPackage(pkg.name, pkg.version))); diff --git a/x-pack/test/fleet_api_integration/apis/epm/delete.ts b/x-pack/test/fleet_api_integration/apis/epm/delete.ts index 9ec8b7318f6c9..e05f9e6e1ee9b 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/delete.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/delete.ts @@ -7,13 +7,13 @@ import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; import { testUsers } from '../test_users'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); + const fleetAndAgents = getService('fleetAndAgents'); const requiredPackage = 'elastic_agent'; const pkgVersion = '0.0.7'; @@ -33,9 +33,9 @@ export default function (providerContext: FtrProviderContext) { describe('delete and force delete scenarios', async () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); before(async () => { + await fleetAndAgents.setup(); await installPackage(requiredPackage, pkgVersion); }); after(async () => { diff --git a/x-pack/test/fleet_api_integration/apis/epm/final_pipeline.ts b/x-pack/test/fleet_api_integration/apis/epm/final_pipeline.ts index 157e0178f0ca4..b2b9cb32d8474 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/final_pipeline.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/final_pipeline.ts @@ -7,7 +7,6 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -import { setupFleetAndAgents } from '../agents/services'; import { skipIfNoDockerRegistry } from '../../helpers'; const TEST_INDEX = 'logs-log.log-test'; @@ -24,6 +23,7 @@ export default function (providerContext: FtrProviderContext) { const supertest = getService('supertest'); const es = getService('es'); const esArchiver = getService('esArchiver'); + const fleetAndAgents = getService('fleetAndAgents'); function indexUsingApiKey(body: any, apiKey: string): Promise<{ body: Record }> { const supertestWithoutAuth = getService('esSupertestWithoutAuth'); @@ -38,8 +38,8 @@ export default function (providerContext: FtrProviderContext) { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); // Use the custom log package to test the fleet final pipeline before(async () => { diff --git a/x-pack/test/fleet_api_integration/apis/epm/get.ts b/x-pack/test/fleet_api_integration/apis/epm/get.ts index c98bb318bdf41..6941f14b1bbe6 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/get.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/get.ts @@ -11,7 +11,6 @@ import fs from 'fs'; import path from 'path'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; import { testUsers } from '../test_users'; import { bundlePackage, removeBundledPackages } from './install_bundled'; @@ -20,6 +19,7 @@ export default function (providerContext: FtrProviderContext) { const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); + const fleetAndAgents = getService('fleetAndAgents'); const testPkgName = 'apache'; const testPkgVersion = '0.1.4'; @@ -54,7 +54,10 @@ export default function (providerContext: FtrProviderContext) { describe('EPM - get', () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); it('returns package info from the registry if it was installed from the registry', async function () { // this will install through the registry by default diff --git a/x-pack/test/fleet_api_integration/apis/epm/get_templates_inputs.ts b/x-pack/test/fleet_api_integration/apis/epm/get_templates_inputs.ts index 744e805c5e229..0f77bde3b15fa 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/get_templates_inputs.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/get_templates_inputs.ts @@ -10,7 +10,6 @@ import fs from 'fs'; import path from 'path'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; import { testUsers } from '../test_users'; export default function (providerContext: FtrProviderContext) { @@ -18,6 +17,7 @@ export default function (providerContext: FtrProviderContext) { const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); + const fleetAndAgents = getService('fleetAndAgents'); const testPkgName = 'apache'; const testPkgVersion = '0.1.4'; @@ -36,8 +36,8 @@ export default function (providerContext: FtrProviderContext) { describe('EPM Templates - Get Inputs', () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); before(async () => { + await fleetAndAgents.setup(); const buf = fs.readFileSync(testPkgArchiveZip); await supertest .post(`/api/fleet/epm/packages`) diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_bundled.ts b/x-pack/test/fleet_api_integration/apis/epm/install_bundled.ts index ffef558628804..dbda057f0ba25 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_bundled.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_bundled.ts @@ -13,7 +13,6 @@ import { ToolingLog } from '@kbn/tooling-log'; import { BUNDLED_PACKAGE_DIR } from '../../config.base'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; const BUNDLED_PACKAGE_FIXTURES_DIR = path.join( path.dirname(__filename), @@ -55,10 +54,14 @@ export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); const log = getService('log'); + const fleetAndAgents = getService('fleetAndAgents'); - describe('Installing bundled packages', async () => { + describe('Installing bundled packages', () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); afterEach(async () => { await removeBundledPackages(log); diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_by_upload.ts b/x-pack/test/fleet_api_integration/apis/epm/install_by_upload.ts index e7f3d1d3c0f66..12c29eb5e25e7 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_by_upload.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_by_upload.ts @@ -13,7 +13,6 @@ import { HTTPError } from 'superagent'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry, isDockerRegistryEnabledOrSkipped } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; import { testUsers } from '../test_users'; /* @@ -26,6 +25,7 @@ export default function (providerContext: FtrProviderContext) { const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); const esClient = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); const testPkgArchiveTgz = path.join( path.dirname(__filename), @@ -71,7 +71,10 @@ export default function (providerContext: FtrProviderContext) { describe('Installs packages from direct upload', async () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); afterEach(async () => { if (isDockerRegistryEnabledOrSkipped(providerContext)) { diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_dynamic_template_metric.ts b/x-pack/test/fleet_api_integration/apis/epm/install_dynamic_template_metric.ts index 9bcf3fc673eab..740739963971e 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_dynamic_template_metric.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_dynamic_template_metric.ts @@ -8,12 +8,12 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); const es = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); const deletePackage = async (name: string, version: string) => { await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx'); @@ -21,7 +21,10 @@ export default function (providerContext: FtrProviderContext) { describe('metric_type with dynamic_templates', async () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); after(async () => { await deletePackage('no_tsdb_to_tsdb', '0.2.0'); diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_endpoint.ts b/x-pack/test/fleet_api_integration/apis/epm/install_endpoint.ts index f1e915ec2f048..672b0c881b027 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_endpoint.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_endpoint.ts @@ -8,7 +8,6 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry, isDockerRegistryEnabledOrSkipped } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; import { bundlePackage, removeBundledPackages } from './install_bundled'; export default function (providerContext: FtrProviderContext) { @@ -19,11 +18,11 @@ export default function (providerContext: FtrProviderContext) { describe('Install endpoint package', () => { const { getService } = providerContext; skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); const supertest = getService('supertest'); const es = getService('es'); const log = getService('log'); + const fleetAndAgents = getService('fleetAndAgents'); const pkgName = 'endpoint'; const pkgVersion = '8.6.1'; @@ -46,6 +45,7 @@ export default function (providerContext: FtrProviderContext) { }; before(async () => { + await fleetAndAgents.setup(); if (!isDockerRegistryEnabledOrSkipped(providerContext)) return; await bundlePackage('endpoint-8.6.1'); await installPackage('endpoint', '8.6.1'); diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_error_rollback.ts b/x-pack/test/fleet_api_integration/apis/epm/install_error_rollback.ts index 5f4c5b784a280..348808d75f846 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_error_rollback.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_error_rollback.ts @@ -8,7 +8,6 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; @@ -18,6 +17,7 @@ export default function (providerContext: FtrProviderContext) { const badPackageVersion = '0.2.0'; const goodUpgradePackageVersion = '0.3.0'; const kibanaServer = getService('kibanaServer'); + const fleetAndAgents = getService('fleetAndAgents'); const installPackage = (pkg: string, version: string) => { return supertest @@ -41,7 +41,10 @@ export default function (providerContext: FtrProviderContext) { describe('package installation error handling and rollback', async () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); beforeEach(async () => { await kibanaServer.savedObjects.cleanStandardList(); diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_hidden_datastreams.ts b/x-pack/test/fleet_api_integration/apis/epm/install_hidden_datastreams.ts index 45a80bfa88456..dff9a69b90f97 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_hidden_datastreams.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_hidden_datastreams.ts @@ -8,20 +8,23 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); const es = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); const deletePackage = async (name: string, version: string) => { await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx'); }; - describe('installing with hidden datastream', async () => { + describe('installing with hidden datastream', () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); afterEach(async () => { await deletePackage('apm', '8.8.0'); diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_integration_in_multiple_spaces.ts b/x-pack/test/fleet_api_integration/apis/epm/install_integration_in_multiple_spaces.ts index 8fe4ac81ea7cc..06ccf86a582d2 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_integration_in_multiple_spaces.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_integration_in_multiple_spaces.ts @@ -10,7 +10,6 @@ import { PACKAGES_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common'; import pRetry from 'p-retry'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry, isDockerRegistryEnabledOrSkipped } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; const testSpaceId = 'fleet_test_space'; @@ -20,6 +19,7 @@ export default function (providerContext: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const es = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); const pkgName = 'system'; const pkgVersion = '1.27.0'; @@ -72,9 +72,9 @@ export default function (providerContext: FtrProviderContext) { describe('When installing system integration in multiple spaces', async () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); before(async () => { + await fleetAndAgents.setup(); if (!isDockerRegistryEnabledOrSkipped(providerContext)) { return; } diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_overrides.ts b/x-pack/test/fleet_api_integration/apis/epm/install_overrides.ts index 1fd228e6ce799..a96ec23e6e77c 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_overrides.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_overrides.ts @@ -8,12 +8,12 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry, isDockerRegistryEnabledOrSkipped } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); const es = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); const mappingsPackage = 'overrides'; const mappingsPackageVersion = '0.1.0'; @@ -23,7 +23,10 @@ export default function (providerContext: FtrProviderContext) { describe('installs packages that include settings and mappings overrides', async () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); after(async () => { if (isDockerRegistryEnabledOrSkipped(providerContext)) { diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts b/x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts index 86c1a612c0eb5..b804d3b8a20bc 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts @@ -7,11 +7,11 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry, isDockerRegistryEnabledOrSkipped } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); + const fleetAndAgents = getService('fleetAndAgents'); const testPackage = 'prerelease'; const testPackageVersion = '0.1.0-dev.0+abc'; @@ -20,9 +20,12 @@ export default function (providerContext: FtrProviderContext) { await supertest.delete(`/api/fleet/epm/packages/${pkg}/${version}`).set('kbn-xsrf', 'xxxx'); }; - describe('installs package that has a prerelease version', async () => { + describe('installs package that has a prerelease version', () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); after(async () => { if (isDockerRegistryEnabledOrSkipped(providerContext)) { diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts index 83cb1fb6e312f..d8e6f2de86032 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts @@ -12,7 +12,6 @@ import { AssetReference } from '@kbn/fleet-plugin/common/types'; import { FLEET_INSTALL_FORMAT_VERSION } from '@kbn/fleet-plugin/server/constants'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry, isDockerRegistryEnabledOrSkipped } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; function checkErrorWithResponseDataOrThrow(err: any) { if (!err?.response?.data) { @@ -25,6 +24,7 @@ export default function (providerContext: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); const supertest = getService('supertest'); const es: Client = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); const pkgName = 'all_assets'; const pkgVersion = '0.1.0'; const logsTemplateName = `logs-${pkgName}.test_logs`; @@ -40,12 +40,12 @@ export default function (providerContext: FtrProviderContext) { .send({ force: true }); }; - describe('installs and uninstalls all assets', async () => { + describe('installs and uninstalls all assets', () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); describe('installs all assets when installing a package for the first time', async () => { before(async () => { + await fleetAndAgents.setup(); if (!isDockerRegistryEnabledOrSkipped(providerContext)) return; await installPackage(pkgName, pkgVersion); }); diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_remove_kbn_assets_in_space.ts b/x-pack/test/fleet_api_integration/apis/epm/install_remove_kbn_assets_in_space.ts index 9cbc9261f37be..f46242402fce9 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_remove_kbn_assets_in_space.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_remove_kbn_assets_in_space.ts @@ -7,7 +7,6 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry, isDockerRegistryEnabledOrSkipped } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; const testSpaceId = 'fleet_test_space'; @@ -15,6 +14,7 @@ export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const kibanaServer = getService('kibanaServer'); const supertest = getService('supertest'); + const fleetAndAgents = getService('fleetAndAgents'); const pkgName = 'only_dashboard'; const pkgVersion = '0.1.0'; @@ -43,18 +43,18 @@ export default function (providerContext: FtrProviderContext) { await supertest.delete(`/api/spaces/space/${spaceId}`).set('kbn-xsrf', 'xxxx').send(); }; - describe('installs and uninstalls all assets (non default space)', async () => { + describe('installs and uninstalls all assets (non default space)', () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); before(async () => { + await fleetAndAgents.setup(); await createSpace(testSpaceId); }); after(async () => { await deleteSpace(testSpaceId); }); - describe('installs all assets when installing a package for the first time in non default space', async () => { + describe('installs all assets when installing a package for the first time in non default space', () => { before(async () => { if (!isDockerRegistryEnabledOrSkipped(providerContext)) return; await installPackageInSpace(pkgName, pkgVersion, testSpaceId); @@ -70,7 +70,7 @@ export default function (providerContext: FtrProviderContext) { }); }); - describe('uninstalls all assets when uninstalling a package from a different space', async () => { + describe('uninstalls all assets when uninstalling a package from a different space', () => { before(async () => { if (!isDockerRegistryEnabledOrSkipped(providerContext)) return; await installPackageInSpace(pkgName, pkgVersion, testSpaceId); diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_remove_multiple.ts b/x-pack/test/fleet_api_integration/apis/epm/install_remove_multiple.ts index 3d509fc819f0d..f4d1a6106396d 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_remove_multiple.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_remove_multiple.ts @@ -10,7 +10,6 @@ import path from 'path'; import fs from 'fs'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry, isDockerRegistryEnabledOrSkipped } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; @@ -20,6 +19,7 @@ export default function (providerContext: FtrProviderContext) { const pkgVersion = '0.1.0'; const experimentalPkgName = 'experimental'; const experimental2PkgName = 'experimental2'; + const fleetAndAgents = getService('fleetAndAgents'); const uploadPkgName = 'apache'; @@ -57,11 +57,12 @@ export default function (providerContext: FtrProviderContext) { return Promise.all(uninstallingPackagesPromise); }; - describe('installs and uninstalls multiple packages side effects', async () => { + describe('installs and uninstalls multiple packages side effects', () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); before(async () => { + await fleetAndAgents.setup(); + if (!isDockerRegistryEnabledOrSkipped(providerContext)) return; await installPackages([ { name: pkgName, version: pkgVersion }, diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_runtime_field.ts b/x-pack/test/fleet_api_integration/apis/epm/install_runtime_field.ts index 6f8bc6f4e3ccd..ab43043456761 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_runtime_field.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_runtime_field.ts @@ -9,12 +9,12 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry, isDockerRegistryEnabledOrSkipped } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); const es = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); const testPackage = 'runtime_fields'; const testPackageVersion = '0.0.1'; @@ -23,9 +23,12 @@ export default function (providerContext: FtrProviderContext) { await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx'); }; - describe('package with runtime fields', async () => { + describe('package with runtime fields', () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); after(async () => { if (isDockerRegistryEnabledOrSkipped(providerContext)) { diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_tag_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/install_tag_assets.ts index cf1e5be7726ce..6a668e6b87c51 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_tag_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_tag_assets.ts @@ -9,13 +9,13 @@ import fs from 'fs'; import path from 'path'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry, isDockerRegistryEnabledOrSkipped } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; const testSpaceId = 'fleet_test_space'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const kibanaServer = getService('kibanaServer'); const supertest = getService('supertest'); + const fleetAndAgents = getService('fleetAndAgents'); const pkgName = 'only_dashboard'; const pkgVersion = '0.1.0'; @@ -67,9 +67,9 @@ export default function (providerContext: FtrProviderContext) { }; describe('Assets tagging', () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); before(async () => { + await fleetAndAgents.setup(); await createSpace(testSpaceId); }); diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_tsds_disable.ts b/x-pack/test/fleet_api_integration/apis/epm/install_tsds_disable.ts index 321596dde9f9e..3f01308661963 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_tsds_disable.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_tsds_disable.ts @@ -8,12 +8,12 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); const es = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); const deletePackage = async (name: string, version: string) => { await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx'); @@ -21,7 +21,10 @@ export default function (providerContext: FtrProviderContext) { describe('installing with tsds disabled', async () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); after(async () => { await deletePackage('nginx', '1.12.1-beta'); diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_update.ts b/x-pack/test/fleet_api_integration/apis/epm/install_update.ts index c36efd6066b6e..d823df132ed47 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_update.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_update.ts @@ -12,12 +12,12 @@ import { } from '@kbn/fleet-plugin/common/constants'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const kibanaServer = getService('kibanaServer'); const supertest = getService('supertest'); + const fleetAndAgents = getService('fleetAndAgents'); const deletePackage = async (name: string, version: string) => { await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx'); @@ -25,7 +25,10 @@ export default function (providerContext: FtrProviderContext) { describe('installing and updating scenarios', async () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); after(async () => { await deletePackage('multiple_versions', '0.3.0'); diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_with_signature_verification.ts b/x-pack/test/fleet_api_integration/apis/epm/install_with_signature_verification.ts index 7ee3a2637d6af..f0da6118b73f8 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_with_signature_verification.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_with_signature_verification.ts @@ -10,13 +10,13 @@ import { INGEST_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; import { Installation } from '@kbn/fleet-plugin/server/types'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry, isDockerRegistryEnabledOrSkipped } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; const TEST_KEY_ID = 'd2a182a7b0e00c14'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const es: Client = getService('es'); const supertest = getService('supertest'); + const fleetAndAgents = getService('fleetAndAgents'); const uninstallPackage = async (pkg: string, version: string) => { await supertest.delete(`/api/fleet/epm/packages/${pkg}/${version}`).set('kbn-xsrf', 'xxxx'); @@ -39,7 +39,10 @@ export default function (providerContext: FtrProviderContext) { describe('Installs verified and unverified packages', async () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); describe('verified package', async () => { after(async () => { diff --git a/x-pack/test/fleet_api_integration/apis/epm/list.ts b/x-pack/test/fleet_api_integration/apis/epm/list.ts index 6bccbc37a678c..e3dd62af4aa08 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/list.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/list.ts @@ -8,7 +8,6 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; import { testUsers } from '../test_users'; import { bundlePackage, removeBundledPackages } from './install_bundled'; @@ -17,6 +16,7 @@ export default function (providerContext: FtrProviderContext) { const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); + const fleetAndAgents = getService('fleetAndAgents'); // use function () {} and not () => {} here // because `this` has to point to the Mocha context @@ -28,8 +28,8 @@ export default function (providerContext: FtrProviderContext) { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); after(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); }); diff --git a/x-pack/test/fleet_api_integration/apis/epm/package_install_complete.ts b/x-pack/test/fleet_api_integration/apis/epm/package_install_complete.ts index 5552d9504c8fe..45efd25163b18 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/package_install_complete.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/package_install_complete.ts @@ -12,19 +12,22 @@ import { } from '@kbn/fleet-plugin/common/constants'; import { skipIfNoDockerRegistry, isDockerRegistryEnabledOrSkipped } from '../../helpers'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); + const fleetAndAgents = getService('fleetAndAgents'); const pkgName = 'multiple_versions'; const pkgVersion = '0.1.0'; const pkgUpdateVersion = '0.2.0'; describe('setup checks packages completed install', async () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); describe('package install', async () => { before(async () => { diff --git a/x-pack/test/fleet_api_integration/apis/epm/remove_legacy_templates.ts b/x-pack/test/fleet_api_integration/apis/epm/remove_legacy_templates.ts index bce10e14428f7..567d6f504eb4a 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/remove_legacy_templates.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/remove_legacy_templates.ts @@ -11,13 +11,13 @@ import fs from 'fs'; import { promisify } from 'util'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry, isDockerRegistryEnabledOrSkipped } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; const sleep = promisify(setTimeout); export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); const esClient = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); const uploadPkgName = 'apache'; const uploadPkgVersion = '0.1.4'; @@ -100,7 +100,10 @@ export default function (providerContext: FtrProviderContext) { describe('Legacy component template removal', async () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); afterEach(async () => { if (!isDockerRegistryEnabledOrSkipped(providerContext)) return; diff --git a/x-pack/test/fleet_api_integration/apis/epm/routing_rules.ts b/x-pack/test/fleet_api_integration/apis/epm/routing_rules.ts index 33ef065ee7d49..059b72f75d735 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/routing_rules.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/routing_rules.ts @@ -7,7 +7,6 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -import { setupFleetAndAgents } from '../agents/services'; import { skipIfNoDockerRegistry } from '../../helpers'; const TEST_WRITE_INDEX = 'logs-routing_rules.test-test'; @@ -21,13 +20,14 @@ export default function (providerContext: FtrProviderContext) { const supertest = getService('supertest'); const es = getService('es'); const esArchiver = getService('esArchiver'); + const fleetAndAgents = getService('fleetAndAgents'); describe('routing rules for fleet managed datastreams', () => { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); before(async () => { await supertest diff --git a/x-pack/test/fleet_api_integration/apis/epm/setup.ts b/x-pack/test/fleet_api_integration/apis/epm/setup.ts index 001cab435d75b..187fb53b1716f 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/setup.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/setup.ts @@ -9,7 +9,6 @@ import expect from '@kbn/expect'; import { GetInfoResponse, InstalledRegistry } from '@kbn/fleet-plugin/common/types'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; @@ -17,6 +16,7 @@ export default function (providerContext: FtrProviderContext) { const supertestWithoutAuth = getService('supertestWithoutAuth'); const log = getService('log'); const es = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); const uninstallPackage = async (name: string, version: string) => { await supertest @@ -27,7 +27,11 @@ export default function (providerContext: FtrProviderContext) { describe('setup api', async () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); + after(async () => { await uninstallPackage('deprecated', '0.1.0'); await uninstallPackage('multiple_versions', '0.3.0'); diff --git a/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts index a932172cf0960..d6d32e443fd58 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts @@ -10,13 +10,13 @@ import { FLEET_INSTALL_FORMAT_VERSION } from '@kbn/fleet-plugin/server/constants import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const kibanaServer = getService('kibanaServer'); const supertest = getService('supertest'); const es = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); const pkgName = 'all_assets'; const pkgVersion = '0.1.0'; const pkgUpdateVersion = '0.2.0'; @@ -36,9 +36,9 @@ export default function (providerContext: FtrProviderContext) { describe('updates all assets when updating a package to a different version', async () => { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); before(async () => { + await fleetAndAgents.setup(); await installPackage(pkgName, pkgVersion); await installPackage(pkgName, pkgUpdateVersion); }); diff --git a/x-pack/test/fleet_api_integration/apis/fleet_proxies/crud.ts b/x-pack/test/fleet_api_integration/apis/fleet_proxies/crud.ts index a2441b4532805..9e0a0873b4b91 100644 --- a/x-pack/test/fleet_api_integration/apis/fleet_proxies/crud.ts +++ b/x-pack/test/fleet_api_integration/apis/fleet_proxies/crud.ts @@ -8,7 +8,6 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; @@ -16,6 +15,7 @@ export default function (providerContext: FtrProviderContext) { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const es = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); async function getLatestFleetPolicies(policyId: string): Promise { const policyDocRes = await es.search({ @@ -36,8 +36,8 @@ export default function (providerContext: FtrProviderContext) { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); await kibanaServer.savedObjects.cleanStandardList(); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); const existingId = 'test-default-123'; const fleetServerHostId = 'test-fleetserver-123'; diff --git a/x-pack/test/fleet_api_integration/apis/fleet_server_hosts/crud.ts b/x-pack/test/fleet_api_integration/apis/fleet_server_hosts/crud.ts index f17a894f859cc..2b806db92d6ea 100644 --- a/x-pack/test/fleet_api_integration/apis/fleet_server_hosts/crud.ts +++ b/x-pack/test/fleet_api_integration/apis/fleet_server_hosts/crud.ts @@ -8,21 +8,21 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); + const fleetAndAgents = getService('fleetAndAgents'); describe('fleet_fleet_server_hosts_crud', async function () { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); await kibanaServer.savedObjects.cleanStandardList(); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); let defaultFleetServerHostId: string; diff --git a/x-pack/test/fleet_api_integration/apis/fleet_telemetry.ts b/x-pack/test/fleet_api_integration/apis/fleet_telemetry.ts index 03ae82d06f6b7..dad2f59fc8af9 100644 --- a/x-pack/test/fleet_api_integration/apis/fleet_telemetry.ts +++ b/x-pack/test/fleet_api_integration/apis/fleet_telemetry.ts @@ -13,7 +13,6 @@ import expect from '@kbn/expect'; import type { GetAgentsResponse } from '@kbn/fleet-plugin/common'; import { FtrProviderContext } from '../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry, generateAgent } from '../helpers'; -import { setupFleetAndAgents } from './agents/services'; const AGENT_COUNT_WAIT_ATTEMPTS = 3; @@ -22,6 +21,7 @@ export default function (providerContext: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); + const fleetAndAgents = getService('fleetAndAgents'); let agentCount = 0; let pkgVersion: string; @@ -30,10 +30,9 @@ export default function (providerContext: FtrProviderContext) { before(async () => { await kibanaServer.savedObjects.cleanStandardList(); await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); - after(async () => { await kibanaServer.savedObjects.cleanStandardList(); await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); diff --git a/x-pack/test/fleet_api_integration/apis/integrations/elastic_agent.ts b/x-pack/test/fleet_api_integration/apis/integrations/elastic_agent.ts index 401c1b3714bd3..61e4b5e95443d 100644 --- a/x-pack/test/fleet_api_integration/apis/integrations/elastic_agent.ts +++ b/x-pack/test/fleet_api_integration/apis/integrations/elastic_agent.ts @@ -11,19 +11,20 @@ import { FLEET_ELASTIC_AGENT_PACKAGE } from '@kbn/fleet-plugin/common/constants/ import { DASHBOARD_LOCATORS_IDS } from '@kbn/fleet-plugin/common'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { describe('Install elastic_agent package', () => { const { getService } = providerContext; + const fleetAndAgents = getService('fleetAndAgents'); + skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); const kibanaServer = getService('kibanaServer'); const supertest = getService('supertest'); let pkgVersion: string; before(async () => { + await fleetAndAgents.setup(); const getPkRes = await supertest .get(`/api/fleet/epm/packages/${FLEET_ELASTIC_AGENT_PACKAGE}`) .set('kbn-xsrf', 'xxxx') diff --git a/x-pack/test/fleet_api_integration/apis/outputs/crud.ts b/x-pack/test/fleet_api_integration/apis/outputs/crud.ts index b830373e7dbbd..32e14db8f65e6 100644 --- a/x-pack/test/fleet_api_integration/apis/outputs/crud.ts +++ b/x-pack/test/fleet_api_integration/apis/outputs/crud.ts @@ -14,7 +14,6 @@ import { import { v4 as uuidV4 } from 'uuid'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { enableSecrets, skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; @@ -22,6 +21,7 @@ export default function (providerContext: FtrProviderContext) { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const es = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); let pkgVersion: string; @@ -201,8 +201,8 @@ export default function (providerContext: FtrProviderContext) { before(async () => { await kibanaServer.savedObjects.cleanStandardList(); await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); let defaultOutputId: string; let ESOutputId: string; diff --git a/x-pack/test/fleet_api_integration/apis/package_policy/create.ts b/x-pack/test/fleet_api_integration/apis/package_policy/create.ts index 9f9cdbbbdbb3b..5beb4a066dc9d 100644 --- a/x-pack/test/fleet_api_integration/apis/package_policy/create.ts +++ b/x-pack/test/fleet_api_integration/apis/package_policy/create.ts @@ -186,6 +186,28 @@ export default function (providerContext: FtrProviderContext) { expect(response.body.item.policy_ids).to.eql([agentPolicyId, agentPolicyId2]); }); + it('should work with no policy ids', async function () { + const response = await supertest + .post(`/api/fleet/package_policies`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: 'filetest-no-policies', + description: '', + namespace: 'default', + policy_ids: [], + enabled: true, + inputs: [], + package: { + name: 'filetest', + title: 'For File Tests', + version: '0.1.0', + }, + }) + .expect(200); + expect(response.body.item.policy_id).to.eql(null); + expect(response.body.item.policy_ids).to.eql([]); + }); + it('should allow to pass an empty namespace', async function () { await supertest .post(`/api/fleet/package_policies`) diff --git a/x-pack/test/fleet_api_integration/apis/package_policy/input_package_create_upgrade.ts b/x-pack/test/fleet_api_integration/apis/package_policy/input_package_create_upgrade.ts index 1bdb664c3ec07..b6221313bee23 100644 --- a/x-pack/test/fleet_api_integration/apis/package_policy/input_package_create_upgrade.ts +++ b/x-pack/test/fleet_api_integration/apis/package_policy/input_package_create_upgrade.ts @@ -8,7 +8,6 @@ import expect from '@kbn/expect'; import { sortBy } from 'lodash'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; const PACKAGE_NAME = 'input_package_upgrade'; const START_VERSION = '1.0.0'; const UPGRADE_VERSION = '1.1.0'; @@ -20,6 +19,8 @@ export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); const es = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); + const uninstallPackage = async (name: string, version: string) => { await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx'); }; @@ -176,6 +177,10 @@ export default function (providerContext: FtrProviderContext) { describe('Package Policy - input package behavior', async function () { skipIfNoDockerRegistry(providerContext); + before(async () => { + await fleetAndAgents.setup(); + }); + let agentPolicyId: string; beforeEach(async () => { await installPackage(PACKAGE_NAME, START_VERSION); @@ -188,7 +193,6 @@ export default function (providerContext: FtrProviderContext) { await uninstallPackage(PACKAGE_NAME, START_VERSION); }); - setupFleetAndAgents(providerContext); it('should not have created any ES assets on install', async () => { const installation = await getInstallationSavedObject(PACKAGE_NAME, START_VERSION); diff --git a/x-pack/test/fleet_api_integration/apis/package_policy/input_package_rollback.ts b/x-pack/test/fleet_api_integration/apis/package_policy/input_package_rollback.ts index f470b872a8e52..2f58f5e982dac 100644 --- a/x-pack/test/fleet_api_integration/apis/package_policy/input_package_rollback.ts +++ b/x-pack/test/fleet_api_integration/apis/package_policy/input_package_rollback.ts @@ -8,7 +8,6 @@ import expect from '@kbn/expect'; import { sortBy } from 'lodash'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; const PACKAGE_NAME = 'input_package_upgrade'; const START_VERSION = '1.0.0'; @@ -18,6 +17,8 @@ const expectIdArraysEqual = (arr1: any[], arr2: any[]) => { export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); + const fleetAndAgents = getService('fleetAndAgents'); + const uninstallPackage = async (name: string, version: string) => { await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx'); }; @@ -109,12 +110,12 @@ export default function (providerContext: FtrProviderContext) { before(async () => { const agentPolicy = await createAgentPolicy(); agentPolicyId = agentPolicy.id; + await fleetAndAgents.setup(); }); after(async () => { await deleteAgentPolicy(agentPolicyId); }); - setupFleetAndAgents(providerContext); it('should rollback package install on package policy create failure', async () => { const res = await createPackagePolicyWithDataset(agentPolicyId, 'test*', 400); diff --git a/x-pack/test/fleet_api_integration/apis/package_policy/update.ts b/x-pack/test/fleet_api_integration/apis/package_policy/update.ts index 6c456bea90d3d..a8b89723a01ab 100644 --- a/x-pack/test/fleet_api_integration/apis/package_policy/update.ts +++ b/x-pack/test/fleet_api_integration/apis/package_policy/update.ts @@ -320,6 +320,35 @@ export default function (providerContext: FtrProviderContext) { expect(response.body.item.policy_ids).to.eql([agentPolicyId, managedAgentPolicyId]); }); + it('should work with no policy ids', async function () { + const { body: packagePolicyResponse } = await supertest + .post(`/api/fleet/package_policies`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: 'filetest-to-clear-policy', + description: '', + namespace: 'default', + policy_id: agentPolicyId, + policy_ids: [agentPolicyId], + enabled: true, + inputs: [], + package: { + name: 'filetest', + title: 'For File Tests', + version: '0.1.0', + }, + }); + const response = await supertest + .put(`/api/fleet/package_policies/${packagePolicyResponse.item.id}`) + .set('kbn-xsrf', 'xxxx') + .send({ + policy_ids: [], + }) + .expect(200); + expect(response.body.item.policy_id).to.eql(null); + expect(response.body.item.policy_ids).to.eql([]); + }); + it('should trim whitespace from name on update', async function () { await supertest .put(`/api/fleet/package_policies/${packagePolicyId}`) diff --git a/x-pack/test/fleet_api_integration/apis/package_policy/upgrade.ts b/x-pack/test/fleet_api_integration/apis/package_policy/upgrade.ts index 066d8fc93f1fd..60f0ef0ecdc3d 100644 --- a/x-pack/test/fleet_api_integration/apis/package_policy/upgrade.ts +++ b/x-pack/test/fleet_api_integration/apis/package_policy/upgrade.ts @@ -12,7 +12,6 @@ import { import { sortBy } from 'lodash'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; const expectIdArraysEqual = (arr1: any[], arr2: any[]) => { expect(sortBy(arr1, 'id')).to.eql(sortBy(arr2, 'id')); @@ -24,6 +23,8 @@ export default function (providerContext: FtrProviderContext) { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const es = getService('es'); + const fleetAndAgents = getService('fleetAndAgents'); + function withTestPackage(name: string, version: string) { const pkgRoute = `/api/fleet/epm/packages/${name}/${version}`; before(async function () { @@ -62,6 +63,7 @@ export default function (providerContext: FtrProviderContext) { before(async () => { await kibanaServer.savedObjects.cleanStandardList(); await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); + await fleetAndAgents.setup(); }); after(async () => { @@ -71,8 +73,6 @@ export default function (providerContext: FtrProviderContext) { ); }); - setupFleetAndAgents(providerContext); - describe('when package version is not installed', function () { beforeEach(async function () { const { body: agentPolicyResponse } = await supertest diff --git a/x-pack/test/fleet_api_integration/apis/policy_secrets.ts b/x-pack/test/fleet_api_integration/apis/policy_secrets.ts index 86e32ca567413..0abeb46accd5a 100644 --- a/x-pack/test/fleet_api_integration/apis/policy_secrets.ts +++ b/x-pack/test/fleet_api_integration/apis/policy_secrets.ts @@ -18,7 +18,6 @@ import moment from 'moment'; import { v4 as uuidv4 } from 'uuid'; import { FtrProviderContext } from '../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../helpers'; -import { setupFleetAndAgents } from './agents/services'; const secretVar = (id: string) => `$co.elastic.secret{${id}}`; @@ -53,6 +52,7 @@ export default function (providerContext: FtrProviderContext) { const es: Client = getService('es'); const kibanaServer = getService('kibanaServer'); const supertest = getService('supertest'); + const fleetAndAgents = getService('fleetAndAgents'); const createAgentPolicy = async () => { const { body: agentPolicyResponse } = await supertest @@ -377,9 +377,9 @@ export default function (providerContext: FtrProviderContext) { }; skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); before(async () => { + await fleetAndAgents.setup(); await getService('esArchiver').load( 'x-pack/test/functional/es_archives/fleet/empty_fleet_server' ); diff --git a/x-pack/test/fleet_api_integration/apis/settings/enrollment.ts b/x-pack/test/fleet_api_integration/apis/settings/enrollment.ts index 046c5408dcbee..663f2889a9bfe 100644 --- a/x-pack/test/fleet_api_integration/apis/settings/enrollment.ts +++ b/x-pack/test/fleet_api_integration/apis/settings/enrollment.ts @@ -8,16 +8,19 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const fleetAndAgents = getService('fleetAndAgents'); describe('Enrollment settings - get', async function () { skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); + + before(async () => { + await fleetAndAgents.setup(); + }); it('should respond with empty enrollment settings on empty cluster', async function () { const response = await supertest diff --git a/x-pack/test/fleet_api_integration/apis/settings/get.ts b/x-pack/test/fleet_api_integration/apis/settings/get.ts index 3d6a3adb394c2..154fcb7fe0e8f 100644 --- a/x-pack/test/fleet_api_integration/apis/settings/get.ts +++ b/x-pack/test/fleet_api_integration/apis/settings/get.ts @@ -8,20 +8,20 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); + const fleetAndAgents = getService('fleetAndAgents'); describe('Settings - get', async function () { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); after(async () => { await kibanaServer.savedObjects.cleanStandardList(); diff --git a/x-pack/test/fleet_api_integration/apis/settings/update.ts b/x-pack/test/fleet_api_integration/apis/settings/update.ts index cc9f499967055..1a609373b4051 100644 --- a/x-pack/test/fleet_api_integration/apis/settings/update.ts +++ b/x-pack/test/fleet_api_integration/apis/settings/update.ts @@ -9,7 +9,6 @@ import expect from '@kbn/expect'; import { AGENT_POLICY_INDEX } from '@kbn/fleet-plugin/common'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { setupFleetAndAgents } from '../agents/services'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; @@ -17,14 +16,15 @@ export default function (providerContext: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); const esClient = getService('es'); const esArchiver = getService('esArchiver'); + const fleetAndAgents = getService('fleetAndAgents'); // Skipped as the Fleet Server hosts settings values are no longer used as of https://github.com/elastic/kibana/issues/137785 describe.skip('Settings - update', async function () { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); + await fleetAndAgents.setup(); }); - setupFleetAndAgents(providerContext); const createdAgentPolicyIds: string[] = []; after(async () => { diff --git a/x-pack/test/fleet_api_integration/apis/uninstall_token/privileges.ts b/x-pack/test/fleet_api_integration/apis/uninstall_token/privileges.ts index 25b23074bd7c1..d956a5aabe7b6 100644 --- a/x-pack/test/fleet_api_integration/apis/uninstall_token/privileges.ts +++ b/x-pack/test/fleet_api_integration/apis/uninstall_token/privileges.ts @@ -8,7 +8,6 @@ import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; import { runPrivilegeTests } from '../../privileges_helpers'; -import { setupFleetAndAgents } from '../agents/services'; import { testUsers } from '../test_users'; import { generateNAgentPolicies } from '../../helpers'; @@ -17,6 +16,7 @@ export default function (providerContext: FtrProviderContext) { const supertestWithoutAuth = getService('supertestWithoutAuth'); const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); + const fleetAndAgents = getService('fleetAndAgents'); describe('fleet_uninstall_token_privileges', () => { before(async () => { @@ -28,10 +28,10 @@ export default function (providerContext: FtrProviderContext) { }); before(async () => { await generateNAgentPolicies(supertest, 2); + await fleetAndAgents.setup(); }); skipIfNoDockerRegistry(providerContext); - setupFleetAndAgents(providerContext); const SCENARIOS = [ { diff --git a/x-pack/test/functional/apps/dashboard/group2/panel_titles.ts b/x-pack/test/functional/apps/dashboard/group2/panel_titles.ts index 1eb629fdf0d35..33297ac310630 100644 --- a/x-pack/test/functional/apps/dashboard/group2/panel_titles.ts +++ b/x-pack/test/functional/apps/dashboard/group2/panel_titles.ts @@ -88,7 +88,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - describe('nick by reference', () => { + describe('by reference', () => { const VIS_LIBRARY_DESCRIPTION = 'Vis library description'; let count = 0; diff --git a/x-pack/test/functional/apps/dashboard/group2/sync_colors.ts b/x-pack/test/functional/apps/dashboard/group2/sync_colors.ts index a388a4d90af3b..ecd5c86d22955 100644 --- a/x-pack/test/functional/apps/dashboard/group2/sync_colors.ts +++ b/x-pack/test/functional/apps/dashboard/group2/sync_colors.ts @@ -7,6 +7,7 @@ import { DebugState } from '@elastic/charts'; import expect from '@kbn/expect'; +import chroma from 'chroma-js'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { @@ -51,73 +52,104 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await kibanaServer.savedObjects.cleanStandardList(); }); - it('should sync colors on dashboard by default', async function () { + it('should sync colors on dashboard for legacy default palette', async function () { await PageObjects.dashboard.navigateToApp(); await elasticChart.setNewChartUiDebugFlag(true); await PageObjects.dashboard.clickCreateDashboardPrompt(); + + // create non-filtered xy chart await dashboardAddPanel.clickCreateNewLink(); await PageObjects.lens.goToTimeRange(); - await PageObjects.lens.configureDimension({ dimension: 'lnsXY_yDimensionPanel > lns-empty-dimension', operation: 'count', field: 'Records', }); - await PageObjects.lens.configureDimension({ dimension: 'lnsXY_splitDimensionPanel > lns-empty-dimension', operation: 'terms', field: 'geo.src', palette: { mode: 'legacy', id: 'default' }, }); - - await PageObjects.lens.save('vis1', false, true); + await PageObjects.lens.saveAndReturn(); await PageObjects.header.waitUntilLoadingHasFinished(); - await dashboardAddPanel.clickCreateNewLink(); + // create filtered xy chart + await dashboardAddPanel.clickCreateNewLink(); await PageObjects.lens.configureDimension({ dimension: 'lnsXY_yDimensionPanel > lns-empty-dimension', operation: 'count', field: 'Records', }); - await PageObjects.lens.configureDimension({ dimension: 'lnsXY_splitDimensionPanel > lns-empty-dimension', operation: 'terms', field: 'geo.src', palette: { mode: 'legacy', id: 'default' }, }); - await filterBar.addFilter({ field: 'geo.src', operation: 'is not', value: 'CN' }); + await PageObjects.lens.saveAndReturn(); + await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.lens.save('vis2', false, true); + // create datatable vis + await dashboardAddPanel.clickCreateNewLink(); + await PageObjects.lens.switchToVisualization('lnsDatatable'); + await PageObjects.lens.configureDimension({ + dimension: 'lnsDatatable_rows > lns-empty-dimension', + operation: 'terms', + field: 'geo.src', + keepOpen: true, + }); + await PageObjects.lens.setTermsNumberOfValues(5); + await PageObjects.lens.setTableDynamicColoring('cell'); + await PageObjects.lens.setPalette('default', true); + await PageObjects.lens.closeDimensionEditor(); + await PageObjects.lens.configureDimension({ + dimension: 'lnsDatatable_metrics > lns-empty-dimension', + operation: 'count', + field: 'Records', + }); + await PageObjects.lens.saveAndReturn(); + + // Set dashboard to sync colors await PageObjects.dashboard.openSettingsFlyout(); await dashboardSettings.toggleSyncColors(true); await dashboardSettings.clickApplyButton(); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.dashboard.waitForRenderComplete(); - const colorMapping1 = getColorMapping(await PageObjects.dashboard.getPanelChartDebugState(0)); - const colorMapping2 = getColorMapping(await PageObjects.dashboard.getPanelChartDebugState(1)); + const colorMappings1 = Object.entries( + getColorMapping(await PageObjects.dashboard.getPanelChartDebugState(0)) + ); + const colorMappings2 = Object.entries( + getColorMapping(await PageObjects.dashboard.getPanelChartDebugState(1)) + ); - expect(Object.keys(colorMapping1)).to.have.length(6); - expect(Object.keys(colorMapping1)).to.have.length(6); - const panel1Keys = ['CN']; - const panel2Keys = ['PK']; - const sharedKeys = ['IN', 'US', 'ID', 'BR', 'Other']; - // colors for keys exclusive to panel 1 should not occur in panel 2 - panel1Keys.forEach((panel1Key) => { - const assignedColor = colorMapping1[panel1Key]; - expect(Object.values(colorMapping2)).not.to.contain(assignedColor); - }); - // colors for keys exclusive to panel 2 should not occur in panel 1 - panel2Keys.forEach((panel2Key) => { - const assignedColor = colorMapping2[panel2Key]; - expect(Object.values(colorMapping1)).not.to.contain(assignedColor); + const els = await PageObjects.lens.getDatatableCellsByColumn(0); + const colorMappings3 = await Promise.all( + els.map(async (el) => [ + await el.getVisibleText(), + chroma((await PageObjects.lens.getStylesFromCell(el))['background-color']).hex(), // eui converts hex to rgb + ]) + ); + + expect(colorMappings1).to.have.length(6); + expect(colorMappings2).to.have.length(6); + expect(colorMappings3).to.have.length(6); + + const mergedColorAssignments = new Map>(); + + [...colorMappings1, ...colorMappings2, ...colorMappings3].forEach(([key, color]) => { + if (!mergedColorAssignments.has(key)) mergedColorAssignments.set(key, new Set()); + mergedColorAssignments.get(key)?.add(color); }); - // colors for keys used in both panels should be synced - sharedKeys.forEach((sharedKey) => { - expect(colorMapping1[sharedKey]).to.eql(colorMapping2[sharedKey]); + + // Each key should have only been assigned one color across all 3 visualizations + mergedColorAssignments.forEach((colors, key) => { + expect(colors.size).eql( + 1, + `Key "${key}" was assigned multiple colors: ${JSON.stringify([...colors])}` + ); }); }); diff --git a/x-pack/test/functional/apps/dataset_quality/dataset_quality_flyout.ts b/x-pack/test/functional/apps/dataset_quality/dataset_quality_details.ts similarity index 69% rename from x-pack/test/functional/apps/dataset_quality/dataset_quality_flyout.ts rename to x-pack/test/functional/apps/dataset_quality/dataset_quality_details.ts index 52ccfad201a53..3ac6cf8b46945 100644 --- a/x-pack/test/functional/apps/dataset_quality/dataset_quality_flyout.ts +++ b/x-pack/test/functional/apps/dataset_quality/dataset_quality_details.ts @@ -10,6 +10,7 @@ import { DatasetQualityFtrProviderContext } from './config'; import { createDegradedFieldsRecord, datasetNames, + defaultNamespace, getInitialTestLogs, getLogsForDataset, productionNamespace, @@ -33,8 +34,9 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid const retry = getService('retry'); const browser = getService('browser'); const to = '2024-01-01T12:00:00.000Z'; + const apacheAccessDatasetName = 'apache.access'; - const apacheAccessDatasetHumanName = 'Apache access logs'; + const apacheAccessDataStreamName = `logs-${apacheAccessDatasetName}-${productionNamespace}`; const apacheIntegrationId = 'apache'; const apachePkg = { name: 'apache', @@ -42,15 +44,18 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid }; const bitbucketDatasetName = 'atlassian_bitbucket.audit'; - const bitbucketDatasetHumanName = 'Bitbucket Audit Logs'; + const bitbucketAuditDataStreamName = `logs-${bitbucketDatasetName}-${defaultNamespace}`; const bitbucketPkg = { name: 'atlassian_bitbucket', version: '1.14.0', }; + const regularDatasetName = datasetNames[0]; + const regularDataStreamName = `logs-${datasetNames[0]}-${defaultNamespace}`; const degradedDatasetName = datasetNames[2]; + const degradedDataStreamName = `logs-${degradedDatasetName}-${defaultNamespace}`; - describe('Flyout', () => { + describe('Dataset Quality Details', () => { before(async () => { // Install Apache Integration and ingest logs for it await PageObjects.observabilityLogsExplorer.installPackage(apachePkg); @@ -85,8 +90,6 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid // Index logs for Bitbucket integration getLogsForDataset({ to, count: 10, dataset: bitbucketDatasetName }), ]); - - await PageObjects.datasetQuality.navigateTo(); }); after(async () => { @@ -95,21 +98,49 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid await synthtrace.clean(); }); - describe('open flyout', () => { - it('should open the flyout for the right dataset', async () => { - const testDatasetName = datasetNames[1]; + describe('navigate to dataset details', () => { + it('should navigate to right dataset', async () => { + await PageObjects.datasetQuality.navigateToDetails({ dataStream: regularDataStreamName }); + + await testSubjects.existOrFail( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsTitle + ); + }); + + it('should navigate to details page from a main page', async () => { + await PageObjects.datasetQuality.navigateTo(); + + const synthDataset = await testSubjects.find( + 'datasetQualityTableDetailsLink-logs-synth.1-default', + 20 * 1000 + ); - await PageObjects.datasetQuality.openDatasetFlyout(testDatasetName); + await synthDataset.click(); await testSubjects.existOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutTitle + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsTitle ); + }); - await PageObjects.datasetQuality.closeFlyout(); + it('should show an empty prompt with error message when the dataset is not found', async () => { + const nonExistentDataStreamName = 'logs-non.existent-production'; + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: nonExistentDataStreamName, + }); + + await testSubjects.existOrFail( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsEmptyPrompt + ); + + const emptyPromptBody = await testSubjects.getVisibleText( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsEmptyPromptBody + ); + + expect(emptyPromptBody).to.contain(nonExistentDataStreamName); }); it('reflects the breakdown field state in url', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ dataStream: degradedDataStreamName }); const breakdownField = 'service.name'; await PageObjects.datasetQuality.selectBreakdownField(breakdownField); @@ -128,46 +159,72 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid const currentUrl = await browser.getCurrentUrl(); expect(currentUrl).to.not.contain('breakdownField'); }); - await PageObjects.datasetQuality.closeFlyout(); }); }); - describe('integrations', () => { - it('should hide the integration section for non integrations', async () => { - const testDatasetName = datasetNames[1]; + describe('overview summary panel', () => { + it('should show summary KPIs', async () => { + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); - await PageObjects.datasetQuality.openDatasetFlyout(testDatasetName); + const { docsCountTotal, degradedDocs, services, hosts, size } = + await PageObjects.datasetQuality.parseOverviewSummaryPanelKpis(); + expect(parseInt(docsCountTotal, 10)).to.be(226); + expect(parseInt(degradedDocs, 10)).to.be(1); + expect(parseInt(services, 10)).to.be(3); + expect(parseInt(hosts, 10)).to.be(52); + expect(parseInt(size, 10)).to.be.greaterThan(0); + }); + }); + describe('overview integrations', () => { + it('should hide the integration section for non integrations', async () => { + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: regularDataStreamName, + }); + + // The Integration row should not be present await testSubjects.missingOrFail( PageObjects.datasetQuality.testSubjectSelectors - .datasetQualityFlyoutFieldsListIntegrationDetails + .datasetQualityDetailsIntegrationRowIntegration ); - await PageObjects.datasetQuality.closeFlyout(); + // The Version row should not be present + await testSubjects.missingOrFail( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationRowVersion + ); }); it('should shows the integration section for integrations', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); await testSubjects.existOrFail( PageObjects.datasetQuality.testSubjectSelectors - .datasetQualityFlyoutFieldsListIntegrationDetails + .datasetQualityDetailsIntegrationRowIntegration + ); + + await testSubjects.existOrFail( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationRowVersion ); await retry.tryForTime(5000, async () => { const integrationNameExists = await PageObjects.datasetQuality.doesTextExist( PageObjects.datasetQuality.testSubjectSelectors - .datasetQualityFlyoutFieldsListIntegrationDetails, + .datasetQualityDetailsIntegrationRowIntegration, apacheIntegrationId ); expect(integrationNameExists).to.be(true); }); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should show the integration actions menu with correct actions', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); + await PageObjects.datasetQuality.openIntegrationActionsMenu(); const actions = await Promise.all( @@ -177,23 +234,26 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid ); expect(actions.length).to.eql(3); - await PageObjects.datasetQuality.closeFlyout(); }); it('should hide integration dashboard for integrations without dashboards', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(bitbucketDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: bitbucketAuditDataStreamName, + }); + await PageObjects.datasetQuality.openIntegrationActionsMenu(); await testSubjects.missingOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutIntegrationAction( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationAction( integrationActions.viewDashboards ) ); - await PageObjects.datasetQuality.closeFlyout(); }); it('Should navigate to integration overview page on clicking integration overview action', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(bitbucketDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: bitbucketAuditDataStreamName, + }); await PageObjects.datasetQuality.openIntegrationActionsMenu(); const action = await PageObjects.datasetQuality.getIntegrationActionButtonByAction( @@ -208,12 +268,12 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid expect(parsedUrl.pathname).to.contain('/app/integrations/detail/atlassian_bitbucket'); }); - - await PageObjects.datasetQuality.navigateTo(); }); it('should navigate to index template page in clicking Integration template', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); await PageObjects.datasetQuality.openIntegrationActionsMenu(); const action = await PageObjects.datasetQuality.getIntegrationActionButtonByAction( @@ -229,11 +289,12 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid `/app/management/data/index_management/templates/logs-${apacheAccessDatasetName}` ); }); - await PageObjects.datasetQuality.navigateTo(); }); it('should navigate to the selected dashboard on clicking integration dashboard action ', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); await PageObjects.datasetQuality.openIntegrationActionsMenu(); const action = await PageObjects.datasetQuality.getIntegrationActionButtonByAction( @@ -251,119 +312,87 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid const breadcrumbText = await testSubjects.getVisibleText('breadcrumb last'); expect(breadcrumbText).to.eql(dashboardText); - - await PageObjects.datasetQuality.navigateTo(); - }); - }); - - describe('summary panel', () => { - it('should show summary KPIs', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); - - const { docsCountTotal, degradedDocs, services, hosts, size } = - await PageObjects.datasetQuality.parseFlyoutKpis(); - expect(parseInt(docsCountTotal, 10)).to.be(226); - expect(parseInt(degradedDocs, 10)).to.be(1); - expect(parseInt(services, 10)).to.be(3); - expect(parseInt(hosts, 10)).to.be(52); - expect(parseInt(size, 10)).to.be.greaterThan(0); - - await PageObjects.datasetQuality.closeFlyout(); }); }); describe('navigation', () => { - afterEach(async () => { - // Navigate back to dataset quality page after each test - await PageObjects.datasetQuality.navigateTo(); - }); - it('should go to log explorer page when the open in log explorer button is clicked', async () => { - const testDatasetName = datasetNames[2]; - await PageObjects.datasetQuality.openDatasetFlyout(testDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: regularDataStreamName, + }); - const logExplorerButton = await PageObjects.datasetQuality.getFlyoutLogsExplorerButton(); + const logExplorerButton = + await PageObjects.datasetQuality.getDatasetQualityDetailsHeaderButton(); await logExplorerButton.click(); // Confirm dataset selector text in observability logs explorer const datasetSelectorText = await PageObjects.observabilityLogsExplorer.getDataSourceSelectorButtonText(); - expect(datasetSelectorText).to.eql(testDatasetName); + expect(datasetSelectorText).to.eql(regularDatasetName); }); - it('should go log explorer for degraded docs when the show all button is clicked', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + it('should go log explorer for degraded docs when the button next to breakdown selector is clicked', async () => { + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); - const degradedDocsShowAllSelector = `${PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutKpiLink}-${PageObjects.datasetQuality.texts.degradedDocs}`; - await testSubjects.click(degradedDocsShowAllSelector); + await testSubjects.click( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsLinkToDiscover + ); // Confirm dataset selector text in observability logs explorer const datasetSelectorText = await PageObjects.observabilityLogsExplorer.getDataSourceSelectorButtonText(); expect(datasetSelectorText).to.contain(apacheAccessDatasetName); }); - - // Blocked by https://github.com/elastic/kibana/issues/181705 - // Its a test written ahead of its time. - it.skip('goes to infra hosts for hosts when show all is clicked', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); - - const hostsShowAllSelector = `${PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutKpiLink}-${PageObjects.datasetQuality.texts.hosts}`; - await testSubjects.click(hostsShowAllSelector); - - // Confirm url contains metrics/hosts - await retry.tryForTime(5000, async () => { - const currentUrl = await browser.getCurrentUrl(); - const parsedUrl = new URL(currentUrl); - expect(parsedUrl.pathname).to.contain('/app/metrics/hosts'); - }); - }); }); describe('degraded fields table', () => { it(' should show empty degraded fields table when no degraded fields are present', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(datasetNames[0]); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: regularDataStreamName, + }); await testSubjects.existOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutDegradedTableNoData + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsDegradedTableNoData ); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should show the degraded fields table with data when present', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); await testSubjects.existOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutDegradedFieldTable + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsDegradedFieldTable ); const rows = - await PageObjects.datasetQuality.getDatasetQualityFlyoutDegradedFieldTableRows(); + await PageObjects.datasetQuality.getDatasetQualityDetailsDegradedFieldTableRows(); expect(rows.length).to.eql(2); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should display Spark Plot for every row of degraded fields', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); const rows = - await PageObjects.datasetQuality.getDatasetQualityFlyoutDegradedFieldTableRows(); + await PageObjects.datasetQuality.getDatasetQualityDetailsDegradedFieldTableRows(); const sparkPlots = await testSubjects.findAll( PageObjects.datasetQuality.testSubjectSelectors.datasetQualitySparkPlot ); expect(rows.length).to.be(sparkPlots.length); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should sort the table when the count table header is clicked', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); const table = await PageObjects.datasetQuality.parseDegradedFieldTable(); @@ -374,12 +403,12 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid const sortedCellTexts = await countColumn.getCellTexts(); expect(cellTexts.reverse()).to.eql(sortedCellTexts); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should update the URL when the table is sorted', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); const table = await PageObjects.datasetQuality.parseDegradedFieldTable(); const countColumn = table['Docs count']; @@ -405,8 +434,6 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid 'sort:(direction:asc,field:count)' ); }); - - await PageObjects.datasetQuality.closeFlyout(); }); // This is the only test which ingest data during the test. @@ -414,7 +441,9 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid // Even though this test ingest data, it can also be freely moved inside // this describe block, and it won't affect any of the existing tests it('should update the table when new data is ingested and the flyout is refreshed using the time selector', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); const table = await PageObjects.datasetQuality.parseDegradedFieldTable(); @@ -429,7 +458,7 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid }), ]); - await PageObjects.datasetQuality.refreshFlyout(); + await PageObjects.datasetQuality.refreshDetailsPageData(); const updatedTable = await PageObjects.datasetQuality.parseDegradedFieldTable(); const updatedCountColumn = updatedTable['Docs count']; @@ -440,8 +469,6 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid const singleValueNow = parseInt(updatedCellTexts[0], 10); expect(singleValueNow).to.be.greaterThan(singleValuePreviously); - - await PageObjects.datasetQuality.closeFlyout(); }); }); }); diff --git a/x-pack/test/functional/apps/dataset_quality/dataset_quality_privileges.ts b/x-pack/test/functional/apps/dataset_quality/dataset_quality_privileges.ts index c7c3cbf709931..c94a083946066 100644 --- a/x-pack/test/functional/apps/dataset_quality/dataset_quality_privileges.ts +++ b/x-pack/test/functional/apps/dataset_quality/dataset_quality_privileges.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { DatasetQualityFtrProviderContext } from './config'; -import { getInitialTestLogs, getLogsForDataset } from './data'; +import { datasetNames, defaultNamespace, getInitialTestLogs, getLogsForDataset } from './data'; export default function ({ getService, getPageObjects }: DatasetQualityFtrProviderContext) { const PageObjects = getPageObjects([ @@ -25,6 +25,8 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid const apacheAccessDatasetName = 'apache.access'; const apacheAccessDatasetHumanName = 'Apache access logs'; + const regularDataStreamName = `logs-${datasetNames[0]}-${defaultNamespace}`; + const apacheAccessDataStreamName = `logs-${apacheAccessDatasetName}-${defaultNamespace}`; describe('Dataset quality handles user privileges', () => { before(async () => { @@ -170,35 +172,39 @@ export default function ({ getService, getPageObjects }: DatasetQualityFtrProvid ); }); - it('flyout shows insufficient privileges warning for underprivileged data stream', async () => { - await PageObjects.datasetQuality.openDatasetFlyout('synth.1'); + it('Details page shows insufficient privileges warning for underprivileged data stream', async () => { + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: regularDataStreamName, + }); await testSubjects.existOrFail( `${PageObjects.datasetQuality.testSubjectSelectors.datasetQualityInsufficientPrivileges}-Size` ); - await PageObjects.datasetQuality.closeFlyout(); + await PageObjects.datasetQuality.navigateTo(); }); it('"View dashboards" and "See integration" are hidden for underprivileged user', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); await PageObjects.datasetQuality.openIntegrationActionsMenu(); // "See Integration" is hidden await testSubjects.missingOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutIntegrationAction( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationAction( 'Overview' ) ); // "View Dashboards" is hidden await testSubjects.missingOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutIntegrationAction( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationAction( 'ViewDashboards' ) ); - await PageObjects.datasetQuality.closeFlyout(); + await PageObjects.datasetQuality.navigateTo(); }); }); }); diff --git a/x-pack/test/functional/apps/dataset_quality/index.ts b/x-pack/test/functional/apps/dataset_quality/index.ts index f22af151ca6c9..ec975f6cafff6 100644 --- a/x-pack/test/functional/apps/dataset_quality/index.ts +++ b/x-pack/test/functional/apps/dataset_quality/index.ts @@ -13,7 +13,7 @@ export default function ({ loadTestFile }: DatasetQualityFtrProviderContext) { loadTestFile(require.resolve('./dataset_quality_summary')); loadTestFile(require.resolve('./dataset_quality_table')); loadTestFile(require.resolve('./dataset_quality_table_filters')); - loadTestFile(require.resolve('./dataset_quality_flyout')); loadTestFile(require.resolve('./dataset_quality_privileges')); + loadTestFile(require.resolve('./dataset_quality_details')); }); } diff --git a/x-pack/test/functional/apps/lens/group4/show_underlying_data.ts b/x-pack/test/functional/apps/lens/group4/show_underlying_data.ts index fee3756e11759..2d9035238452f 100644 --- a/x-pack/test/functional/apps/lens/group4/show_underlying_data.ts +++ b/x-pack/test/functional/apps/lens/group4/show_underlying_data.ts @@ -48,7 +48,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await browser.switchToWindow(discoverWindowHandle); await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.existOrFail('unifiedHistogramChart'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await testSubjects.existOrFail('unifiedDataTableToolbar'); // check the table columns const columns = await PageObjects.discover.getColumnHeaders(); expect(columns).to.eql(['@timestamp', 'extension.raw', 'bytes']); diff --git a/x-pack/test/functional/apps/lens/open_in_lens/tsvb/dashboard.ts b/x-pack/test/functional/apps/lens/open_in_lens/tsvb/dashboard.ts index e61dd9e9ffb97..880c35c98975e 100644 --- a/x-pack/test/functional/apps/lens/open_in_lens/tsvb/dashboard.ts +++ b/x-pack/test/functional/apps/lens/open_in_lens/tsvb/dashboard.ts @@ -89,15 +89,20 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await dashboard.waitForRenderComplete(); const originalEmbeddableCount = await canvas.getEmbeddableCount(); - await retry.try(async () => { - await dashboardPanelActions.customizePanel(); - await dashboardCustomizePanel.enableCustomTimeRange(); + + await panelActions.customizePanel(); + await dashboardCustomizePanel.expectCustomizePanelSettingsFlyoutOpen(); + await dashboardCustomizePanel.enableCustomTimeRange(); + await retry.waitFor('quick menu', async () => { await dashboardCustomizePanel.openDatePickerQuickMenu(); - await dashboardCustomizePanel.clickCommonlyUsedTimeRange('Last_30 days'); - await dashboardCustomizePanel.clickSaveButton(); - await dashboard.waitForRenderComplete(); - await dashboardBadgeActions.expectExistsTimeRangeBadgeAction(); + return await testSubjects.exists('superDatePickerCommonlyUsed_Last_30 days'); }); + await dashboardCustomizePanel.clickCommonlyUsedTimeRange('Last_30 days'); + await dashboardCustomizePanel.clickSaveButton(); + await dashboardCustomizePanel.expectCustomizePanelSettingsFlyoutClosed(); + await dashboard.waitForRenderComplete(); + await dashboardBadgeActions.expectExistsTimeRangeBadgeAction(); + await panelActions.openContextMenu(); await panelActions.clickEdit(); diff --git a/x-pack/test/functional/apps/managed_content/managed_content.ts b/x-pack/test/functional/apps/managed_content/managed_content.ts index 24f88fd72dc36..63ac63e0c7bf6 100644 --- a/x-pack/test/functional/apps/managed_content/managed_content.ts +++ b/x-pack/test/functional/apps/managed_content/managed_content.ts @@ -112,7 +112,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('maps', async () => { await PageObjects.common.navigateToActualUrl( 'maps', - 'map/managed-d7ab-46eb-a807-8fed28ed8566' + 'map/managed-d7ab-46eb-a807-8fed28ed8566', + { ensureCurrentUrl: false } ); await PageObjects.maps.waitForLayerAddPanelClosed(); @@ -120,7 +121,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.common.navigateToActualUrl( 'maps', - 'map/unmanaged-d7ab-46eb-a807-8fed28ed8566' + 'map/unmanaged-d7ab-46eb-a807-8fed28ed8566', + { ensureCurrentUrl: false } ); await PageObjects.maps.waitForLayerAddPanelClosed(); diff --git a/x-pack/test/functional/apps/slo/embeddables/overview_embeddable.ts b/x-pack/test/functional/apps/slo/embeddables/overview_embeddable.ts index 5a531d6cf5bb5..3624513b7cbb7 100644 --- a/x-pack/test/functional/apps/slo/embeddables/overview_embeddable.ts +++ b/x-pack/test/functional/apps/slo/embeddables/overview_embeddable.ts @@ -23,6 +23,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('overview embeddable', function () { before(async () => { await loadTestData(getService); + await slo.createUser(); await slo.deleteAllSLOs(); await slo.create(sloData); await PageObjects.dashboard.navigateToApp(); diff --git a/x-pack/test/functional/page_objects/dataset_quality.ts b/x-pack/test/functional/page_objects/dataset_quality.ts index b2d07161ddbaa..8fdc021af79fc 100644 --- a/x-pack/test/functional/page_objects/dataset_quality.ts +++ b/x-pack/test/functional/page_objects/dataset_quality.ts @@ -7,12 +7,11 @@ import querystring from 'querystring'; import rison from '@kbn/rison'; -import expect from '@kbn/expect'; -import { TimeUnitId } from '@elastic/eui'; import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { DATA_QUALITY_URL_STATE_KEY, datasetQualityUrlSchemaV1, + datasetQualityDetailsUrlSchemaV1, } from '@kbn/data-quality-plugin/common'; import { DEFAULT_DEGRADED_FIELD_SORT_DIRECTION, @@ -26,15 +25,18 @@ const defaultPageState: datasetQualityUrlSchemaV1.UrlSchema = { page: 0, }, filters: {}, - flyout: { - degradedFields: { - table: { - page: 0, - rowsPerPage: 10, - sort: { - field: DEFAULT_DEGRADED_FIELD_SORT_FIELD, - direction: DEFAULT_DEGRADED_FIELD_SORT_DIRECTION, - }, +}; + +const defaultDetailsPageState: datasetQualityDetailsUrlSchemaV1.UrlSchema = { + v: 1, + dataStream: 'logs-synth.1-default', + degradedFields: { + table: { + page: 0, + rowsPerPage: 10, + sort: { + field: DEFAULT_DEGRADED_FIELD_SORT_FIELD, + direction: DEFAULT_DEGRADED_FIELD_SORT_DIRECTION, }, }, }, @@ -49,7 +51,10 @@ type SummaryPanelKpi = Record< string >; -type FlyoutKpi = Record<'docsCountTotal' | 'size' | 'services' | 'hosts' | 'degradedDocs', string>; +type SummaryPanelKPI = Record< + 'docsCountTotal' | 'size' | 'services' | 'hosts' | 'degradedDocs', + string +>; const texts = { noActivityText: 'No activity in the selected timeframe', @@ -58,7 +63,7 @@ const texts = { datasetHealthGood: 'Good', activeDatasets: 'Active Data Sets', estimatedData: 'Estimated Data', - docsCountTotal: 'Docs count (total)', + docsCountTotal: 'Total count', size: 'Size', services: 'Services', hosts: 'Hosts', @@ -86,20 +91,16 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv datasetQualityTable: 'datasetQualityTable', datasetQualityFiltersContainer: 'datasetQualityFiltersContainer', datasetQualityExpandButton: 'datasetQualityExpandButton', - datasetQualityFlyout: 'datasetQualityFlyout', - datasetQualityFlyoutBody: 'datasetQualityFlyoutBody', - datasetQualityFlyoutTitle: 'datasetQualityFlyoutTitle', - datasetQualityFlyoutDegradedFieldTable: 'datasetQualityFlyoutDegradedFieldTable', - datasetQualityFlyoutDegradedTableNoData: 'datasetQualityFlyoutDegradedTableNoData', + datasetDetailsContainer: 'datasetDetailsContainer', + datasetQualityDetailsTitle: 'datasetQualityDetailsTitle', + datasetQualityDetailsDegradedFieldTable: 'datasetQualityDetailsDegradedFieldTable', + datasetQualityDetailsDegradedTableNoData: 'datasetQualityDetailsDegradedTableNoData', datasetQualitySparkPlot: 'datasetQualitySparkPlot', - datasetQualityHeaderButton: 'datasetQualityHeaderButton', - datasetQualityFlyoutFieldValue: 'datasetQualityFlyoutFieldValue', - datasetQualityFlyoutFieldsListIntegrationDetails: - 'datasetQualityFlyoutFieldsList-integration_details', - datasetQualityFlyoutIntegrationLoading: 'datasetQualityFlyoutIntegrationLoading', - datasetQualityFlyoutIntegrationActionsButton: 'datasetQualityFlyoutIntegrationActionsButton', - datasetQualityFlyoutIntegrationAction: (action: string) => - `datasetQualityFlyoutIntegrationAction${action}`, + datasetQualityDetailsHeaderButton: 'datasetQualityDetailsHeaderButton', + datasetQualityDetailsIntegrationLoading: 'datasetQualityDetailsIntegrationLoading', + datasetQualityDetailsIntegrationActionsButton: 'datasetQualityDetailsIntegrationActionsButton', + datasetQualityDetailsIntegrationAction: (action: string) => + `datasetQualityDetailsIntegrationAction${action}`, datasetQualityFilterBarFieldSearch: 'datasetQualityFilterBarFieldSearch', datasetQualityIntegrationsSelectable: 'datasetQualityIntegrationsSelectable', datasetQualityIntegrationsSelectableButton: 'datasetQualityIntegrationsSelectableButton', @@ -107,9 +108,13 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv datasetQualityNamespacesSelectableButton: 'datasetQualityNamespacesSelectableButton', datasetQualityQualitiesSelectable: 'datasetQualityQualitiesSelectable', datasetQualityQualitiesSelectableButton: 'datasetQualityQualitiesSelectableButton', + datasetQualityDetailsEmptyPrompt: 'datasetQualityDetailsEmptyPrompt', + datasetQualityDetailsEmptyPromptBody: 'datasetQualityDetailsEmptyPromptBody', datasetQualityDatasetHealthKpi: 'datasetQualityDatasetHealthKpi', - datasetQualityFlyoutKpiValue: 'datasetQualityFlyoutKpiValue', - datasetQualityFlyoutKpiLink: 'datasetQualityFlyoutKpiLink', + datasetQualityDetailsSummaryKpiValue: 'datasetQualityDetailsSummaryKpiValue', + datasetQualityDetailsIntegrationRowIntegration: 'datasetQualityDetailsFieldsList-integration', + datasetQualityDetailsIntegrationRowVersion: 'datasetQualityDetailsFieldsList-version', + datasetQualityDetailsLinkToDiscover: 'datasetQualityDetailsLinkToDiscover', datasetQualityInsufficientPrivileges: 'datasetQualityInsufficientPrivileges', datasetQualityNoDataEmptyState: 'datasetQualityNoDataEmptyState', datasetQualityNoPrivilegesEmptyState: 'datasetQualityNoPrivilegesEmptyState', @@ -117,7 +122,6 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv superDatePickerToggleQuickMenuButton: 'superDatePickerToggleQuickMenuButton', superDatePickerApplyTimeButton: 'superDatePickerApplyTimeButton', superDatePickerQuickMenu: 'superDatePickerQuickMenu', - euiFlyoutCloseButton: 'euiFlyoutCloseButton', unifiedHistogramBreakdownSelectorButton: 'unifiedHistogramBreakdownSelectorButton', unifiedHistogramBreakdownSelectorSelectorSearch: 'unifiedHistogramBreakdownSelectorSelectorSearch', @@ -156,19 +160,30 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv ); }, - async waitUntilTableLoaded() { - await find.waitForDeletedByCssSelector('.euiBasicTable-loading', 20 * 1000); - }, + async navigateToDetails(pageState: datasetQualityDetailsUrlSchemaV1.UrlSchema) { + const queryStringParams = querystring.stringify({ + [DATA_QUALITY_URL_STATE_KEY]: rison.encode( + datasetQualityDetailsUrlSchemaV1.urlSchemaRT.encode({ + ...defaultDetailsPageState, + ...pageState, + }) + ), + }); - async waitUntilTableInFlyoutLoaded() { - await find.waitForDeletedByCssSelector('.euiFlyoutBody .euiBasicTable-loading', 20 * 1000); + return PageObjects.common.navigateToUrlWithBrowserHistory( + 'management', + '/data/data_quality/details', + queryStringParams, + { + // the check sometimes is too slow for the page so it misses the point + // in time before the app rewrites the URL + ensureCurrentUrl: false, + } + ); }, - async waitUntilIntegrationsInFlyoutLoaded() { - await find.waitForDeletedByCssSelector( - '.euiSkeletonTitle .datasetQualityFlyoutIntegrationLoading', - 10 * 1000 - ); + async waitUntilTableLoaded() { + await find.waitForDeletedByCssSelector('.euiBasicTable-loading', 20 * 1000); }, async waitUntilSummaryPanelLoaded(isStateful: boolean = true) { @@ -213,14 +228,14 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv return testSubjects.find(testSubjectSelectors.datasetQualityTable); }, - getDatasetQualityFlyoutDegradedFieldTable(): Promise { - return testSubjects.find(testSubjectSelectors.datasetQualityFlyoutDegradedFieldTable); + getDatasetQualityDetailsDegradedFieldTable(): Promise { + return testSubjects.find(testSubjectSelectors.datasetQualityDetailsDegradedFieldTable); }, - async getDatasetQualityFlyoutDegradedFieldTableRows(): Promise { - await this.waitUntilTableInFlyoutLoaded(); + async getDatasetQualityDetailsDegradedFieldTableRows(): Promise { + await this.waitUntilTableLoaded(); const table = await testSubjects.find( - testSubjectSelectors.datasetQualityFlyoutDegradedFieldTable + testSubjectSelectors.datasetQualityDetailsDegradedFieldTable ); const tBody = await table.findByTagName('tbody'); return tBody.findAllByTagName('tr'); @@ -265,8 +280,8 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv }, async parseDegradedFieldTable() { - await this.waitUntilTableInFlyoutLoaded(); - const table = await this.getDatasetQualityFlyoutDegradedFieldTable(); + await this.waitUntilTableLoaded(); + const table = await this.getDatasetQualityDetailsDegradedFieldTable(); return this.parseTable(table, ['Field', 'Docs count', 'Last Occurrence']); }, @@ -302,46 +317,11 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv return find.clickByCssSelector(selectors.showFullDatasetNamesSwitch); }, - async openDatasetFlyout(datasetName: string) { - await this.waitUntilTableLoaded(); - const cols = await this.parseDatasetTable(); - const datasetNameCol = cols['Data Set Name']; - const datasetNameColCellTexts = await datasetNameCol.getCellTexts(); - const testDatasetRowIndex = datasetNameColCellTexts.findIndex( - (dName) => dName === datasetName + async refreshDetailsPageData() { + const datasetDetailsContainer: WebElementWrapper = await testSubjects.find( + testSubjectSelectors.datasetDetailsContainer ); - - expect(testDatasetRowIndex).to.be.greaterThan(-1); - - const expandColumn = cols['0']; - const expandButtons = await expandColumn.getCellChildren( - `[data-test-subj=${testSubjectSelectors.datasetQualityExpandButton}]` - ); - - expect(expandButtons.length).to.be.greaterThan(0); - - const datasetExpandButton = expandButtons[testDatasetRowIndex]; - - // Check if 'title' attribute is "Expand" or "Collapse" - const isCollapsed = (await datasetExpandButton.getAttribute('title')) === 'Expand'; - - // Open if collapsed - if (isCollapsed) { - await datasetExpandButton.click(); - } - - await this.waitUntilIntegrationsInFlyoutLoaded(); - }, - - async closeFlyout() { - return testSubjects.click(testSubjectSelectors.euiFlyoutCloseButton); - }, - - async refreshFlyout() { - const flyoutContainer: WebElementWrapper = await testSubjects.find( - testSubjectSelectors.datasetQualityFlyoutBody - ); - const refreshButton = await flyoutContainer.findByTestSubject( + const refreshButton = await datasetDetailsContainer.findByTestSubject( testSubjectSelectors.superDatePickerApplyTimeButton ); return refreshButton.click(); @@ -357,27 +337,27 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv return false; }, - getFlyoutLogsExplorerButton() { - return testSubjects.find(testSubjectSelectors.datasetQualityHeaderButton); + getDatasetQualityDetailsHeaderButton() { + return testSubjects.find(testSubjectSelectors.datasetQualityDetailsHeaderButton); }, openIntegrationActionsMenu() { - return testSubjects.click(testSubjectSelectors.datasetQualityFlyoutIntegrationActionsButton); + return testSubjects.click(testSubjectSelectors.datasetQualityDetailsIntegrationActionsButton); }, getIntegrationActionButtonByAction(action: string) { - return testSubjects.find(testSubjectSelectors.datasetQualityFlyoutIntegrationAction(action)); + return testSubjects.find(testSubjectSelectors.datasetQualityDetailsIntegrationAction(action)); }, getIntegrationDashboardButtons() { return testSubjects.findAll( - testSubjectSelectors.datasetQualityFlyoutIntegrationAction('Dashboard') + testSubjectSelectors.datasetQualityDetailsIntegrationAction('Dashboard') ); }, // `excludeKeys` needed to circumvent `_stats` not available in Serverless https://github.com/elastic/kibana/issues/178954 // TODO: Remove `excludeKeys` when `_stats` is available in Serverless - async parseFlyoutKpis(excludeKeys: string[] = []): Promise { + async parseOverviewSummaryPanelKpis(excludeKeys: string[] = []): Promise { const kpiTitleAndKeys = [ { title: texts.docsCountTotal, key: 'docsCountTotal' }, { title: texts.size, key: 'size' }, @@ -390,7 +370,7 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv kpiTitleAndKeys.map(async ({ title, key }) => ({ key, value: await testSubjects.getVisibleText( - `${testSubjectSelectors.datasetQualityFlyoutKpiValue}-${title}` + `${testSubjectSelectors.datasetQualityDetailsSummaryKpiValue}-${title}` ), })) ); @@ -400,52 +380,10 @@ export function DatasetQualityPageObject({ getPageObjects, getService }: FtrProv ...acc, [key]: value, }), - {} as FlyoutKpi + {} as SummaryPanelKPI ); }, - async setDatePickerLastXUnits( - container: WebElementWrapper, - timeValue: number, - unit: TimeUnitId - ) { - // Only click the menu button found under the provided container - const datePickerToggleQuickMenuButton = await container.findByTestSubject( - testSubjectSelectors.superDatePickerToggleQuickMenuButton - ); - await datePickerToggleQuickMenuButton.click(); - - const datePickerQuickMenu = await testSubjects.find( - testSubjectSelectors.superDatePickerQuickMenu - ); - - const timeTenseSelect = await datePickerQuickMenu.findByCssSelector( - `select[aria-label="Time tense"]` - ); - const timeValueInput = await datePickerQuickMenu.findByCssSelector( - `input[aria-label="Time value"]` - ); - const timeUnitSelect = await datePickerQuickMenu.findByCssSelector( - `select[aria-label="Time unit"]` - ); - - await timeTenseSelect.focus(); - await timeTenseSelect.type('Last'); - - await timeValueInput.focus(); - await timeValueInput.clearValue(); - await timeValueInput.type(timeValue.toString()); - - await timeUnitSelect.focus(); - await timeUnitSelect.type(unit); - - await ( - await datePickerQuickMenu.findByCssSelector(selectors.superDatePickerApplyButton) - ).click(); - - return testSubjects.missingOrFail(testSubjectSelectors.superDatePickerQuickMenu); - }, - /** * Selects a breakdown field from the unified histogram breakdown selector * @param fieldText The text of the field to select. Use 'No breakdown' to clear the selection diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index 19a80b2dfce7c..4c32a87a57ba3 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -173,7 +173,7 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont }, /** - * Changes the specified dimension to the specified operation and (optinally) field. + * Changes the specified dimension to the specified operation and optionally the field. * * @param opts.dimension - the selector of the dimension being changed * @param opts.operation - the desired operation ID for the dimension @@ -1129,8 +1129,7 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont return el.getVisibleText(); }, - async getDatatableCellStyle(rowIndex = 0, colIndex = 0) { - const el = await this.getDatatableCell(rowIndex, colIndex); + async getStylesFromCell(el: WebElementWrapper) { const styleString = (await el.getAttribute('style')) ?? ''; return styleString.split(';').reduce>((memo, cssLine) => { const [prop, value] = cssLine.split(':'); @@ -1141,6 +1140,11 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont }, {}); }, + async getDatatableCellStyle(rowIndex = 0, colIndex = 0) { + const el = await this.getDatatableCell(rowIndex, colIndex); + return this.getStylesFromCell(el); + }, + async getDatatableCellSpanStyle(rowIndex = 0, colIndex = 0) { const el = await (await this.getDatatableCell(rowIndex, colIndex)).findByCssSelector('span'); const styleString = (await el.getAttribute('style')) ?? ''; @@ -1174,6 +1178,12 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont ); }, + async getDatatableCellsByColumn(colIndex = 0) { + return await find.allByCssSelector( + `[data-test-subj="lnsDataTable"] [data-test-subj="dataGridRowCell"][data-gridcell-column-index="${colIndex}"]` + ); + }, + async isDatatableHeaderSorted(index = 0) { return find.existsByCssSelector( `[data-test-subj="lnsDataTable"] [data-test-subj="dataGridHeader"] [role=columnheader]:nth-child(${ @@ -1240,10 +1250,15 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont async setPalette(paletteId: string, isLegacy: boolean) { await testSubjects.click('lns_colorEditing_trigger'); + // This action needs to be slowed WAY down, otherwise it will not correctly set the palette + await PageObjects.common.sleep(200); await testSubjects.setEuiSwitch( 'lns_colorMappingOrLegacyPalette_switch', isLegacy ? 'uncheck' : 'check' ); + + await PageObjects.common.sleep(200); + if (isLegacy) { await testSubjects.click('lns-palettePicker'); await find.clickByCssSelector(`#${paletteId}`); @@ -1251,6 +1266,8 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont await testSubjects.click('kbnColoring_ColorMapping_PalettePicker'); await testSubjects.click(`kbnColoring_ColorMapping_Palette-${paletteId}`); } + await PageObjects.common.sleep(200); + await this.closePaletteEditor(); }, @@ -1380,6 +1397,11 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont }; }, + async hoverOverDimensionButton(index = 0) { + const dimensionButton = (await testSubjects.findAll('lns-dimensionTrigger'))[index]; + await dimensionButton.moveMouseTo(); + }, + async getMetricVisualizationData() { const tiles = await this.getMetricTiles(); const showingBar = Boolean(await findService.existsByCssSelector('.echSingleMetricProgress')); diff --git a/x-pack/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts b/x-pack/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts index ff20297efdeca..68b1d97d531dc 100644 --- a/x-pack/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts +++ b/x-pack/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts @@ -77,7 +77,7 @@ export default function ApiTest({ getService, getPageObjects }: FtrProviderConte message: { role: MessageRole.System, content: - 'You are a helpful assistant for Elastic Observability. Your goal is to help the Elastic Observability users to quickly assess what is happening in their observed systems. You can help them visualise and analyze data, investigate their systems, perform root cause analysis or identify optimisation opportunities.\n\nIt\'s very important to not assume what the user is meaning. Ask them for clarification if needed.\n\nIf you are unsure about which function should be used and with what arguments, ask the user for clarification or confirmation.\n\nIn KQL ("kqlFilter")) escaping happens with double quotes, not single quotes. Some characters that need escaping are: \':()\\ /". Always put a field value in double quotes. Best: service.name:"opbeans-go". Wrong: service.name:opbeans-go. This is very important!\n\nYou can use Github-flavored Markdown in your responses. If a function returns an array, consider using a Markdown table to format the response.\n\nNote that ES|QL (the Elasticsearch Query Language which is a new piped language) is the preferred query language.\n\nYou MUST use the "query" function when the user wants to:\n- visualize data\n- run any arbitrary query\n- breakdown or filter ES|QL queries that are displayed on the current page\n- convert queries from another language to ES|QL\n- asks general questions about ES|QL\n\nDO NOT UNDER ANY CIRCUMSTANCES generate ES|QL queries or explain anything about the ES|QL query language yourself.\nDO NOT UNDER ANY CIRCUMSTANCES try to correct an ES|QL query yourself - always use the "query" function for this.\n\nDO NOT UNDER ANY CIRCUMSTANCES USE ES|QL syntax (`service.name == "foo"`) with "kqlFilter" (`service.name:"foo"`).\n\nEven if the "context" function was used before that, follow it up with the "query" function. If a query fails, do not attempt to correct it yourself. Again you should call the "query" function,\neven if it has been called before.\n\nWhen the "visualize_query" function has been called, a visualization has been displayed to the user. DO NOT UNDER ANY CIRCUMSTANCES follow up a "visualize_query" function call with your own visualization attempt.\nIf the "execute_query" function has been called, summarize these results for the user. The user does not see a visualization in this case.\n\nYou MUST use the get_dataset_info function function before calling the "query" or "changes" function.\n\nIf a function requires an index, you MUST use the results from the dataset info functions.\n\n\n\nThe user is able to change the language which they want you to reply in on the settings page of the AI Assistant for Observability, which can be found in the Stack Management app under the option AI Assistants.\nIf the user asks how to change the language, reply in the same language the user asked in.You do not have a working memory. If the user expects you to remember the previous conversations, tell them they can set up the knowledge base.\n\nYou MUST respond in the users preferred language which is: English.', + 'You are a helpful assistant for Elastic Observability. Your goal is to help the Elastic Observability users to quickly assess what is happening in their observed systems. You can help them visualise and analyze data, investigate their systems, perform root cause analysis or identify optimisation opportunities.\n\nIt\'s very important to not assume what the user is meaning. Ask them for clarification if needed.\n\nIf you are unsure about which function should be used and with what arguments, ask the user for clarification or confirmation.\n\nIn KQL ("kqlFilter")) escaping happens with double quotes, not single quotes. Some characters that need escaping are: \':()\\ /". Always put a field value in double quotes. Best: service.name:"opbeans-go". Wrong: service.name:opbeans-go. This is very important!\n\nYou can use Github-flavored Markdown in your responses. If a function returns an array, consider using a Markdown table to format the response.\n\nNote that ES|QL (the Elasticsearch Query Language which is a new piped language) is the preferred query language.\n\nYou MUST use the "query" function when the user wants to:\n- visualize data\n- run any arbitrary query\n- breakdown or filter ES|QL queries that are displayed on the current page\n- convert queries from another language to ES|QL\n- asks general questions about ES|QL\n\nDO NOT UNDER ANY CIRCUMSTANCES generate ES|QL queries or explain anything about the ES|QL query language yourself.\nDO NOT UNDER ANY CIRCUMSTANCES try to correct an ES|QL query yourself - always use the "query" function for this.\n\nDO NOT UNDER ANY CIRCUMSTANCES USE ES|QL syntax (`service.name == "foo"`) with "kqlFilter" (`service.name:"foo"`).\n\nEven if the "context" function was used before that, follow it up with the "query" function. If a query fails, do not attempt to correct it yourself. Again you should call the "query" function,\neven if it has been called before.\n\nWhen the "visualize_query" function has been called, a visualization has been displayed to the user. DO NOT UNDER ANY CIRCUMSTANCES follow up a "visualize_query" function call with your own visualization attempt.\nIf the "execute_query" function has been called, summarize these results for the user. The user does not see a visualization in this case.\n\nYou MUST use the get_dataset_info function function before calling the "query" or "changes" function.\n\nIf a function requires an index, you MUST use the results from the dataset info functions.\n\n\n\nThe user is able to change the language which they want you to reply in on the settings page of the AI Assistant for Observability, which can be found in the Stack Management app under the option AI Assistants.\nIf the user asks how to change the language, reply in the same language the user asked in.You do not have a working memory. If the user expects you to remember the previous conversations, tell them they can set up the knowledge base.', }, }, { @@ -398,10 +398,6 @@ export default function ApiTest({ getService, getPageObjects }: FtrProviderConte expect(messages.length).to.eql(9); expect(messages[0].message.role).to.eql('system'); - // Verify that system message extension that happen on the server are captured in the telemetry - expect(messages[0].message.content).to.contain( - 'You MUST respond in the users preferred language which is: English.' - ); }); }); }); diff --git a/x-pack/test/observability_ai_assistant_functional/tests/feature_controls/settings_security.spec.ts b/x-pack/test/observability_ai_assistant_functional/tests/feature_controls/settings_security.spec.ts index 7c2262008d8a2..ef87707c62a2c 100644 --- a/x-pack/test/observability_ai_assistant_functional/tests/feature_controls/settings_security.spec.ts +++ b/x-pack/test/observability_ai_assistant_functional/tests/feature_controls/settings_security.spec.ts @@ -7,7 +7,6 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; -import { interceptRequest } from '../../common/intercept_request'; import { createAndLoginUserWithCustomRole, deleteAndLogoutUser } from './helpers'; export default function ({ getPageObjects, getService }: FtrProviderContext) { @@ -15,13 +14,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'error', 'navigationalSearch', 'security']); const ui = getService('observabilityAIAssistantUI'); const testSubjects = getService('testSubjects'); - const driver = getService('__webdriver__'); - const retry = getService('retry'); - const toasts = getService('toasts'); describe('ai assistant management privileges', () => { - // FLAKY: https://github.com/elastic/kibana/issues/190637 - describe.skip('all privileges', () => { + describe('all privileges', () => { before(async () => { await createAndLoginUserWithCustomRole(getPageObjects, getService, { // we need all these privileges to view and modify Obs AI Assistant settings view @@ -79,34 +74,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await logsIndexPatternInput.type('logs-*'); await saveButton.click(); }); - it('displays failure toast on failed request', async () => { - const logsIndexPatternInput = await testSubjects.find( - ui.pages.settings.logsIndexPatternInput - ); - // Wait until the input has the default value 'logs-*' to prevent flakiness - await retry.waitFor('input field to have default value', async () => { - const value = await logsIndexPatternInput.getAttribute('value'); - return value === 'logs-*'; - }); - await logsIndexPatternInput.clearValue(); - await logsIndexPatternInput.type('test'); - - await interceptRequest( - driver.driver, - '*kibana\\/settings*', - (responseFactory) => { - return responseFactory.fail(); - }, - async () => { - await testSubjects.click(ui.pages.settings.saveButton); - } - ); - - await retry.waitFor('Error saving settings toast', async () => { - const count = await toasts.getCount(); - return count > 0; - }); - }); }); describe('with advancedSettings read privilege', () => { before(async () => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/trial_license_complete_tier/configs/ess.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/trial_license_complete_tier/configs/ess.config.ts new file mode 100644 index 0000000000000..eee14323c9b98 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/trial_license_complete_tier/configs/ess.config.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile( + require.resolve('../../../../../../../config/ess/config.base.trial') + ); + + const testConfig = { + ...functionalConfig.getAll(), + testFiles: [require.resolve('..')], + junit: { + reportName: + 'Rules Management - Prebuilt Rule Customization Integration Tests - ESS Env - Trial License', + }, + }; + testConfig.kbnTestServer.serverArgs = testConfig.kbnTestServer.serverArgs.map((arg: string) => { + // Override the default value of `--xpack.securitySolution.enableExperimental` to enable the prebuilt rules customization feature + if (arg.includes('--xpack.securitySolution.enableExperimental')) { + return `--xpack.securitySolution.enableExperimental=${JSON.stringify([ + 'prebuiltRulesCustomizationEnabled', + ])}`; + } + return arg; + }); + + return testConfig; +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/trial_license_complete_tier/configs/serverless.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/trial_license_complete_tier/configs/serverless.config.ts new file mode 100644 index 0000000000000..79a23c85d2279 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/trial_license_complete_tier/configs/serverless.config.ts @@ -0,0 +1,21 @@ +/* + * 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 { createTestConfig } from '../../../../../../../config/serverless/config.base'; + +export default createTestConfig({ + testFiles: [require.resolve('..')], + junit: { + reportName: + 'Rules Management - Prebuilt Rule Customization Integration Tests - Serverless Env - Complete Tier', + }, + kbnTestServerArgs: [ + `--xpack.securitySolution.enableExperimental=${JSON.stringify([ + 'prebuiltRulesCustomizationEnabled', + ])}`, + ], +}); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/trial_license_complete_tier/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/trial_license_complete_tier/index.ts new file mode 100644 index 0000000000000..76a461d438463 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/trial_license_complete_tier/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../../../../ftr_provider_context'; + +export default ({ loadTestFile }: FtrProviderContext): void => { + describe('Rules Management - Prebuilt Rules - Update Prebuilt Rules Package', function () { + loadTestFile(require.resolve('./is_customized_calculation')); + }); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/trial_license_complete_tier/is_customized_calculation.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/trial_license_complete_tier/is_customized_calculation.ts new file mode 100644 index 0000000000000..72f9062f66ca1 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/prebuilt_rules/prebuilt_rule_customization/trial_license_complete_tier/is_customized_calculation.ts @@ -0,0 +1,200 @@ +/* + * 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 { + BulkActionEditTypeEnum, + BulkActionTypeEnum, +} from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/bulk_actions/bulk_actions_route.gen'; +import expect from 'expect'; +import { deleteAllRules } from '../../../../../../../common/utils/security_solution'; +import { FtrProviderContext } from '../../../../../../ftr_provider_context'; +import { + createPrebuiltRuleAssetSavedObjects, + createRuleAssetSavedObject, + deleteAllPrebuiltRuleAssets, + installPrebuiltRules, +} from '../../../../utils'; + +export default ({ getService }: FtrProviderContext): void => { + const es = getService('es'); + const supertest = getService('supertest'); + const securitySolutionApi = getService('securitySolutionApi'); + const log = getService('log'); + + const ruleAsset = createRuleAssetSavedObject({ + rule_id: '000047bb-b27a-47ec-8b62-ef1a5d2c9e19', + tags: ['test-tag'], + }); + + describe('@ess @serverless @skipInServerlessMKI is_customized calculation', () => { + beforeEach(async () => { + await deleteAllRules(supertest, log); + await deleteAllPrebuiltRuleAssets(es, log); + }); + + describe('prebuilt rules', () => { + it('should set is_customized to true on bulk rule modification', async () => { + await createPrebuiltRuleAssetSavedObjects(es, [ruleAsset]); + await installPrebuiltRules(es, supertest); + + const { body: findResult } = await securitySolutionApi + .findRules({ + query: { + per_page: 1, + filter: `alert.attributes.params.immutable: true`, + }, + }) + .expect(200); + const prebuiltRule = findResult.data[0]; + expect(prebuiltRule).not.toBeNull(); + expect(prebuiltRule.rule_source.is_customized).toEqual(false); + + const { body: bulkResult } = await securitySolutionApi + .performRulesBulkAction({ + query: {}, + body: { + ids: [prebuiltRule.id], + action: BulkActionTypeEnum.edit, + [BulkActionTypeEnum.edit]: [ + { + type: BulkActionEditTypeEnum.add_tags, + value: ['new-tag'], + }, + ], + }, + }) + .expect(200); + + expect(bulkResult.attributes.summary).toEqual({ + failed: 0, + skipped: 0, + succeeded: 1, + total: 1, + }); + expect(bulkResult.attributes.results.updated[0].rule_source.is_customized).toEqual(true); + }); + + it('should leave is_customized intact if the change has been skipped', async () => { + await createPrebuiltRuleAssetSavedObjects(es, [ruleAsset]); + await installPrebuiltRules(es, supertest); + + const { body: findResult } = await securitySolutionApi + .findRules({ + query: { + per_page: 1, + filter: `alert.attributes.params.immutable: true`, + }, + }) + .expect(200); + const prebuiltRule = findResult.data[0]; + expect(prebuiltRule).not.toBeNull(); + expect(prebuiltRule.rule_source.is_customized).toEqual(false); + + const { body: bulkResult } = await securitySolutionApi + .performRulesBulkAction({ + query: {}, + body: { + ids: [prebuiltRule.id], + action: BulkActionTypeEnum.edit, + [BulkActionTypeEnum.edit]: [ + { + type: BulkActionEditTypeEnum.add_tags, + // This tag is already present on the rule, so the change will be skipped + value: [prebuiltRule.tags[0]], + }, + ], + }, + }) + .expect(200); + + expect(bulkResult.attributes.summary).toEqual({ + failed: 0, + skipped: 1, + succeeded: 0, + total: 1, + }); + + // Check that the rule has not been customized + const { body: findResultAfter } = await securitySolutionApi + .findRules({ + query: { + per_page: 1, + filter: `alert.attributes.params.immutable: true`, + }, + }) + .expect(200); + expect(findResultAfter.data[0].rule_source.is_customized).toEqual(false); + }); + + it('should set is_customized to false if the change has been reverted', async () => { + await createPrebuiltRuleAssetSavedObjects(es, [ruleAsset]); + await installPrebuiltRules(es, supertest); + + const { body: findResult } = await securitySolutionApi + .findRules({ + query: { + per_page: 1, + filter: `alert.attributes.params.immutable: true`, + }, + }) + .expect(200); + const prebuiltRule = findResult.data[0]; + expect(prebuiltRule).not.toBeNull(); + expect(prebuiltRule.rule_source.is_customized).toEqual(false); + + // Add a tag to the rule + const { body: bulkResult } = await securitySolutionApi + .performRulesBulkAction({ + query: {}, + body: { + ids: [prebuiltRule.id], + action: BulkActionTypeEnum.edit, + [BulkActionTypeEnum.edit]: [ + { + type: BulkActionEditTypeEnum.add_tags, + value: ['new-tag'], + }, + ], + }, + }) + .expect(200); + + expect(bulkResult.attributes.summary).toEqual({ + failed: 0, + skipped: 0, + succeeded: 1, + total: 1, + }); + + // Remove the added tag + const { body: revertResult } = await securitySolutionApi + .performRulesBulkAction({ + query: {}, + body: { + ids: [prebuiltRule.id], + action: BulkActionTypeEnum.edit, + [BulkActionTypeEnum.edit]: [ + { + type: BulkActionEditTypeEnum.delete_tags, + value: ['new-tag'], + }, + ], + }, + }) + .expect(200); + + expect(revertResult.attributes.summary).toEqual({ + failed: 0, + skipped: 0, + succeeded: 1, + total: 1, + }); + + expect(revertResult.attributes.results.updated[0].rule_source.is_customized).toEqual(false); + }); + }); + }); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/perform_bulk_action.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/perform_bulk_action.ts index 43afebc55decd..c6c85751593a4 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/perform_bulk_action.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/perform_bulk_action.ts @@ -34,12 +34,7 @@ import { removeServerGeneratedProperties, updateUsername, } from '../../../utils'; -import { - createRule, - createAlertsIndex, - deleteAllRules, - deleteAllAlerts, -} from '../../../../../../common/utils/security_solution'; +import { createRule, deleteAllRules } from '../../../../../../common/utils/security_solution'; import { deleteAllExceptions } from '../../../../lists_and_exception_lists/utils'; import { FtrProviderContext } from '../../../../../ftr_provider_context'; @@ -90,14 +85,12 @@ export default ({ getService }: FtrProviderContext): void => { describe('@ess @serverless @skipInServerless perform_bulk_action', () => { beforeEach(async () => { - await createAlertsIndex(supertest, log); + await deleteAllRules(supertest, log); await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); }); afterEach(async () => { - await deleteAllAlerts(supertest, log, es); - await deleteAllRules(supertest, log); - await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/hosts'); }); it('should export rules', async () => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rules_table/rules_table_filtering.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rules_table/rules_table_filtering.cy.ts index 117fc0eee632b..f23f703e3815a 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rules_table/rules_table_filtering.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rules_table/rules_table_filtering.cy.ts @@ -73,8 +73,8 @@ describe('Rules table: filtering', { tags: ['@ess', '@serverless'] }, () => { name: 'Failed rule', rule_id: 'failed_rule', index: ['test_index'], - // Setting a crazy large "Additional look-back time" to force a failure - from: 'now-9007199254746990s', + // Setting a malformed query to force a failure + query: 'host.name: "*', enabled: true, }) ); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/explore/urls/state.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/explore/urls/state.cy.ts index 4e34fedb1dd43..7531cf30a7752 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/explore/urls/state.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/explore/urls/state.cy.ts @@ -59,8 +59,8 @@ const ABSOLUTE_DATE = { endTime: 'Aug 1, 2019 @ 20:33:29.186', endTimeTimeline: '2019-08-02T21:03:29.186Z', endTimeTimelineFormatted: 'Aug 2, 2019 @ 21:03:29.186', - newEndTimeTyped: 'Aug 01, 2019 @ 15:03:29.186', - newStartTimeTyped: 'Aug 01, 2019 @ 14:33:29.186', + newEndTimeTyped: 'Aug 1, 2019 @ 15:03:29.186', + newStartTimeTyped: 'Aug 1, 2019 @ 14:33:29.186', startTime: 'Aug 1, 2019 @ 20:03:29.186', startTimeTimeline: '2019-08-02T20:03:29.186Z', startTimeTimelineFormatted: 'Aug 2, 2019 @ 20:03:29.186', diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/fields_browser.ts b/x-pack/test/security_solution_cypress/cypress/tasks/fields_browser.ts index f9e83fb449b77..c05bfbc6d281b 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/fields_browser.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/fields_browser.ts @@ -75,6 +75,8 @@ export const toggleCategory = (category: string) => { }; export const removesMessageField = () => { + cy.get(FIELDS_BROWSER_FILTER_INPUT).clear(); + cy.get(FIELDS_BROWSER_FILTER_INPUT).type('message'); cy.get(FIELDS_BROWSER_MESSAGE_CHECKBOX).uncheck(); }; diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/rule_snoozing.ts b/x-pack/test/security_solution_cypress/cypress/tasks/rule_snoozing.ts index 33ade4482951a..9c1f5d45fe072 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/rule_snoozing.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/rule_snoozing.ts @@ -119,8 +119,7 @@ function snoozeRuleInOpenPopover(duration: SnoozeDuration): void { cy.log(`Snooze a rule for ${value} ${units}`); - cy.get(SNOOZE_POPOVER_INTERVAL_VALUE_INPUT).clear(); - cy.get(SNOOZE_POPOVER_INTERVAL_VALUE_INPUT).type(value.toString()); + cy.get(SNOOZE_POPOVER_INTERVAL_VALUE_INPUT).type(`{selectAll}${value.toString()}`); cy.get(SNOOZE_POPOVER_INTERVAL_UNIT_INPUT).select(units); cy.get(SNOOZE_POPOVER_APPLY_BUTTON).click(); } diff --git a/x-pack/test/security_solution_endpoint/apps/integrations/artifact_entries_list.ts b/x-pack/test/security_solution_endpoint/apps/integrations/artifact_entries_list.ts index 9cb093b6edae8..1f5d406617ae2 100644 --- a/x-pack/test/security_solution_endpoint/apps/integrations/artifact_entries_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/integrations/artifact_entries_list.ts @@ -35,7 +35,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const retry = getService('retry'); const esClient = getService('es'); const supertest = getService('supertest'); - const find = getService('find'); const toasts = getService('toasts'); const policyTestResources = getService('policyTestResources'); const unzipPromisify = promisify(unzip); @@ -52,12 +51,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { .set('kbn-xsrf', 'true'); }; - // Failing: See https://github.com/elastic/kibana/issues/187314 - // Failing: See https://github.com/elastic/kibana/issues/187383 - // Failing: See https://github.com/elastic/kibana/issues/188131 - // Failing: See https://github.com/elastic/kibana/issues/188125 - describe.skip('For each artifact list under management', function () { - targetTags(this, ['@ess', '@skipInServerless']); + describe('For each artifact list under management', function () { + targetTags(this, ['@ess', '@serverless']); this.timeout(60_000 * 5); let indexedData: IndexedHostsAndAlertsResponse; @@ -154,9 +149,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { suffix?: string ) => { for (const formAction of actions) { - if (formAction.type === 'customClick') { - await find.clickByCssSelector(formAction.selector, testSubjects.FIND_TIME); - } else if (formAction.type === 'click') { + if (formAction.type === 'click') { await testSubjects.click(formAction.selector); } else if (formAction.type === 'input') { const newValue = (formAction.value || '') + (suffix ? suffix : ''); @@ -265,7 +258,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it(`should be able to update an existing ${testData.title} entry`, async () => { - await createArtifact(testData); + await endpointArtifactsTestResources.createArtifact(testData.listId, testData.createBody); + await browser.refresh(); + await updateArtifact(testData, { policyId: policyInfo.packagePolicy.id }); // Check edited artifact is in the list with new values (wait for list to be updated) @@ -299,7 +294,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it(`should be able to delete the existing ${testData.title} entry`, async () => { - await createArtifact(testData); + await endpointArtifactsTestResources.createArtifact(testData.listId, testData.createBody); + await browser.refresh(); + await deleteArtifact(testData); // We only expect one artifact to have been visible await testSubjects.missingOrFail(testData.delete.card); @@ -336,7 +333,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); const testData = getCreateMultipleData(); - it(`should get correct atifact when multiple entries are created`, async () => { + it(`should get correct artifact when multiple entries are created`, async () => { // Create first trusted app await createArtifact(testData, { policyId: firstPolicy.packagePolicy.id, diff --git a/x-pack/test/security_solution_endpoint/apps/integrations/mocks.ts b/x-pack/test/security_solution_endpoint/apps/integrations/mocks.ts index 47523694b4349..de88f99048c6c 100644 --- a/x-pack/test/security_solution_endpoint/apps/integrations/mocks.ts +++ b/x-pack/test/security_solution_endpoint/apps/integrations/mocks.ts @@ -7,8 +7,11 @@ import { FullAgentPolicy } from '@kbn/fleet-plugin/common/types'; import { ArtifactElasticsearchProperties } from '@kbn/fleet-plugin/server/services/artifacts/types'; +import { GLOBAL_ARTIFACT_TAG } from '@kbn/security-solution-plugin/common/endpoint/service/artifacts'; import { InternalUnifiedManifestBaseSchema } from '@kbn/security-solution-plugin/server/endpoint/schemas/artifacts'; import { TranslatedExceptionListItem } from '@kbn/security-solution-plugin/server/endpoint/schemas/artifacts/lists'; +import { CreateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; +import { ENDPOINT_ARTIFACT_LISTS } from '@kbn/securitysolution-list-constants'; export interface AgentPolicyResponseType { _index: string; @@ -119,6 +122,19 @@ export const getArtifactsListTestsData = () => [ confirmSelector: 'trustedAppsListPage-deleteModal-submitButton', card: 'trustedAppsListPage-card', }, + listId: ENDPOINT_ARTIFACT_LISTS.trustedApps.id, + createBody: { + entries: [ + { + type: 'match', + field: 'process.hash.sha256', + value: 'a4370c0cf81686c0b696fa6261c9d3e0d810ae704ab8301839dffd5d5112f476', + operator: 'included', + }, + ], + tags: [GLOBAL_ARTIFACT_TAG], + os_types: ['windows'], + } as Partial, urlPath: 'trusted_apps', pageObject: 'trustedApps', fleetArtifact: { @@ -206,8 +222,9 @@ export const getArtifactsListTestsData = () => [ selector: 'fieldAutocompleteComboBox', }, { - type: 'customClick', - selector: 'button[title="agent.ephemeral_id"]', + type: 'input', + selector: 'fieldAutocompleteComboBox', + value: 'agent.ephemeral_id', }, { type: 'click', @@ -247,10 +264,6 @@ export const getArtifactsListTestsData = () => [ selector: 'fieldAutocompleteComboBox', value: 'agent.id', }, - { - type: 'customClick', - selector: 'button[title="agent.id"]', - }, { type: 'input', selector: 'valuesAutocompleteMatch', @@ -281,6 +294,19 @@ export const getArtifactsListTestsData = () => [ confirmSelector: 'EventFiltersListPage-deleteModal-submitButton', card: 'EventFiltersListPage-card', }, + listId: ENDPOINT_ARTIFACT_LISTS.eventFilters.id, + createBody: { + entries: [ + { + field: 'agent.ephemeral_id', + value: 'endpoint', + type: 'match', + operator: 'included', + }, + ], + tags: [GLOBAL_ARTIFACT_TAG], + os_types: ['windows'], + } as Partial, urlPath: 'event_filters', pageObject: 'eventFilters', fleetArtifact: { @@ -456,6 +482,31 @@ export const getArtifactsListTestsData = () => [ card: 'blocklistCard', }, pageObject: 'blocklist', + listId: ENDPOINT_ARTIFACT_LISTS.blocklists.id, + createBody: { + entries: [ + { + type: 'match_any', + field: 'file.hash.md5', + value: ['741462ab431a22233c787baab9b653c7'], + operator: 'included', + }, + { + type: 'match_any', + field: 'file.hash.sha1', + value: ['aedb279e378bed6c2db3c9dc9e12ba635e0b391c'], + operator: 'included', + }, + { + type: 'match_any', + field: 'file.hash.sha256', + value: ['a4370c0cf81686c0b696fa6261c9d3e0d810ae704ab8301839dffd5d5112f476'], + operator: 'included', + }, + ], + tags: [GLOBAL_ARTIFACT_TAG], + os_types: ['windows'], + } as Partial, urlPath: 'blocklist', fleetArtifact: { identifier: 'endpoint-blocklist-windows-v1', @@ -610,6 +661,19 @@ export const getArtifactsListTestsData = () => [ confirmSelector: 'hostIsolationExceptionsDeletionConfirm', card: 'hostIsolationExceptionsCard', }, + listId: ENDPOINT_ARTIFACT_LISTS.hostIsolationExceptions.id, + createBody: { + entries: [ + { + type: 'match', + field: 'destination.ip', + value: '1.1.1.1', + operator: 'included', + }, + ], + tags: [GLOBAL_ARTIFACT_TAG], + os_types: ['windows', 'linux', 'macos'], + } as Partial, pageObject: 'hostIsolationExceptions', urlPath: 'host_isolation_exceptions', fleetArtifact: { diff --git a/x-pack/test/security_solution_endpoint/services/endpoint_artifacts.ts b/x-pack/test/security_solution_endpoint/services/endpoint_artifacts.ts index 6f24f543c89ef..ce0d5ce6cda41 100644 --- a/x-pack/test/security_solution_endpoint/services/endpoint_artifacts.ts +++ b/x-pack/test/security_solution_endpoint/services/endpoint_artifacts.ts @@ -10,7 +10,12 @@ import type { CreateExceptionListSchema, ExceptionListItemSchema, } from '@kbn/securitysolution-io-ts-list-types'; -import { EXCEPTION_LIST_ITEM_URL, EXCEPTION_LIST_URL } from '@kbn/securitysolution-list-constants'; +import { + ENDPOINT_ARTIFACT_LISTS, + ENDPOINT_ARTIFACT_LIST_IDS, + EXCEPTION_LIST_ITEM_URL, + EXCEPTION_LIST_URL, +} from '@kbn/securitysolution-list-constants'; import { Response } from 'superagent'; import { ExceptionsListItemGenerator } from '@kbn/security-solution-plugin/common/endpoint/data_generators/exceptions_list_item_generator'; import { TRUSTED_APPS_EXCEPTION_LIST_DEFINITION } from '@kbn/security-solution-plugin/public/management/pages/trusted_apps/constants'; @@ -122,6 +127,26 @@ export class EndpointArtifactsTestResources extends FtrService { return this.createExceptionItem(blocklist); } + async createArtifact( + listId: (typeof ENDPOINT_ARTIFACT_LIST_IDS)[number], + overrides: Partial = {} + ): Promise { + switch (listId) { + case ENDPOINT_ARTIFACT_LISTS.trustedApps.id: { + return this.createTrustedApp(overrides); + } + case ENDPOINT_ARTIFACT_LISTS.eventFilters.id: { + return this.createEventFilter(overrides); + } + case ENDPOINT_ARTIFACT_LISTS.blocklists.id: { + return this.createBlocklist(overrides); + } + case ENDPOINT_ARTIFACT_LISTS.hostIsolationExceptions.id: { + return this.createHostIsolationException(overrides); + } + } + } + async getArtifactsFromUnifiedManifestSO(): Promise< Array< InternalUnifiedManifestSchemaResponseType['_source']['endpoint:unified-user-artifact-manifest'] diff --git a/x-pack/test/stack_functional_integration/apps/ccs/ccs_console.js b/x-pack/test/stack_functional_integration/apps/ccs/ccs_console.js index 01205ed528a1c..e105ceecf6cf7 100644 --- a/x-pack/test/stack_functional_integration/apps/ccs/ccs_console.js +++ b/x-pack/test/stack_functional_integration/apps/ccs/ccs_console.js @@ -31,7 +31,7 @@ export default function ({ getService, getPageObjects }) { }); it('it should be able to access remote data', async () => { await PageObjects.console.monaco.enterText( - '\nGET ftr-remote:makelogs工程-*/_search\n {\n "query": {\n "bool": {\n "must": [\n {"match": {"extension" : "jpg"} \n}\n}\n}\n}\n}' + '\nGET ftr-remote:makelogs工程-*/_search\n {\n "query": {\n "bool": {\n "must": [\n {"match": {"extension" : "jpg"} \n}\n]\n}\n}\n}' ); await PageObjects.console.clickPlay(); await retry.try(async () => { diff --git a/x-pack/test_serverless/api_integration/services/transform/security_common.ts b/x-pack/test_serverless/api_integration/services/transform/security_common.ts index 3b34bb5687925..8133af4b1f9db 100644 --- a/x-pack/test_serverless/api_integration/services/transform/security_common.ts +++ b/x-pack/test_serverless/api_integration/services/transform/security_common.ts @@ -8,6 +8,10 @@ import { ProvidedType } from '@kbn/test'; import { Client } from '@elastic/elasticsearch'; +import { + TOTAL_INDEX_PRIVILEGE_SET_EDITOR, + TOTAL_INDEX_PRIVILEGE_SET_VIEWER, +} from '@kbn/slo-plugin/server/services/get_diagnosis'; import { FtrProviderContext } from '../../ftr_provider_context'; export type TransformSecurityCommon = ProvidedType; @@ -33,14 +37,18 @@ export function TransformSecurityCommonProvider({ getService }: FtrProviderConte { name: 'transform_dest', elasticsearch: { - indices: [{ names: ['.slo-*'], privileges: ['read', 'index', 'manage', 'delete'] }], + indices: [ + { names: ['.slo-observability.*'], privileges: TOTAL_INDEX_PRIVILEGE_SET_EDITOR }, + ], }, kibana: [], }, { name: 'transform_dest_readonly', elasticsearch: { - indices: [{ names: ['.slo-*'], privileges: ['read'] }], + indices: [ + { names: ['.slo-observability.*'], privileges: TOTAL_INDEX_PRIVILEGE_SET_VIEWER }, + ], }, kibana: [], }, diff --git a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/find_csp_benchmark_rule.ts b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/find_csp_benchmark_rule.ts index b03ba641ddd10..cefe3dc598b40 100644 --- a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/find_csp_benchmark_rule.ts +++ b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/find_csp_benchmark_rule.ts @@ -9,7 +9,7 @@ import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import type { CspBenchmarkRule, FindCspBenchmarkRuleResponse, -} from '@kbn/cloud-security-posture-plugin/common/types/latest'; +} from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { createPackagePolicy } from '@kbn/test-suites-xpack/api_integration/apis/cloud_security_posture/helper'; import { FtrProviderContext } from '../../../ftr_provider_context'; diff --git a/x-pack/test_serverless/functional/test_suites/common/saved_objects_management/hidden_types.ts b/x-pack/test_serverless/functional/test_suites/common/saved_objects_management/hidden_types.ts index 9a48fd898d3c7..ffac914961061 100644 --- a/x-pack/test_serverless/functional/test_suites/common/saved_objects_management/hidden_types.ts +++ b/x-pack/test_serverless/functional/test_suites/common/saved_objects_management/hidden_types.ts @@ -7,6 +7,7 @@ import path from 'path'; import expect from '@kbn/expect'; +import { byIdAscComparator } from '@kbn/core-saved-objects-import-export-server-internal/src/export/utils'; import { FtrProviderContext } from '../../../ftr_provider_context'; const fixturePaths = { @@ -55,11 +56,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { .expect(200) .then((resp) => { expect( - resp.body.saved_objects.map((obj: any) => ({ - id: obj.id, - type: obj.type, - hidden: obj.meta.hiddenType, - })) + resp.body.saved_objects + .map((obj: any) => ({ + id: obj.id, + type: obj.type, + hidden: obj.meta.hiddenType, + })) + .sort(byIdAscComparator) ).to.eql([ { id: 'obj_1', diff --git a/x-pack/test_serverless/functional/test_suites/common/visualizations/group2/open_in_lens/agg_based/goal.ts b/x-pack/test_serverless/functional/test_suites/common/visualizations/group2/open_in_lens/agg_based/goal.ts index 15da3d48d9037..819cf92062cbb 100644 --- a/x-pack/test_serverless/functional/test_suites/common/visualizations/group2/open_in_lens/agg_based/goal.ts +++ b/x-pack/test_serverless/functional/test_suites/common/visualizations/group2/open_in_lens/agg_based/goal.ts @@ -21,9 +21,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); describe('Goal', function describeIndexTests() { - // fails on MKI, see https://github.com/elastic/kibana/issues/191238 - this.tags(['failsOnMKI']); - const fixture = 'x-pack/test_serverless/functional/fixtures/kbn_archiver/lens/open_in_lens/agg_based/goal.json'; @@ -49,6 +46,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('should convert to Lens', async () => { await panelActions.convertToLensByTitle('Goal - Basic'); await lens.waitForVisualization('mtrVis'); + + // hovering over dimension button to make sure neither of metrics are hovered so the color is stable + await lens.hoverOverDimensionButton(); const data = await lens.getMetricVisualizationData(); expect(data.length).to.be.equal(1); expect(data).to.eql([ @@ -76,6 +76,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(await dimensions[0].getVisibleText()).to.be('Average machine.ram'); expect(await dimensions[1].getVisibleText()).to.be('Static value: 1'); + // hovering over dimension button to make sure neither of metrics are hovered so the color is stable + await lens.hoverOverDimensionButton(); const data = await lens.getMetricVisualizationData(); expect(data.length).to.be.equal(1); expect(data).to.eql([ @@ -104,6 +106,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(await dimensions[1].getVisibleText()).to.be('Static value: 1'); expect(await dimensions[2].getVisibleText()).to.be('@timestamp'); + // hovering over dimension button to make sure neither of metrics are hovered so the color is stable + await lens.hoverOverDimensionButton(); const data = await lens.getMetricVisualizationData(); expect(data.length).to.be.equal(1); expect(data).to.eql([ @@ -132,6 +136,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(await dimensions[1].getVisibleText()).to.be('Static value: 13300000000'); expect(await dimensions[2].getVisibleText()).to.be('machine.os.raw: Descending'); + // hovering over dimension button to make sure neither of metrics are hovered so the color is stable + await lens.hoverOverDimensionButton(); const data = await lens.getMetricVisualizationData(); expect(data.length).to.be.equal(6); expect(data).to.eql([ diff --git a/x-pack/test_serverless/functional/test_suites/common/visualizations/group2/open_in_lens/agg_based/metric.ts b/x-pack/test_serverless/functional/test_suites/common/visualizations/group2/open_in_lens/agg_based/metric.ts index 860f7f2cee1c3..213d3b17cea11 100644 --- a/x-pack/test_serverless/functional/test_suites/common/visualizations/group2/open_in_lens/agg_based/metric.ts +++ b/x-pack/test_serverless/functional/test_suites/common/visualizations/group2/open_in_lens/agg_based/metric.ts @@ -20,8 +20,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const panelActions = getService('dashboardPanelActions'); const kibanaServer = getService('kibanaServer'); - // Failing: See https://github.com/elastic/kibana/issues/191153 - describe.skip('Metric', function describeIndexTests() { + describe('Metric', function describeIndexTests() { const fixture = 'x-pack/test_serverless/functional/fixtures/kbn_archiver/lens/open_in_lens/agg_based/metric.json'; @@ -44,6 +43,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await panelActions.convertToLensByTitle('Metric - Basic'); await lens.waitForVisualization('mtrVis'); + // hovering over dimension button to make sure neither of metrics are hovered so the color is stable + await lens.hoverOverDimensionButton(); const data = await lens.getMetricVisualizationData(); expect(data.length).to.be.equal(1); expect(data).to.eql([ @@ -70,6 +71,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(dimensions).to.have.length(1); expect(await dimensions[0].getVisibleText()).to.be('Average machine.ram'); + // hovering over dimension button to make sure neither of metrics are hovered so the color is stable + await lens.hoverOverDimensionButton(); const data = await lens.getMetricVisualizationData(); expect(data.length).to.be.equal(1); expect(data).to.eql([ @@ -97,6 +100,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(await dimensions[0].getVisibleText()).to.be('Overall Max of Count'); expect(await dimensions[1].getVisibleText()).to.be('@timestamp'); + // hovering over dimension button to make sure neither of metrics are hovered so the color is stable + await lens.hoverOverDimensionButton(); const data = await lens.getMetricVisualizationData(); expect(data.length).to.be.equal(1); expect(data).to.eql([ @@ -129,6 +134,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(dimensions).to.have.length(2); expect(await dimensions[0].getVisibleText()).to.be('Average machine.ram'); expect(await dimensions[1].getVisibleText()).to.be('machine.os.raw: Descending'); + + // hovering over dimension button to make sure neither of metrics are hovered so the color is stable + await lens.hoverOverDimensionButton(); + const data = await lens.getMetricVisualizationData(); expect(data.length).to.be.equal(6); expect(data).to.eql([ diff --git a/x-pack/test_serverless/functional/test_suites/common/visualizations/group3/open_in_lens/tsvb/dashboard.ts b/x-pack/test_serverless/functional/test_suites/common/visualizations/group3/open_in_lens/tsvb/dashboard.ts index 2569695008ed1..c41bf13a1e678 100644 --- a/x-pack/test_serverless/functional/test_suites/common/visualizations/group3/open_in_lens/tsvb/dashboard.ts +++ b/x-pack/test_serverless/functional/test_suites/common/visualizations/group3/open_in_lens/tsvb/dashboard.ts @@ -84,11 +84,18 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await dashboard.waitForRenderComplete(); const originalEmbeddableCount = await canvas.getEmbeddableCount(); + await dashboardPanelActions.customizePanel(); + await dashboardCustomizePanel.expectCustomizePanelSettingsFlyoutOpen(); await dashboardCustomizePanel.enableCustomTimeRange(); await dashboardCustomizePanel.openDatePickerQuickMenu(); + await retry.waitFor('quick menu', async () => { + await dashboardCustomizePanel.openDatePickerQuickMenu(); + return await testSubjects.exists('superDatePickerCommonlyUsed_Last_30 days'); + }); await dashboardCustomizePanel.clickCommonlyUsedTimeRange('Last_30 days'); await dashboardCustomizePanel.clickSaveButton(); + await dashboardCustomizePanel.expectCustomizePanelSettingsFlyoutClosed(); await dashboard.waitForRenderComplete(); await dashboardBadgeActions.expectExistsTimeRangeBadgeAction(); diff --git a/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_flyout.ts b/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_details.ts similarity index 69% rename from x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_flyout.ts rename to x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_details.ts index fda145ebfea7f..bca31c506a770 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_flyout.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/dataset_quality_details.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import { defaultNamespace } from '@kbn/test-suites-xpack/functional/apps/dataset_quality/data'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { datasetNames, @@ -38,7 +39,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const excludeKeysFromServerless = ['size']; // https://github.com/elastic/kibana/issues/178954 const apacheAccessDatasetName = 'apache.access'; - const apacheAccessDatasetHumanName = 'Apache access logs'; + const apacheAccessDataStreamName = `logs-${apacheAccessDatasetName}-${productionNamespace}`; const apacheIntegrationId = 'apache'; const apachePkg = { name: 'apache', @@ -46,13 +47,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }; const bitbucketDatasetName = 'atlassian_bitbucket.audit'; - const bitbucketDatasetHumanName = 'Bitbucket Audit Logs'; + const bitbucketAuditDataStreamName = `logs-${bitbucketDatasetName}-${defaultNamespace}`; const bitbucketPkg = { name: 'atlassian_bitbucket', version: '1.14.0', }; + const regularDatasetName = datasetNames[0]; + const regularDataStreamName = `logs-${datasetNames[0]}-${defaultNamespace}`; const degradedDatasetName = datasetNames[2]; + const degradedDataStreamName = `logs-${degradedDatasetName}-${defaultNamespace}`; describe('Flyout', function () { before(async () => { @@ -91,8 +95,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ]); await PageObjects.svlCommonPage.loginWithPrivilegedRole(); - - await PageObjects.datasetQuality.navigateTo(); }); after(async () => { @@ -101,21 +103,49 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await synthtrace.clean(); }); - describe('open flyout', () => { - it('should open the flyout for the right dataset', async () => { - const testDatasetName = datasetNames[1]; + describe('navigate to dataset details', () => { + it('should navigate to right dataset', async () => { + await PageObjects.datasetQuality.navigateToDetails({ dataStream: regularDataStreamName }); + + await testSubjects.existOrFail( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsTitle + ); + }); + + it('should navigate to details page from a main page', async () => { + await PageObjects.datasetQuality.navigateTo(); + + const synthDataset = await testSubjects.find( + 'datasetQualityTableDetailsLink-logs-synth.1-default', + 20 * 1000 + ); + + await synthDataset.click(); + + await testSubjects.existOrFail( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsTitle + ); + }); - await PageObjects.datasetQuality.openDatasetFlyout(testDatasetName); + it('should show an empty prompt with error message when the dataset is not found', async () => { + const nonExistentDataStreamName = 'logs-non.existent-production'; + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: nonExistentDataStreamName, + }); await testSubjects.existOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutTitle + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsEmptyPrompt + ); + + const emptyPromptBody = await testSubjects.getVisibleText( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsEmptyPromptBody ); - await PageObjects.datasetQuality.closeFlyout(); + expect(emptyPromptBody).to.contain(nonExistentDataStreamName); }); it('reflects the breakdown field state in url', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ dataStream: degradedDataStreamName }); const breakdownField = 'service.name'; await PageObjects.datasetQuality.selectBreakdownField(breakdownField); @@ -134,46 +164,71 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const currentUrl = await browser.getCurrentUrl(); expect(currentUrl).to.not.contain('breakdownField'); }); - await PageObjects.datasetQuality.closeFlyout(); }); }); - describe('integrations', () => { - it('should hide the integration section for non integrations', async () => { - const testDatasetName = datasetNames[1]; + describe('overview summary panel', () => { + it('should show summary KPIs', async () => { + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); - await PageObjects.datasetQuality.openDatasetFlyout(testDatasetName); + const { docsCountTotal, degradedDocs, services, hosts } = + await PageObjects.datasetQuality.parseOverviewSummaryPanelKpis(excludeKeysFromServerless); + expect(parseInt(docsCountTotal, 10)).to.be(226); + expect(parseInt(degradedDocs, 10)).to.be(1); + expect(parseInt(services, 10)).to.be(3); + expect(parseInt(hosts, 10)).to.be(52); + }); + }); + describe('overview integrations', () => { + it('should hide the integration section for non integrations', async () => { + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: regularDataStreamName, + }); + + // The Integration row should not be present await testSubjects.missingOrFail( PageObjects.datasetQuality.testSubjectSelectors - .datasetQualityFlyoutFieldsListIntegrationDetails + .datasetQualityDetailsIntegrationRowIntegration ); - await PageObjects.datasetQuality.closeFlyout(); + // The Version row should not be present + await testSubjects.missingOrFail( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationRowVersion + ); }); it('should shows the integration section for integrations', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); await testSubjects.existOrFail( PageObjects.datasetQuality.testSubjectSelectors - .datasetQualityFlyoutFieldsListIntegrationDetails + .datasetQualityDetailsIntegrationRowIntegration + ); + + await testSubjects.existOrFail( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationRowVersion ); await retry.tryForTime(5000, async () => { const integrationNameExists = await PageObjects.datasetQuality.doesTextExist( PageObjects.datasetQuality.testSubjectSelectors - .datasetQualityFlyoutFieldsListIntegrationDetails, + .datasetQualityDetailsIntegrationRowIntegration, apacheIntegrationId ); expect(integrationNameExists).to.be(true); }); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should show the integration actions menu with correct actions', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); + await PageObjects.datasetQuality.openIntegrationActionsMenu(); const actions = await Promise.all( @@ -183,23 +238,26 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); expect(actions.length).to.eql(3); - await PageObjects.datasetQuality.closeFlyout(); }); it('should hide integration dashboard for integrations without dashboards', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(bitbucketDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: bitbucketAuditDataStreamName, + }); + await PageObjects.datasetQuality.openIntegrationActionsMenu(); await testSubjects.missingOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutIntegrationAction( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsIntegrationAction( integrationActions.viewDashboards ) ); - await PageObjects.datasetQuality.closeFlyout(); }); it('Should navigate to integration overview page on clicking integration overview action', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(bitbucketDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: bitbucketAuditDataStreamName, + }); await PageObjects.datasetQuality.openIntegrationActionsMenu(); const action = await PageObjects.datasetQuality.getIntegrationActionButtonByAction( @@ -214,12 +272,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(parsedUrl.pathname).to.contain('/app/integrations/detail/atlassian_bitbucket'); }); - - await PageObjects.datasetQuality.navigateTo(); }); it('should navigate to index template page in clicking Integration template', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); await PageObjects.datasetQuality.openIntegrationActionsMenu(); const action = await PageObjects.datasetQuality.getIntegrationActionButtonByAction( @@ -235,11 +293,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { `/app/management/data/index_management/templates/logs-${apacheAccessDatasetName}` ); }); - await PageObjects.datasetQuality.navigateTo(); }); it('should navigate to the selected dashboard on clicking integration dashboard action ', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); await PageObjects.datasetQuality.openIntegrationActionsMenu(); const action = await PageObjects.datasetQuality.getIntegrationActionButtonByAction( @@ -257,118 +316,87 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const breadcrumbText = await testSubjects.getVisibleText('breadcrumb last'); expect(breadcrumbText).to.eql(dashboardText); - - await PageObjects.datasetQuality.navigateTo(); - }); - }); - - describe('summary panel', () => { - it('should show summary KPIs', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); - - const { docsCountTotal, degradedDocs, services, hosts } = - await PageObjects.datasetQuality.parseFlyoutKpis(excludeKeysFromServerless); - expect(parseInt(docsCountTotal, 10)).to.be(226); - expect(parseInt(degradedDocs, 10)).to.be(1); - expect(parseInt(services, 10)).to.be(3); - expect(parseInt(hosts, 10)).to.be(52); - - await PageObjects.datasetQuality.closeFlyout(); }); }); describe('navigation', () => { - afterEach(async () => { - // Navigate back to dataset quality page after each test - await PageObjects.datasetQuality.navigateTo(); - }); - it('should go to log explorer page when the open in log explorer button is clicked', async () => { - const testDatasetName = datasetNames[2]; - await PageObjects.datasetQuality.openDatasetFlyout(testDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: regularDataStreamName, + }); - const logExplorerButton = await PageObjects.datasetQuality.getFlyoutLogsExplorerButton(); + const logExplorerButton = + await PageObjects.datasetQuality.getDatasetQualityDetailsHeaderButton(); await logExplorerButton.click(); // Confirm dataset selector text in observability logs explorer const datasetSelectorText = await PageObjects.observabilityLogsExplorer.getDataSourceSelectorButtonText(); - expect(datasetSelectorText).to.eql(testDatasetName); + expect(datasetSelectorText).to.eql(regularDatasetName); }); - it('should go log explorer for degraded docs when the show all button is clicked', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); + it('should go log explorer for degraded docs when the button next to breakdown selector is clicked', async () => { + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: apacheAccessDataStreamName, + }); - const degradedDocsShowAllSelector = `${PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutKpiLink}-${PageObjects.datasetQuality.texts.degradedDocs}`; - await testSubjects.click(degradedDocsShowAllSelector); + await testSubjects.click( + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsLinkToDiscover + ); // Confirm dataset selector text in observability logs explorer const datasetSelectorText = await PageObjects.observabilityLogsExplorer.getDataSourceSelectorButtonText(); expect(datasetSelectorText).to.contain(apacheAccessDatasetName); }); - - // Blocked by https://github.com/elastic/kibana/issues/181705 - // Its a test written ahead of its time. - it.skip('goes to infra hosts for hosts when show all is clicked', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(apacheAccessDatasetHumanName); - - const hostsShowAllSelector = `${PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutKpiLink}-${PageObjects.datasetQuality.texts.hosts}`; - await testSubjects.click(hostsShowAllSelector); - - // Confirm url contains metrics/hosts - await retry.tryForTime(5000, async () => { - const currentUrl = await browser.getCurrentUrl(); - const parsedUrl = new URL(currentUrl); - expect(parsedUrl.pathname).to.contain('/app/metrics/hosts'); - }); - }); }); describe('degraded fields table', () => { it(' should show empty degraded fields table when no degraded fields are present', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(datasetNames[0]); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: regularDataStreamName, + }); await testSubjects.existOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutDegradedTableNoData + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsDegradedTableNoData ); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should show the degraded fields table with data when present', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); await testSubjects.existOrFail( - PageObjects.datasetQuality.testSubjectSelectors.datasetQualityFlyoutDegradedFieldTable + PageObjects.datasetQuality.testSubjectSelectors.datasetQualityDetailsDegradedFieldTable ); const rows = - await PageObjects.datasetQuality.getDatasetQualityFlyoutDegradedFieldTableRows(); + await PageObjects.datasetQuality.getDatasetQualityDetailsDegradedFieldTableRows(); expect(rows.length).to.eql(2); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should display Spark Plot for every row of degraded fields', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); const rows = - await PageObjects.datasetQuality.getDatasetQualityFlyoutDegradedFieldTableRows(); + await PageObjects.datasetQuality.getDatasetQualityDetailsDegradedFieldTableRows(); const sparkPlots = await testSubjects.findAll( PageObjects.datasetQuality.testSubjectSelectors.datasetQualitySparkPlot ); expect(rows.length).to.be(sparkPlots.length); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should sort the table when the count table header is clicked', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); const table = await PageObjects.datasetQuality.parseDegradedFieldTable(); @@ -379,12 +407,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const sortedCellTexts = await countColumn.getCellTexts(); expect(cellTexts.reverse()).to.eql(sortedCellTexts); - - await PageObjects.datasetQuality.closeFlyout(); }); it('should update the URL when the table is sorted', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); const table = await PageObjects.datasetQuality.parseDegradedFieldTable(); const countColumn = table['Docs count']; @@ -410,8 +438,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'sort:(direction:asc,field:count)' ); }); - - await PageObjects.datasetQuality.closeFlyout(); }); // This is the only test which ingest data during the test. @@ -419,7 +445,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // Even though this test ingest data, it can also be freely moved inside // this describe block, and it won't affect any of the existing tests it('should update the table when new data is ingested and the flyout is refreshed using the time selector', async () => { - await PageObjects.datasetQuality.openDatasetFlyout(degradedDatasetName); + await PageObjects.datasetQuality.navigateToDetails({ + dataStream: degradedDataStreamName, + }); const table = await PageObjects.datasetQuality.parseDegradedFieldTable(); @@ -434,7 +462,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }), ]); - await PageObjects.datasetQuality.refreshFlyout(); + await PageObjects.datasetQuality.refreshDetailsPageData(); const updatedTable = await PageObjects.datasetQuality.parseDegradedFieldTable(); const updatedCountColumn = updatedTable['Docs count']; @@ -445,8 +473,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const singleValueNow = parseInt(updatedCellTexts[0], 10); expect(singleValueNow).to.be.greaterThan(singleValuePreviously); - - await PageObjects.datasetQuality.closeFlyout(); }); }); }); diff --git a/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/index.ts b/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/index.ts index 30547ceb941b3..683c879ae4e3d 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/index.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/dataset_quality/index.ts @@ -13,7 +13,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./dataset_quality_summary')); loadTestFile(require.resolve('./dataset_quality_table')); loadTestFile(require.resolve('./dataset_quality_table_filters')); - loadTestFile(require.resolve('./dataset_quality_flyout')); loadTestFile(require.resolve('./dataset_quality_privileges')); + loadTestFile(require.resolve('./dataset_quality_details')); }); } diff --git a/x-pack/test_serverless/tsconfig.json b/x-pack/test_serverless/tsconfig.json index 7a7747a964caa..1770916bbace2 100644 --- a/x-pack/test_serverless/tsconfig.json +++ b/x-pack/test_serverless/tsconfig.json @@ -98,5 +98,6 @@ "@kbn/test-suites-src", "@kbn/console-plugin", "@kbn/cloud-security-posture-common", + "@kbn/core-saved-objects-import-export-server-internal", ] } diff --git a/yarn.lock b/yarn.lock index 15ae0b8e5fcee..25bcf4d4d9253 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1334,10 +1334,10 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.24.1", "@babel/runtime@^7.24.7", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12" - integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.24.1", "@babel/runtime@^7.24.7", "@babel/runtime@^7.25.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.0.tgz#3af9a91c1b739c569d5d80cc917280919c544ecb" + integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw== dependencies: regenerator-runtime "^0.14.0" @@ -1612,7 +1612,7 @@ dependencies: tslib "^2.0.0" -"@elastic/apm-rum-core@^5.21.0", "@elastic/apm-rum-core@^5.21.1": +"@elastic/apm-rum-core@^5.21.1": version "5.21.1" resolved "https://registry.yarnpkg.com/@elastic/apm-rum-core/-/apm-rum-core-5.21.1.tgz#ea6f2268629193962c194ae1d29971e2c5b2e531" integrity sha512-/LyLhVdJ+zcsKogwq2AEYARc//RDXOoTHWPERLay4sCsvvxc4/GkkhhOC40CqI0oMu4kUAoJInQWZuCM7zCZRQ== @@ -1675,20 +1675,19 @@ dependencies: tslib "^1.9.3" -"@elastic/ebt@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@elastic/ebt/-/ebt-1.0.0.tgz#49a3772363c0e6e180e451a4aa24e219add4a6f3" - integrity sha512-/M3/bW8Kk4osYWM7xx5R0ePH1xr1fLER36bkw/HY8vHlHv+WCHnyLhL1yqQdCrq+eVunAPcoGawHXgi52SV05A== +"@elastic/ebt@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@elastic/ebt/-/ebt-1.1.1.tgz#48c46c3860e2f1937f53fb718a26e5a5a7b9c76c" + integrity sha512-r809op8EdzOV57Jrt+r3YObKueVEDcAwoBLaeUx/IYoJF9lLNEbI8XIVccnvNJwTxaFpc3z3qLyZye0/T5k5/w== dependencies: - "@babel/runtime" "^7.24.7" + "@babel/runtime" "^7.25.0" fp-ts "^2.3.1" io-ts "^2.0.5" lodash.get "^4.4.2" lodash.has "^4.5.2" - moment "^2.29.4" + moment "^2.30.1" node-fetch "^2.6.7" - rxjs "^7.5.5" - typescript "^5.5.4" + rxjs "^7.8.1" "@elastic/ecs-helpers@^2.1.1": version "2.1.1" @@ -5811,6 +5810,10 @@ version "0.0.0" uid "" +"@kbn/observability-utils@link:x-pack/packages/observability/observability_utils": + version "0.0.0" + uid "" + "@kbn/oidc-provider-plugin@link:x-pack/test/security_api_integration/plugins/oidc_provider": version "0.0.0" uid "" @@ -6339,6 +6342,10 @@ version "0.0.0" uid "" +"@kbn/security-ui-components@link:x-pack/packages/security/ui_components": + version "0.0.0" + uid "" + "@kbn/securitysolution-autocomplete@link:packages/kbn-securitysolution-autocomplete": version "0.0.0" uid "" @@ -9661,7 +9668,7 @@ resolved "https://registry.yarnpkg.com/@testim/chrome-version/-/chrome-version-1.1.4.tgz#86e04e677cd6c05fa230dd15ac223fa72d1d7090" integrity sha512-kIhULpw9TrGYnHp/8VfdcneIcxKnLixmADtukQRtJUmsVlMg0niMkwV0xZmi8hqa57xqilIHjWFA0GKvEjVU5g== -"@testing-library/dom@^8.0.0": +"@testing-library/dom@^8.0.0", "@testing-library/dom@^8.19.0": version "8.19.0" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.19.0.tgz#bd3f83c217ebac16694329e413d9ad5fdcfd785f" integrity sha512-6YWYPPpxG3e/xOo6HIWwB/58HukkwIVTOaZ0VwdMVjhRUX/01E4FtQbck9GazOOj7MXHc5RBzMrU86iBJHbI+A== @@ -23444,17 +23451,17 @@ moment-duration-format@^2.3.2: resolved "https://registry.yarnpkg.com/moment-duration-format/-/moment-duration-format-2.3.2.tgz#5fa2b19b941b8d277122ff3f87a12895ec0d6212" integrity sha512-cBMXjSW+fjOb4tyaVHuaVE/A5TqkukDWiOfxxAjY+PEqmmBQlLwn+8OzwPiG3brouXKY5Un4pBjAeB6UToXHaQ== -moment-timezone@^0.5.43: - version "0.5.43" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.43.tgz#3dd7f3d0c67f78c23cd1906b9b2137a09b3c4790" - integrity sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ== +moment-timezone@^0.5.45: + version "0.5.45" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.45.tgz#cb685acd56bac10e69d93c536366eb65aa6bcf5c" + integrity sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ== dependencies: moment "^2.29.4" -moment@>=2.14.0, moment@^2.10.6, moment@^2.29.4: - version "2.29.4" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" - integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== +moment@>=2.14.0, moment@^2.10.6, moment@^2.29.4, moment@^2.30.1: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== monaco-editor@^0.44.0: version "0.44.0" @@ -27809,10 +27816,10 @@ rxjs@^6.4.0, rxjs@^6.6.0, rxjs@^6.6.7: dependencies: tslib "^1.9.0" -rxjs@^7.4.0, rxjs@^7.5.5: - version "7.8.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.0.tgz#90a938862a82888ff4c7359811a595e14e1e09a4" - integrity sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg== +rxjs@^7.4.0, rxjs@^7.5.5, rxjs@^7.8.1: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== dependencies: tslib "^2.1.0" @@ -30645,7 +30652,7 @@ typescript-tuple@^2.2.1: dependencies: typescript-compare "^0.0.2" -typescript@5, typescript@5.1.6, typescript@^3.3.3333, typescript@^5.0.4, typescript@^5.5.4: +typescript@5, typescript@5.1.6, typescript@^3.3.3333, typescript@^5.0.4: version "5.1.6" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274" integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==