From 4b1fdda2436ed6c952cc42ea442213b050c58268 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Thu, 22 May 2025 17:08:22 +0100 Subject: [PATCH 01/20] [ML] AIOps: Adding ability to disable AIOps in kibana --- .../plugins/shared/aiops/kibana.jsonc | 3 +- .../shared/aiops/server/config_schema.ts | 22 ++ .../plugins/shared/aiops/server/index.ts | 5 +- .../shared/aiops/server/lib/capabilities.ts | 31 ++ .../plugins/shared/aiops/server/plugin.ts | 3 +- .../platform/plugins/shared/ml/kibana.jsonc | 3 +- .../components/ml_page/side_nav.tsx | 8 +- .../application/overview/overview_ml_page.tsx | 331 +++++++++--------- .../lib/capabilities/capabilities_switcher.ts | 13 +- .../plugins/shared/ml/server/plugin.ts | 3 +- .../plugins/shared/ml/server/types.ts | 2 + .../alert_details_app_section/index.tsx | 9 +- .../alert_details_app_section.tsx | 6 +- .../plugins/observability/public/plugin.ts | 2 +- .../custom_kql/custom_kql_panels.tsx | 7 +- .../observability/plugins/slo/public/types.ts | 2 +- 16 files changed, 276 insertions(+), 174 deletions(-) create mode 100644 x-pack/platform/plugins/shared/aiops/server/config_schema.ts create mode 100644 x-pack/platform/plugins/shared/aiops/server/lib/capabilities.ts diff --git a/x-pack/platform/plugins/shared/aiops/kibana.jsonc b/x-pack/platform/plugins/shared/aiops/kibana.jsonc index d327a131aec4d..c5eb89834c7e5 100644 --- a/x-pack/platform/plugins/shared/aiops/kibana.jsonc +++ b/x-pack/platform/plugins/shared/aiops/kibana.jsonc @@ -11,6 +11,7 @@ "id": "aiops", "browser": true, "server": true, + "configPath": ["xpack", "aiops"], "requiredPlugins": [ "charts", "data", @@ -38,4 +39,4 @@ "cases" ] } -} \ No newline at end of file +} diff --git a/x-pack/platform/plugins/shared/aiops/server/config_schema.ts b/x-pack/platform/plugins/shared/aiops/server/config_schema.ts new file mode 100644 index 0000000000000..87dc5b3ddac2e --- /dev/null +++ b/x-pack/platform/plugins/shared/aiops/server/config_schema.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 type { TypeOf } from '@kbn/config-schema'; +import { schema } from '@kbn/config-schema'; +import type { PluginConfigDescriptor } from '@kbn/core/server'; + +export const configSchema = schema.object({ + enabled: schema.maybe(schema.boolean()), +}); + +export type ConfigSchema = TypeOf; + +export const config: PluginConfigDescriptor = { + schema: configSchema, + exposeToBrowser: { + enabled: true, + }, +}; diff --git a/x-pack/platform/plugins/shared/aiops/server/index.ts b/x-pack/platform/plugins/shared/aiops/server/index.ts index dca8bed715650..446129038f3a9 100755 --- a/x-pack/platform/plugins/shared/aiops/server/index.ts +++ b/x-pack/platform/plugins/shared/aiops/server/index.ts @@ -6,10 +6,13 @@ */ import type { PluginInitializerContext } from '@kbn/core/server'; +import type { ConfigSchema } from './config_schema'; -export async function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { const { AiopsPlugin } = await import('./plugin'); return new AiopsPlugin(initializerContext); } export type { AiopsPluginSetup, AiopsPluginStart } from './types'; + +export { config } from './config_schema'; diff --git a/x-pack/platform/plugins/shared/aiops/server/lib/capabilities.ts b/x-pack/platform/plugins/shared/aiops/server/lib/capabilities.ts new file mode 100644 index 0000000000000..826b9bc244d81 --- /dev/null +++ b/x-pack/platform/plugins/shared/aiops/server/lib/capabilities.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 { CoreSetup } from '@kbn/core/server'; +import type { AiopsPluginStartDeps } from '../types'; + +export const setupCapabilities = ( + core: Pick, 'capabilities' | 'getStartServices'>, + enabled: boolean +) => { + core.capabilities.registerProvider(() => { + return { + aiops: { + enabled, + }, + }; + }); + + core.capabilities.registerSwitcher( + async (request, capabilities, useDefaultCapabilities) => { + return {}; + }, + { + capabilityPath: 'aiops.*', + } + ); +}; diff --git a/x-pack/platform/plugins/shared/aiops/server/plugin.ts b/x-pack/platform/plugins/shared/aiops/server/plugin.ts index 4df2199847403..5d80cb4879939 100755 --- a/x-pack/platform/plugins/shared/aiops/server/plugin.ts +++ b/x-pack/platform/plugins/shared/aiops/server/plugin.ts @@ -29,6 +29,7 @@ import { defineRoute as defineLogRateAnalysisFieldCandidatesRoute } from './rout import { defineRoute as defineLogRateAnalysisRoute } from './routes/log_rate_analysis/define_route'; import { defineRoute as defineCategorizationFieldValidationRoute } from './routes/categorization_field_validation/define_route'; import { registerCasesPersistableState } from './register_cases'; +import type { ConfigSchema } from './config_schema'; export class AiopsPlugin implements Plugin @@ -37,7 +38,7 @@ export class AiopsPlugin private licenseSubscription: Subscription | null = null; private usageCounter?: UsageCounter; - constructor(initializerContext: PluginInitializerContext) { + constructor(initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get(); } diff --git a/x-pack/platform/plugins/shared/ml/kibana.jsonc b/x-pack/platform/plugins/shared/ml/kibana.jsonc index 4c21db50280bc..697d456129eff 100644 --- a/x-pack/platform/plugins/shared/ml/kibana.jsonc +++ b/x-pack/platform/plugins/shared/ml/kibana.jsonc @@ -11,7 +11,6 @@ "server": true, "configPath": ["xpack", "ml"], "requiredPlugins": [ - "aiops", "charts", "cloud", "data", @@ -36,6 +35,7 @@ "fieldsMetadata" ], "optionalPlugins": [ + "aiops", "alerting", "dashboard", "home", @@ -49,6 +49,7 @@ "cases", ], "requiredBundles": [ + "aiops", "cases", "charts", "dashboard", diff --git a/x-pack/platform/plugins/shared/ml/public/application/components/ml_page/side_nav.tsx b/x-pack/platform/plugins/shared/ml/public/application/components/ml_page/side_nav.tsx index ee1b0b43c80a8..af256755ac291 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/components/ml_page/side_nav.tsx +++ b/x-pack/platform/plugins/shared/ml/public/application/components/ml_page/side_nav.tsx @@ -17,6 +17,7 @@ import { isFullLicense } from '../../license'; import type { MlRoute } from '../../routing'; import { ML_PAGES } from '../../../../common/constants/locator'; import { useEnabledFeatures } from '../../contexts/ml'; +import { usePermissionCheck } from '../../capabilities/check_capabilities'; export interface Tab { id: string; @@ -38,6 +39,7 @@ export function useSideNavItems(activeRoute: MlRoute | undefined) { const mlFeaturesDisabled = !isFullLicense(); const { isADEnabled, isDFAEnabled } = useEnabledFeatures(); + const [canUseAiops] = usePermissionCheck(['canUseAiops']); const [globalState] = useUrlState('_g'); @@ -158,6 +160,10 @@ export function useSideNavItems(activeRoute: MlRoute | undefined) { : []), ]; + if (canUseAiops === false) { + return mlTabs; + } + mlTabs.push({ id: 'aiops_section', name: i18n.translate('xpack.ml.navMenu.aiopsTabLinkText', { @@ -203,7 +209,7 @@ export function useSideNavItems(activeRoute: MlRoute | undefined) { }); return mlTabs; - }, [mlFeaturesDisabled, isADEnabled, isDFAEnabled]); + }, [mlFeaturesDisabled, isADEnabled, isDFAEnabled, canUseAiops]); const getTabItem: (tab: Tab) => EuiSideNavItemType = useCallback( (tab: Tab) => { diff --git a/x-pack/platform/plugins/shared/ml/public/application/overview/overview_ml_page.tsx b/x-pack/platform/plugins/shared/ml/public/application/overview/overview_ml_page.tsx index adbed61da01de..c4e9797738917 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/overview/overview_ml_page.tsx +++ b/x-pack/platform/plugins/shared/ml/public/application/overview/overview_ml_page.tsx @@ -43,6 +43,7 @@ import { DataVisualizerGrid } from './data_visualizer_grid'; import { OverviewFooterItem } from './components/overview_ml_footer_item'; import bannerImageLight from './components/welcome--light.png'; import bannerImageDark from './components/welcome--dark.png'; +import { usePermissionCheck } from '../capabilities/check_capabilities'; export const overviewPanelDefaultState = Object.freeze({ nodes: true, @@ -118,6 +119,7 @@ export const OverviewPage: FC = () => { const { colorMode } = useEuiTheme(); const isDarkTheme = colorMode === 'DARK'; const { isADEnabled, isDFAEnabled, isNLPEnabled } = useEnabledFeatures(); + const [canUseAiops] = usePermissionCheck(['canUseAiops']); const helpLink = docLinks.links.ml.guide; const trainedModelsDocLink = docLinks.links.ml.trainedModels; const navigateToPath = useNavigateToPath(); @@ -237,169 +239,180 @@ export const OverviewPage: FC = () => { ) : null} - - -

- {i18n.translate('xpack.ml.overview.aiopsLabsTitle', { - defaultMessage: 'AIOps Labs', - })} -

-
- - - navigateToPath('/aiops/log_rate_analysis_index_select')} - iconType="logRateAnalysis" - aria-label={i18n.translate('xpack.ml.overview.logRateAnalysis.title', { - defaultMessage: 'Log Rate Analysis', - })} - /> - } - title={ - + + +

+ {i18n.translate('xpack.ml.overview.aiopsLabsTitle', { + defaultMessage: 'AIOps Labs', + })} +

+
+ + + navigateToPath('/aiops/log_rate_analysis_index_select')} + iconType="logRateAnalysis" + aria-label={i18n.translate('xpack.ml.overview.logRateAnalysis.title', { + defaultMessage: 'Log Rate Analysis', + })} + /> + } + title={ + + } + titleElement="h3" + titleSize="s" + description={ + <> + + + } + footer={ + navigateToPath('/aiops/log_rate_analysis_index_select')} + data-test-subj="mlOverviewCardLogRateAnalysisButton" + > + + + } + data-test-subj="mlOverviewCardLogRateAnalysis" /> - } - titleElement="h3" - titleSize="s" - description={ - <> - - - } - footer={ - navigateToPath('/aiops/log_rate_analysis_index_select')} - data-test-subj="mlOverviewCardLogRateAnalysisButton" - > - - - } - data-test-subj="mlOverviewCardLogRateAnalysis" - /> - +
- - navigateToPath('/aiops/log_categorization_index_select')} - aria-label={i18n.translate('xpack.ml.overview.logPatternAnalysisTitle', { - defaultMessage: 'Log Pattern Analysis', - })} - /> - } - title={ - + navigateToPath('/aiops/log_categorization_index_select')} + aria-label={i18n.translate('xpack.ml.overview.logPatternAnalysisTitle', { + defaultMessage: 'Log Pattern Analysis', + })} + /> + } + title={ + + } + titleElement="h3" + titleSize="s" + description={ + <> + + + } + footer={ + navigateToPath('/aiops/log_categorization_index_select')} + data-test-subj="mlOverviewCardLogPatternAnalysisButton" + > + + + } + data-test-subj="mlOverviewCardLogPatternAnalysis" /> - } - titleElement="h3" - titleSize="s" - description={ - <> - - - } - footer={ - navigateToPath('/aiops/log_categorization_index_select')} - data-test-subj="mlOverviewCardLogPatternAnalysisButton" - > - - - } - data-test-subj="mlOverviewCardLogPatternAnalysis" - /> - - - navigateToPath('/aiops/change_point_detection_index_select')} - aria-label={i18n.translate('xpack.ml.overview.changePointDetection.title', { - defaultMessage: 'Change Point Detection', - })} - /> - } - title={ - + + + navigateToPath('/aiops/change_point_detection_index_select') + } + aria-label={i18n.translate( + 'xpack.ml.overview.changePointDetection.title', + { + defaultMessage: 'Change Point Detection', + } + )} + /> + } + title={ + + } + titleElement="h3" + titleSize="s" + description={ + <> + + + } + footer={ + + navigateToPath('/aiops/change_point_detection_index_select') + } + data-test-subj="mlOverviewCardChangePointDetectionButton" + aria-label={i18n.translate( + 'xpack.ml.overview.changePointDetection.startDetectionButton', + { + defaultMessage: 'Start detection', + } + )} + > + + + } + data-test-subj="mlOverviewCardChangePointDetection" /> - } - titleElement="h3" - titleSize="s" - description={ - <> - - - } - footer={ - navigateToPath('/aiops/change_point_detection_index_select')} - data-test-subj="mlOverviewCardChangePointDetectionButton" - aria-label={i18n.translate( - 'xpack.ml.overview.changePointDetection.startDetectionButton', - { - defaultMessage: 'Start detection', - } - )} - > - - - } - data-test-subj="mlOverviewCardChangePointDetection" - /> - -
-
- + + + + + + ) : null}

diff --git a/x-pack/platform/plugins/shared/ml/server/lib/capabilities/capabilities_switcher.ts b/x-pack/platform/plugins/shared/ml/server/lib/capabilities/capabilities_switcher.ts index 90cefe20a059d..ce67db47a32b2 100644 --- a/x-pack/platform/plugins/shared/ml/server/lib/capabilities/capabilities_switcher.ts +++ b/x-pack/platform/plugins/shared/ml/server/lib/capabilities/capabilities_switcher.ts @@ -10,6 +10,7 @@ import type { Observable } from 'rxjs'; import { firstValueFrom } from 'rxjs'; import type { CapabilitiesSwitcher, CoreSetup, Logger } from '@kbn/core/server'; import type { ILicense } from '@kbn/licensing-plugin/common/types'; +import type { AiopsPluginSetup } from '@kbn/aiops-plugin/server'; import type { MlFeatures } from '../../../common/constants/app'; import { isFullLicense, isMinimumLicense, isMlEnabled } from '../../../common/license'; import { @@ -22,10 +23,11 @@ export const setupCapabilitiesSwitcher = ( coreSetup: CoreSetup, license$: Observable, enabledFeatures: MlFeatures, - logger: Logger + logger: Logger, + aiops: AiopsPluginSetup | undefined ) => { coreSetup.capabilities.registerSwitcher( - getSwitcher(license$, logger, enabledFeatures, coreSetup.getStartServices), + getSwitcher(license$, logger, enabledFeatures, coreSetup.getStartServices, aiops), { capabilityPath: 'ml.*', } @@ -36,7 +38,8 @@ function getSwitcher( license$: Observable, logger: Logger, enabledFeatures: MlFeatures, - getStartServices: CoreSetup['getStartServices'] + getStartServices: CoreSetup['getStartServices'], + aiops: AiopsPluginSetup | undefined ): CapabilitiesSwitcher { return async (request, capabilities) => { const isAnonymousRequest = !request.route.options.authRequired; @@ -55,6 +58,10 @@ function getSwitcher( const originalCapabilities = capabilities.ml as MlCapabilities; const mlCaps = cloneDeep(originalCapabilities); + if (aiops === undefined) { + mlCaps.canUseAiops = false; + } + // full license, leave capabilities as they were if (mlEnabled && isFullLicense(license)) { return { ml: applyEnabledFeatures(mlCaps, enabledFeatures, isServerless) }; diff --git a/x-pack/platform/plugins/shared/ml/server/plugin.ts b/x-pack/platform/plugins/shared/ml/server/plugin.ts index beeab9767d951..7a6e1fb01db2e 100644 --- a/x-pack/platform/plugins/shared/ml/server/plugin.ts +++ b/x-pack/platform/plugins/shared/ml/server/plugin.ts @@ -178,7 +178,8 @@ export class MlServerPlugin coreSetup, plugins.licensing.license$, this.enabledFeatures, - this.log + this.log, + plugins.aiops ); setupSavedObjects(coreSetup.savedObjects); this.savedObjectsSyncService.registerSyncTask( diff --git a/x-pack/platform/plugins/shared/ml/server/types.ts b/x-pack/platform/plugins/shared/ml/server/types.ts index 261ebfd7e2369..c0a8ef24ef2ca 100644 --- a/x-pack/platform/plugins/shared/ml/server/types.ts +++ b/x-pack/platform/plugins/shared/ml/server/types.ts @@ -27,6 +27,7 @@ import type { TaskManagerStartContract, } from '@kbn/task-manager-plugin/server'; import type { CasesServerSetup } from '@kbn/cases-plugin/server'; +import type { AiopsPluginSetup } from '@kbn/aiops-plugin/server'; import type { RouteGuard } from './lib/route_guard'; import type { ResolveMlCapabilities } from '../common/types/capabilities'; import type { MlLicense } from '../common/license'; @@ -53,6 +54,7 @@ export interface SavedObjectsRouteDeps { } export interface PluginsSetup { + aiops?: AiopsPluginSetup; cloud: CloudSetup; data: DataPluginSetup; fieldFormats: FieldFormatsSetup; diff --git a/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx b/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx index 4984c16a25941..f8a9840b174a5 100644 --- a/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx +++ b/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx @@ -20,6 +20,7 @@ import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-tim import { get, identity } from 'lodash'; import { useElasticChartsTheme } from '@kbn/charts-theme'; import { useLogView } from '@kbn/logs-shared-plugin/public'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; import { useKibanaContextForPlugin } from '../../../../hooks/use_kibana'; import { Comparator, @@ -37,6 +38,9 @@ import { useLicense } from '../../../../hooks/use_license'; const formatThreshold = (threshold: number) => String(threshold); const AlertDetailsAppSection = ({ rule, alert }: AlertDetailsAppSectionProps) => { + const { + services: { application }, + } = useKibana(); const { logsShared } = useKibanaContextForPlugin().services; const baseTheme = useElasticChartsTheme(); const timeRange = getPaddedAlertTimeRange(alert.fields[ALERT_START]!, alert.fields[ALERT_END]); @@ -64,6 +68,7 @@ const AlertDetailsAppSection = ({ rule, alert }: AlertDetailsAppSectionProps) => const { hasAtLeast } = useLicense(); const hasLicenseForLogRateAnalysis = hasAtLeast('platinum'); + const aiopsEnabled = application?.capabilities.aiops?.enabled ?? false; const getLogRatioChart = () => { if (isRatioRule(rule.params.criteria)) { @@ -191,7 +196,9 @@ const AlertDetailsAppSection = ({ rule, alert }: AlertDetailsAppSectionProps) => }; const getLogRateAnalysisSection = () => { - return hasLicenseForLogRateAnalysis ? : null; + return hasLicenseForLogRateAnalysis && aiopsEnabled ? ( + + ) : null; }; return ( diff --git a/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx b/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx index 525959710d289..e2af892a03ddd 100644 --- a/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx +++ b/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx @@ -59,6 +59,7 @@ export default function AlertDetailsAppSection({ alert }: AppSectionProps) { const { charts, data, + application, share: { url: { locators }, }, @@ -66,6 +67,7 @@ export default function AlertDetailsAppSection({ alert }: AppSectionProps) { const { hasAtLeast } = useLicense(); const { euiTheme } = useEuiTheme(); const hasLogRateAnalysisLicense = hasAtLeast('platinum'); + const aiopsEnabled = application?.capabilities.aiops?.enabled ?? false; const [dataView, setDataView] = useState(); const [, setDataViewError] = useState(); const [timeRange, setTimeRange] = useState({ from: 'now-15m', to: 'now' }); @@ -173,7 +175,7 @@ export default function AlertDetailsAppSection({ alert }: AppSectionProps) { - + ); })} - {hasLogRateAnalysisLicense && ( + {hasLogRateAnalysisLicense && aiopsEnabled && ( )} diff --git a/x-pack/solutions/observability/plugins/observability/public/plugin.ts b/x-pack/solutions/observability/plugins/observability/public/plugin.ts index f5ced4272aa04..dd4f2799d9eb5 100644 --- a/x-pack/solutions/observability/plugins/observability/public/plugin.ts +++ b/x-pack/solutions/observability/plugins/observability/public/plugin.ts @@ -156,7 +156,7 @@ export interface ObservabilityPublicPluginsStart { unifiedSearch: UnifiedSearchPublicPluginStart; home?: HomePublicPluginStart; cloud?: CloudStart; - aiops: AiopsPluginStart; + aiops?: AiopsPluginStart; serverless?: ServerlessPluginStart; uiSettings: IUiSettingsClient; uiActions: UiActionsStart; diff --git a/x-pack/solutions/observability/plugins/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx b/x-pack/solutions/observability/plugins/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx index 1a75a30766423..b30399d2d0bfc 100644 --- a/x-pack/solutions/observability/plugins/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx @@ -7,6 +7,7 @@ import { GetSLOResponse } from '@kbn/slo-schema'; import React from 'react'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; import { LogRateAnalysisPanel } from './log_rate_analysis_panel'; import { BurnRateAlert, BurnRateRule } from '../../../types'; import { useLicense } from '../../../../../hooks/use_license'; @@ -19,8 +20,12 @@ interface Props { export function CustomKqlPanels({ slo, alert, rule }: Props) { const { hasAtLeast } = useLicense(); + const { + services: { application }, + } = useKibana(); + const aiopsEnabled = application?.capabilities.aiops?.enabled ?? false; const hasLicenseForLogRateAnalysis = hasAtLeast('platinum'); - return hasLicenseForLogRateAnalysis ? ( + return hasLicenseForLogRateAnalysis && aiopsEnabled ? ( ) : null; } diff --git a/x-pack/solutions/observability/plugins/slo/public/types.ts b/x-pack/solutions/observability/plugins/slo/public/types.ts index e903660eccc14..6b5c591547ede 100644 --- a/x-pack/solutions/observability/plugins/slo/public/types.ts +++ b/x-pack/solutions/observability/plugins/slo/public/types.ts @@ -73,7 +73,7 @@ export interface SLOPublicPluginsSetup { } export interface SLOPublicPluginsStart { - aiops: AiopsPluginStart; + aiops?: AiopsPluginStart; cases: CasesPublicStart; charts: ChartsPluginStart; cloud?: CloudStart; From cd02e46b8b9813ee5dd88a8518a7ae4229b35faf Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Thu, 22 May 2025 17:10:58 +0100 Subject: [PATCH 02/20] updating jsonc files --- x-pack/solutions/observability/plugins/infra/kibana.jsonc | 3 ++- .../observability/plugins/observability/kibana.jsonc | 5 +++-- x-pack/solutions/observability/plugins/slo/kibana.jsonc | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/x-pack/solutions/observability/plugins/infra/kibana.jsonc b/x-pack/solutions/observability/plugins/infra/kibana.jsonc index d62cbf3402f6d..683432f2bd0f7 100644 --- a/x-pack/solutions/observability/plugins/infra/kibana.jsonc +++ b/x-pack/solutions/observability/plugins/infra/kibana.jsonc @@ -11,7 +11,6 @@ "browser": true, "configPath": ["xpack", "infra"], "requiredPlugins": [ - "aiops", "alerting", "cases", "charts", @@ -42,6 +41,7 @@ "fieldsMetadata" ], "optionalPlugins": [ + "aiops", "spaces", "ml", "home", @@ -53,6 +53,7 @@ "serverless" ], "requiredBundles": [ + "aiops", "unifiedSearch", "observability", "licenseManagement", diff --git a/x-pack/solutions/observability/plugins/observability/kibana.jsonc b/x-pack/solutions/observability/plugins/observability/kibana.jsonc index 4a83799bfdb6e..63dd635854e2d 100644 --- a/x-pack/solutions/observability/plugins/observability/kibana.jsonc +++ b/x-pack/solutions/observability/plugins/observability/kibana.jsonc @@ -15,7 +15,6 @@ "observability" ], "requiredPlugins": [ - "aiops", "alerting", "cases", "charts", @@ -48,6 +47,7 @@ "fieldsMetadata" ], "optionalPlugins": [ + "aiops", "discover", "home", "usageCollection", @@ -60,6 +60,7 @@ "streams" ], "requiredBundles": [ + "aiops", "data", "discover", "kibanaReact", @@ -72,4 +73,4 @@ "common" ] } -} \ No newline at end of file +} diff --git a/x-pack/solutions/observability/plugins/slo/kibana.jsonc b/x-pack/solutions/observability/plugins/slo/kibana.jsonc index 81c17bb581053..f2c61c0bd660b 100644 --- a/x-pack/solutions/observability/plugins/slo/kibana.jsonc +++ b/x-pack/solutions/observability/plugins/slo/kibana.jsonc @@ -10,7 +10,6 @@ "server": true, "configPath": ["xpack", "slo"], "requiredPlugins": [ - "aiops", "alerting", "cases", "charts", @@ -39,6 +38,7 @@ "apmSourcesAccess" ], "optionalPlugins": [ + "aiops", "cloud", "discover", "embeddableEnhanced", @@ -48,6 +48,7 @@ "spaces" ], "requiredBundles": [ + "aiops", "controls", "embeddable", "ingestPipelines", From 111a6d01b160b55e3b8f7ae59f9431ceb016fc3b Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 23 May 2025 09:27:37 +0000 Subject: [PATCH 03/20] [CI] Auto-commit changed files from 'node scripts/yarn_deduplicate' --- x-pack/platform/plugins/shared/aiops/tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/platform/plugins/shared/aiops/tsconfig.json b/x-pack/platform/plugins/shared/aiops/tsconfig.json index 08b9f8720e814..6f00afb60ab03 100644 --- a/x-pack/platform/plugins/shared/aiops/tsconfig.json +++ b/x-pack/platform/plugins/shared/aiops/tsconfig.json @@ -76,6 +76,7 @@ "@kbn/observability-ai-assistant-plugin", "@kbn/apm-utils", "@kbn/ml-field-stats-flyout", + "@kbn/config-schema", ], "exclude": [ "target/**/*", From 48980c48723f9951e624271e2fb8ddc0123c8770 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Fri, 23 May 2025 16:56:43 +0100 Subject: [PATCH 04/20] switching to ui.enabled --- .../plugins/shared/aiops/server/config_schema.ts | 8 ++++++-- .../platform/plugins/shared/aiops/server/index.ts | 2 +- .../plugins/shared/aiops/server/lib/capabilities.ts | 4 +++- .../lib/capabilities/capabilities_switcher.ts | 13 ++++++------- x-pack/platform/plugins/shared/ml/server/plugin.ts | 3 +-- x-pack/platform/plugins/shared/ml/server/types.ts | 2 -- .../observability/plugins/infra/kibana.jsonc | 3 +-- .../components/alert_details_app_section/index.tsx | 4 +++- .../plugins/observability/kibana.jsonc | 3 +-- .../alert_details_app_section.tsx | 4 +++- .../plugins/observability/public/plugin.ts | 4 +--- .../observability/plugins/slo/kibana.jsonc | 3 +-- .../custom_panels/custom_kql/custom_kql_panels.tsx | 4 +++- .../observability/plugins/slo/public/types.ts | 2 +- 14 files changed, 31 insertions(+), 28 deletions(-) diff --git a/x-pack/platform/plugins/shared/aiops/server/config_schema.ts b/x-pack/platform/plugins/shared/aiops/server/config_schema.ts index 87dc5b3ddac2e..5d7bee1af5f59 100644 --- a/x-pack/platform/plugins/shared/aiops/server/config_schema.ts +++ b/x-pack/platform/plugins/shared/aiops/server/config_schema.ts @@ -9,7 +9,11 @@ import { schema } from '@kbn/config-schema'; import type { PluginConfigDescriptor } from '@kbn/core/server'; export const configSchema = schema.object({ - enabled: schema.maybe(schema.boolean()), + ui: schema.maybe( + schema.object({ + enabled: schema.maybe(schema.boolean()), + }) + ), }); export type ConfigSchema = TypeOf; @@ -17,6 +21,6 @@ export type ConfigSchema = TypeOf; export const config: PluginConfigDescriptor = { schema: configSchema, exposeToBrowser: { - enabled: true, + ui: true, }, }; diff --git a/x-pack/platform/plugins/shared/aiops/server/index.ts b/x-pack/platform/plugins/shared/aiops/server/index.ts index 446129038f3a9..a92dc37137ee0 100755 --- a/x-pack/platform/plugins/shared/aiops/server/index.ts +++ b/x-pack/platform/plugins/shared/aiops/server/index.ts @@ -15,4 +15,4 @@ export async function plugin(initializerContext: PluginInitializerContext { return { aiops: { - enabled, + ui: { + enabled, + }, }, }; }); diff --git a/x-pack/platform/plugins/shared/ml/server/lib/capabilities/capabilities_switcher.ts b/x-pack/platform/plugins/shared/ml/server/lib/capabilities/capabilities_switcher.ts index ce67db47a32b2..148cb04bbdd61 100644 --- a/x-pack/platform/plugins/shared/ml/server/lib/capabilities/capabilities_switcher.ts +++ b/x-pack/platform/plugins/shared/ml/server/lib/capabilities/capabilities_switcher.ts @@ -10,7 +10,7 @@ import type { Observable } from 'rxjs'; import { firstValueFrom } from 'rxjs'; import type { CapabilitiesSwitcher, CoreSetup, Logger } from '@kbn/core/server'; import type { ILicense } from '@kbn/licensing-plugin/common/types'; -import type { AiopsPluginSetup } from '@kbn/aiops-plugin/server'; +import type { ConfigSchema as AiopsConfigSchema } from '@kbn/aiops-plugin/server'; import type { MlFeatures } from '../../../common/constants/app'; import { isFullLicense, isMinimumLicense, isMlEnabled } from '../../../common/license'; import { @@ -23,11 +23,10 @@ export const setupCapabilitiesSwitcher = ( coreSetup: CoreSetup, license$: Observable, enabledFeatures: MlFeatures, - logger: Logger, - aiops: AiopsPluginSetup | undefined + logger: Logger ) => { coreSetup.capabilities.registerSwitcher( - getSwitcher(license$, logger, enabledFeatures, coreSetup.getStartServices, aiops), + getSwitcher(license$, logger, enabledFeatures, coreSetup.getStartServices), { capabilityPath: 'ml.*', } @@ -38,8 +37,7 @@ function getSwitcher( license$: Observable, logger: Logger, enabledFeatures: MlFeatures, - getStartServices: CoreSetup['getStartServices'], - aiops: AiopsPluginSetup | undefined + getStartServices: CoreSetup['getStartServices'] ): CapabilitiesSwitcher { return async (request, capabilities) => { const isAnonymousRequest = !request.route.options.authRequired; @@ -58,7 +56,8 @@ function getSwitcher( const originalCapabilities = capabilities.ml as MlCapabilities; const mlCaps = cloneDeep(originalCapabilities); - if (aiops === undefined) { + const aiopsCapabilities: AiopsConfigSchema = capabilities.aiops; + if (aiopsCapabilities?.ui?.enabled === false) { mlCaps.canUseAiops = false; } diff --git a/x-pack/platform/plugins/shared/ml/server/plugin.ts b/x-pack/platform/plugins/shared/ml/server/plugin.ts index 7a6e1fb01db2e..beeab9767d951 100644 --- a/x-pack/platform/plugins/shared/ml/server/plugin.ts +++ b/x-pack/platform/plugins/shared/ml/server/plugin.ts @@ -178,8 +178,7 @@ export class MlServerPlugin coreSetup, plugins.licensing.license$, this.enabledFeatures, - this.log, - plugins.aiops + this.log ); setupSavedObjects(coreSetup.savedObjects); this.savedObjectsSyncService.registerSyncTask( diff --git a/x-pack/platform/plugins/shared/ml/server/types.ts b/x-pack/platform/plugins/shared/ml/server/types.ts index c0a8ef24ef2ca..261ebfd7e2369 100644 --- a/x-pack/platform/plugins/shared/ml/server/types.ts +++ b/x-pack/platform/plugins/shared/ml/server/types.ts @@ -27,7 +27,6 @@ import type { TaskManagerStartContract, } from '@kbn/task-manager-plugin/server'; import type { CasesServerSetup } from '@kbn/cases-plugin/server'; -import type { AiopsPluginSetup } from '@kbn/aiops-plugin/server'; import type { RouteGuard } from './lib/route_guard'; import type { ResolveMlCapabilities } from '../common/types/capabilities'; import type { MlLicense } from '../common/license'; @@ -54,7 +53,6 @@ export interface SavedObjectsRouteDeps { } export interface PluginsSetup { - aiops?: AiopsPluginSetup; cloud: CloudSetup; data: DataPluginSetup; fieldFormats: FieldFormatsSetup; diff --git a/x-pack/solutions/observability/plugins/infra/kibana.jsonc b/x-pack/solutions/observability/plugins/infra/kibana.jsonc index 683432f2bd0f7..d62cbf3402f6d 100644 --- a/x-pack/solutions/observability/plugins/infra/kibana.jsonc +++ b/x-pack/solutions/observability/plugins/infra/kibana.jsonc @@ -11,6 +11,7 @@ "browser": true, "configPath": ["xpack", "infra"], "requiredPlugins": [ + "aiops", "alerting", "cases", "charts", @@ -41,7 +42,6 @@ "fieldsMetadata" ], "optionalPlugins": [ - "aiops", "spaces", "ml", "home", @@ -53,7 +53,6 @@ "serverless" ], "requiredBundles": [ - "aiops", "unifiedSearch", "observability", "licenseManagement", diff --git a/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx b/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx index f8a9840b174a5..4b1a7174b7d97 100644 --- a/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx +++ b/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx @@ -17,6 +17,7 @@ import moment from 'moment'; import { EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-time-range-util'; +import type { ConfigSchema as AiopsConfigSchema } from '@kbn/aiops-plugin/server'; import { get, identity } from 'lodash'; import { useElasticChartsTheme } from '@kbn/charts-theme'; import { useLogView } from '@kbn/logs-shared-plugin/public'; @@ -68,7 +69,8 @@ const AlertDetailsAppSection = ({ rule, alert }: AlertDetailsAppSectionProps) => const { hasAtLeast } = useLicense(); const hasLicenseForLogRateAnalysis = hasAtLeast('platinum'); - const aiopsEnabled = application?.capabilities.aiops?.enabled ?? false; + const aiopsCapabilities: AiopsConfigSchema | undefined = application?.capabilities.aiops; + const aiopsEnabled = aiopsCapabilities?.ui?.enabled ?? false; const getLogRatioChart = () => { if (isRatioRule(rule.params.criteria)) { diff --git a/x-pack/solutions/observability/plugins/observability/kibana.jsonc b/x-pack/solutions/observability/plugins/observability/kibana.jsonc index 63dd635854e2d..e83a03dadd23d 100644 --- a/x-pack/solutions/observability/plugins/observability/kibana.jsonc +++ b/x-pack/solutions/observability/plugins/observability/kibana.jsonc @@ -15,6 +15,7 @@ "observability" ], "requiredPlugins": [ + "aiops", "alerting", "cases", "charts", @@ -47,7 +48,6 @@ "fieldsMetadata" ], "optionalPlugins": [ - "aiops", "discover", "home", "usageCollection", @@ -60,7 +60,6 @@ "streams" ], "requiredBundles": [ - "aiops", "data", "discover", "kibanaReact", diff --git a/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx b/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx index e2af892a03ddd..417c9fb39a9e4 100644 --- a/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx +++ b/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx @@ -21,6 +21,7 @@ import { transparentize, } from '@elastic/eui'; import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-time-range-util'; +import type { ConfigSchema as AiopsConfigSchema } from '@kbn/aiops-plugin/server'; import { ALERT_END, ALERT_START, @@ -67,7 +68,8 @@ export default function AlertDetailsAppSection({ alert }: AppSectionProps) { const { hasAtLeast } = useLicense(); const { euiTheme } = useEuiTheme(); const hasLogRateAnalysisLicense = hasAtLeast('platinum'); - const aiopsEnabled = application?.capabilities.aiops?.enabled ?? false; + const aiopsCapabilities: AiopsConfigSchema = application.capabilities.aiops; + const aiopsEnabled = aiopsCapabilities?.ui?.enabled ?? false; const [dataView, setDataView] = useState(); const [, setDataViewError] = useState(); const [timeRange, setTimeRange] = useState({ from: 'now-15m', to: 'now' }); diff --git a/x-pack/solutions/observability/plugins/observability/public/plugin.ts b/x-pack/solutions/observability/plugins/observability/public/plugin.ts index 5cb89edefa890..f5ced4272aa04 100644 --- a/x-pack/solutions/observability/plugins/observability/public/plugin.ts +++ b/x-pack/solutions/observability/plugins/observability/public/plugin.ts @@ -6,7 +6,6 @@ */ import { CasesDeepLinkId, CasesPublicStart, getCasesDeepLinks } from '@kbn/cases-plugin/public'; -import { DashboardStart } from '@kbn/dashboard-plugin/public'; import type { ChartsPluginStart } from '@kbn/charts-plugin/public'; import type { CloudStart } from '@kbn/cloud-plugin/public'; import type { ContentManagementPublicStart } from '@kbn/content-management-plugin/public'; @@ -134,7 +133,6 @@ export interface ObservabilityPublicPluginsStart { cases: CasesPublicStart; charts: ChartsPluginStart; contentManagement: ContentManagementPublicStart; - dashboard: DashboardStart; data: DataPublicPluginStart; dataViews: DataViewsPublicPluginStart; dataViewEditor: DataViewEditorStart; @@ -158,7 +156,7 @@ export interface ObservabilityPublicPluginsStart { unifiedSearch: UnifiedSearchPublicPluginStart; home?: HomePublicPluginStart; cloud?: CloudStart; - aiops?: AiopsPluginStart; + aiops: AiopsPluginStart; serverless?: ServerlessPluginStart; uiSettings: IUiSettingsClient; uiActions: UiActionsStart; diff --git a/x-pack/solutions/observability/plugins/slo/kibana.jsonc b/x-pack/solutions/observability/plugins/slo/kibana.jsonc index f2c61c0bd660b..81c17bb581053 100644 --- a/x-pack/solutions/observability/plugins/slo/kibana.jsonc +++ b/x-pack/solutions/observability/plugins/slo/kibana.jsonc @@ -10,6 +10,7 @@ "server": true, "configPath": ["xpack", "slo"], "requiredPlugins": [ + "aiops", "alerting", "cases", "charts", @@ -38,7 +39,6 @@ "apmSourcesAccess" ], "optionalPlugins": [ - "aiops", "cloud", "discover", "embeddableEnhanced", @@ -48,7 +48,6 @@ "spaces" ], "requiredBundles": [ - "aiops", "controls", "embeddable", "ingestPipelines", diff --git a/x-pack/solutions/observability/plugins/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx b/x-pack/solutions/observability/plugins/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx index b30399d2d0bfc..c922b695d2c19 100644 --- a/x-pack/solutions/observability/plugins/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx @@ -8,6 +8,7 @@ import { GetSLOResponse } from '@kbn/slo-schema'; import React from 'react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; +import type { ConfigSchema as AiopsConfigSchema } from '@kbn/aiops-plugin/server'; import { LogRateAnalysisPanel } from './log_rate_analysis_panel'; import { BurnRateAlert, BurnRateRule } from '../../../types'; import { useLicense } from '../../../../../hooks/use_license'; @@ -23,7 +24,8 @@ export function CustomKqlPanels({ slo, alert, rule }: Props) { const { services: { application }, } = useKibana(); - const aiopsEnabled = application?.capabilities.aiops?.enabled ?? false; + const aiopsCapabilities: AiopsConfigSchema | undefined = application?.capabilities.aiops; + const aiopsEnabled = aiopsCapabilities?.ui?.enabled ?? false; const hasLicenseForLogRateAnalysis = hasAtLeast('platinum'); return hasLicenseForLogRateAnalysis && aiopsEnabled ? ( diff --git a/x-pack/solutions/observability/plugins/slo/public/types.ts b/x-pack/solutions/observability/plugins/slo/public/types.ts index 6b5c591547ede..e903660eccc14 100644 --- a/x-pack/solutions/observability/plugins/slo/public/types.ts +++ b/x-pack/solutions/observability/plugins/slo/public/types.ts @@ -73,7 +73,7 @@ export interface SLOPublicPluginsSetup { } export interface SLOPublicPluginsStart { - aiops?: AiopsPluginStart; + aiops: AiopsPluginStart; cases: CasesPublicStart; charts: ChartsPluginStart; cloud?: CloudStart; From bdbcf1f0035d08672a5e855c17051f1456207805 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Fri, 23 May 2025 16:57:34 +0100 Subject: [PATCH 05/20] updating test --- .../test/plugin_functional/test_suites/core_plugins/rendering.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platform/test/plugin_functional/test_suites/core_plugins/rendering.ts b/src/platform/test/plugin_functional/test_suites/core_plugins/rendering.ts index 81c446a6cb36f..7e5601a7a4fa9 100644 --- a/src/platform/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/src/platform/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -204,6 +204,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'vis_type_xy.readOnly (boolean?|never)', 'vis_type_vega.enableExternalUrls (boolean?)', 'xpack.actions.email.domain_allowlist (array)', + 'xpack.aiops.enabled (boolean?)', 'xpack.apm.serviceMapEnabled (boolean?)', 'xpack.apm.ui.enabled (boolean?)', 'xpack.apm.ui.maxTraceItems (number?)', From 67bb42b1baae30fd3898ebd0ab99556bdb8a2e9b Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Fri, 23 May 2025 16:59:43 +0100 Subject: [PATCH 06/20] fixing test --- .../plugin_functional/test_suites/core_plugins/rendering.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/test/plugin_functional/test_suites/core_plugins/rendering.ts b/src/platform/test/plugin_functional/test_suites/core_plugins/rendering.ts index 7e5601a7a4fa9..5bd7350311c2e 100644 --- a/src/platform/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/src/platform/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -204,7 +204,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'vis_type_xy.readOnly (boolean?|never)', 'vis_type_vega.enableExternalUrls (boolean?)', 'xpack.actions.email.domain_allowlist (array)', - 'xpack.aiops.enabled (boolean?)', + 'xpack.aiops.ui.enabled (boolean?)', 'xpack.apm.serviceMapEnabled (boolean?)', 'xpack.apm.ui.enabled (boolean?)', 'xpack.apm.ui.maxTraceItems (number?)', From 934ae28502b18394fad3b1ac2532cf29c16bf091 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Fri, 23 May 2025 17:01:16 +0100 Subject: [PATCH 07/20] reverting config change --- x-pack/platform/plugins/shared/ml/kibana.jsonc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/platform/plugins/shared/ml/kibana.jsonc b/x-pack/platform/plugins/shared/ml/kibana.jsonc index 697d456129eff..4c21db50280bc 100644 --- a/x-pack/platform/plugins/shared/ml/kibana.jsonc +++ b/x-pack/platform/plugins/shared/ml/kibana.jsonc @@ -11,6 +11,7 @@ "server": true, "configPath": ["xpack", "ml"], "requiredPlugins": [ + "aiops", "charts", "cloud", "data", @@ -35,7 +36,6 @@ "fieldsMetadata" ], "optionalPlugins": [ - "aiops", "alerting", "dashboard", "home", @@ -49,7 +49,6 @@ "cases", ], "requiredBundles": [ - "aiops", "cases", "charts", "dashboard", From c75808d6238d506fb03b500a595c9f666885e640 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Fri, 23 May 2025 17:22:03 +0100 Subject: [PATCH 08/20] fixing discover --- .../log_categorization_enabled.ts | 13 ++++++++++++- .../platform/plugins/shared/aiops/public/plugin.tsx | 2 +- .../platform/plugins/shared/aiops/server/plugin.ts | 6 +++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/x-pack/platform/plugins/shared/aiops/public/components/log_categorization/log_categorization_enabled.ts b/x-pack/platform/plugins/shared/aiops/public/components/log_categorization/log_categorization_enabled.ts index 6df61a20f993a..e1e5d649e93f8 100644 --- a/x-pack/platform/plugins/shared/aiops/public/components/log_categorization/log_categorization_enabled.ts +++ b/x-pack/platform/plugins/shared/aiops/public/components/log_categorization/log_categorization_enabled.ts @@ -5,15 +5,26 @@ * 2.0. */ +import type { ApplicationStart } from '@kbn/core/public'; import type { DataView } from '@kbn/data-views-plugin/public'; import { ES_FIELD_TYPES } from '@kbn/field-types'; import type { LicensingPluginStart } from '@kbn/licensing-plugin/public'; import { firstValueFrom } from 'rxjs'; +import type { ConfigSchema } from '../../../server'; -export function getPatternAnalysisAvailable(licensing: LicensingPluginStart) { +export function getPatternAnalysisAvailable( + licensing: LicensingPluginStart, + application: ApplicationStart +) { const lic = firstValueFrom(licensing.license$); return async (dataView: DataView) => { const isPlatinum = (await lic).hasAtLeast('platinum'); + const aiopsCapabilities: ConfigSchema = application.capabilities.aiops; + const aiopsEnabled = aiopsCapabilities?.ui?.enabled; + if (!aiopsEnabled) { + return false; + } + return ( isPlatinum && dataView.isTimeBased() && diff --git a/x-pack/platform/plugins/shared/aiops/public/plugin.tsx b/x-pack/platform/plugins/shared/aiops/public/plugin.tsx index d8c3dfd4c3636..84d1e786ea1b0 100755 --- a/x-pack/platform/plugins/shared/aiops/public/plugin.tsx +++ b/x-pack/platform/plugins/shared/aiops/public/plugin.tsx @@ -58,7 +58,7 @@ export class AiopsPlugin const { getPatternAnalysisAvailable } = await import( './components/log_categorization/log_categorization_enabled' ); - return getPatternAnalysisAvailable(plugins.licensing); + return getPatternAnalysisAvailable(plugins.licensing, core.application); }, PatternAnalysisComponent, }; diff --git a/x-pack/platform/plugins/shared/aiops/server/plugin.ts b/x-pack/platform/plugins/shared/aiops/server/plugin.ts index 5d80cb4879939..5ebb796f91d3b 100755 --- a/x-pack/platform/plugins/shared/aiops/server/plugin.ts +++ b/x-pack/platform/plugins/shared/aiops/server/plugin.ts @@ -30,6 +30,7 @@ import { defineRoute as defineLogRateAnalysisRoute } from './routes/log_rate_ana import { defineRoute as defineCategorizationFieldValidationRoute } from './routes/categorization_field_validation/define_route'; import { registerCasesPersistableState } from './register_cases'; import type { ConfigSchema } from './config_schema'; +import { setupCapabilities } from './lib/capabilities'; export class AiopsPlugin implements Plugin @@ -37,16 +38,19 @@ export class AiopsPlugin private readonly logger: Logger; private licenseSubscription: Subscription | null = null; private usageCounter?: UsageCounter; + private aiopsEnabled: boolean = true; constructor(initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get(); + this.aiopsEnabled = initializerContext.config.get().ui?.enabled ?? true; } public setup( core: CoreSetup, plugins: AiopsPluginSetupDeps ) { - this.logger.debug('aiops: Setup'); + setupCapabilities(core, this.aiopsEnabled); + this.usageCounter = plugins.usageCollection?.createUsageCounter(AIOPS_PLUGIN_ID); // Subscribe to license changes and store the current license in `currentLicense`. From 51706c23e73878b065e761aabd54e3c183847134 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Sat, 24 May 2025 13:53:23 +0100 Subject: [PATCH 09/20] fixing types --- .../observability/plugins/observability/public/plugin.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/solutions/observability/plugins/observability/public/plugin.ts b/x-pack/solutions/observability/plugins/observability/public/plugin.ts index f5ced4272aa04..8696af87a6315 100644 --- a/x-pack/solutions/observability/plugins/observability/public/plugin.ts +++ b/x-pack/solutions/observability/plugins/observability/public/plugin.ts @@ -6,6 +6,7 @@ */ import { CasesDeepLinkId, CasesPublicStart, getCasesDeepLinks } from '@kbn/cases-plugin/public'; +import { DashboardStart } from '@kbn/dashboard-plugin/public'; import type { ChartsPluginStart } from '@kbn/charts-plugin/public'; import type { CloudStart } from '@kbn/cloud-plugin/public'; import type { ContentManagementPublicStart } from '@kbn/content-management-plugin/public'; @@ -133,6 +134,7 @@ export interface ObservabilityPublicPluginsStart { cases: CasesPublicStart; charts: ChartsPluginStart; contentManagement: ContentManagementPublicStart; + dashboard: DashboardStart; data: DataPublicPluginStart; dataViews: DataViewsPublicPluginStart; dataViewEditor: DataViewEditorStart; From 7a61e903114a56d51b769e12d9e356c220946c96 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Tue, 27 May 2025 10:50:04 +0100 Subject: [PATCH 10/20] removing exposing to browser --- .../plugin_functional/test_suites/core_plugins/rendering.ts | 1 - x-pack/platform/plugins/shared/aiops/server/config_schema.ts | 3 --- 2 files changed, 4 deletions(-) diff --git a/src/platform/test/plugin_functional/test_suites/core_plugins/rendering.ts b/src/platform/test/plugin_functional/test_suites/core_plugins/rendering.ts index 5bd7350311c2e..81c446a6cb36f 100644 --- a/src/platform/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/src/platform/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -204,7 +204,6 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'vis_type_xy.readOnly (boolean?|never)', 'vis_type_vega.enableExternalUrls (boolean?)', 'xpack.actions.email.domain_allowlist (array)', - 'xpack.aiops.ui.enabled (boolean?)', 'xpack.apm.serviceMapEnabled (boolean?)', 'xpack.apm.ui.enabled (boolean?)', 'xpack.apm.ui.maxTraceItems (number?)', diff --git a/x-pack/platform/plugins/shared/aiops/server/config_schema.ts b/x-pack/platform/plugins/shared/aiops/server/config_schema.ts index 5d7bee1af5f59..1694d6d2c5e4a 100644 --- a/x-pack/platform/plugins/shared/aiops/server/config_schema.ts +++ b/x-pack/platform/plugins/shared/aiops/server/config_schema.ts @@ -20,7 +20,4 @@ export type ConfigSchema = TypeOf; export const config: PluginConfigDescriptor = { schema: configSchema, - exposeToBrowser: { - ui: true, - }, }; From 1420876562cffdadb0d66f239e02dc08bab6afe1 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Tue, 27 May 2025 14:03:33 +0100 Subject: [PATCH 11/20] updating capability path --- .../platform/plugins/shared/aiops/server/lib/capabilities.ts | 4 +--- .../ml/server/lib/capabilities/capabilities_switcher.ts | 4 +--- .../components/alert_details_app_section/index.tsx | 4 +--- .../alert_details_app_section/alert_details_app_section.tsx | 4 +--- .../components/custom_panels/custom_kql/custom_kql_panels.tsx | 4 +--- 5 files changed, 5 insertions(+), 15 deletions(-) diff --git a/x-pack/platform/plugins/shared/aiops/server/lib/capabilities.ts b/x-pack/platform/plugins/shared/aiops/server/lib/capabilities.ts index f6f2a3c41dd07..826b9bc244d81 100644 --- a/x-pack/platform/plugins/shared/aiops/server/lib/capabilities.ts +++ b/x-pack/platform/plugins/shared/aiops/server/lib/capabilities.ts @@ -15,9 +15,7 @@ export const setupCapabilities = ( core.capabilities.registerProvider(() => { return { aiops: { - ui: { - enabled, - }, + enabled, }, }; }); diff --git a/x-pack/platform/plugins/shared/ml/server/lib/capabilities/capabilities_switcher.ts b/x-pack/platform/plugins/shared/ml/server/lib/capabilities/capabilities_switcher.ts index 148cb04bbdd61..79326859ee232 100644 --- a/x-pack/platform/plugins/shared/ml/server/lib/capabilities/capabilities_switcher.ts +++ b/x-pack/platform/plugins/shared/ml/server/lib/capabilities/capabilities_switcher.ts @@ -10,7 +10,6 @@ import type { Observable } from 'rxjs'; import { firstValueFrom } from 'rxjs'; import type { CapabilitiesSwitcher, CoreSetup, Logger } from '@kbn/core/server'; import type { ILicense } from '@kbn/licensing-plugin/common/types'; -import type { ConfigSchema as AiopsConfigSchema } from '@kbn/aiops-plugin/server'; import type { MlFeatures } from '../../../common/constants/app'; import { isFullLicense, isMinimumLicense, isMlEnabled } from '../../../common/license'; import { @@ -56,8 +55,7 @@ function getSwitcher( const originalCapabilities = capabilities.ml as MlCapabilities; const mlCaps = cloneDeep(originalCapabilities); - const aiopsCapabilities: AiopsConfigSchema = capabilities.aiops; - if (aiopsCapabilities?.ui?.enabled === false) { + if (capabilities.aiops.enabled === false) { mlCaps.canUseAiops = false; } diff --git a/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx b/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx index 4b1a7174b7d97..8117cefc6cf23 100644 --- a/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx +++ b/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx @@ -17,7 +17,6 @@ import moment from 'moment'; import { EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-time-range-util'; -import type { ConfigSchema as AiopsConfigSchema } from '@kbn/aiops-plugin/server'; import { get, identity } from 'lodash'; import { useElasticChartsTheme } from '@kbn/charts-theme'; import { useLogView } from '@kbn/logs-shared-plugin/public'; @@ -69,8 +68,7 @@ const AlertDetailsAppSection = ({ rule, alert }: AlertDetailsAppSectionProps) => const { hasAtLeast } = useLicense(); const hasLicenseForLogRateAnalysis = hasAtLeast('platinum'); - const aiopsCapabilities: AiopsConfigSchema | undefined = application?.capabilities.aiops; - const aiopsEnabled = aiopsCapabilities?.ui?.enabled ?? false; + const aiopsEnabled = application?.capabilities.aiops.enabled ?? false; const getLogRatioChart = () => { if (isRatioRule(rule.params.criteria)) { diff --git a/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx b/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx index 417c9fb39a9e4..87f8aeb8da8e0 100644 --- a/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx +++ b/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx @@ -21,7 +21,6 @@ import { transparentize, } from '@elastic/eui'; import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-time-range-util'; -import type { ConfigSchema as AiopsConfigSchema } from '@kbn/aiops-plugin/server'; import { ALERT_END, ALERT_START, @@ -68,8 +67,7 @@ export default function AlertDetailsAppSection({ alert }: AppSectionProps) { const { hasAtLeast } = useLicense(); const { euiTheme } = useEuiTheme(); const hasLogRateAnalysisLicense = hasAtLeast('platinum'); - const aiopsCapabilities: AiopsConfigSchema = application.capabilities.aiops; - const aiopsEnabled = aiopsCapabilities?.ui?.enabled ?? false; + const aiopsEnabled = application.capabilities.aiops.enabled; const [dataView, setDataView] = useState(); const [, setDataViewError] = useState(); const [timeRange, setTimeRange] = useState({ from: 'now-15m', to: 'now' }); diff --git a/x-pack/solutions/observability/plugins/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx b/x-pack/solutions/observability/plugins/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx index c922b695d2c19..6aa717dd294e8 100644 --- a/x-pack/solutions/observability/plugins/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx @@ -8,7 +8,6 @@ import { GetSLOResponse } from '@kbn/slo-schema'; import React from 'react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; -import type { ConfigSchema as AiopsConfigSchema } from '@kbn/aiops-plugin/server'; import { LogRateAnalysisPanel } from './log_rate_analysis_panel'; import { BurnRateAlert, BurnRateRule } from '../../../types'; import { useLicense } from '../../../../../hooks/use_license'; @@ -24,8 +23,7 @@ export function CustomKqlPanels({ slo, alert, rule }: Props) { const { services: { application }, } = useKibana(); - const aiopsCapabilities: AiopsConfigSchema | undefined = application?.capabilities.aiops; - const aiopsEnabled = aiopsCapabilities?.ui?.enabled ?? false; + const aiopsEnabled = application?.capabilities.aiops.enabled ?? false; const hasLicenseForLogRateAnalysis = hasAtLeast('platinum'); return hasLicenseForLogRateAnalysis && aiopsEnabled ? ( From 4c24a8a14020b5f980b2fde836a82bd0f236ca8c Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Tue, 27 May 2025 14:57:28 +0100 Subject: [PATCH 12/20] reverting auto lint change --- .../alert_details_app_section/alert_details_app_section.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx b/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx index 87f8aeb8da8e0..0a4c39fdf1284 100644 --- a/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx +++ b/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx @@ -175,7 +175,7 @@ export default function AlertDetailsAppSection({ alert }: AppSectionProps) { - + Date: Tue, 27 May 2025 15:00:23 +0100 Subject: [PATCH 13/20] reverting auto linting change --- .../observability/plugins/observability/kibana.jsonc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/solutions/observability/plugins/observability/kibana.jsonc b/x-pack/solutions/observability/plugins/observability/kibana.jsonc index e83a03dadd23d..90be2bfe751ce 100644 --- a/x-pack/solutions/observability/plugins/observability/kibana.jsonc +++ b/x-pack/solutions/observability/plugins/observability/kibana.jsonc @@ -32,14 +32,12 @@ "features", "files", "inspector", - "lens", "observabilityShared", "ruleRegistry", "triggersActionsUi", "security", "share", "unifiedSearch", - "visualizations", "dashboard", "expressions", "logsShared", @@ -50,6 +48,7 @@ "optionalPlugins": [ "discover", "home", + "lens", "usageCollection", "cloud", "spaces", @@ -57,7 +56,8 @@ "guidedOnboarding", "observabilityAIAssistant", "investigate", - "streams" + "streams", + "visualizations" ], "requiredBundles": [ "data", From 800f5ecc5e1d805bc5620a92255d616c2d35af47 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Tue, 27 May 2025 15:02:58 +0100 Subject: [PATCH 14/20] reverting auto linting change --- .../observability/plugins/observability/kibana.jsonc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/solutions/observability/plugins/observability/kibana.jsonc b/x-pack/solutions/observability/plugins/observability/kibana.jsonc index 90be2bfe751ce..4a83799bfdb6e 100644 --- a/x-pack/solutions/observability/plugins/observability/kibana.jsonc +++ b/x-pack/solutions/observability/plugins/observability/kibana.jsonc @@ -32,12 +32,14 @@ "features", "files", "inspector", + "lens", "observabilityShared", "ruleRegistry", "triggersActionsUi", "security", "share", "unifiedSearch", + "visualizations", "dashboard", "expressions", "logsShared", @@ -48,7 +50,6 @@ "optionalPlugins": [ "discover", "home", - "lens", "usageCollection", "cloud", "spaces", @@ -56,8 +57,7 @@ "guidedOnboarding", "observabilityAIAssistant", "investigate", - "streams", - "visualizations" + "streams" ], "requiredBundles": [ "data", @@ -72,4 +72,4 @@ "common" ] } -} +} \ No newline at end of file From e4f20d2125035963d45a49c10e0dd7b52266d3cd Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Tue, 27 May 2025 17:23:16 +0100 Subject: [PATCH 15/20] fixing discover check --- .../log_categorization/log_categorization_enabled.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/x-pack/platform/plugins/shared/aiops/public/components/log_categorization/log_categorization_enabled.ts b/x-pack/platform/plugins/shared/aiops/public/components/log_categorization/log_categorization_enabled.ts index e1e5d649e93f8..cd8e88bc7ccd7 100644 --- a/x-pack/platform/plugins/shared/aiops/public/components/log_categorization/log_categorization_enabled.ts +++ b/x-pack/platform/plugins/shared/aiops/public/components/log_categorization/log_categorization_enabled.ts @@ -10,7 +10,6 @@ import type { DataView } from '@kbn/data-views-plugin/public'; import { ES_FIELD_TYPES } from '@kbn/field-types'; import type { LicensingPluginStart } from '@kbn/licensing-plugin/public'; import { firstValueFrom } from 'rxjs'; -import type { ConfigSchema } from '../../../server'; export function getPatternAnalysisAvailable( licensing: LicensingPluginStart, @@ -19,8 +18,7 @@ export function getPatternAnalysisAvailable( const lic = firstValueFrom(licensing.license$); return async (dataView: DataView) => { const isPlatinum = (await lic).hasAtLeast('platinum'); - const aiopsCapabilities: ConfigSchema = application.capabilities.aiops; - const aiopsEnabled = aiopsCapabilities?.ui?.enabled; + const aiopsEnabled = application.capabilities.aiops.enabled; if (!aiopsEnabled) { return false; } From 4b064894ffc89035ab1ddb5470ec014b21ccc00a Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Tue, 27 May 2025 19:36:19 +0100 Subject: [PATCH 16/20] improving capabilities check --- .../components/alert_details_app_section/index.tsx | 2 +- .../alert_details_app_section/alert_details_app_section.tsx | 4 ++-- .../components/custom_panels/custom_kql/custom_kql_panels.tsx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx b/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx index 8117cefc6cf23..f8a9840b174a5 100644 --- a/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx +++ b/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx @@ -68,7 +68,7 @@ const AlertDetailsAppSection = ({ rule, alert }: AlertDetailsAppSectionProps) => const { hasAtLeast } = useLicense(); const hasLicenseForLogRateAnalysis = hasAtLeast('platinum'); - const aiopsEnabled = application?.capabilities.aiops.enabled ?? false; + const aiopsEnabled = application?.capabilities.aiops?.enabled ?? false; const getLogRatioChart = () => { if (isRatioRule(rule.params.criteria)) { diff --git a/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx b/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx index 0a4c39fdf1284..dd8e865cd21c4 100644 --- a/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx +++ b/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx @@ -67,7 +67,7 @@ export default function AlertDetailsAppSection({ alert }: AppSectionProps) { const { hasAtLeast } = useLicense(); const { euiTheme } = useEuiTheme(); const hasLogRateAnalysisLicense = hasAtLeast('platinum'); - const aiopsEnabled = application.capabilities.aiops.enabled; + const aiopsEnabled = application.capabilities.aiops?.enabled ?? false; const [dataView, setDataView] = useState(); const [, setDataViewError] = useState(); const [timeRange, setTimeRange] = useState({ from: 'now-15m', to: 'now' }); @@ -175,7 +175,7 @@ export default function AlertDetailsAppSection({ alert }: AppSectionProps) { - + From 2f62bafb0b633cfa95d19528dd40d15d5f479dd8 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Wed, 28 May 2025 13:00:10 +0100 Subject: [PATCH 17/20] fixing aiops links in ml --- x-pack/platform/plugins/shared/aiops/public/plugin.tsx | 3 ++- .../application/components/anomalies_table/links_menu.tsx | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/x-pack/platform/plugins/shared/aiops/public/plugin.tsx b/x-pack/platform/plugins/shared/aiops/public/plugin.tsx index 84d1e786ea1b0..e1dd924a6003e 100755 --- a/x-pack/platform/plugins/shared/aiops/public/plugin.tsx +++ b/x-pack/platform/plugins/shared/aiops/public/plugin.tsx @@ -33,8 +33,9 @@ export class AiopsPlugin Promise.all([firstValueFrom(licensing.license$), core.getStartServices()]).then( ([license, [coreStart, pluginStart]]) => { const { canUseAiops } = coreStart.application.capabilities.ml; + const aiopsEnabled = coreStart.application.capabilities.aiops.enabled; - if (license.hasAtLeast('platinum') && canUseAiops) { + if (license.hasAtLeast('platinum') && canUseAiops && aiopsEnabled) { if (embeddable) { registerEmbeddables(embeddable, core); } diff --git a/x-pack/platform/plugins/shared/ml/public/application/components/anomalies_table/links_menu.tsx b/x-pack/platform/plugins/shared/ml/public/application/components/anomalies_table/links_menu.tsx index 927e2a7ec87c9..0bcd21c5909bc 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/components/anomalies_table/links_menu.tsx +++ b/x-pack/platform/plugins/shared/ml/public/application/components/anomalies_table/links_menu.tsx @@ -765,7 +765,7 @@ export const LinksMenuUI = (props: LinksMenuProps) => { }; const { anomaly, showViewSeriesLink } = props; - const canUpdateJob = usePermissionCheck('canUpdateJob'); + const [canUpdateJob, canUseAiops] = usePermissionCheck(['canUpdateJob', 'canUseAiops']); const canConfigureRules = isRuleSupported(anomaly.source) && canUpdateJob; const contextMenuItems = useMemo(() => { @@ -929,7 +929,7 @@ export const LinksMenuUI = (props: LinksMenuProps) => { ); } - if (openInLogRateAnalysisUrl) { + if (openInLogRateAnalysisUrl && canUseAiops) { items.push( { ); } - if (messageField !== null) { + if (messageField !== null && canUseAiops) { items.push( Date: Wed, 28 May 2025 13:01:57 +0100 Subject: [PATCH 18/20] reverting auto lint change --- .../alert_details_app_section/alert_details_app_section.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx b/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx index dd8e865cd21c4..b34b88aac28e2 100644 --- a/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx +++ b/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx @@ -175,7 +175,7 @@ export default function AlertDetailsAppSection({ alert }: AppSectionProps) { - + Date: Fri, 30 May 2025 13:55:43 +0100 Subject: [PATCH 19/20] adding license check to switcher --- .../discover/public/__mocks__/services.ts | 1 - .../view_mode_toggle.test.tsx | 5 --- .../view_mode_toggle/view_mode_toggle.tsx | 39 ++--------------- .../log_categorization_enabled.ts | 32 -------------- .../plugins/shared/aiops/public/plugin.tsx | 42 +++++++------------ .../shared/aiops/public/types/index.ts | 2 - .../shared/aiops/server/lib/capabilities.ts | 16 +++++-- .../plugins/shared/aiops/server/types.ts | 3 +- .../alert_details_app_section/index.tsx | 7 +--- .../alert_details_app_section.tsx | 9 +--- .../custom_kql/custom_kql_panels.tsx | 7 +--- 11 files changed, 36 insertions(+), 127 deletions(-) delete mode 100644 x-pack/platform/plugins/shared/aiops/public/components/log_categorization/log_categorization_enabled.ts diff --git a/src/platform/plugins/shared/discover/public/__mocks__/services.ts b/src/platform/plugins/shared/discover/public/__mocks__/services.ts index f67c46f6d6944..10d0237887c02 100644 --- a/src/platform/plugins/shared/discover/public/__mocks__/services.ts +++ b/src/platform/plugins/shared/discover/public/__mocks__/services.ts @@ -172,7 +172,6 @@ export function createDiscoverServicesMock(): DiscoverServices { FieldStatisticsTable: jest.fn(() => createElement('div')), }, aiops: { - getPatternAnalysisAvailable: jest.fn().mockResolvedValue(jest.fn().mockResolvedValue(true)), PatternAnalysisComponent: jest.fn(() => createElement('div')), }, docLinks: docLinksServiceMock.createStartContract(), diff --git a/src/platform/plugins/shared/discover/public/components/view_mode_toggle/view_mode_toggle.test.tsx b/src/platform/plugins/shared/discover/public/components/view_mode_toggle/view_mode_toggle.test.tsx index c118a075975b0..c64047ab6cb74 100644 --- a/src/platform/plugins/shared/discover/public/components/view_mode_toggle/view_mode_toggle.test.tsx +++ b/src/platform/plugins/shared/discover/public/components/view_mode_toggle/view_mode_toggle.test.tsx @@ -36,11 +36,6 @@ describe('Document view mode toggle component', () => { uiSettings: { get: () => showFieldStatistics, }, - aiops: { - getPatternAnalysisAvailable: jest - .fn() - .mockResolvedValue(jest.fn().mockResolvedValue(useDataViewWithTextFields)), - }, }; const dataViewWithTextFields = { diff --git a/src/platform/plugins/shared/discover/public/components/view_mode_toggle/view_mode_toggle.tsx b/src/platform/plugins/shared/discover/public/components/view_mode_toggle/view_mode_toggle.tsx index 5b77a184d9253..65ad3c8f5c49c 100644 --- a/src/platform/plugins/shared/discover/public/components/view_mode_toggle/view_mode_toggle.tsx +++ b/src/platform/plugins/shared/discover/public/components/view_mode_toggle/view_mode_toggle.tsx @@ -7,13 +7,12 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import React, { useMemo, useEffect, useState, type ReactElement, useCallback } from 'react'; +import React, { useMemo, useEffect, type ReactElement } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiTab, EuiTabs, useEuiTheme } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { css } from '@emotion/react'; import { SHOW_FIELD_STATISTICS } from '@kbn/discover-utils'; import type { DataView } from '@kbn/data-views-plugin/common'; -import useMountedState from 'react-use/lib/useMountedState'; import { VIEW_MODE } from '../../../common/constants'; import { useDiscoverServices } from '../../hooks/use_discover_services'; import type { DiscoverStateContainer } from '../../application/main/state_management/discover_state'; @@ -37,13 +36,9 @@ export const DocumentViewModeToggle = ({ dataView: DataView; }) => { const { euiTheme } = useEuiTheme(); - const { - uiSettings, - dataVisualizer: dataVisualizerService, - aiops: aiopsService, - } = useDiscoverServices(); + const { uiSettings, dataVisualizer: dataVisualizerService, application } = useDiscoverServices(); - const [showPatternAnalysisTab, setShowPatternAnalysisTab] = useState(null); + const showPatternAnalysisTab = application.capabilities.aiops?.enabled ?? false; const showFieldStatisticsTab = useMemo( () => // If user opens saved search with field stats in ES|QL, @@ -53,34 +48,6 @@ export const DocumentViewModeToggle = ({ (!isEsqlMode && uiSettings.get(SHOW_FIELD_STATISTICS) && dataVisualizerService !== undefined), [dataVisualizerService, uiSettings, isEsqlMode, viewMode] ); - const isMounted = useMountedState(); - - const setShowPatternAnalysisTabWrapper = useCallback( - (value: boolean) => { - if (isMounted()) { - setShowPatternAnalysisTab(value); - } - }, - [isMounted] - ); - - useEffect( - function checkForPatternAnalysis() { - if (!aiopsService || isEsqlMode) { - setShowPatternAnalysisTab(false); - return; - } - aiopsService - .getPatternAnalysisAvailable() - .then((patternAnalysisAvailable) => { - patternAnalysisAvailable(dataView) - .then(setShowPatternAnalysisTabWrapper) - .catch(() => setShowPatternAnalysisTabWrapper(false)); - }) - .catch(() => setShowPatternAnalysisTabWrapper(false)); - }, - [aiopsService, dataView, isEsqlMode, setShowPatternAnalysisTabWrapper] - ); useEffect(() => { if (showPatternAnalysisTab === false && viewMode === VIEW_MODE.PATTERN_LEVEL) { diff --git a/x-pack/platform/plugins/shared/aiops/public/components/log_categorization/log_categorization_enabled.ts b/x-pack/platform/plugins/shared/aiops/public/components/log_categorization/log_categorization_enabled.ts deleted file mode 100644 index cd8e88bc7ccd7..0000000000000 --- a/x-pack/platform/plugins/shared/aiops/public/components/log_categorization/log_categorization_enabled.ts +++ /dev/null @@ -1,32 +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 { ApplicationStart } from '@kbn/core/public'; -import type { DataView } from '@kbn/data-views-plugin/public'; -import { ES_FIELD_TYPES } from '@kbn/field-types'; -import type { LicensingPluginStart } from '@kbn/licensing-plugin/public'; -import { firstValueFrom } from 'rxjs'; - -export function getPatternAnalysisAvailable( - licensing: LicensingPluginStart, - application: ApplicationStart -) { - const lic = firstValueFrom(licensing.license$); - return async (dataView: DataView) => { - const isPlatinum = (await lic).hasAtLeast('platinum'); - const aiopsEnabled = application.capabilities.aiops.enabled; - if (!aiopsEnabled) { - return false; - } - - return ( - isPlatinum && - dataView.isTimeBased() && - dataView.fields.some((f) => f.esTypes?.includes(ES_FIELD_TYPES.TEXT)) - ); - }; -} diff --git a/x-pack/platform/plugins/shared/aiops/public/plugin.tsx b/x-pack/platform/plugins/shared/aiops/public/plugin.tsx index e1dd924a6003e..5fdbb99d3cb0d 100755 --- a/x-pack/platform/plugins/shared/aiops/public/plugin.tsx +++ b/x-pack/platform/plugins/shared/aiops/public/plugin.tsx @@ -7,7 +7,6 @@ import type { CoreStart, Plugin } from '@kbn/core/public'; import { type CoreSetup } from '@kbn/core/public'; -import { firstValueFrom } from 'rxjs'; import { getChangePointDetectionComponent } from './shared_components'; import { LogCategorizationForDiscover as PatternAnalysisComponent } from './shared_lazy_components'; @@ -26,41 +25,30 @@ export type AiopsCoreSetup = CoreSetup; export class AiopsPlugin implements Plugin { - public setup( - core: AiopsCoreSetup, - { embeddable, cases, licensing, uiActions }: AiopsPluginSetupDeps - ) { - Promise.all([firstValueFrom(licensing.license$), core.getStartServices()]).then( - ([license, [coreStart, pluginStart]]) => { - const { canUseAiops } = coreStart.application.capabilities.ml; - const aiopsEnabled = coreStart.application.capabilities.aiops.enabled; - - if (license.hasAtLeast('platinum') && canUseAiops && aiopsEnabled) { - if (embeddable) { - registerEmbeddables(embeddable, core); - } + public setup(core: AiopsCoreSetup, { embeddable, cases, uiActions }: AiopsPluginSetupDeps) { + core.getStartServices().then(([coreStart, pluginStart]) => { + const { canUseAiops } = coreStart.application.capabilities.ml; + const aiopsEnabled = coreStart.application.capabilities.aiops.enabled; + + if (canUseAiops && aiopsEnabled) { + if (embeddable) { + registerEmbeddables(embeddable, core); + } - if (uiActions) { - registerAiopsUiActions(uiActions, coreStart, pluginStart); - } + if (uiActions) { + registerAiopsUiActions(uiActions, coreStart, pluginStart); + } - if (cases) { - registerCases(cases, coreStart, pluginStart); - } + if (cases) { + registerCases(cases, coreStart, pluginStart); } } - ); + }); } public start(core: CoreStart, plugins: AiopsPluginStartDeps): AiopsPluginStart { return { ChangePointDetectionComponent: getChangePointDetectionComponent(core, plugins), - getPatternAnalysisAvailable: async () => { - const { getPatternAnalysisAvailable } = await import( - './components/log_categorization/log_categorization_enabled' - ); - return getPatternAnalysisAvailable(plugins.licensing, core.application); - }, PatternAnalysisComponent, }; } diff --git a/x-pack/platform/plugins/shared/aiops/public/types/index.ts b/x-pack/platform/plugins/shared/aiops/public/types/index.ts index 561c91b178eac..93fe400f6bd69 100644 --- a/x-pack/platform/plugins/shared/aiops/public/types/index.ts +++ b/x-pack/platform/plugins/shared/aiops/public/types/index.ts @@ -19,7 +19,6 @@ import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/ import type { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public'; import type { CasesPublicSetup } from '@kbn/cases-plugin/public'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; -import type { DataView } from '@kbn/data-views-plugin/public'; import type { ChangePointDetectionSharedComponent } from '../shared_components'; import type { LogCategorizationEmbeddableWrapperProps } from '../components/log_categorization/log_categorization_for_embeddable/log_categorization_for_discover_wrapper'; @@ -50,7 +49,6 @@ export interface AiopsPluginStartDeps { export type AiopsPluginSetup = void; export interface AiopsPluginStart { - getPatternAnalysisAvailable: () => Promise<(dataView: DataView) => Promise>; PatternAnalysisComponent: React.ComponentType; ChangePointDetectionComponent: ChangePointDetectionSharedComponent; } diff --git a/x-pack/platform/plugins/shared/aiops/server/lib/capabilities.ts b/x-pack/platform/plugins/shared/aiops/server/lib/capabilities.ts index 826b9bc244d81..2f3c099d0c7e4 100644 --- a/x-pack/platform/plugins/shared/aiops/server/lib/capabilities.ts +++ b/x-pack/platform/plugins/shared/aiops/server/lib/capabilities.ts @@ -6,12 +6,10 @@ */ import type { CoreSetup } from '@kbn/core/server'; +import { firstValueFrom } from 'rxjs'; import type { AiopsPluginStartDeps } from '../types'; -export const setupCapabilities = ( - core: Pick, 'capabilities' | 'getStartServices'>, - enabled: boolean -) => { +export const setupCapabilities = (core: CoreSetup, enabled: boolean) => { core.capabilities.registerProvider(() => { return { aiops: { @@ -22,6 +20,16 @@ export const setupCapabilities = ( core.capabilities.registerSwitcher( async (request, capabilities, useDefaultCapabilities) => { + const [, { licensing }] = await core.getStartServices(); + const lic = await firstValueFrom(licensing.license$); + if (lic.hasAtLeast('platinum') === false) { + return { + aiops: { + enabled: false, + }, + }; + } + return {}; }, { diff --git a/x-pack/platform/plugins/shared/aiops/server/types.ts b/x-pack/platform/plugins/shared/aiops/server/types.ts index 58a2103d33a33..842df9243bcb3 100755 --- a/x-pack/platform/plugins/shared/aiops/server/types.ts +++ b/x-pack/platform/plugins/shared/aiops/server/types.ts @@ -6,7 +6,7 @@ */ import type { PluginSetup, PluginStart } from '@kbn/data-plugin/server'; -import type { LicensingPluginSetup } from '@kbn/licensing-plugin/server'; +import type { LicensingPluginSetup, LicensingPluginStart } from '@kbn/licensing-plugin/server'; import type { CasesServerSetup } from '@kbn/cases-plugin/server'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; @@ -19,6 +19,7 @@ export interface AiopsPluginSetupDeps { export interface AiopsPluginStartDeps { data: PluginStart; + licensing: LicensingPluginStart; } /** diff --git a/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx b/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx index f8a9840b174a5..60f272682135e 100644 --- a/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx +++ b/x-pack/solutions/observability/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx @@ -33,7 +33,6 @@ import type { AlertDetailsAppSectionProps } from './types'; import { Threshold } from '../../../common/components/threshold'; import { LogRateAnalysis } from './components/log_rate_analysis'; import { LogThresholdCountChart, LogThresholdRatioChart } from './components/threhsold_chart'; -import { useLicense } from '../../../../hooks/use_license'; const formatThreshold = (threshold: number) => String(threshold); @@ -66,8 +65,6 @@ const AlertDetailsAppSection = ({ rule, alert }: AlertDetailsAppSectionProps) => logViews: logsShared.logViews.client, }); - const { hasAtLeast } = useLicense(); - const hasLicenseForLogRateAnalysis = hasAtLeast('platinum'); const aiopsEnabled = application?.capabilities.aiops?.enabled ?? false; const getLogRatioChart = () => { @@ -196,9 +193,7 @@ const AlertDetailsAppSection = ({ rule, alert }: AlertDetailsAppSectionProps) => }; const getLogRateAnalysisSection = () => { - return hasLicenseForLogRateAnalysis && aiopsEnabled ? ( - - ) : null; + return aiopsEnabled ? : null; }; return ( diff --git a/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx b/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx index b34b88aac28e2..cc0f148784d35 100644 --- a/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx +++ b/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx @@ -38,7 +38,6 @@ import moment from 'moment'; import { DISCOVER_APP_LOCATOR, DiscoverAppLocatorParams } from '@kbn/discover-plugin/common'; import { TimeRange } from '@kbn/es-query'; import { getGroupFilters } from '../../../../../common/custom_threshold_rule/helpers/get_group'; -import { useLicense } from '../../../../hooks/use_license'; import { useKibana } from '../../../../utils/kibana_react'; import { metricValueFormatter } from '../../../../../common/custom_threshold_rule/metric_value_formatter'; import { Threshold } from '../threshold'; @@ -64,9 +63,7 @@ export default function AlertDetailsAppSection({ alert }: AppSectionProps) { url: { locators }, }, } = services; - const { hasAtLeast } = useLicense(); const { euiTheme } = useEuiTheme(); - const hasLogRateAnalysisLicense = hasAtLeast('platinum'); const aiopsEnabled = application.capabilities.aiops?.enabled ?? false; const [dataView, setDataView] = useState(); const [, setDataViewError] = useState(); @@ -175,7 +172,7 @@ export default function AlertDetailsAppSection({ alert }: AppSectionProps) { - + ); })} - {hasLogRateAnalysisLicense && aiopsEnabled && ( - - )} + {aiopsEnabled && } ); } diff --git a/x-pack/solutions/observability/plugins/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx b/x-pack/solutions/observability/plugins/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx index b30399d2d0bfc..0ca39ecce2012 100644 --- a/x-pack/solutions/observability/plugins/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/components/alert_details/components/custom_panels/custom_kql/custom_kql_panels.tsx @@ -10,7 +10,6 @@ import React from 'react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { LogRateAnalysisPanel } from './log_rate_analysis_panel'; import { BurnRateAlert, BurnRateRule } from '../../../types'; -import { useLicense } from '../../../../../hooks/use_license'; interface Props { slo: GetSLOResponse; @@ -19,13 +18,9 @@ interface Props { } export function CustomKqlPanels({ slo, alert, rule }: Props) { - const { hasAtLeast } = useLicense(); const { services: { application }, } = useKibana(); const aiopsEnabled = application?.capabilities.aiops?.enabled ?? false; - const hasLicenseForLogRateAnalysis = hasAtLeast('platinum'); - return hasLicenseForLogRateAnalysis && aiopsEnabled ? ( - - ) : null; + return aiopsEnabled ? : null; } From e650afeb265d90f6c46fa60236a25e6cb17c22ae Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Fri, 30 May 2025 16:24:59 +0100 Subject: [PATCH 20/20] reinstating getPatternAnalysisAvailable --- .../discover/public/__mocks__/services.ts | 1 + .../view_mode_toggle.test.tsx | 5 +++ .../view_mode_toggle/view_mode_toggle.tsx | 38 +++++++++++++++++-- .../log_categorization_enabled.ts | 24 ++++++++++++ .../plugins/shared/aiops/public/plugin.tsx | 6 +++ .../shared/aiops/public/types/index.ts | 2 + 6 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 x-pack/platform/plugins/shared/aiops/public/components/log_categorization/log_categorization_enabled.ts diff --git a/src/platform/plugins/shared/discover/public/__mocks__/services.ts b/src/platform/plugins/shared/discover/public/__mocks__/services.ts index 10d0237887c02..73e55a6f07104 100644 --- a/src/platform/plugins/shared/discover/public/__mocks__/services.ts +++ b/src/platform/plugins/shared/discover/public/__mocks__/services.ts @@ -172,6 +172,7 @@ export function createDiscoverServicesMock(): DiscoverServices { FieldStatisticsTable: jest.fn(() => createElement('div')), }, aiops: { + getPatternAnalysisAvailable: jest.fn().mockResolvedValue(jest.fn(() => true)), PatternAnalysisComponent: jest.fn(() => createElement('div')), }, docLinks: docLinksServiceMock.createStartContract(), diff --git a/src/platform/plugins/shared/discover/public/components/view_mode_toggle/view_mode_toggle.test.tsx b/src/platform/plugins/shared/discover/public/components/view_mode_toggle/view_mode_toggle.test.tsx index c64047ab6cb74..d576678c15192 100644 --- a/src/platform/plugins/shared/discover/public/components/view_mode_toggle/view_mode_toggle.test.tsx +++ b/src/platform/plugins/shared/discover/public/components/view_mode_toggle/view_mode_toggle.test.tsx @@ -36,6 +36,11 @@ describe('Document view mode toggle component', () => { uiSettings: { get: () => showFieldStatistics, }, + aiops: { + getPatternAnalysisAvailable: jest + .fn() + .mockResolvedValue(jest.fn(() => useDataViewWithTextFields)), + }, }; const dataViewWithTextFields = { diff --git a/src/platform/plugins/shared/discover/public/components/view_mode_toggle/view_mode_toggle.tsx b/src/platform/plugins/shared/discover/public/components/view_mode_toggle/view_mode_toggle.tsx index 65ad3c8f5c49c..d9baa1d1db63b 100644 --- a/src/platform/plugins/shared/discover/public/components/view_mode_toggle/view_mode_toggle.tsx +++ b/src/platform/plugins/shared/discover/public/components/view_mode_toggle/view_mode_toggle.tsx @@ -7,12 +7,13 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import React, { useMemo, useEffect, type ReactElement } from 'react'; +import React, { useMemo, useEffect, useState, type ReactElement, useCallback } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiTab, EuiTabs, useEuiTheme } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { css } from '@emotion/react'; import { SHOW_FIELD_STATISTICS } from '@kbn/discover-utils'; import type { DataView } from '@kbn/data-views-plugin/common'; +import useMountedState from 'react-use/lib/useMountedState'; import { VIEW_MODE } from '../../../common/constants'; import { useDiscoverServices } from '../../hooks/use_discover_services'; import type { DiscoverStateContainer } from '../../application/main/state_management/discover_state'; @@ -36,9 +37,13 @@ export const DocumentViewModeToggle = ({ dataView: DataView; }) => { const { euiTheme } = useEuiTheme(); - const { uiSettings, dataVisualizer: dataVisualizerService, application } = useDiscoverServices(); + const { + uiSettings, + dataVisualizer: dataVisualizerService, + aiops: aiopsService, + } = useDiscoverServices(); - const showPatternAnalysisTab = application.capabilities.aiops?.enabled ?? false; + const [showPatternAnalysisTab, setShowPatternAnalysisTab] = useState(null); const showFieldStatisticsTab = useMemo( () => // If user opens saved search with field stats in ES|QL, @@ -48,6 +53,33 @@ export const DocumentViewModeToggle = ({ (!isEsqlMode && uiSettings.get(SHOW_FIELD_STATISTICS) && dataVisualizerService !== undefined), [dataVisualizerService, uiSettings, isEsqlMode, viewMode] ); + const isMounted = useMountedState(); + + const setShowPatternAnalysisTabWrapper = useCallback( + (value: boolean) => { + if (isMounted()) { + setShowPatternAnalysisTab(value); + } + }, + [isMounted] + ); + + useEffect( + function checkForPatternAnalysis() { + if (!aiopsService || isEsqlMode) { + setShowPatternAnalysisTab(false); + return; + } + aiopsService + .getPatternAnalysisAvailable() + .then((patternAnalysisAvailable) => { + const available = patternAnalysisAvailable(dataView); + setShowPatternAnalysisTabWrapper(available); + }) + .catch(() => setShowPatternAnalysisTabWrapper(false)); + }, + [aiopsService, dataView, isEsqlMode, setShowPatternAnalysisTabWrapper] + ); useEffect(() => { if (showPatternAnalysisTab === false && viewMode === VIEW_MODE.PATTERN_LEVEL) { diff --git a/x-pack/platform/plugins/shared/aiops/public/components/log_categorization/log_categorization_enabled.ts b/x-pack/platform/plugins/shared/aiops/public/components/log_categorization/log_categorization_enabled.ts new file mode 100644 index 0000000000000..d33db8a1fab1e --- /dev/null +++ b/x-pack/platform/plugins/shared/aiops/public/components/log_categorization/log_categorization_enabled.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 { ApplicationStart } from '@kbn/core/public'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import { ES_FIELD_TYPES } from '@kbn/field-types'; + +export function getPatternAnalysisAvailable(application: ApplicationStart) { + return (dataView: DataView) => { + const aiopsEnabled = application.capabilities.aiops.enabled; + if (!aiopsEnabled) { + return false; + } + + return ( + dataView.isTimeBased() && + dataView.fields.some((f) => f.esTypes?.includes(ES_FIELD_TYPES.TEXT)) + ); + }; +} diff --git a/x-pack/platform/plugins/shared/aiops/public/plugin.tsx b/x-pack/platform/plugins/shared/aiops/public/plugin.tsx index 5fdbb99d3cb0d..846041f08fc87 100755 --- a/x-pack/platform/plugins/shared/aiops/public/plugin.tsx +++ b/x-pack/platform/plugins/shared/aiops/public/plugin.tsx @@ -49,6 +49,12 @@ export class AiopsPlugin public start(core: CoreStart, plugins: AiopsPluginStartDeps): AiopsPluginStart { return { ChangePointDetectionComponent: getChangePointDetectionComponent(core, plugins), + getPatternAnalysisAvailable: async () => { + const { getPatternAnalysisAvailable } = await import( + './components/log_categorization/log_categorization_enabled' + ); + return getPatternAnalysisAvailable(core.application); + }, PatternAnalysisComponent, }; } diff --git a/x-pack/platform/plugins/shared/aiops/public/types/index.ts b/x-pack/platform/plugins/shared/aiops/public/types/index.ts index 93fe400f6bd69..6b68904700d09 100644 --- a/x-pack/platform/plugins/shared/aiops/public/types/index.ts +++ b/x-pack/platform/plugins/shared/aiops/public/types/index.ts @@ -19,6 +19,7 @@ import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/ import type { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public'; import type { CasesPublicSetup } from '@kbn/cases-plugin/public'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; +import type { DataView } from '@kbn/data-views-plugin/public'; import type { ChangePointDetectionSharedComponent } from '../shared_components'; import type { LogCategorizationEmbeddableWrapperProps } from '../components/log_categorization/log_categorization_for_embeddable/log_categorization_for_discover_wrapper'; @@ -49,6 +50,7 @@ export interface AiopsPluginStartDeps { export type AiopsPluginSetup = void; export interface AiopsPluginStart { + getPatternAnalysisAvailable: () => Promise<(dataView: DataView) => boolean>; PatternAnalysisComponent: React.ComponentType; ChangePointDetectionComponent: ChangePointDetectionSharedComponent; }