diff --git a/src/platform/plugins/shared/discover/public/__mocks__/services.ts b/src/platform/plugins/shared/discover/public/__mocks__/services.ts index f67c46f6d6944..73e55a6f07104 100644 --- a/src/platform/plugins/shared/discover/public/__mocks__/services.ts +++ b/src/platform/plugins/shared/discover/public/__mocks__/services.ts @@ -172,7 +172,7 @@ export function createDiscoverServicesMock(): DiscoverServices { FieldStatisticsTable: jest.fn(() => createElement('div')), }, aiops: { - getPatternAnalysisAvailable: jest.fn().mockResolvedValue(jest.fn().mockResolvedValue(true)), + 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 c118a075975b0..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 @@ -39,7 +39,7 @@ describe('Document view mode toggle component', () => { aiops: { getPatternAnalysisAvailable: jest .fn() - .mockResolvedValue(jest.fn().mockResolvedValue(useDataViewWithTextFields)), + .mockResolvedValue(jest.fn(() => useDataViewWithTextFields)), }, }; 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..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 @@ -73,9 +73,8 @@ export const DocumentViewModeToggle = ({ aiopsService .getPatternAnalysisAvailable() .then((patternAnalysisAvailable) => { - patternAnalysisAvailable(dataView) - .then(setShowPatternAnalysisTabWrapper) - .catch(() => setShowPatternAnalysisTabWrapper(false)); + const available = patternAnalysisAvailable(dataView); + setShowPatternAnalysisTabWrapper(available); }) .catch(() => setShowPatternAnalysisTabWrapper(false)); }, 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/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..d33db8a1fab1e 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,17 +5,18 @@ * 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) { - const lic = firstValueFrom(licensing.license$); - return async (dataView: DataView) => { - const isPlatinum = (await lic).hasAtLeast('platinum'); +export function getPatternAnalysisAvailable(application: ApplicationStart) { + return (dataView: DataView) => { + 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 d8c3dfd4c3636..846041f08fc87 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,29 +25,25 @@ 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; - - if (license.hasAtLeast('platinum') && canUseAiops) { - 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 { @@ -58,7 +53,7 @@ export class AiopsPlugin const { getPatternAnalysisAvailable } = await import( './components/log_categorization/log_categorization_enabled' ); - return getPatternAnalysisAvailable(plugins.licensing); + 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 561c91b178eac..6b68904700d09 100644 --- a/x-pack/platform/plugins/shared/aiops/public/types/index.ts +++ b/x-pack/platform/plugins/shared/aiops/public/types/index.ts @@ -50,7 +50,7 @@ export interface AiopsPluginStartDeps { export type AiopsPluginSetup = void; export interface AiopsPluginStart { - getPatternAnalysisAvailable: () => Promise<(dataView: DataView) => Promise>; + getPatternAnalysisAvailable: () => Promise<(dataView: DataView) => boolean>; PatternAnalysisComponent: React.ComponentType; ChangePointDetectionComponent: ChangePointDetectionSharedComponent; } 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..1694d6d2c5e4a --- /dev/null +++ b/x-pack/platform/plugins/shared/aiops/server/config_schema.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; 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({ + ui: schema.maybe( + schema.object({ + enabled: schema.maybe(schema.boolean()), + }) + ), +}); + +export type ConfigSchema = TypeOf; + +export const config: PluginConfigDescriptor = { + schema: configSchema, +}; diff --git a/x-pack/platform/plugins/shared/aiops/server/index.ts b/x-pack/platform/plugins/shared/aiops/server/index.ts index dca8bed715650..a92dc37137ee0 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, type ConfigSchema } 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..2f3c099d0c7e4 --- /dev/null +++ b/x-pack/platform/plugins/shared/aiops/server/lib/capabilities.ts @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { CoreSetup } from '@kbn/core/server'; +import { firstValueFrom } from 'rxjs'; +import type { AiopsPluginStartDeps } from '../types'; + +export const setupCapabilities = (core: CoreSetup, enabled: boolean) => { + core.capabilities.registerProvider(() => { + return { + aiops: { + enabled, + }, + }; + }); + + 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 {}; + }, + { + 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..5ebb796f91d3b 100755 --- a/x-pack/platform/plugins/shared/aiops/server/plugin.ts +++ b/x-pack/platform/plugins/shared/aiops/server/plugin.ts @@ -29,6 +29,8 @@ 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'; +import { setupCapabilities } from './lib/capabilities'; export class AiopsPlugin implements Plugin @@ -36,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) { + 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`. 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/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/**/*", 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( 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..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 @@ -55,6 +55,10 @@ function getSwitcher( const originalCapabilities = capabilities.ml as MlCapabilities; const mlCaps = cloneDeep(originalCapabilities); + if (capabilities.aiops.enabled === false) { + 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/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..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 @@ -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, @@ -32,11 +33,13 @@ 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); 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]); @@ -62,8 +65,7 @@ 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 = () => { if (isRatioRule(rule.params.criteria)) { @@ -191,7 +193,7 @@ const AlertDetailsAppSection = ({ rule, alert }: AlertDetailsAppSectionProps) => }; const getLogRateAnalysisSection = () => { - return hasLicenseForLogRateAnalysis ? : 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 525959710d289..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'; @@ -59,13 +58,13 @@ export default function AlertDetailsAppSection({ alert }: AppSectionProps) { const { charts, data, + application, share: { 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(); const [timeRange, setTimeRange] = useState({ from: 'now-15m', to: 'now' }); @@ -173,7 +172,7 @@ export default function AlertDetailsAppSection({ alert }: AppSectionProps) { - + ); })} - {hasLogRateAnalysisLicense && ( - - )} + {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 1a75a30766423..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 @@ -7,9 +7,9 @@ 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'; interface Props { slo: GetSLOResponse; @@ -18,9 +18,9 @@ interface Props { } export function CustomKqlPanels({ slo, alert, rule }: Props) { - const { hasAtLeast } = useLicense(); - const hasLicenseForLogRateAnalysis = hasAtLeast('platinum'); - return hasLicenseForLogRateAnalysis ? ( - - ) : null; + const { + services: { application }, + } = useKibana(); + const aiopsEnabled = application?.capabilities.aiops?.enabled ?? false; + return aiopsEnabled ? : null; }