mirror of
https://github.com/elastic/kibana.git
synced 2025-06-28 03:01:21 -04:00
[ML] Removing global isServerless flag (#166651)
Removed `isServerless` flag which lived in our global context and had to be passed about to the various components which create their own version of the context using `getMlGlobalServices` This PR adds a new context which contains flags for all of the features which can be toggled when in serverless mode. Flags added: ``` showNodeInfo showMLNavMenu showLicenseInfo isADEnabled isDFAEnabled isNLPEnabled ``` The enabled features flags are now read from the config file client side, rather than using capabilities. Additional changes: - Changes the wording of the awaiting ML node callout in serverless. - In the search project, the default ML page is the trained models list and not Overview - Reenables the Memory Usage page for all projects --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
e522f0a178
commit
c18513e23d
76 changed files with 399 additions and 379 deletions
|
@ -258,6 +258,9 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
|
||||||
'xpack.license_management.ui.enabled (boolean)',
|
'xpack.license_management.ui.enabled (boolean)',
|
||||||
'xpack.maps.preserveDrawingBuffer (boolean)',
|
'xpack.maps.preserveDrawingBuffer (boolean)',
|
||||||
'xpack.maps.showMapsInspectorAdapter (boolean)',
|
'xpack.maps.showMapsInspectorAdapter (boolean)',
|
||||||
|
'xpack.ml.ad.enabled (boolean)',
|
||||||
|
'xpack.ml.dfa.enabled (boolean)',
|
||||||
|
'xpack.ml.nlp.enabled (boolean)',
|
||||||
'xpack.osquery.actionEnabled (boolean)',
|
'xpack.osquery.actionEnabled (boolean)',
|
||||||
'xpack.remote_clusters.ui.enabled (boolean)',
|
'xpack.remote_clusters.ui.enabled (boolean)',
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -72,10 +72,6 @@ export interface FullTimeRangeSelectorProps {
|
||||||
* @param value - The time field range response.
|
* @param value - The time field range response.
|
||||||
*/
|
*/
|
||||||
apiPath?: SetFullTimeRangeApiPath;
|
apiPath?: SetFullTimeRangeApiPath;
|
||||||
/**
|
|
||||||
* Optional flag to disable the frozen data tier choice.
|
|
||||||
*/
|
|
||||||
hideFrozenDataTierChoice?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,13 +92,12 @@ export const FullTimeRangeSelector: FC<FullTimeRangeSelectorProps> = (props) =>
|
||||||
disabled,
|
disabled,
|
||||||
callback,
|
callback,
|
||||||
apiPath,
|
apiPath,
|
||||||
hideFrozenDataTierChoice = false,
|
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
http,
|
http,
|
||||||
notifications: { toasts },
|
notifications: { toasts },
|
||||||
isServerless,
|
showFrozenDataTierChoice,
|
||||||
} = useDatePickerContext();
|
} = useDatePickerContext();
|
||||||
|
|
||||||
// wrapper around setFullTimeRange to allow for the calling of the optional callBack prop
|
// wrapper around setFullTimeRange to allow for the calling of the optional callBack prop
|
||||||
|
@ -114,9 +109,7 @@ export const FullTimeRangeSelector: FC<FullTimeRangeSelectorProps> = (props) =>
|
||||||
toasts,
|
toasts,
|
||||||
http,
|
http,
|
||||||
query,
|
query,
|
||||||
isServerless || hideFrozenDataTierChoice
|
showFrozenDataTierChoice ? frozenDataPreference === FROZEN_TIER_PREFERENCE.EXCLUDE : false,
|
||||||
? false
|
|
||||||
: frozenDataPreference === FROZEN_TIER_PREFERENCE.EXCLUDE,
|
|
||||||
apiPath
|
apiPath
|
||||||
);
|
);
|
||||||
if (typeof callback === 'function' && fullTimeRange !== undefined) {
|
if (typeof callback === 'function' && fullTimeRange !== undefined) {
|
||||||
|
@ -138,8 +131,7 @@ export const FullTimeRangeSelector: FC<FullTimeRangeSelectorProps> = (props) =>
|
||||||
toasts,
|
toasts,
|
||||||
http,
|
http,
|
||||||
query,
|
query,
|
||||||
isServerless,
|
showFrozenDataTierChoice,
|
||||||
hideFrozenDataTierChoice,
|
|
||||||
frozenDataPreference,
|
frozenDataPreference,
|
||||||
apiPath,
|
apiPath,
|
||||||
callback,
|
callback,
|
||||||
|
@ -230,7 +222,7 @@ export const FullTimeRangeSelector: FC<FullTimeRangeSelectorProps> = (props) =>
|
||||||
/>
|
/>
|
||||||
</EuiButton>
|
</EuiButton>
|
||||||
</EuiToolTip>
|
</EuiToolTip>
|
||||||
{isServerless || hideFrozenDataTierChoice ? null : (
|
{showFrozenDataTierChoice ? (
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
<EuiPopover
|
<EuiPopover
|
||||||
id={'mlFullTimeRangeSelectorOption'}
|
id={'mlFullTimeRangeSelectorOption'}
|
||||||
|
@ -256,7 +248,7 @@ export const FullTimeRangeSelector: FC<FullTimeRangeSelectorProps> = (props) =>
|
||||||
{popoverContent}
|
{popoverContent}
|
||||||
</EuiPopover>
|
</EuiPopover>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
)}
|
) : null}
|
||||||
</EuiFlexGroup>
|
</EuiFlexGroup>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,9 +45,9 @@ export interface DatePickerDependencies {
|
||||||
*/
|
*/
|
||||||
i18n: I18nStart;
|
i18n: I18nStart;
|
||||||
/**
|
/**
|
||||||
* Optional flag to indicate whether kibana is running in serverless
|
* Optional flag to disable the frozen data tier choice.
|
||||||
*/
|
*/
|
||||||
isServerless?: boolean;
|
showFrozenDataTierChoice?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -51,19 +51,19 @@ export interface ChangePointDetectionAppStateProps {
|
||||||
/** App dependencies */
|
/** App dependencies */
|
||||||
appDependencies: AiopsAppDependencies;
|
appDependencies: AiopsAppDependencies;
|
||||||
/** Optional flag to indicate whether kibana is running in serverless */
|
/** Optional flag to indicate whether kibana is running in serverless */
|
||||||
isServerless?: boolean;
|
showFrozenDataTierChoice?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ChangePointDetectionAppState: FC<ChangePointDetectionAppStateProps> = ({
|
export const ChangePointDetectionAppState: FC<ChangePointDetectionAppStateProps> = ({
|
||||||
dataView,
|
dataView,
|
||||||
savedSearch,
|
savedSearch,
|
||||||
appDependencies,
|
appDependencies,
|
||||||
isServerless = false,
|
showFrozenDataTierChoice = true,
|
||||||
}) => {
|
}) => {
|
||||||
const datePickerDeps: DatePickerDependencies = {
|
const datePickerDeps: DatePickerDependencies = {
|
||||||
...pick(appDependencies, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
|
...pick(appDependencies, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
|
||||||
uiSettingsKeys: UI_SETTINGS,
|
uiSettingsKeys: UI_SETTINGS,
|
||||||
isServerless,
|
showFrozenDataTierChoice,
|
||||||
};
|
};
|
||||||
|
|
||||||
const warning = timeSeriesDataViewWarning(dataView, 'change_point_detection');
|
const warning = timeSeriesDataViewWarning(dataView, 'change_point_detection');
|
||||||
|
|
|
@ -36,14 +36,14 @@ export interface LogCategorizationAppStateProps {
|
||||||
/** App dependencies */
|
/** App dependencies */
|
||||||
appDependencies: AiopsAppDependencies;
|
appDependencies: AiopsAppDependencies;
|
||||||
/** Optional flag to indicate whether kibana is running in serverless */
|
/** Optional flag to indicate whether kibana is running in serverless */
|
||||||
isServerless?: boolean;
|
showFrozenDataTierChoice?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LogCategorizationAppState: FC<LogCategorizationAppStateProps> = ({
|
export const LogCategorizationAppState: FC<LogCategorizationAppStateProps> = ({
|
||||||
dataView,
|
dataView,
|
||||||
savedSearch,
|
savedSearch,
|
||||||
appDependencies,
|
appDependencies,
|
||||||
isServerless = false,
|
showFrozenDataTierChoice = true,
|
||||||
}) => {
|
}) => {
|
||||||
if (!dataView) return null;
|
if (!dataView) return null;
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ export const LogCategorizationAppState: FC<LogCategorizationAppStateProps> = ({
|
||||||
const datePickerDeps: DatePickerDependencies = {
|
const datePickerDeps: DatePickerDependencies = {
|
||||||
...pick(appDependencies, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
|
...pick(appDependencies, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
|
||||||
uiSettingsKeys: UI_SETTINGS,
|
uiSettingsKeys: UI_SETTINGS,
|
||||||
isServerless,
|
showFrozenDataTierChoice,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -41,7 +41,7 @@ export interface LogRateAnalysisAppStateProps {
|
||||||
/** Option to make main histogram sticky */
|
/** Option to make main histogram sticky */
|
||||||
stickyHistogram?: boolean;
|
stickyHistogram?: boolean;
|
||||||
/** Optional flag to indicate whether kibana is running in serverless */
|
/** Optional flag to indicate whether kibana is running in serverless */
|
||||||
isServerless?: boolean;
|
showFrozenDataTierChoice?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LogRateAnalysisAppState: FC<LogRateAnalysisAppStateProps> = ({
|
export const LogRateAnalysisAppState: FC<LogRateAnalysisAppStateProps> = ({
|
||||||
|
@ -49,7 +49,7 @@ export const LogRateAnalysisAppState: FC<LogRateAnalysisAppStateProps> = ({
|
||||||
savedSearch,
|
savedSearch,
|
||||||
appDependencies,
|
appDependencies,
|
||||||
stickyHistogram,
|
stickyHistogram,
|
||||||
isServerless = false,
|
showFrozenDataTierChoice = true,
|
||||||
}) => {
|
}) => {
|
||||||
if (!dataView) return null;
|
if (!dataView) return null;
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ export const LogRateAnalysisAppState: FC<LogRateAnalysisAppStateProps> = ({
|
||||||
const datePickerDeps: DatePickerDependencies = {
|
const datePickerDeps: DatePickerDependencies = {
|
||||||
...pick(appDependencies, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
|
...pick(appDependencies, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
|
||||||
uiSettingsKeys: UI_SETTINGS,
|
uiSettingsKeys: UI_SETTINGS,
|
||||||
isServerless,
|
showFrozenDataTierChoice,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -58,7 +58,7 @@ export interface LogRateAnalysisContentWrapperProps {
|
||||||
*/
|
*/
|
||||||
onAnalysisCompleted?: (d: LogRateAnalysisResultsData) => void;
|
onAnalysisCompleted?: (d: LogRateAnalysisResultsData) => void;
|
||||||
/** Optional flag to indicate whether kibana is running in serverless */
|
/** Optional flag to indicate whether kibana is running in serverless */
|
||||||
isServerless?: boolean;
|
showFrozenDataTierChoice?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LogRateAnalysisContentWrapper: FC<LogRateAnalysisContentWrapperProps> = ({
|
export const LogRateAnalysisContentWrapper: FC<LogRateAnalysisContentWrapperProps> = ({
|
||||||
|
@ -72,7 +72,7 @@ export const LogRateAnalysisContentWrapper: FC<LogRateAnalysisContentWrapperProp
|
||||||
barColorOverride,
|
barColorOverride,
|
||||||
barHighlightColorOverride,
|
barHighlightColorOverride,
|
||||||
onAnalysisCompleted,
|
onAnalysisCompleted,
|
||||||
isServerless = false,
|
showFrozenDataTierChoice = true,
|
||||||
}) => {
|
}) => {
|
||||||
if (!dataView) return null;
|
if (!dataView) return null;
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ export const LogRateAnalysisContentWrapper: FC<LogRateAnalysisContentWrapperProp
|
||||||
const datePickerDeps = {
|
const datePickerDeps = {
|
||||||
...pick(appDependencies, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
|
...pick(appDependencies, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
|
||||||
uiSettingsKeys: UI_SETTINGS,
|
uiSettingsKeys: UI_SETTINGS,
|
||||||
|
showFrozenDataTierChoice,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -265,10 +265,13 @@ export const DataVisualizerStateContextProvider: FC<DataVisualizerStateContextPr
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
getAdditionalLinks?: GetAdditionalLinks;
|
getAdditionalLinks?: GetAdditionalLinks;
|
||||||
isServerless?: boolean;
|
showFrozenDataTierChoice?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IndexDataVisualizer: FC<Props> = ({ getAdditionalLinks, isServerless = false }) => {
|
export const IndexDataVisualizer: FC<Props> = ({
|
||||||
|
getAdditionalLinks,
|
||||||
|
showFrozenDataTierChoice = true,
|
||||||
|
}) => {
|
||||||
const coreStart = getCoreStart();
|
const coreStart = getCoreStart();
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
|
@ -302,7 +305,7 @@ export const IndexDataVisualizer: FC<Props> = ({ getAdditionalLinks, isServerles
|
||||||
const datePickerDeps: DatePickerDependencies = {
|
const datePickerDeps: DatePickerDependencies = {
|
||||||
...pick(services, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
|
...pick(services, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
|
||||||
uiSettingsKeys: UI_SETTINGS,
|
uiSettingsKeys: UI_SETTINGS,
|
||||||
isServerless,
|
showFrozenDataTierChoice,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -16,3 +16,23 @@ export const ML_APP_NAME = i18n.translate('xpack.ml.navMenu.mlAppNameText', {
|
||||||
export const ML_APP_ROUTE = '/app/ml';
|
export const ML_APP_ROUTE = '/app/ml';
|
||||||
export const ML_INTERNAL_BASE_PATH = '/internal/ml';
|
export const ML_INTERNAL_BASE_PATH = '/internal/ml';
|
||||||
export const ML_EXTERNAL_BASE_PATH = '/api/ml';
|
export const ML_EXTERNAL_BASE_PATH = '/api/ml';
|
||||||
|
|
||||||
|
export type MlFeatures = Record<'ad' | 'dfa' | 'nlp', boolean>;
|
||||||
|
|
||||||
|
export interface ConfigSchema {
|
||||||
|
ad?: { enabled: boolean };
|
||||||
|
dfa?: { enabled: boolean };
|
||||||
|
nlp?: { enabled: boolean };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initEnabledFeatures(enabledFeatures: MlFeatures, config: ConfigSchema) {
|
||||||
|
if (config.ad?.enabled !== undefined) {
|
||||||
|
enabledFeatures.ad = config.ad.enabled;
|
||||||
|
}
|
||||||
|
if (config.dfa?.enabled !== undefined) {
|
||||||
|
enabledFeatures.dfa = config.dfa.enabled;
|
||||||
|
}
|
||||||
|
if (config.nlp?.enabled !== undefined) {
|
||||||
|
enabledFeatures.nlp = config.nlp.enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -15,15 +15,16 @@ import { ChangePointDetection } from '@kbn/aiops-plugin/public';
|
||||||
|
|
||||||
import { useDataSource } from '../contexts/ml/data_source_context';
|
import { useDataSource } from '../contexts/ml/data_source_context';
|
||||||
import { useFieldStatsTrigger, FieldStatsFlyoutProvider } from '../components/field_stats_flyout';
|
import { useFieldStatsTrigger, FieldStatsFlyoutProvider } from '../components/field_stats_flyout';
|
||||||
import { useMlKibana, useIsServerless } from '../contexts/kibana';
|
import { useMlKibana } from '../contexts/kibana';
|
||||||
import { HelpMenu } from '../components/help_menu';
|
import { HelpMenu } from '../components/help_menu';
|
||||||
import { TechnicalPreviewBadge } from '../components/technical_preview_badge';
|
import { TechnicalPreviewBadge } from '../components/technical_preview_badge';
|
||||||
|
|
||||||
import { MlPageHeader } from '../components/page_header';
|
import { MlPageHeader } from '../components/page_header';
|
||||||
|
import { useEnabledFeatures } from '../contexts/ml/serverless_context';
|
||||||
|
|
||||||
export const ChangePointDetectionPage: FC = () => {
|
export const ChangePointDetectionPage: FC = () => {
|
||||||
const { services } = useMlKibana();
|
const { services } = useMlKibana();
|
||||||
const isServerless = useIsServerless();
|
const { showNodeInfo } = useEnabledFeatures();
|
||||||
|
|
||||||
const { selectedDataView: dataView, selectedSavedSearch: savedSearch } = useDataSource();
|
const { selectedDataView: dataView, selectedSavedSearch: savedSearch } = useDataSource();
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ export const ChangePointDetectionPage: FC = () => {
|
||||||
<ChangePointDetection
|
<ChangePointDetection
|
||||||
dataView={dataView}
|
dataView={dataView}
|
||||||
savedSearch={savedSearch}
|
savedSearch={savedSearch}
|
||||||
isServerless={isServerless}
|
showFrozenDataTierChoice={showNodeInfo}
|
||||||
appDependencies={{
|
appDependencies={{
|
||||||
...pick(services, [
|
...pick(services, [
|
||||||
'application',
|
'application',
|
||||||
|
|
|
@ -11,14 +11,15 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { LogCategorization } from '@kbn/aiops-plugin/public';
|
import { LogCategorization } from '@kbn/aiops-plugin/public';
|
||||||
import { useDataSource } from '../contexts/ml/data_source_context';
|
import { useDataSource } from '../contexts/ml/data_source_context';
|
||||||
import { useMlKibana, useIsServerless } from '../contexts/kibana';
|
import { useMlKibana } from '../contexts/kibana';
|
||||||
|
import { useEnabledFeatures } from '../contexts/ml';
|
||||||
import { HelpMenu } from '../components/help_menu';
|
import { HelpMenu } from '../components/help_menu';
|
||||||
import { TechnicalPreviewBadge } from '../components/technical_preview_badge';
|
import { TechnicalPreviewBadge } from '../components/technical_preview_badge';
|
||||||
import { MlPageHeader } from '../components/page_header';
|
import { MlPageHeader } from '../components/page_header';
|
||||||
|
|
||||||
export const LogCategorizationPage: FC = () => {
|
export const LogCategorizationPage: FC = () => {
|
||||||
const { services } = useMlKibana();
|
const { services } = useMlKibana();
|
||||||
const isServerless = useIsServerless();
|
const { showNodeInfo } = useEnabledFeatures();
|
||||||
|
|
||||||
const { selectedDataView: dataView, selectedSavedSearch: savedSearch } = useDataSource();
|
const { selectedDataView: dataView, selectedSavedSearch: savedSearch } = useDataSource();
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ export const LogCategorizationPage: FC = () => {
|
||||||
<LogCategorization
|
<LogCategorization
|
||||||
dataView={dataView}
|
dataView={dataView}
|
||||||
savedSearch={savedSearch}
|
savedSearch={savedSearch}
|
||||||
isServerless={isServerless}
|
showFrozenDataTierChoice={showNodeInfo}
|
||||||
appDependencies={pick(services, [
|
appDependencies={pick(services, [
|
||||||
'application',
|
'application',
|
||||||
'data',
|
'data',
|
||||||
|
|
|
@ -12,14 +12,15 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { LogRateAnalysis } from '@kbn/aiops-plugin/public';
|
import { LogRateAnalysis } from '@kbn/aiops-plugin/public';
|
||||||
import { useDataSource } from '../contexts/ml/data_source_context';
|
import { useDataSource } from '../contexts/ml/data_source_context';
|
||||||
import { useMlKibana, useIsServerless } from '../contexts/kibana';
|
import { useMlKibana } from '../contexts/kibana';
|
||||||
import { HelpMenu } from '../components/help_menu';
|
import { HelpMenu } from '../components/help_menu';
|
||||||
import { TechnicalPreviewBadge } from '../components/technical_preview_badge';
|
import { TechnicalPreviewBadge } from '../components/technical_preview_badge';
|
||||||
import { MlPageHeader } from '../components/page_header';
|
import { MlPageHeader } from '../components/page_header';
|
||||||
|
import { useEnabledFeatures } from '../contexts/ml';
|
||||||
|
|
||||||
export const LogRateAnalysisPage: FC = () => {
|
export const LogRateAnalysisPage: FC = () => {
|
||||||
const { services } = useMlKibana();
|
const { services } = useMlKibana();
|
||||||
const isServerless = useIsServerless();
|
const { showNodeInfo } = useEnabledFeatures();
|
||||||
|
|
||||||
const { selectedDataView: dataView, selectedSavedSearch: savedSearch } = useDataSource();
|
const { selectedDataView: dataView, selectedSavedSearch: savedSearch } = useDataSource();
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ export const LogRateAnalysisPage: FC = () => {
|
||||||
stickyHistogram={false}
|
stickyHistogram={false}
|
||||||
dataView={dataView}
|
dataView={dataView}
|
||||||
savedSearch={savedSearch}
|
savedSearch={savedSearch}
|
||||||
isServerless={isServerless}
|
showFrozenDataTierChoice={showNodeInfo}
|
||||||
appDependencies={pick(services, [
|
appDependencies={pick(services, [
|
||||||
'application',
|
'application',
|
||||||
'data',
|
'data',
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-pl
|
||||||
import { StorageContextProvider } from '@kbn/ml-local-storage';
|
import { StorageContextProvider } from '@kbn/ml-local-storage';
|
||||||
import useLifecycles from 'react-use/lib/useLifecycles';
|
import useLifecycles from 'react-use/lib/useLifecycles';
|
||||||
import useObservable from 'react-use/lib/useObservable';
|
import useObservable from 'react-use/lib/useObservable';
|
||||||
|
import type { MlFeatures } from '../../common/constants/app';
|
||||||
import { MlLicense } from '../../common/license';
|
import { MlLicense } from '../../common/license';
|
||||||
import { MlCapabilitiesService } from './capabilities/check_capabilities';
|
import { MlCapabilitiesService } from './capabilities/check_capabilities';
|
||||||
import { ML_STORAGE_KEYS } from '../../common/types/storage';
|
import { ML_STORAGE_KEYS } from '../../common/types/storage';
|
||||||
|
@ -30,6 +31,7 @@ import { MlRouter } from './routing';
|
||||||
import { mlApiServicesProvider } from './services/ml_api_service';
|
import { mlApiServicesProvider } from './services/ml_api_service';
|
||||||
import { HttpService } from './services/http_service';
|
import { HttpService } from './services/http_service';
|
||||||
import type { PageDependencies } from './routing/router';
|
import type { PageDependencies } from './routing/router';
|
||||||
|
import { EnabledFeaturesContextProvider } from './contexts/ml';
|
||||||
|
|
||||||
export type MlDependencies = Omit<
|
export type MlDependencies = Omit<
|
||||||
MlSetupDependencies,
|
MlSetupDependencies,
|
||||||
|
@ -42,6 +44,7 @@ interface AppProps {
|
||||||
deps: MlDependencies;
|
deps: MlDependencies;
|
||||||
appMountParams: AppMountParameters;
|
appMountParams: AppMountParameters;
|
||||||
isServerless: boolean;
|
isServerless: boolean;
|
||||||
|
mlFeatures: MlFeatures;
|
||||||
}
|
}
|
||||||
|
|
||||||
const localStorage = new Storage(window.localStorage);
|
const localStorage = new Storage(window.localStorage);
|
||||||
|
@ -49,11 +52,7 @@ const localStorage = new Storage(window.localStorage);
|
||||||
/**
|
/**
|
||||||
* Provides global services available across the entire ML app.
|
* Provides global services available across the entire ML app.
|
||||||
*/
|
*/
|
||||||
export function getMlGlobalServices(
|
export function getMlGlobalServices(httpStart: HttpStart, usageCollection?: UsageCollectionSetup) {
|
||||||
httpStart: HttpStart,
|
|
||||||
isServerless: boolean,
|
|
||||||
usageCollection?: UsageCollectionSetup
|
|
||||||
) {
|
|
||||||
const httpService = new HttpService(httpStart);
|
const httpService = new HttpService(httpStart);
|
||||||
const mlApiServices = mlApiServicesProvider(httpService);
|
const mlApiServices = mlApiServicesProvider(httpService);
|
||||||
|
|
||||||
|
@ -63,7 +62,6 @@ export function getMlGlobalServices(
|
||||||
mlUsageCollection: mlUsageCollectionProvider(usageCollection),
|
mlUsageCollection: mlUsageCollectionProvider(usageCollection),
|
||||||
mlCapabilities: new MlCapabilitiesService(mlApiServices),
|
mlCapabilities: new MlCapabilitiesService(mlApiServices),
|
||||||
mlLicense: new MlLicense(),
|
mlLicense: new MlLicense(),
|
||||||
isServerless,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +71,7 @@ export interface MlServicesContext {
|
||||||
|
|
||||||
export type MlGlobalServices = ReturnType<typeof getMlGlobalServices>;
|
export type MlGlobalServices = ReturnType<typeof getMlGlobalServices>;
|
||||||
|
|
||||||
const App: FC<AppProps> = ({ coreStart, deps, appMountParams, isServerless }) => {
|
const App: FC<AppProps> = ({ coreStart, deps, appMountParams, isServerless, mlFeatures }) => {
|
||||||
const pageDeps: PageDependencies = {
|
const pageDeps: PageDependencies = {
|
||||||
history: appMountParams.history,
|
history: appMountParams.history,
|
||||||
setHeaderActionMenu: appMountParams.setHeaderActionMenu,
|
setHeaderActionMenu: appMountParams.setHeaderActionMenu,
|
||||||
|
@ -106,9 +104,9 @@ const App: FC<AppProps> = ({ coreStart, deps, appMountParams, isServerless }) =>
|
||||||
contentManagement: deps.contentManagement,
|
contentManagement: deps.contentManagement,
|
||||||
presentationUtil: deps.presentationUtil,
|
presentationUtil: deps.presentationUtil,
|
||||||
...coreStart,
|
...coreStart,
|
||||||
mlServices: getMlGlobalServices(coreStart.http, isServerless, deps.usageCollection),
|
mlServices: getMlGlobalServices(coreStart.http, deps.usageCollection),
|
||||||
};
|
};
|
||||||
}, [deps, coreStart, isServerless]);
|
}, [deps, coreStart]);
|
||||||
|
|
||||||
useLifecycles(
|
useLifecycles(
|
||||||
function setupLicenseOnMount() {
|
function setupLicenseOnMount() {
|
||||||
|
@ -132,7 +130,7 @@ const App: FC<AppProps> = ({ coreStart, deps, appMountParams, isServerless }) =>
|
||||||
const datePickerDeps: DatePickerDependencies = {
|
const datePickerDeps: DatePickerDependencies = {
|
||||||
...pick(services, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
|
...pick(services, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
|
||||||
uiSettingsKeys: UI_SETTINGS,
|
uiSettingsKeys: UI_SETTINGS,
|
||||||
isServerless,
|
showFrozenDataTierChoice: !isServerless,
|
||||||
};
|
};
|
||||||
|
|
||||||
const I18nContext = coreStart.i18n.Context;
|
const I18nContext = coreStart.i18n.Context;
|
||||||
|
@ -146,7 +144,9 @@ const App: FC<AppProps> = ({ coreStart, deps, appMountParams, isServerless }) =>
|
||||||
<KibanaContextProvider services={services}>
|
<KibanaContextProvider services={services}>
|
||||||
<StorageContextProvider storage={localStorage} storageKeys={ML_STORAGE_KEYS}>
|
<StorageContextProvider storage={localStorage} storageKeys={ML_STORAGE_KEYS}>
|
||||||
<DatePickerContextProvider {...datePickerDeps}>
|
<DatePickerContextProvider {...datePickerDeps}>
|
||||||
|
<EnabledFeaturesContextProvider isServerless={isServerless} mlFeatures={mlFeatures}>
|
||||||
<MlRouter pageDeps={pageDeps} />
|
<MlRouter pageDeps={pageDeps} />
|
||||||
|
</EnabledFeaturesContextProvider>
|
||||||
</DatePickerContextProvider>
|
</DatePickerContextProvider>
|
||||||
</StorageContextProvider>
|
</StorageContextProvider>
|
||||||
</KibanaContextProvider>
|
</KibanaContextProvider>
|
||||||
|
@ -160,7 +160,8 @@ export const renderApp = (
|
||||||
coreStart: CoreStart,
|
coreStart: CoreStart,
|
||||||
deps: MlDependencies,
|
deps: MlDependencies,
|
||||||
appMountParams: AppMountParameters,
|
appMountParams: AppMountParameters,
|
||||||
isServerless: boolean
|
isServerless: boolean,
|
||||||
|
mlFeatures: MlFeatures
|
||||||
) => {
|
) => {
|
||||||
setDependencyCache({
|
setDependencyCache({
|
||||||
timefilter: deps.data.query.timefilter,
|
timefilter: deps.data.query.timefilter,
|
||||||
|
@ -194,6 +195,7 @@ export const renderApp = (
|
||||||
deps={deps}
|
deps={deps}
|
||||||
appMountParams={appMountParams}
|
appMountParams={appMountParams}
|
||||||
isServerless={isServerless}
|
isServerless={isServerless}
|
||||||
|
mlFeatures={mlFeatures}
|
||||||
/>,
|
/>,
|
||||||
appMountParams.element
|
appMountParams.element
|
||||||
);
|
);
|
||||||
|
|
|
@ -32,7 +32,7 @@ import { JobsExportService } from './jobs_export_service';
|
||||||
import type { JobDependencies } from './jobs_export_service';
|
import type { JobDependencies } from './jobs_export_service';
|
||||||
import { toastNotificationServiceProvider } from '../../../services/toast_notification_service';
|
import { toastNotificationServiceProvider } from '../../../services/toast_notification_service';
|
||||||
import type { JobType } from '../../../../../common/types/saved_objects';
|
import type { JobType } from '../../../../../common/types/saved_objects';
|
||||||
import { usePermissionCheck } from '../../../capabilities/check_capabilities';
|
import { useEnabledFeatures } from '../../../contexts/ml';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isDisabled: boolean;
|
isDisabled: boolean;
|
||||||
|
@ -68,7 +68,7 @@ export const ExportJobsFlyout: FC<Props> = ({ isDisabled, currentTab }) => {
|
||||||
() => toastNotificationServiceProvider(toasts),
|
() => toastNotificationServiceProvider(toasts),
|
||||||
[toasts]
|
[toasts]
|
||||||
);
|
);
|
||||||
const [isADEnabled, isDFAEnabled] = usePermissionCheck(['isADEnabled', 'isDFAEnabled']);
|
const { isADEnabled, isDFAEnabled } = useEnabledFeatures();
|
||||||
|
|
||||||
const [jobDependencies, setJobDependencies] = useState<JobDependencies>([]);
|
const [jobDependencies, setJobDependencies] = useState<JobDependencies>([]);
|
||||||
const [selectedJobDependencies, setSelectedJobDependencies] = useState<JobDependencies>([]);
|
const [selectedJobDependencies, setSelectedJobDependencies] = useState<JobDependencies>([]);
|
||||||
|
|
|
@ -40,7 +40,7 @@ import { toastNotificationServiceProvider } from '../../../services/toast_notifi
|
||||||
import { JobImportService } from './jobs_import_service';
|
import { JobImportService } from './jobs_import_service';
|
||||||
import { useValidateIds } from './validate';
|
import { useValidateIds } from './validate';
|
||||||
import type { ImportedAdJob, JobIdObject, SkippedJobs } from './jobs_import_service';
|
import type { ImportedAdJob, JobIdObject, SkippedJobs } from './jobs_import_service';
|
||||||
import { usePermissionCheck } from '../../../capabilities/check_capabilities';
|
import { useEnabledFeatures } from '../../../contexts/ml';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isDisabled: boolean;
|
isDisabled: boolean;
|
||||||
|
@ -82,7 +82,7 @@ export const ImportJobsFlyout: FC<Props> = ({ isDisabled }) => {
|
||||||
() => toastNotificationServiceProvider(toasts),
|
() => toastNotificationServiceProvider(toasts),
|
||||||
[toasts]
|
[toasts]
|
||||||
);
|
);
|
||||||
const [isADEnabled, isDFAEnabled] = usePermissionCheck(['isADEnabled', 'isDFAEnabled']);
|
const { isADEnabled, isDFAEnabled } = useEnabledFeatures();
|
||||||
|
|
||||||
const [validateIds] = useValidateIds(
|
const [validateIds] = useValidateIds(
|
||||||
jobType,
|
jobType,
|
||||||
|
|
|
@ -25,7 +25,7 @@ import { JobMessage } from '../../../../common/types/audit_message';
|
||||||
import { blurButtonOnClick } from '../../util/component_utils';
|
import { blurButtonOnClick } from '../../util/component_utils';
|
||||||
|
|
||||||
import { JobIcon } from '../job_message_icon';
|
import { JobIcon } from '../job_message_icon';
|
||||||
import { useIsServerless } from '../../contexts/kibana';
|
import { useEnabledFeatures } from '../../contexts/ml';
|
||||||
|
|
||||||
interface JobMessagesProps {
|
interface JobMessagesProps {
|
||||||
messages: JobMessage[];
|
messages: JobMessage[];
|
||||||
|
@ -46,7 +46,7 @@ export const JobMessages: FC<JobMessagesProps> = ({
|
||||||
refreshMessage,
|
refreshMessage,
|
||||||
actionHandler,
|
actionHandler,
|
||||||
}) => {
|
}) => {
|
||||||
const isServerless = useIsServerless();
|
const { showNodeInfo } = useEnabledFeatures();
|
||||||
const columns: Array<EuiBasicTableColumn<JobMessage>> = useMemo(() => {
|
const columns: Array<EuiBasicTableColumn<JobMessage>> = useMemo(() => {
|
||||||
const cols = [
|
const cols = [
|
||||||
{
|
{
|
||||||
|
@ -90,7 +90,7 @@ export const JobMessages: FC<JobMessagesProps> = ({
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (isServerless === false) {
|
if (showNodeInfo) {
|
||||||
cols.splice(2, 0, {
|
cols.splice(2, 0, {
|
||||||
field: 'node_name',
|
field: 'node_name',
|
||||||
name: i18n.translate('xpack.ml.jobMessages.nodeLabel', {
|
name: i18n.translate('xpack.ml.jobMessages.nodeLabel', {
|
||||||
|
@ -101,7 +101,7 @@ export const JobMessages: FC<JobMessagesProps> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
return cols;
|
return cols;
|
||||||
}, [isServerless, refreshMessage]);
|
}, [showNodeInfo, refreshMessage]);
|
||||||
|
|
||||||
if (typeof actionHandler === 'function') {
|
if (typeof actionHandler === 'function') {
|
||||||
columns.push({
|
columns.push({
|
||||||
|
|
|
@ -18,10 +18,10 @@ import {
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
|
|
||||||
import type { SyncSavedObjectResponse, SyncResult } from '../../../../common/types/saved_objects';
|
import type { SyncSavedObjectResponse, SyncResult } from '../../../../common/types/saved_objects';
|
||||||
import { usePermissionCheck } from '../../capabilities/check_capabilities';
|
import { useEnabledFeatures } from '../../contexts/ml';
|
||||||
|
|
||||||
export const SyncList: FC<{ syncItems: SyncSavedObjectResponse | null }> = ({ syncItems }) => {
|
export const SyncList: FC<{ syncItems: SyncSavedObjectResponse | null }> = ({ syncItems }) => {
|
||||||
const [isADEnabled] = usePermissionCheck(['isADEnabled']);
|
const { isADEnabled } = useEnabledFeatures();
|
||||||
|
|
||||||
if (syncItems === null) {
|
if (syncItems === null) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -10,15 +10,15 @@ import React, { FC } from 'react';
|
||||||
import { EuiCallOut, EuiSpacer } from '@elastic/eui';
|
import { EuiCallOut, EuiSpacer } from '@elastic/eui';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { lazyMlNodesAvailable } from '../../ml_nodes_check';
|
import { lazyMlNodesAvailable } from '../../ml_nodes_check';
|
||||||
import { useIsServerless } from '../../contexts/kibana';
|
import { useEnabledFeatures } from '../../contexts/ml';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
jobCount: number;
|
jobCount: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const JobsAwaitingNodeWarning: FC<Props> = ({ jobCount }) => {
|
export const JobsAwaitingNodeWarning: FC<Props> = ({ jobCount }) => {
|
||||||
const isServerless = useIsServerless();
|
const { showNodeInfo } = useEnabledFeatures();
|
||||||
if (isServerless || lazyMlNodesAvailable() === false || jobCount === 0) {
|
if (showNodeInfo === false || lazyMlNodesAvailable() === false || jobCount === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,33 +11,19 @@ import { EuiCallOut, EuiSpacer } from '@elastic/eui';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { JobType } from '../../../../common/types/saved_objects';
|
import { JobType } from '../../../../common/types/saved_objects';
|
||||||
import { lazyMlNodesAvailable } from '../../ml_nodes_check';
|
import { lazyMlNodesAvailable } from '../../ml_nodes_check';
|
||||||
import { useIsServerless } from '../../contexts/kibana';
|
import { useEnabledFeatures } from '../../contexts/ml';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
jobType: JobType;
|
jobType: JobType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NewJobAwaitingNodeWarning: FC<Props> = () => {
|
export const NewJobAwaitingNodeWarning: FC<Props> = () => {
|
||||||
const isServerless = useIsServerless();
|
const { showNodeInfo } = useEnabledFeatures();
|
||||||
if (lazyMlNodesAvailable() === false) {
|
if (lazyMlNodesAvailable() === false) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return isServerless ? (
|
return showNodeInfo ? (
|
||||||
<>
|
|
||||||
<EuiCallOut
|
|
||||||
title={
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.ml.jobsAwaitingNodeWarning.serverless.title"
|
|
||||||
defaultMessage="Machine learning is starting..."
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
color="primary"
|
|
||||||
iconType="iInCircle"
|
|
||||||
/>
|
|
||||||
<EuiSpacer size="m" />
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
<>
|
||||||
<EuiCallOut
|
<EuiCallOut
|
||||||
title={
|
title={
|
||||||
|
@ -58,5 +44,19 @@ export const NewJobAwaitingNodeWarning: FC<Props> = () => {
|
||||||
</EuiCallOut>
|
</EuiCallOut>
|
||||||
<EuiSpacer size="m" />
|
<EuiSpacer size="m" />
|
||||||
</>
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<EuiCallOut
|
||||||
|
title={
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.jobsAwaitingNodeWarning.serverless.title"
|
||||||
|
defaultMessage="Machine learning is starting..."
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
color="primary"
|
||||||
|
iconType="iInCircle"
|
||||||
|
/>
|
||||||
|
<EuiSpacer size="m" />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { countBy } from 'lodash';
|
||||||
import useMount from 'react-use/lib/useMount';
|
import useMount from 'react-use/lib/useMount';
|
||||||
import { useMlApiContext } from '../../contexts/kibana';
|
import { useMlApiContext } from '../../contexts/kibana';
|
||||||
import { useToastNotificationService } from '../../services/toast_notification_service';
|
import { useToastNotificationService } from '../../services/toast_notification_service';
|
||||||
import { usePermissionCheck } from '../../capabilities/check_capabilities';
|
import { useEnabledFeatures } from '../../contexts/ml';
|
||||||
|
|
||||||
type EntityType = 'anomaly_detector' | 'data_frame_analytics' | 'trained_models';
|
type EntityType = 'anomaly_detector' | 'data_frame_analytics' | 'trained_models';
|
||||||
|
|
||||||
|
@ -61,11 +61,7 @@ export const MlEntitySelector: FC<MlEntitySelectorProps> = ({
|
||||||
onSelectionChange,
|
onSelectionChange,
|
||||||
handleDuplicates = false,
|
handleDuplicates = false,
|
||||||
}) => {
|
}) => {
|
||||||
const [isADEnabled, isDFAEnabled, isNLPEnabled] = usePermissionCheck([
|
const { isADEnabled, isDFAEnabled, isNLPEnabled } = useEnabledFeatures();
|
||||||
'isADEnabled',
|
|
||||||
'isDFAEnabled',
|
|
||||||
'isNLPEnabled',
|
|
||||||
]);
|
|
||||||
const { jobs: jobsApi, trainedModels, dataFrameAnalytics } = useMlApiContext();
|
const { jobs: jobsApi, trainedModels, dataFrameAnalytics } = useMlApiContext();
|
||||||
const { displayErrorToast } = useToastNotificationService();
|
const { displayErrorToast } = useToastNotificationService();
|
||||||
const visColorsBehindText = euiPaletteColorBlindBehindText();
|
const visColorsBehindText = euiPaletteColorBlindBehindText();
|
||||||
|
|
|
@ -20,7 +20,7 @@ import { DatePickerWrapper } from '@kbn/ml-date-picker';
|
||||||
|
|
||||||
import * as routes from '../../routing/routes';
|
import * as routes from '../../routing/routes';
|
||||||
import { MlPageWrapper } from '../../routing/ml_page_wrapper';
|
import { MlPageWrapper } from '../../routing/ml_page_wrapper';
|
||||||
import { useMlKibana, useNavigateToPath, useIsServerless } from '../../contexts/kibana';
|
import { useMlKibana, useNavigateToPath } from '../../contexts/kibana';
|
||||||
import type { MlRoute, PageDependencies } from '../../routing/router';
|
import type { MlRoute, PageDependencies } from '../../routing/router';
|
||||||
import { useActiveRoute } from '../../routing/use_active_route';
|
import { useActiveRoute } from '../../routing/use_active_route';
|
||||||
import { useDocTitle } from '../../routing/use_doc_title';
|
import { useDocTitle } from '../../routing/use_doc_title';
|
||||||
|
@ -28,6 +28,7 @@ import { useDocTitle } from '../../routing/use_doc_title';
|
||||||
import { MlPageHeaderRenderer } from '../page_header/page_header';
|
import { MlPageHeaderRenderer } from '../page_header/page_header';
|
||||||
|
|
||||||
import { useSideNavItems } from './side_nav';
|
import { useSideNavItems } from './side_nav';
|
||||||
|
import { useEnabledFeatures } from '../../contexts/ml';
|
||||||
|
|
||||||
const ML_APP_SELECTOR = '[data-test-subj="mlApp"]';
|
const ML_APP_SELECTOR = '[data-test-subj="mlApp"]';
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ export const MlPage: FC<{ pageDeps: PageDependencies }> = React.memo(({ pageDeps
|
||||||
mlServices: { httpService },
|
mlServices: { httpService },
|
||||||
},
|
},
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
const isServerless = useIsServerless();
|
const { showMLNavMenu } = useEnabledFeatures();
|
||||||
|
|
||||||
const headerPortalNode = useMemo(() => createHtmlPortalNode(), []);
|
const headerPortalNode = useMemo(() => createHtmlPortalNode(), []);
|
||||||
const [isHeaderMounted, setIsHeaderMounted] = useState(false);
|
const [isHeaderMounted, setIsHeaderMounted] = useState(false);
|
||||||
|
@ -127,7 +128,7 @@ export const MlPage: FC<{ pageDeps: PageDependencies }> = React.memo(({ pageDeps
|
||||||
data-test-subj={'mlApp'}
|
data-test-subj={'mlApp'}
|
||||||
restrictWidth={false}
|
restrictWidth={false}
|
||||||
solutionNav={
|
solutionNav={
|
||||||
isServerless === false
|
showMLNavMenu
|
||||||
? {
|
? {
|
||||||
name: i18n.translate('xpack.ml.plugin.title', {
|
name: i18n.translate('xpack.ml.plugin.title', {
|
||||||
defaultMessage: 'Machine Learning',
|
defaultMessage: 'Machine Learning',
|
||||||
|
|
|
@ -16,4 +16,3 @@ export { useMlApiContext } from './use_ml_api_context';
|
||||||
export { useFieldFormatter } from './use_field_formatter';
|
export { useFieldFormatter } from './use_field_formatter';
|
||||||
export { useCurrentThemeVars } from './use_current_theme';
|
export { useCurrentThemeVars } from './use_current_theme';
|
||||||
export { useMlLicenseInfo } from './use_ml_license';
|
export { useMlLicenseInfo } from './use_ml_license';
|
||||||
export { useIsServerless } from './use_is_serverless';
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
||||||
* or more contributor license agreements. Licensed under the Elastic License
|
|
||||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
|
||||||
* 2.0.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { useMlKibana } from './kibana_context';
|
|
||||||
|
|
||||||
export function useIsServerless(): boolean {
|
|
||||||
return useMlKibana().services.mlServices.isServerless;
|
|
||||||
}
|
|
|
@ -6,3 +6,4 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export { DataSourceContextProvider, useDataSource } from './data_source_context';
|
export { DataSourceContextProvider, useDataSource } from './data_source_context';
|
||||||
|
export { EnabledFeaturesContextProvider, useEnabledFeatures } from './serverless_context';
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||||
|
* 2.0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { createContext, FC, useContext, useMemo } from 'react';
|
||||||
|
import type { MlFeatures } from '../../../../common/constants/app';
|
||||||
|
|
||||||
|
export interface EnabledFeatures {
|
||||||
|
showNodeInfo: boolean;
|
||||||
|
showMLNavMenu: boolean;
|
||||||
|
showLicenseInfo: boolean;
|
||||||
|
isADEnabled: boolean;
|
||||||
|
isDFAEnabled: boolean;
|
||||||
|
isNLPEnabled: boolean;
|
||||||
|
}
|
||||||
|
export const EnabledFeaturesContext = createContext({
|
||||||
|
showNodeInfo: true,
|
||||||
|
showMLNavMenu: true,
|
||||||
|
showLicenseInfo: true,
|
||||||
|
isADEnabled: true,
|
||||||
|
isDFAEnabled: true,
|
||||||
|
isNLPEnabled: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
isServerless: boolean;
|
||||||
|
mlFeatures: MlFeatures;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EnabledFeaturesContextProvider: FC<Props> = ({
|
||||||
|
children,
|
||||||
|
isServerless,
|
||||||
|
mlFeatures,
|
||||||
|
}) => {
|
||||||
|
const features: EnabledFeatures = {
|
||||||
|
showNodeInfo: !isServerless,
|
||||||
|
showMLNavMenu: !isServerless,
|
||||||
|
showLicenseInfo: !isServerless,
|
||||||
|
isADEnabled: mlFeatures.ad,
|
||||||
|
isDFAEnabled: mlFeatures.dfa,
|
||||||
|
isNLPEnabled: mlFeatures.nlp,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EnabledFeaturesContext.Provider value={features}>{children}</EnabledFeaturesContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useEnabledFeatures() {
|
||||||
|
const context = useContext(EnabledFeaturesContext);
|
||||||
|
return useMemo(() => {
|
||||||
|
return context;
|
||||||
|
}, [context]);
|
||||||
|
}
|
|
@ -37,8 +37,8 @@ import {
|
||||||
useNotifications,
|
useNotifications,
|
||||||
useNavigateToPath,
|
useNavigateToPath,
|
||||||
useMlKibana,
|
useMlKibana,
|
||||||
useIsServerless,
|
|
||||||
} from '../../../../contexts/kibana';
|
} from '../../../../contexts/kibana';
|
||||||
|
import { useEnabledFeatures } from '../../../../contexts/ml';
|
||||||
import { getDataViewIdFromName } from '../../../../util/index_utils';
|
import { getDataViewIdFromName } from '../../../../util/index_utils';
|
||||||
import { useNavigateToWizardWithClonedJob } from '../../analytics_management/components/action_clone/clone_action_name';
|
import { useNavigateToWizardWithClonedJob } from '../../analytics_management/components/action_clone/clone_action_name';
|
||||||
import {
|
import {
|
||||||
|
@ -55,9 +55,9 @@ interface Props {
|
||||||
refreshJobsCallback: () => void;
|
refreshJobsCallback: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getListItemsFactory(isServerless: boolean) {
|
function getListItemsFactory(showLicenseInfo: boolean) {
|
||||||
return (details: Record<string, any>): EuiDescriptionListProps['listItems'] => {
|
return (details: Record<string, any>): EuiDescriptionListProps['listItems'] => {
|
||||||
if (isServerless) {
|
if (showLicenseInfo === false) {
|
||||||
delete details.license_level;
|
delete details.license_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,8 +94,8 @@ export const Controls: FC<Props> = React.memo(
|
||||||
const canCreateDataFrameAnalytics: boolean = usePermissionCheck('canCreateDataFrameAnalytics');
|
const canCreateDataFrameAnalytics: boolean = usePermissionCheck('canCreateDataFrameAnalytics');
|
||||||
const canDeleteDataFrameAnalytics: boolean = usePermissionCheck('canDeleteDataFrameAnalytics');
|
const canDeleteDataFrameAnalytics: boolean = usePermissionCheck('canDeleteDataFrameAnalytics');
|
||||||
const deleteAction = useDeleteAction(canDeleteDataFrameAnalytics);
|
const deleteAction = useDeleteAction(canDeleteDataFrameAnalytics);
|
||||||
const isServerless = useIsServerless();
|
const { showLicenseInfo } = useEnabledFeatures();
|
||||||
const getListItems = useMemo(() => getListItemsFactory(isServerless), [isServerless]);
|
const getListItems = useMemo(() => getListItemsFactory(showLicenseInfo), [showLicenseInfo]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
closeDeleteJobCheckModal,
|
closeDeleteJobCheckModal,
|
||||||
|
|
|
@ -15,13 +15,14 @@ import type {
|
||||||
GetAdditionalLinksParams,
|
GetAdditionalLinksParams,
|
||||||
} from '@kbn/data-visualizer-plugin/public';
|
} from '@kbn/data-visualizer-plugin/public';
|
||||||
import { useTimefilter } from '@kbn/ml-date-picker';
|
import { useTimefilter } from '@kbn/ml-date-picker';
|
||||||
import { useMlKibana, useMlLocator, useIsServerless } from '../../contexts/kibana';
|
import { useMlKibana, useMlLocator } from '../../contexts/kibana';
|
||||||
import { HelpMenu } from '../../components/help_menu';
|
import { HelpMenu } from '../../components/help_menu';
|
||||||
import { ML_PAGES } from '../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../common/constants/locator';
|
||||||
import { isFullLicense } from '../../license';
|
import { isFullLicense } from '../../license';
|
||||||
import { mlNodesAvailable, getMlNodeCount } from '../../ml_nodes_check/check_ml_nodes';
|
import { mlNodesAvailable, getMlNodeCount } from '../../ml_nodes_check/check_ml_nodes';
|
||||||
import { checkPermission } from '../../capabilities/check_capabilities';
|
import { checkPermission } from '../../capabilities/check_capabilities';
|
||||||
import { MlPageHeader } from '../../components/page_header';
|
import { MlPageHeader } from '../../components/page_header';
|
||||||
|
import { useEnabledFeatures } from '../../contexts/ml';
|
||||||
|
|
||||||
export const IndexDataVisualizerPage: FC = () => {
|
export const IndexDataVisualizerPage: FC = () => {
|
||||||
useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false });
|
useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false });
|
||||||
|
@ -37,7 +38,7 @@ export const IndexDataVisualizerPage: FC = () => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
const isServerless = useIsServerless();
|
const { showNodeInfo } = useEnabledFeatures();
|
||||||
const mlLocator = useMlLocator()!;
|
const mlLocator = useMlLocator()!;
|
||||||
const mlFeaturesDisabled = !isFullLicense();
|
const mlFeaturesDisabled = !isFullLicense();
|
||||||
getMlNodeCount();
|
getMlNodeCount();
|
||||||
|
@ -191,7 +192,7 @@ export const IndexDataVisualizerPage: FC = () => {
|
||||||
</MlPageHeader>
|
</MlPageHeader>
|
||||||
<IndexDataVisualizer
|
<IndexDataVisualizer
|
||||||
getAdditionalLinks={getAdditionalLinks}
|
getAdditionalLinks={getAdditionalLinks}
|
||||||
isServerless={isServerless}
|
showFrozenDataTierChoice={showNodeInfo}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
@ -137,7 +137,7 @@ export class JobsListView extends Component {
|
||||||
loadFullJob(jobId)
|
loadFullJob(jobId)
|
||||||
.then((job) => {
|
.then((job) => {
|
||||||
const fullJobsList = { ...this.state.fullJobsList };
|
const fullJobsList = { ...this.state.fullJobsList };
|
||||||
if (this.props.isServerless) {
|
if (this.props.showNodeInfo === false) {
|
||||||
job = removeNodeInfo(job);
|
job = removeNodeInfo(job);
|
||||||
}
|
}
|
||||||
fullJobsList[jobId] = job;
|
fullJobsList[jobId] = job;
|
||||||
|
@ -318,7 +318,7 @@ export class JobsListView extends Component {
|
||||||
const fullJobsList = {};
|
const fullJobsList = {};
|
||||||
const jobsSummaryList = jobs.map((job) => {
|
const jobsSummaryList = jobs.map((job) => {
|
||||||
if (job.fullJob !== undefined) {
|
if (job.fullJob !== undefined) {
|
||||||
if (this.props.isServerless) {
|
if (this.props.showNodeInfo === false) {
|
||||||
job.fullJob = removeNodeInfo(job.fullJob);
|
job.fullJob = removeNodeInfo(job.fullJob);
|
||||||
}
|
}
|
||||||
fullJobsList[job.id] = job.fullJob;
|
fullJobsList[job.id] = job.fullJob;
|
||||||
|
@ -417,7 +417,7 @@ export class JobsListView extends Component {
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
<JobStatsBar
|
<JobStatsBar
|
||||||
jobsSummaryList={jobsSummaryList}
|
jobsSummaryList={jobsSummaryList}
|
||||||
isServerless={this.props.isServerless}
|
showNodeInfo={this.props.showNodeInfo}
|
||||||
/>
|
/>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
|
|
|
@ -12,11 +12,9 @@ import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
|
|
||||||
function createJobStats(jobsSummaryList, isServerless) {
|
function createJobStats(jobsSummaryList, showNodeInfo) {
|
||||||
const displayNodeInfo = isServerless === false;
|
|
||||||
|
|
||||||
const jobStats = {
|
const jobStats = {
|
||||||
...(displayNodeInfo
|
...(showNodeInfo
|
||||||
? {
|
? {
|
||||||
activeNodes: {
|
activeNodes: {
|
||||||
label: i18n.translate('xpack.ml.jobsList.statsBar.activeMLNodesLabel', {
|
label: i18n.translate('xpack.ml.jobsList.statsBar.activeMLNodesLabel', {
|
||||||
|
@ -100,20 +98,20 @@ function createJobStats(jobsSummaryList, isServerless) {
|
||||||
jobStats.failed.show = false;
|
jobStats.failed.show = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (displayNodeInfo) {
|
if (showNodeInfo) {
|
||||||
jobStats.activeNodes.value = Object.keys(mlNodes).length;
|
jobStats.activeNodes.value = Object.keys(mlNodes).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
return jobStats;
|
return jobStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const JobStatsBar = ({ jobsSummaryList, isServerless }) => {
|
export const JobStatsBar = ({ jobsSummaryList, showNodeInfo }) => {
|
||||||
const jobStats = createJobStats(jobsSummaryList, isServerless);
|
const jobStats = createJobStats(jobsSummaryList, showNodeInfo);
|
||||||
|
|
||||||
return <StatsBar stats={jobStats} dataTestSub={'mlJobStatsBar'} />;
|
return <StatsBar stats={jobStats} dataTestSub={'mlJobStatsBar'} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
JobStatsBar.propTypes = {
|
JobStatsBar.propTypes = {
|
||||||
jobsSummaryList: PropTypes.array.isRequired,
|
jobsSummaryList: PropTypes.array.isRequired,
|
||||||
isServerless: PropTypes.bool.isRequired,
|
showNodeInfo: PropTypes.bool.isRequired,
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,10 +12,11 @@ import { JobsListView } from './components/jobs_list_view';
|
||||||
import { ML_PAGES } from '../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../common/constants/locator';
|
||||||
import { ListingPageUrlState } from '../../../../common/types/common';
|
import { ListingPageUrlState } from '../../../../common/types/common';
|
||||||
import { HelpMenu } from '../../components/help_menu';
|
import { HelpMenu } from '../../components/help_menu';
|
||||||
import { useIsServerless, useMlKibana } from '../../contexts/kibana';
|
import { useMlKibana } from '../../contexts/kibana';
|
||||||
import { MlPageHeader } from '../../components/page_header';
|
import { MlPageHeader } from '../../components/page_header';
|
||||||
import { HeaderMenuPortal } from '../../components/header_menu_portal';
|
import { HeaderMenuPortal } from '../../components/header_menu_portal';
|
||||||
import { JobsActionMenu } from '../components/jobs_action_menu';
|
import { JobsActionMenu } from '../components/jobs_action_menu';
|
||||||
|
import { useEnabledFeatures } from '../../contexts/ml';
|
||||||
|
|
||||||
interface PageUrlState {
|
interface PageUrlState {
|
||||||
pageKey: typeof ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE;
|
pageKey: typeof ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE;
|
||||||
|
@ -42,7 +43,8 @@ export const JobsPage: FC<JobsPageProps> = ({ isMlEnabledInSpace, lastRefresh })
|
||||||
const {
|
const {
|
||||||
services: { docLinks },
|
services: { docLinks },
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
const isServerless = useIsServerless();
|
|
||||||
|
const { showNodeInfo } = useEnabledFeatures();
|
||||||
const helpLink = docLinks.links.ml.anomalyDetection;
|
const helpLink = docLinks.links.ml.anomalyDetection;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -57,7 +59,7 @@ export const JobsPage: FC<JobsPageProps> = ({ isMlEnabledInSpace, lastRefresh })
|
||||||
lastRefresh={lastRefresh}
|
lastRefresh={lastRefresh}
|
||||||
jobsViewState={pageState}
|
jobsViewState={pageState}
|
||||||
onJobsViewStateUpdate={setPageState}
|
onJobsViewStateUpdate={setPageState}
|
||||||
isServerless={isServerless}
|
showNodeInfo={showNodeInfo}
|
||||||
/>
|
/>
|
||||||
<HelpMenu docLink={helpLink} />
|
<HelpMenu docLink={helpLink} />
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -22,7 +22,7 @@ import { EventRateChart } from '../charts/event_rate_chart';
|
||||||
import { LineChartPoint } from '../../../common/chart_loader';
|
import { LineChartPoint } from '../../../common/chart_loader';
|
||||||
import { JOB_TYPE } from '../../../../../../../common/constants/new_job';
|
import { JOB_TYPE } from '../../../../../../../common/constants/new_job';
|
||||||
import { TimeRangePicker, TimeRange } from '../../../common/components';
|
import { TimeRangePicker, TimeRange } from '../../../common/components';
|
||||||
import { useMlKibana, useIsServerless } from '../../../../../contexts/kibana';
|
import { useMlKibana } from '../../../../../contexts/kibana';
|
||||||
import {
|
import {
|
||||||
ML_FROZEN_TIER_PREFERENCE,
|
ML_FROZEN_TIER_PREFERENCE,
|
||||||
type MlStorageKey,
|
type MlStorageKey,
|
||||||
|
@ -33,7 +33,6 @@ export const TimeRangeStep: FC<StepProps> = ({ setCurrentStep, isCurrentStep })
|
||||||
const timefilter = useTimefilter();
|
const timefilter = useTimefilter();
|
||||||
const { services } = useMlKibana();
|
const { services } = useMlKibana();
|
||||||
const dataSourceContext = useDataSource();
|
const dataSourceContext = useDataSource();
|
||||||
const isServerless = useIsServerless();
|
|
||||||
|
|
||||||
const { jobCreator, jobCreatorUpdate, jobCreatorUpdated, chartLoader, chartInterval } =
|
const { jobCreator, jobCreatorUpdate, jobCreatorUpdated, chartLoader, chartInterval } =
|
||||||
useContext(JobCreatorContext);
|
useContext(JobCreatorContext);
|
||||||
|
@ -138,7 +137,6 @@ export const TimeRangeStep: FC<StepProps> = ({ setCurrentStep, isCurrentStep })
|
||||||
callback={fullTimeRangeCallback}
|
callback={fullTimeRangeCallback}
|
||||||
timefilter={timefilter}
|
timefilter={timefilter}
|
||||||
apiPath={`${ML_INTERNAL_BASE_PATH}/fields_service/time_field_range`}
|
apiPath={`${ML_INTERNAL_BASE_PATH}/fields_service/time_field_range`}
|
||||||
hideFrozenDataTierChoice={isServerless}
|
|
||||||
/>
|
/>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
<EuiFlexItem />
|
<EuiFlexItem />
|
||||||
|
|
|
@ -11,13 +11,15 @@ import type { CoreSetup } from '@kbn/core/public';
|
||||||
import type { ManagementSetup } from '@kbn/management-plugin/public';
|
import type { ManagementSetup } from '@kbn/management-plugin/public';
|
||||||
import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
|
import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
|
||||||
import type { ManagementAppMountParams } from '@kbn/management-plugin/public';
|
import type { ManagementAppMountParams } from '@kbn/management-plugin/public';
|
||||||
|
import type { MlFeatures } from '../../../common/constants/app';
|
||||||
import type { MlStartDependencies } from '../../plugin';
|
import type { MlStartDependencies } from '../../plugin';
|
||||||
|
|
||||||
export function registerManagementSection(
|
export function registerManagementSection(
|
||||||
management: ManagementSetup,
|
management: ManagementSetup,
|
||||||
core: CoreSetup<MlStartDependencies>,
|
core: CoreSetup<MlStartDependencies>,
|
||||||
deps: { usageCollection?: UsageCollectionSetup },
|
deps: { usageCollection?: UsageCollectionSetup },
|
||||||
isServerless: boolean
|
isServerless: boolean,
|
||||||
|
mlFeatures: MlFeatures
|
||||||
) {
|
) {
|
||||||
return management.sections.section.insightsAndAlerting.registerApp({
|
return management.sections.section.insightsAndAlerting.registerApp({
|
||||||
id: 'jobsListLink',
|
id: 'jobsListLink',
|
||||||
|
@ -27,7 +29,7 @@ export function registerManagementSection(
|
||||||
order: 4,
|
order: 4,
|
||||||
async mount(params: ManagementAppMountParams) {
|
async mount(params: ManagementAppMountParams) {
|
||||||
const { mountApp } = await import('./jobs_list');
|
const { mountApp } = await import('./jobs_list');
|
||||||
return mountApp(core, params, deps, isServerless);
|
return mountApp(core, params, deps, isServerless, mlFeatures);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,8 @@ import {
|
||||||
import type { SharePluginStart } from '@kbn/share-plugin/public';
|
import type { SharePluginStart } from '@kbn/share-plugin/public';
|
||||||
import type { SpacesContextProps, SpacesPluginStart } from '@kbn/spaces-plugin/public';
|
import type { SpacesContextProps, SpacesPluginStart } from '@kbn/spaces-plugin/public';
|
||||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||||
import { PLUGIN_ID } from '../../../../../../common/constants/app';
|
import { EnabledFeaturesContextProvider } from '../../../../contexts/ml';
|
||||||
|
import { type MlFeatures, PLUGIN_ID } from '../../../../../../common/constants/app';
|
||||||
|
|
||||||
import { checkGetManagementMlJobsResolver } from '../../../../capabilities/check_capabilities';
|
import { checkGetManagementMlJobsResolver } from '../../../../capabilities/check_capabilities';
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ import { DocsLink } from './docs_link';
|
||||||
|
|
||||||
const getEmptyFunctionComponent: React.FC<SpacesContextProps> = ({ children }) => <>{children}</>;
|
const getEmptyFunctionComponent: React.FC<SpacesContextProps> = ({ children }) => <>{children}</>;
|
||||||
|
|
||||||
export const JobsListPage: FC<{
|
interface Props {
|
||||||
coreStart: CoreStart;
|
coreStart: CoreStart;
|
||||||
share: SharePluginStart;
|
share: SharePluginStart;
|
||||||
history: ManagementAppMountParams['history'];
|
history: ManagementAppMountParams['history'];
|
||||||
|
@ -55,7 +56,10 @@ export const JobsListPage: FC<{
|
||||||
usageCollection?: UsageCollectionSetup;
|
usageCollection?: UsageCollectionSetup;
|
||||||
fieldFormats: FieldFormatsStart;
|
fieldFormats: FieldFormatsStart;
|
||||||
isServerless: boolean;
|
isServerless: boolean;
|
||||||
}> = ({
|
mlFeatures: MlFeatures;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const JobsListPage: FC<Props> = ({
|
||||||
coreStart,
|
coreStart,
|
||||||
share,
|
share,
|
||||||
history,
|
history,
|
||||||
|
@ -64,6 +68,7 @@ export const JobsListPage: FC<{
|
||||||
usageCollection,
|
usageCollection,
|
||||||
fieldFormats,
|
fieldFormats,
|
||||||
isServerless,
|
isServerless,
|
||||||
|
mlFeatures,
|
||||||
}) => {
|
}) => {
|
||||||
const [initialized, setInitialized] = useState(false);
|
const [initialized, setInitialized] = useState(false);
|
||||||
const [accessDenied, setAccessDenied] = useState(false);
|
const [accessDenied, setAccessDenied] = useState(false);
|
||||||
|
@ -74,8 +79,8 @@ export const JobsListPage: FC<{
|
||||||
const theme$ = coreStart.theme.theme$;
|
const theme$ = coreStart.theme.theme$;
|
||||||
|
|
||||||
const mlServices = useMemo(
|
const mlServices = useMemo(
|
||||||
() => getMlGlobalServices(coreStart.http, isServerless, usageCollection),
|
() => getMlGlobalServices(coreStart.http, usageCollection),
|
||||||
[coreStart.http, isServerless, usageCollection]
|
[coreStart.http, usageCollection]
|
||||||
);
|
);
|
||||||
|
|
||||||
const check = async () => {
|
const check = async () => {
|
||||||
|
@ -134,6 +139,7 @@ export const JobsListPage: FC<{
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ContextWrapper feature={PLUGIN_ID}>
|
<ContextWrapper feature={PLUGIN_ID}>
|
||||||
|
<EnabledFeaturesContextProvider isServerless={isServerless} mlFeatures={mlFeatures}>
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<EuiPageTemplate.Header
|
<EuiPageTemplate.Header
|
||||||
pageTitle={
|
pageTitle={
|
||||||
|
@ -190,6 +196,7 @@ export const JobsListPage: FC<{
|
||||||
<SpaceManagement spacesApi={spacesApi} setCurrentTab={setCurrentTabId} />
|
<SpaceManagement spacesApi={spacesApi} setCurrentTab={setCurrentTabId} />
|
||||||
</EuiPageTemplate.Section>
|
</EuiPageTemplate.Section>
|
||||||
</Router>
|
</Router>
|
||||||
|
</EnabledFeaturesContextProvider>
|
||||||
</ContextWrapper>
|
</ContextWrapper>
|
||||||
</KibanaContextProvider>
|
</KibanaContextProvider>
|
||||||
</KibanaThemeProvider>
|
</KibanaThemeProvider>
|
||||||
|
|
|
@ -21,7 +21,7 @@ import {
|
||||||
|
|
||||||
import type { SpacesPluginStart } from '@kbn/spaces-plugin/public';
|
import type { SpacesPluginStart } from '@kbn/spaces-plugin/public';
|
||||||
import { useTableState } from '@kbn/ml-in-memory-table';
|
import { useTableState } from '@kbn/ml-in-memory-table';
|
||||||
import { usePermissionCheck } from '../../../../../capabilities/check_capabilities';
|
import { useEnabledFeatures } from '../../../../../contexts/ml';
|
||||||
import type { JobType, MlSavedObjectType } from '../../../../../../../common/types/saved_objects';
|
import type { JobType, MlSavedObjectType } from '../../../../../../../common/types/saved_objects';
|
||||||
import type {
|
import type {
|
||||||
ManagementListResponse,
|
ManagementListResponse,
|
||||||
|
@ -46,11 +46,7 @@ export const SpaceManagement: FC<Props> = ({ spacesApi, setCurrentTab }) => {
|
||||||
const [filters, setFilters] = useState<SearchFilterConfig[] | undefined>();
|
const [filters, setFilters] = useState<SearchFilterConfig[] | undefined>();
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
const [isADEnabled, isDFAEnabled, isNLPEnabled] = usePermissionCheck([
|
const { isADEnabled, isDFAEnabled, isNLPEnabled } = useEnabledFeatures();
|
||||||
'isADEnabled',
|
|
||||||
'isDFAEnabled',
|
|
||||||
'isNLPEnabled',
|
|
||||||
]);
|
|
||||||
|
|
||||||
const { onTableChange, pagination, sorting, setPageIndex } = useTableState<ManagementItems>(
|
const { onTableChange, pagination, sorting, setPageIndex } = useTableState<ManagementItems>(
|
||||||
items ?? [],
|
items ?? [],
|
||||||
|
|
|
@ -14,6 +14,7 @@ import type { ManagementAppMountParams } from '@kbn/management-plugin/public';
|
||||||
import type { SharePluginStart } from '@kbn/share-plugin/public';
|
import type { SharePluginStart } from '@kbn/share-plugin/public';
|
||||||
import type { SpacesPluginStart } from '@kbn/spaces-plugin/public';
|
import type { SpacesPluginStart } from '@kbn/spaces-plugin/public';
|
||||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||||
|
import type { MlFeatures } from '../../../../common/constants/app';
|
||||||
import type { MlStartDependencies } from '../../../plugin';
|
import type { MlStartDependencies } from '../../../plugin';
|
||||||
import { JobsListPage } from './components';
|
import { JobsListPage } from './components';
|
||||||
import { getJobsListBreadcrumbs } from '../breadcrumbs';
|
import { getJobsListBreadcrumbs } from '../breadcrumbs';
|
||||||
|
@ -26,6 +27,7 @@ const renderApp = (
|
||||||
data: DataPublicPluginStart,
|
data: DataPublicPluginStart,
|
||||||
fieldFormats: FieldFormatsStart,
|
fieldFormats: FieldFormatsStart,
|
||||||
isServerless: boolean,
|
isServerless: boolean,
|
||||||
|
mlFeatures: MlFeatures,
|
||||||
spacesApi?: SpacesPluginStart,
|
spacesApi?: SpacesPluginStart,
|
||||||
usageCollection?: UsageCollectionSetup
|
usageCollection?: UsageCollectionSetup
|
||||||
) => {
|
) => {
|
||||||
|
@ -39,6 +41,7 @@ const renderApp = (
|
||||||
usageCollection,
|
usageCollection,
|
||||||
fieldFormats,
|
fieldFormats,
|
||||||
isServerless,
|
isServerless,
|
||||||
|
mlFeatures,
|
||||||
}),
|
}),
|
||||||
element
|
element
|
||||||
);
|
);
|
||||||
|
@ -51,7 +54,8 @@ export async function mountApp(
|
||||||
core: CoreSetup<MlStartDependencies>,
|
core: CoreSetup<MlStartDependencies>,
|
||||||
params: ManagementAppMountParams,
|
params: ManagementAppMountParams,
|
||||||
deps: { usageCollection?: UsageCollectionSetup },
|
deps: { usageCollection?: UsageCollectionSetup },
|
||||||
isServerless: boolean
|
isServerless: boolean,
|
||||||
|
mlFeatures: MlFeatures
|
||||||
) {
|
) {
|
||||||
const [coreStart, pluginsStart] = await core.getStartServices();
|
const [coreStart, pluginsStart] = await core.getStartServices();
|
||||||
|
|
||||||
|
@ -64,6 +68,7 @@ export async function mountApp(
|
||||||
pluginsStart.data,
|
pluginsStart.data,
|
||||||
pluginsStart.fieldFormats,
|
pluginsStart.fieldFormats,
|
||||||
isServerless,
|
isServerless,
|
||||||
|
mlFeatures,
|
||||||
pluginsStart.spaces,
|
pluginsStart.spaces,
|
||||||
deps.usageCollection
|
deps.usageCollection
|
||||||
);
|
);
|
||||||
|
|
|
@ -29,7 +29,7 @@ import { useFieldFormatter, useMlKibana } from '../../contexts/kibana';
|
||||||
import { useRefresh } from '../../routing/use_refresh';
|
import { useRefresh } from '../../routing/use_refresh';
|
||||||
import { getMemoryItemColor } from '../memory_item_colors';
|
import { getMemoryItemColor } from '../memory_item_colors';
|
||||||
import { useToastNotificationService } from '../../services/toast_notification_service';
|
import { useToastNotificationService } from '../../services/toast_notification_service';
|
||||||
import { usePermissionCheck } from '../../capabilities/check_capabilities';
|
import { useEnabledFeatures } from '../../contexts/ml';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
node?: string;
|
node?: string;
|
||||||
|
@ -73,11 +73,7 @@ export const JobMemoryTreeMap: FC<Props> = ({ node, type, height }) => {
|
||||||
[isDarkTheme]
|
[isDarkTheme]
|
||||||
);
|
);
|
||||||
|
|
||||||
const [isADEnabled, isDFAEnabled, isNLPEnabled] = usePermissionCheck([
|
const { isADEnabled, isDFAEnabled, isNLPEnabled } = useEnabledFeatures();
|
||||||
'isADEnabled',
|
|
||||||
'isDFAEnabled',
|
|
||||||
'isNLPEnabled',
|
|
||||||
]);
|
|
||||||
|
|
||||||
const bytesFormatter = useFieldFormatter(FIELD_FORMAT_IDS.BYTES);
|
const bytesFormatter = useFieldFormatter(FIELD_FORMAT_IDS.BYTES);
|
||||||
const { displayErrorToast } = useToastNotificationService();
|
const { displayErrorToast } = useToastNotificationService();
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { NodesList } from './nodes_overview';
|
||||||
import { MlPageHeader } from '../components/page_header';
|
import { MlPageHeader } from '../components/page_header';
|
||||||
import { MemoryPage, JobMemoryTreeMap } from './memory_tree_map';
|
import { MemoryPage, JobMemoryTreeMap } from './memory_tree_map';
|
||||||
import { SavedObjectsWarning } from '../components/saved_objects_warning';
|
import { SavedObjectsWarning } from '../components/saved_objects_warning';
|
||||||
import { useIsServerless } from '../contexts/kibana';
|
import { useEnabledFeatures } from '../contexts/ml';
|
||||||
|
|
||||||
enum TAB {
|
enum TAB {
|
||||||
NODES,
|
NODES,
|
||||||
|
@ -24,7 +24,7 @@ export const MemoryUsagePage: FC = () => {
|
||||||
const [selectedTab, setSelectedTab] = useState<TAB>(TAB.NODES);
|
const [selectedTab, setSelectedTab] = useState<TAB>(TAB.NODES);
|
||||||
useTimefilter({ timeRangeSelector: false, autoRefreshSelector: true });
|
useTimefilter({ timeRangeSelector: false, autoRefreshSelector: true });
|
||||||
|
|
||||||
const isServerless = useIsServerless();
|
const { showNodeInfo } = useEnabledFeatures();
|
||||||
|
|
||||||
const refresh = useCallback(() => {
|
const refresh = useCallback(() => {
|
||||||
mlTimefilterRefresh$.next({
|
mlTimefilterRefresh$.next({
|
||||||
|
@ -47,7 +47,7 @@ export const MemoryUsagePage: FC = () => {
|
||||||
|
|
||||||
<SavedObjectsWarning onCloseFlyout={refresh} />
|
<SavedObjectsWarning onCloseFlyout={refresh} />
|
||||||
|
|
||||||
{isServerless === false ? (
|
{showNodeInfo ? (
|
||||||
<>
|
<>
|
||||||
<EuiTabs>
|
<EuiTabs>
|
||||||
<EuiTab
|
<EuiTab
|
||||||
|
|
|
@ -33,7 +33,7 @@ import { ModelPipelines } from './pipelines';
|
||||||
import { AllocatedModels } from '../memory_usage/nodes_overview/allocated_models';
|
import { AllocatedModels } from '../memory_usage/nodes_overview/allocated_models';
|
||||||
import type { AllocatedModel, TrainedModelStat } from '../../../common/types/trained_models';
|
import type { AllocatedModel, TrainedModelStat } from '../../../common/types/trained_models';
|
||||||
import { useFieldFormatter } from '../contexts/kibana/use_field_formatter';
|
import { useFieldFormatter } from '../contexts/kibana/use_field_formatter';
|
||||||
import { useIsServerless } from '../contexts/kibana';
|
import { useEnabledFeatures } from '../contexts/ml';
|
||||||
|
|
||||||
interface ExpandedRowProps {
|
interface ExpandedRowProps {
|
||||||
item: ModelItemFull;
|
item: ModelItemFull;
|
||||||
|
@ -114,7 +114,7 @@ export function useListItemsFormatter() {
|
||||||
|
|
||||||
export const ExpandedRow: FC<ExpandedRowProps> = ({ item }) => {
|
export const ExpandedRow: FC<ExpandedRowProps> = ({ item }) => {
|
||||||
const formatToListItems = useListItemsFormatter();
|
const formatToListItems = useListItemsFormatter();
|
||||||
const isServerless = useIsServerless();
|
const { showLicenseInfo, showNodeInfo } = useEnabledFeatures();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
inference_config: inferenceConfig,
|
inference_config: inferenceConfig,
|
||||||
|
@ -151,17 +151,17 @@ export const ExpandedRow: FC<ExpandedRowProps> = ({ item }) => {
|
||||||
estimated_operations,
|
estimated_operations,
|
||||||
estimated_heap_memory_usage_bytes,
|
estimated_heap_memory_usage_bytes,
|
||||||
default_field_map,
|
default_field_map,
|
||||||
...(isServerless ? {} : { license_level }),
|
...(showLicenseInfo ? { license_level } : {}),
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
default_field_map,
|
|
||||||
description,
|
description,
|
||||||
estimated_heap_memory_usage_bytes,
|
|
||||||
estimated_operations,
|
|
||||||
license_level,
|
|
||||||
tags,
|
tags,
|
||||||
version,
|
version,
|
||||||
isServerless,
|
estimated_operations,
|
||||||
|
estimated_heap_memory_usage_bytes,
|
||||||
|
default_field_map,
|
||||||
|
showLicenseInfo,
|
||||||
|
license_level,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const deploymentStatItems: AllocatedModel[] = useMemo<AllocatedModel[]>(() => {
|
const deploymentStatItems: AllocatedModel[] = useMemo<AllocatedModel[]>(() => {
|
||||||
|
@ -200,8 +200,8 @@ export const ExpandedRow: FC<ExpandedRowProps> = ({ item }) => {
|
||||||
}, [stats]);
|
}, [stats]);
|
||||||
|
|
||||||
const hideColumns = useMemo(() => {
|
const hideColumns = useMemo(() => {
|
||||||
return isServerless ? ['model_id', 'node_name'] : ['model_id'];
|
return showNodeInfo ? ['model_id'] : ['model_id', 'node_name'];
|
||||||
}, [isServerless]);
|
}, [showNodeInfo]);
|
||||||
|
|
||||||
const tabs = useMemo<EuiTabbedContentTab[]>(() => {
|
const tabs = useMemo<EuiTabbedContentTab[]>(() => {
|
||||||
return [
|
return [
|
||||||
|
|
|
@ -63,7 +63,7 @@ import { useRefresh } from '../routing/use_refresh';
|
||||||
import { SavedObjectsWarning } from '../components/saved_objects_warning';
|
import { SavedObjectsWarning } from '../components/saved_objects_warning';
|
||||||
import { TestTrainedModelFlyout } from './test_models';
|
import { TestTrainedModelFlyout } from './test_models';
|
||||||
import { AddInferencePipelineFlyout } from '../components/ml_inference';
|
import { AddInferencePipelineFlyout } from '../components/ml_inference';
|
||||||
import { usePermissionCheck } from '../capabilities/check_capabilities';
|
import { useEnabledFeatures } from '../contexts/ml';
|
||||||
|
|
||||||
type Stats = Omit<TrainedModelStat, 'model_id' | 'deployment_stats'>;
|
type Stats = Omit<TrainedModelStat, 'model_id' | 'deployment_stats'>;
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ export const ModelsList: FC<Props> = ({
|
||||||
},
|
},
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
|
|
||||||
const [isNLPEnabled] = usePermissionCheck(['isNLPEnabled']);
|
const { isNLPEnabled } = useEnabledFeatures();
|
||||||
|
|
||||||
useTimefilter({ timeRangeSelector: false, autoRefreshSelector: true });
|
useTimefilter({ timeRangeSelector: false, autoRefreshSelector: true });
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ import type {
|
||||||
NotificationItem,
|
NotificationItem,
|
||||||
} from '../../../../common/types/notifications';
|
} from '../../../../common/types/notifications';
|
||||||
import { useMlKibana } from '../../contexts/kibana';
|
import { useMlKibana } from '../../contexts/kibana';
|
||||||
import { usePermissionCheck } from '../../capabilities/check_capabilities';
|
import { useEnabledFeatures } from '../../contexts/ml';
|
||||||
|
|
||||||
const levelBadgeMap: Record<MlNotificationMessageLevel, IconColor> = {
|
const levelBadgeMap: Record<MlNotificationMessageLevel, IconColor> = {
|
||||||
[ML_NOTIFICATIONS_MESSAGE_LEVEL.ERROR]: 'danger',
|
[ML_NOTIFICATIONS_MESSAGE_LEVEL.ERROR]: 'danger',
|
||||||
|
@ -67,11 +67,7 @@ export const NotificationsList: FC = () => {
|
||||||
},
|
},
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
|
|
||||||
const [isADEnabled, isDFAEnabled, isNLPEnabled] = usePermissionCheck([
|
const { isADEnabled, isDFAEnabled, isNLPEnabled } = useEnabledFeatures();
|
||||||
'isADEnabled',
|
|
||||||
'isDFAEnabled',
|
|
||||||
'isNLPEnabled',
|
|
||||||
]);
|
|
||||||
|
|
||||||
const { displayErrorToast } = useToastNotificationService();
|
const { displayErrorToast } = useToastNotificationService();
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {
|
||||||
import { ML_PAGES } from '../../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../../common/constants/locator';
|
||||||
import { OverviewStatsBar } from '../../../components/collapsible_panel/collapsible_panel';
|
import { OverviewStatsBar } from '../../../components/collapsible_panel/collapsible_panel';
|
||||||
import { CollapsiblePanel } from '../../../components/collapsible_panel';
|
import { CollapsiblePanel } from '../../../components/collapsible_panel';
|
||||||
import { useMlKibana, useMlLink, useIsServerless } from '../../../contexts/kibana';
|
import { useMlKibana, useMlLink } from '../../../contexts/kibana';
|
||||||
import { AnomalyDetectionTable } from './table';
|
import { AnomalyDetectionTable } from './table';
|
||||||
import { ml } from '../../../services/ml_api_service';
|
import { ml } from '../../../services/ml_api_service';
|
||||||
import { getGroupsFromJobs, getStatsBarData } from './utils';
|
import { getGroupsFromJobs, getStatsBarData } from './utils';
|
||||||
|
@ -31,6 +31,7 @@ import { AnomalyTimelineService } from '../../../services/anomaly_timeline_servi
|
||||||
import type { OverallSwimlaneData } from '../../../explorer/explorer_utils';
|
import type { OverallSwimlaneData } from '../../../explorer/explorer_utils';
|
||||||
import { AnomalyDetectionEmptyState } from '../../../jobs/jobs_list/components/anomaly_detection_empty_state';
|
import { AnomalyDetectionEmptyState } from '../../../jobs/jobs_list/components/anomaly_detection_empty_state';
|
||||||
import { overviewPanelDefaultState } from '../../overview_page';
|
import { overviewPanelDefaultState } from '../../overview_page';
|
||||||
|
import { useEnabledFeatures } from '../../../contexts/ml';
|
||||||
|
|
||||||
export type GroupsDictionary = Dictionary<Group>;
|
export type GroupsDictionary = Dictionary<Group>;
|
||||||
|
|
||||||
|
@ -57,7 +58,7 @@ export const AnomalyDetectionPanel: FC<Props> = ({ anomalyTimelineService, setLa
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
|
|
||||||
const { displayErrorToast } = useToastNotificationService();
|
const { displayErrorToast } = useToastNotificationService();
|
||||||
const isServerless = useIsServerless();
|
const { showNodeInfo } = useEnabledFeatures();
|
||||||
|
|
||||||
const refresh = useRefresh();
|
const refresh = useRefresh();
|
||||||
|
|
||||||
|
@ -92,7 +93,7 @@ export const AnomalyDetectionPanel: FC<Props> = ({ anomalyTimelineService, setLa
|
||||||
return job;
|
return job;
|
||||||
});
|
});
|
||||||
const { groups: jobsGroups, count } = getGroupsFromJobs(jobsSummaryList);
|
const { groups: jobsGroups, count } = getGroupsFromJobs(jobsSummaryList);
|
||||||
const stats = getStatsBarData(jobsSummaryList, isServerless);
|
const stats = getStatsBarData(jobsSummaryList, showNodeInfo);
|
||||||
|
|
||||||
const statGroups = groupBy(
|
const statGroups = groupBy(
|
||||||
Object.entries(stats)
|
Object.entries(stats)
|
||||||
|
|
|
@ -74,7 +74,7 @@ export function getGroupsFromJobs(jobs: MlSummaryJobs): {
|
||||||
return { groups, count };
|
return { groups, count };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getStatsBarData(jobsList: MlSummaryJob[] | undefined, isServerless: boolean) {
|
export function getStatsBarData(jobsList: MlSummaryJob[] | undefined, showNodeInfo: boolean) {
|
||||||
const jobStats = {
|
const jobStats = {
|
||||||
total: {
|
total: {
|
||||||
label: i18n.translate('xpack.ml.overviewJobsList.statsBar.totalJobsLabel', {
|
label: i18n.translate('xpack.ml.overviewJobsList.statsBar.totalJobsLabel', {
|
||||||
|
@ -108,9 +108,8 @@ export function getStatsBarData(jobsList: MlSummaryJob[] | undefined, isServerle
|
||||||
show: false,
|
show: false,
|
||||||
group: 0,
|
group: 0,
|
||||||
},
|
},
|
||||||
...(isServerless
|
...(showNodeInfo
|
||||||
? {}
|
? {
|
||||||
: {
|
|
||||||
activeNodes: {
|
activeNodes: {
|
||||||
label: i18n.translate('xpack.ml.overviewJobsList.statsBar.activeMLNodesLabel', {
|
label: i18n.translate('xpack.ml.overviewJobsList.statsBar.activeMLNodesLabel', {
|
||||||
defaultMessage: 'Active ML nodes',
|
defaultMessage: 'Active ML nodes',
|
||||||
|
@ -119,7 +118,8 @@ export function getStatsBarData(jobsList: MlSummaryJob[] | undefined, isServerle
|
||||||
show: true,
|
show: true,
|
||||||
group: 1,
|
group: 1,
|
||||||
},
|
},
|
||||||
}),
|
}
|
||||||
|
: {}),
|
||||||
activeDatafeeds: {
|
activeDatafeeds: {
|
||||||
label: i18n.translate('xpack.ml.jobsList.statsBar.activeDatafeedsLabel', {
|
label: i18n.translate('xpack.ml.jobsList.statsBar.activeDatafeedsLabel', {
|
||||||
defaultMessage: 'Active datafeeds',
|
defaultMessage: 'Active datafeeds',
|
||||||
|
@ -166,7 +166,7 @@ export function getStatsBarData(jobsList: MlSummaryJob[] | undefined, isServerle
|
||||||
jobStats.failed.show = false;
|
jobStats.failed.show = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isServerless === false) {
|
if (showNodeInfo) {
|
||||||
jobStats.activeNodes!.value = Object.keys(mlNodes).length;
|
jobStats.activeNodes!.value = Object.keys(mlNodes).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { AnalyticsPanel } from './analytics_panel';
|
||||||
import { AnomalyTimelineService } from '../../services/anomaly_timeline_service';
|
import { AnomalyTimelineService } from '../../services/anomaly_timeline_service';
|
||||||
import { mlResultsServiceProvider } from '../../services/results_service';
|
import { mlResultsServiceProvider } from '../../services/results_service';
|
||||||
import { useMlKibana } from '../../contexts/kibana';
|
import { useMlKibana } from '../../contexts/kibana';
|
||||||
import { usePermissionCheck } from '../../capabilities/check_capabilities';
|
import { useEnabledFeatures } from '../../contexts/ml';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
createAnomalyDetectionJobDisabled: boolean;
|
createAnomalyDetectionJobDisabled: boolean;
|
||||||
|
@ -33,7 +33,7 @@ export const OverviewContent: FC<Props> = ({
|
||||||
},
|
},
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
|
|
||||||
const [isADEnabled, isDFAEnabled] = usePermissionCheck(['isADEnabled', 'isDFAEnabled']);
|
const { isADEnabled, isDFAEnabled } = useEnabledFeatures();
|
||||||
|
|
||||||
const timefilter = useTimefilter();
|
const timefilter = useTimefilter();
|
||||||
|
|
||||||
|
|
|
@ -36,16 +36,7 @@ export const nodesListRouteFactory = (
|
||||||
});
|
});
|
||||||
|
|
||||||
const PageWrapper: FC = () => {
|
const PageWrapper: FC = () => {
|
||||||
const { context } = useRouteResolver(
|
const { context } = useRouteResolver('full', [], basicResolvers());
|
||||||
'full',
|
|
||||||
// only enabled in non-serverless mode
|
|
||||||
// if a serverless project ever contains all three features
|
|
||||||
// this check will have to be changed to an
|
|
||||||
// explicit isServerless check which will probably
|
|
||||||
// require a change in useRouteResolver
|
|
||||||
['isADEnabled', 'isDFAEnabled', 'isNLPEnabled'],
|
|
||||||
basicResolvers()
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageLoader context={context}>
|
<PageLoader context={context}>
|
||||||
|
|
|
@ -11,6 +11,7 @@ import React, { FC, Suspense } from 'react';
|
||||||
import { Redirect } from 'react-router-dom';
|
import { Redirect } from 'react-router-dom';
|
||||||
import { ML_PAGES } from '../../../locator';
|
import { ML_PAGES } from '../../../locator';
|
||||||
import type { NavigateToPath } from '../../contexts/kibana';
|
import type { NavigateToPath } from '../../contexts/kibana';
|
||||||
|
import { useEnabledFeatures } from '../../contexts/ml/serverless_context';
|
||||||
import { getMlNodeCount } from '../../ml_nodes_check';
|
import { getMlNodeCount } from '../../ml_nodes_check';
|
||||||
import { loadMlServerInfo } from '../../services/ml_server_info';
|
import { loadMlServerInfo } from '../../services/ml_server_info';
|
||||||
import { getBreadcrumbWithUrlForApp } from '../breadcrumbs';
|
import { getBreadcrumbWithUrlForApp } from '../breadcrumbs';
|
||||||
|
@ -67,5 +68,13 @@ export const appRootRouteFactory = (navigateToPath: NavigateToPath, basePath: st
|
||||||
});
|
});
|
||||||
|
|
||||||
const Page: FC = () => {
|
const Page: FC = () => {
|
||||||
|
const { isADEnabled, isDFAEnabled, isNLPEnabled } = useEnabledFeatures();
|
||||||
|
if (isADEnabled === false && isDFAEnabled === false && isNLPEnabled === true) {
|
||||||
|
// if only NLP is enabled, redirect to the trained models page.
|
||||||
|
// in the search serverless project, the overview page is blank, so we
|
||||||
|
// need to redirect to the trained models page instead
|
||||||
|
return <Redirect to={createPath(ML_PAGES.TRAINED_MODELS_MANAGE)} />;
|
||||||
|
}
|
||||||
|
|
||||||
return <Redirect to={createPath(ML_PAGES.OVERVIEW)} />;
|
return <Redirect to={createPath(ML_PAGES.OVERVIEW)} />;
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,7 +27,7 @@ describe('AnomalyChartsEmbeddableFactory', () => {
|
||||||
const [coreStart, pluginsStart] = await getStartServices();
|
const [coreStart, pluginsStart] = await getStartServices();
|
||||||
|
|
||||||
// act
|
// act
|
||||||
const factory = new AnomalyChartsEmbeddableFactory(getStartServices, false);
|
const factory = new AnomalyChartsEmbeddableFactory(getStartServices);
|
||||||
|
|
||||||
await factory.create({
|
await factory.create({
|
||||||
jobIds: ['test-job'],
|
jobIds: ['test-job'],
|
||||||
|
|
|
@ -35,8 +35,7 @@ export class AnomalyChartsEmbeddableFactory
|
||||||
];
|
];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private getStartServices: StartServicesAccessor<MlStartDependencies, MlPluginStart>,
|
private getStartServices: StartServicesAccessor<MlStartDependencies, MlPluginStart>
|
||||||
private isServerless: boolean
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async isEditable() {
|
public async isEditable() {
|
||||||
|
@ -62,7 +61,7 @@ export class AnomalyChartsEmbeddableFactory
|
||||||
const { resolveEmbeddableAnomalyChartsUserInput } = await import(
|
const { resolveEmbeddableAnomalyChartsUserInput } = await import(
|
||||||
'./anomaly_charts_setup_flyout'
|
'./anomaly_charts_setup_flyout'
|
||||||
);
|
);
|
||||||
return await resolveEmbeddableAnomalyChartsUserInput(coreStart, this.isServerless);
|
return await resolveEmbeddableAnomalyChartsUserInput(coreStart);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return Promise.reject();
|
return Promise.reject();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ import { mlApiServicesProvider } from '../../application/services/ml_api_service
|
||||||
|
|
||||||
export async function resolveEmbeddableAnomalyChartsUserInput(
|
export async function resolveEmbeddableAnomalyChartsUserInput(
|
||||||
coreStart: CoreStart,
|
coreStart: CoreStart,
|
||||||
isServerless: boolean,
|
|
||||||
input?: AnomalyChartsEmbeddableInput
|
input?: AnomalyChartsEmbeddableInput
|
||||||
): Promise<Partial<AnomalyChartsEmbeddableInput>> {
|
): Promise<Partial<AnomalyChartsEmbeddableInput>> {
|
||||||
const { http, overlays, theme, i18n } = coreStart;
|
const { http, overlays, theme, i18n } = coreStart;
|
||||||
|
@ -28,7 +27,7 @@ export async function resolveEmbeddableAnomalyChartsUserInput(
|
||||||
|
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const { jobIds } = await resolveJobSelection(coreStart, isServerless, input?.jobIds);
|
const { jobIds } = await resolveJobSelection(coreStart, input?.jobIds);
|
||||||
const title = input?.title ?? getDefaultExplorerChartsPanelTitle(jobIds);
|
const title = input?.title ?? getDefaultExplorerChartsPanelTitle(jobIds);
|
||||||
const { jobs } = await getJobs({ jobId: jobIds.join(',') });
|
const { jobs } = await getJobs({ jobId: jobIds.join(',') });
|
||||||
const influencers = extractInfluencers(jobs);
|
const influencers = extractInfluencers(jobs);
|
||||||
|
|
|
@ -27,7 +27,7 @@ describe('AnomalySwimlaneEmbeddableFactory', () => {
|
||||||
const [coreStart, pluginsStart] = await getStartServices();
|
const [coreStart, pluginsStart] = await getStartServices();
|
||||||
|
|
||||||
// act
|
// act
|
||||||
const factory = new AnomalySwimlaneEmbeddableFactory(getStartServices, false);
|
const factory = new AnomalySwimlaneEmbeddableFactory(getStartServices);
|
||||||
|
|
||||||
await factory.create({
|
await factory.create({
|
||||||
jobIds: ['test-job'],
|
jobIds: ['test-job'],
|
||||||
|
|
|
@ -35,8 +35,7 @@ export class AnomalySwimlaneEmbeddableFactory
|
||||||
];
|
];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private getStartServices: StartServicesAccessor<MlStartDependencies, MlPluginStart>,
|
private getStartServices: StartServicesAccessor<MlStartDependencies, MlPluginStart>
|
||||||
private isServerless: boolean
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async isEditable() {
|
public async isEditable() {
|
||||||
|
@ -60,7 +59,7 @@ export class AnomalySwimlaneEmbeddableFactory
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { resolveAnomalySwimlaneUserInput } = await import('./anomaly_swimlane_setup_flyout');
|
const { resolveAnomalySwimlaneUserInput } = await import('./anomaly_swimlane_setup_flyout');
|
||||||
return await resolveAnomalySwimlaneUserInput(coreStart, this.isServerless);
|
return await resolveAnomalySwimlaneUserInput(coreStart);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return Promise.reject();
|
return Promise.reject();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ import { mlApiServicesProvider } from '../../application/services/ml_api_service
|
||||||
|
|
||||||
export async function resolveAnomalySwimlaneUserInput(
|
export async function resolveAnomalySwimlaneUserInput(
|
||||||
coreStart: CoreStart,
|
coreStart: CoreStart,
|
||||||
isServerless: boolean,
|
|
||||||
input?: AnomalySwimlaneEmbeddableInput
|
input?: AnomalySwimlaneEmbeddableInput
|
||||||
): Promise<Partial<AnomalySwimlaneEmbeddableInput>> {
|
): Promise<Partial<AnomalySwimlaneEmbeddableInput>> {
|
||||||
const { http, overlays, theme, i18n } = coreStart;
|
const { http, overlays, theme, i18n } = coreStart;
|
||||||
|
@ -28,7 +27,7 @@ export async function resolveAnomalySwimlaneUserInput(
|
||||||
|
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const { jobIds } = await resolveJobSelection(coreStart, isServerless, input?.jobIds);
|
const { jobIds } = await resolveJobSelection(coreStart, input?.jobIds);
|
||||||
const title = input?.title ?? getDefaultSwimlanePanelTitle(jobIds);
|
const title = input?.title ?? getDefaultSwimlanePanelTitle(jobIds);
|
||||||
const { jobs } = await getJobs({ jobId: jobIds.join(',') });
|
const { jobs } = await getJobs({ jobId: jobIds.join(',') });
|
||||||
const influencers = extractInfluencers(jobs);
|
const influencers = extractInfluencers(jobs);
|
||||||
|
|
|
@ -26,7 +26,6 @@ import { JobSelectorFlyout } from './components/job_selector_flyout';
|
||||||
*/
|
*/
|
||||||
export async function resolveJobSelection(
|
export async function resolveJobSelection(
|
||||||
coreStart: CoreStart,
|
coreStart: CoreStart,
|
||||||
isServerless: boolean,
|
|
||||||
selectedJobIds?: JobId[]
|
selectedJobIds?: JobId[]
|
||||||
): Promise<{ jobIds: string[]; groups: Array<{ groupId: string; jobIds: string[] }> }> {
|
): Promise<{ jobIds: string[]; groups: Array<{ groupId: string; jobIds: string[] }> }> {
|
||||||
const {
|
const {
|
||||||
|
@ -70,9 +69,7 @@ export async function resolveJobSelection(
|
||||||
|
|
||||||
const flyoutSession = coreStart.overlays.openFlyout(
|
const flyoutSession = coreStart.overlays.openFlyout(
|
||||||
toMountPoint(
|
toMountPoint(
|
||||||
<KibanaContextProvider
|
<KibanaContextProvider services={{ ...coreStart, mlServices: getMlGlobalServices(http) }}>
|
||||||
services={{ ...coreStart, mlServices: getMlGlobalServices(http, isServerless) }}
|
|
||||||
>
|
|
||||||
<JobSelectorFlyout
|
<JobSelectorFlyout
|
||||||
selectedIds={selectedJobIds}
|
selectedIds={selectedJobIds}
|
||||||
withTimeRangeSelector={false}
|
withTimeRangeSelector={false}
|
||||||
|
|
|
@ -15,24 +15,16 @@ export * from './types';
|
||||||
|
|
||||||
export { getEmbeddableComponent } from './get_embeddable_component';
|
export { getEmbeddableComponent } from './get_embeddable_component';
|
||||||
|
|
||||||
export function registerEmbeddables(
|
export function registerEmbeddables(embeddable: EmbeddableSetup, core: MlCoreSetup) {
|
||||||
embeddable: EmbeddableSetup,
|
|
||||||
core: MlCoreSetup,
|
|
||||||
isServerless: boolean
|
|
||||||
) {
|
|
||||||
const anomalySwimlaneEmbeddableFactory = new AnomalySwimlaneEmbeddableFactory(
|
const anomalySwimlaneEmbeddableFactory = new AnomalySwimlaneEmbeddableFactory(
|
||||||
core.getStartServices,
|
core.getStartServices
|
||||||
isServerless
|
|
||||||
);
|
);
|
||||||
embeddable.registerEmbeddableFactory(
|
embeddable.registerEmbeddableFactory(
|
||||||
anomalySwimlaneEmbeddableFactory.type,
|
anomalySwimlaneEmbeddableFactory.type,
|
||||||
anomalySwimlaneEmbeddableFactory
|
anomalySwimlaneEmbeddableFactory
|
||||||
);
|
);
|
||||||
|
|
||||||
const anomalyChartsFactory = new AnomalyChartsEmbeddableFactory(
|
const anomalyChartsFactory = new AnomalyChartsEmbeddableFactory(core.getStartServices);
|
||||||
core.getStartServices,
|
|
||||||
isServerless
|
|
||||||
);
|
|
||||||
|
|
||||||
embeddable.registerEmbeddableFactory(anomalyChartsFactory.type, anomalyChartsFactory);
|
embeddable.registerEmbeddableFactory(anomalyChartsFactory.type, anomalyChartsFactory);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ export function createFlyout(
|
||||||
share: SharePluginStart,
|
share: SharePluginStart,
|
||||||
data: DataPublicPluginStart,
|
data: DataPublicPluginStart,
|
||||||
dashboardService: DashboardStart,
|
dashboardService: DashboardStart,
|
||||||
isServerless: boolean,
|
|
||||||
lens?: LensPublicStart
|
lens?: LensPublicStart
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const {
|
const {
|
||||||
|
@ -54,7 +53,7 @@ export function createFlyout(
|
||||||
data,
|
data,
|
||||||
lens,
|
lens,
|
||||||
dashboardService,
|
dashboardService,
|
||||||
mlServices: getMlGlobalServices(http, isServerless),
|
mlServices: getMlGlobalServices(http),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FlyoutComponent
|
<FlyoutComponent
|
||||||
|
|
|
@ -20,8 +20,7 @@ export async function showLensVisToADJobFlyout(
|
||||||
share: SharePluginStart,
|
share: SharePluginStart,
|
||||||
data: DataPublicPluginStart,
|
data: DataPublicPluginStart,
|
||||||
lens: LensPublicStart,
|
lens: LensPublicStart,
|
||||||
dashboardService: DashboardStart,
|
dashboardService: DashboardStart
|
||||||
isServerless: boolean
|
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return createFlyout(
|
return createFlyout(
|
||||||
LensLayerSelectionFlyout,
|
LensLayerSelectionFlyout,
|
||||||
|
@ -30,7 +29,6 @@ export async function showLensVisToADJobFlyout(
|
||||||
share,
|
share,
|
||||||
data,
|
data,
|
||||||
dashboardService,
|
dashboardService,
|
||||||
isServerless,
|
|
||||||
lens
|
lens
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,16 +19,7 @@ export async function showMapVisToADJobFlyout(
|
||||||
coreStart: CoreStart,
|
coreStart: CoreStart,
|
||||||
share: SharePluginStart,
|
share: SharePluginStart,
|
||||||
data: DataPublicPluginStart,
|
data: DataPublicPluginStart,
|
||||||
dashboardService: DashboardStart,
|
dashboardService: DashboardStart
|
||||||
isServerless: boolean
|
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return createFlyout(
|
return createFlyout(GeoJobFlyout, embeddable, coreStart, share, data, dashboardService);
|
||||||
GeoJobFlyout,
|
|
||||||
embeddable,
|
|
||||||
coreStart,
|
|
||||||
share,
|
|
||||||
data,
|
|
||||||
dashboardService,
|
|
||||||
isServerless
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,14 @@ import { MlLocatorDefinition, type MlLocator } from './locator';
|
||||||
import { setDependencyCache } from './application/util/dependency_cache';
|
import { setDependencyCache } from './application/util/dependency_cache';
|
||||||
import { registerHomeFeature } from './register_home_feature';
|
import { registerHomeFeature } from './register_home_feature';
|
||||||
import { isFullLicense, isMlEnabled } from '../common/license';
|
import { isFullLicense, isMlEnabled } from '../common/license';
|
||||||
import { ML_APP_ROUTE, PLUGIN_ICON_SOLUTION, PLUGIN_ID } from '../common/constants/app';
|
import {
|
||||||
|
initEnabledFeatures,
|
||||||
|
type MlFeatures,
|
||||||
|
ML_APP_ROUTE,
|
||||||
|
PLUGIN_ICON_SOLUTION,
|
||||||
|
PLUGIN_ID,
|
||||||
|
type ConfigSchema,
|
||||||
|
} from '../common/constants/app';
|
||||||
import type { MlCapabilities } from './shared';
|
import type { MlCapabilities } from './shared';
|
||||||
|
|
||||||
export interface MlStartDependencies {
|
export interface MlStartDependencies {
|
||||||
|
@ -113,9 +120,15 @@ export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
|
||||||
private sharedMlServices: MlSharedServices | undefined;
|
private sharedMlServices: MlSharedServices | undefined;
|
||||||
|
|
||||||
private isServerless: boolean = false;
|
private isServerless: boolean = false;
|
||||||
|
private enabledFeatures: MlFeatures = {
|
||||||
|
ad: true,
|
||||||
|
dfa: true,
|
||||||
|
nlp: true,
|
||||||
|
};
|
||||||
|
|
||||||
constructor(private initializerContext: PluginInitializerContext) {
|
constructor(private initializerContext: PluginInitializerContext<ConfigSchema>) {
|
||||||
this.isServerless = initializerContext.env.packageInfo.buildFlavor === 'serverless';
|
this.isServerless = initializerContext.env.packageInfo.buildFlavor === 'serverless';
|
||||||
|
initEnabledFeatures(this.enabledFeatures, initializerContext.config.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
setup(core: MlCoreSetup, pluginsSetup: MlSetupDependencies) {
|
setup(core: MlCoreSetup, pluginsSetup: MlSetupDependencies) {
|
||||||
|
@ -164,7 +177,8 @@ export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
|
||||||
presentationUtil: pluginsStart.presentationUtil,
|
presentationUtil: pluginsStart.presentationUtil,
|
||||||
},
|
},
|
||||||
params,
|
params,
|
||||||
this.isServerless
|
this.isServerless,
|
||||||
|
this.enabledFeatures
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -180,7 +194,8 @@ export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
|
||||||
{
|
{
|
||||||
usageCollection: pluginsSetup.usageCollection,
|
usageCollection: pluginsSetup.usageCollection,
|
||||||
},
|
},
|
||||||
this.isServerless
|
this.isServerless,
|
||||||
|
this.enabledFeatures
|
||||||
).enable();
|
).enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,13 +223,13 @@ export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
|
||||||
registerMapExtension,
|
registerMapExtension,
|
||||||
registerCasesAttachments,
|
registerCasesAttachments,
|
||||||
} = await import('./register_helper');
|
} = await import('./register_helper');
|
||||||
registerSearchLinks(this.appUpdater$, fullLicense, mlCapabilities, this.isServerless);
|
registerSearchLinks(this.appUpdater$, fullLicense, mlCapabilities, !this.isServerless);
|
||||||
|
|
||||||
if (fullLicense) {
|
if (fullLicense) {
|
||||||
registerMlUiActions(pluginsSetup.uiActions, core, this.isServerless);
|
registerMlUiActions(pluginsSetup.uiActions, core);
|
||||||
|
|
||||||
if (mlCapabilities.isADEnabled) {
|
if (this.enabledFeatures.ad) {
|
||||||
registerEmbeddables(pluginsSetup.embeddable, core, this.isServerless);
|
registerEmbeddables(pluginsSetup.embeddable, core);
|
||||||
|
|
||||||
if (pluginsSetup.cases) {
|
if (pluginsSetup.cases) {
|
||||||
registerCasesAttachments(pluginsSetup.cases, coreStart, pluginStart);
|
registerCasesAttachments(pluginsSetup.cases, coreStart, pluginStart);
|
||||||
|
|
|
@ -16,7 +16,7 @@ export function registerSearchLinks(
|
||||||
appUpdater: BehaviorSubject<AppUpdater>,
|
appUpdater: BehaviorSubject<AppUpdater>,
|
||||||
isFullLicense: boolean,
|
isFullLicense: boolean,
|
||||||
mlCapabilities: MlCapabilities,
|
mlCapabilities: MlCapabilities,
|
||||||
isServerless: boolean
|
showMLNavMenu: boolean
|
||||||
) {
|
) {
|
||||||
appUpdater.next(() => ({
|
appUpdater.next(() => ({
|
||||||
keywords: [
|
keywords: [
|
||||||
|
@ -24,6 +24,6 @@ export function registerSearchLinks(
|
||||||
defaultMessage: 'ML',
|
defaultMessage: 'ML',
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
deepLinks: getDeepLinks(isFullLicense, mlCapabilities, isServerless),
|
deepLinks: getDeepLinks(isFullLicense, mlCapabilities, showMLNavMenu),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,13 @@ import type { MlCapabilities } from '../../shared';
|
||||||
function createDeepLinks(
|
function createDeepLinks(
|
||||||
mlCapabilities: MlCapabilities,
|
mlCapabilities: MlCapabilities,
|
||||||
isFullLicense: boolean,
|
isFullLicense: boolean,
|
||||||
isServerless: boolean
|
showMLNavMenu: boolean
|
||||||
) {
|
) {
|
||||||
function getNavStatus(
|
function getNavStatus(
|
||||||
visible: boolean,
|
visible: boolean,
|
||||||
showInServerless: boolean = true
|
showInServerless: boolean = true
|
||||||
): AppNavLinkStatus | undefined {
|
): AppNavLinkStatus | undefined {
|
||||||
if (isServerless) {
|
if (showMLNavMenu === false) {
|
||||||
// in serverless the status needs to be "visible" rather than "default"
|
// in serverless the status needs to be "visible" rather than "default"
|
||||||
// for the links to appear in the nav menu.
|
// for the links to appear in the nav menu.
|
||||||
return showInServerless && visible ? AppNavLinkStatus.visible : AppNavLinkStatus.hidden;
|
return showInServerless && visible ? AppNavLinkStatus.visible : AppNavLinkStatus.hidden;
|
||||||
|
@ -145,7 +145,7 @@ function createDeepLinks(
|
||||||
defaultMessage: 'Memory Usage',
|
defaultMessage: 'Memory Usage',
|
||||||
}),
|
}),
|
||||||
path: `/${ML_PAGES.MEMORY_USAGE}`,
|
path: `/${ML_PAGES.MEMORY_USAGE}`,
|
||||||
navLinkStatus: getNavStatus(isFullLicense, false),
|
navLinkStatus: getNavStatus(isFullLicense, true),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -279,8 +279,8 @@ function createDeepLinks(
|
||||||
export function getDeepLinks(
|
export function getDeepLinks(
|
||||||
isFullLicense: boolean,
|
isFullLicense: boolean,
|
||||||
mlCapabilities: MlCapabilities,
|
mlCapabilities: MlCapabilities,
|
||||||
isServerless: boolean
|
showMLNavMenu: boolean
|
||||||
) {
|
) {
|
||||||
const links = createDeepLinks(mlCapabilities, isFullLicense, isServerless);
|
const links = createDeepLinks(mlCapabilities, isFullLicense, showMLNavMenu);
|
||||||
return Object.values(links).map((link) => link());
|
return Object.values(links).map((link) => link());
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,7 @@ import {
|
||||||
export const EDIT_ANOMALY_CHARTS_PANEL_ACTION = 'editAnomalyChartsPanelAction';
|
export const EDIT_ANOMALY_CHARTS_PANEL_ACTION = 'editAnomalyChartsPanelAction';
|
||||||
|
|
||||||
export function createEditAnomalyChartsPanelAction(
|
export function createEditAnomalyChartsPanelAction(
|
||||||
getStartServices: MlCoreSetup['getStartServices'],
|
getStartServices: MlCoreSetup['getStartServices']
|
||||||
isServerless: boolean
|
|
||||||
): UiActionsActionDefinition<EditAnomalyChartsPanelContext> {
|
): UiActionsActionDefinition<EditAnomalyChartsPanelContext> {
|
||||||
return {
|
return {
|
||||||
id: 'edit-anomaly-charts',
|
id: 'edit-anomaly-charts',
|
||||||
|
@ -44,7 +43,6 @@ export function createEditAnomalyChartsPanelAction(
|
||||||
|
|
||||||
const result = await resolveEmbeddableAnomalyChartsUserInput(
|
const result = await resolveEmbeddableAnomalyChartsUserInput(
|
||||||
coreStart,
|
coreStart,
|
||||||
isServerless,
|
|
||||||
embeddable.getInput()
|
embeddable.getInput()
|
||||||
);
|
);
|
||||||
embeddable.updateInput(result);
|
embeddable.updateInput(result);
|
||||||
|
|
|
@ -14,8 +14,7 @@ import { ANOMALY_SWIMLANE_EMBEDDABLE_TYPE, EditSwimlanePanelContext } from '../e
|
||||||
export const EDIT_SWIMLANE_PANEL_ACTION = 'editSwimlanePanelAction';
|
export const EDIT_SWIMLANE_PANEL_ACTION = 'editSwimlanePanelAction';
|
||||||
|
|
||||||
export function createEditSwimlanePanelAction(
|
export function createEditSwimlanePanelAction(
|
||||||
getStartServices: MlCoreSetup['getStartServices'],
|
getStartServices: MlCoreSetup['getStartServices']
|
||||||
isServerless: boolean
|
|
||||||
): UiActionsActionDefinition<EditSwimlanePanelContext> {
|
): UiActionsActionDefinition<EditSwimlanePanelContext> {
|
||||||
return {
|
return {
|
||||||
id: 'edit-anomaly-swimlane',
|
id: 'edit-anomaly-swimlane',
|
||||||
|
@ -39,11 +38,7 @@ export function createEditSwimlanePanelAction(
|
||||||
'../embeddables/anomaly_swimlane/anomaly_swimlane_setup_flyout'
|
'../embeddables/anomaly_swimlane/anomaly_swimlane_setup_flyout'
|
||||||
);
|
);
|
||||||
|
|
||||||
const result = await resolveAnomalySwimlaneUserInput(
|
const result = await resolveAnomalySwimlaneUserInput(coreStart, embeddable.getInput());
|
||||||
coreStart,
|
|
||||||
isServerless,
|
|
||||||
embeddable.getInput()
|
|
||||||
);
|
|
||||||
embeddable.updateInput(result);
|
embeddable.updateInput(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return Promise.reject();
|
return Promise.reject();
|
||||||
|
|
|
@ -34,24 +34,17 @@ export { SWIM_LANE_SELECTION_TRIGGER };
|
||||||
*/
|
*/
|
||||||
export function registerMlUiActions(
|
export function registerMlUiActions(
|
||||||
uiActions: UiActionsSetup,
|
uiActions: UiActionsSetup,
|
||||||
core: CoreSetup<MlStartDependencies, MlPluginStart>,
|
core: CoreSetup<MlStartDependencies, MlPluginStart>
|
||||||
isServerless: boolean
|
|
||||||
) {
|
) {
|
||||||
// Initialize actions
|
// Initialize actions
|
||||||
const editSwimlanePanelAction = createEditSwimlanePanelAction(
|
const editSwimlanePanelAction = createEditSwimlanePanelAction(core.getStartServices);
|
||||||
core.getStartServices,
|
|
||||||
isServerless
|
|
||||||
);
|
|
||||||
const openInExplorerAction = createOpenInExplorerAction(core.getStartServices);
|
const openInExplorerAction = createOpenInExplorerAction(core.getStartServices);
|
||||||
const applyInfluencerFiltersAction = createApplyInfluencerFiltersAction(core.getStartServices);
|
const applyInfluencerFiltersAction = createApplyInfluencerFiltersAction(core.getStartServices);
|
||||||
const applyEntityFieldFilterAction = createApplyEntityFieldFiltersAction(core.getStartServices);
|
const applyEntityFieldFilterAction = createApplyEntityFieldFiltersAction(core.getStartServices);
|
||||||
const applyTimeRangeSelectionAction = createApplyTimeRangeSelectionAction(core.getStartServices);
|
const applyTimeRangeSelectionAction = createApplyTimeRangeSelectionAction(core.getStartServices);
|
||||||
const clearSelectionAction = createClearSelectionAction(core.getStartServices);
|
const clearSelectionAction = createClearSelectionAction(core.getStartServices);
|
||||||
const editExplorerPanelAction = createEditAnomalyChartsPanelAction(
|
const editExplorerPanelAction = createEditAnomalyChartsPanelAction(core.getStartServices);
|
||||||
core.getStartServices,
|
const visToAdJobAction = createVisToADJobAction(core.getStartServices);
|
||||||
isServerless
|
|
||||||
);
|
|
||||||
const visToAdJobAction = createVisToADJobAction(core.getStartServices, isServerless);
|
|
||||||
|
|
||||||
// Register actions
|
// Register actions
|
||||||
uiActions.registerAction(editSwimlanePanelAction);
|
uiActions.registerAction(editSwimlanePanelAction);
|
||||||
|
|
|
@ -15,8 +15,7 @@ import { isLensEmbeddable, isMapEmbeddable } from '../application/jobs/new_job/j
|
||||||
export const CREATE_LENS_VIS_TO_ML_AD_JOB_ACTION = 'createMLADJobAction';
|
export const CREATE_LENS_VIS_TO_ML_AD_JOB_ACTION = 'createMLADJobAction';
|
||||||
|
|
||||||
export function createVisToADJobAction(
|
export function createVisToADJobAction(
|
||||||
getStartServices: MlCoreSetup['getStartServices'],
|
getStartServices: MlCoreSetup['getStartServices']
|
||||||
isServerless: boolean
|
|
||||||
): UiActionsActionDefinition<{ embeddable: Embeddable | MapEmbeddable }> {
|
): UiActionsActionDefinition<{ embeddable: Embeddable | MapEmbeddable }> {
|
||||||
return {
|
return {
|
||||||
id: 'create-ml-ad-job-action',
|
id: 'create-ml-ad-job-action',
|
||||||
|
@ -40,26 +39,11 @@ export function createVisToADJobAction(
|
||||||
if (lens === undefined) {
|
if (lens === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await showLensVisToADJobFlyout(
|
await showLensVisToADJobFlyout(embeddable, coreStart, share, data, lens, dashboard);
|
||||||
embeddable,
|
|
||||||
coreStart,
|
|
||||||
share,
|
|
||||||
data,
|
|
||||||
lens,
|
|
||||||
dashboard,
|
|
||||||
isServerless
|
|
||||||
);
|
|
||||||
} else if (isMapEmbeddable(embeddable)) {
|
} else if (isMapEmbeddable(embeddable)) {
|
||||||
const [{ showMapVisToADJobFlyout }, [coreStart, { share, data, dashboard }]] =
|
const [{ showMapVisToADJobFlyout }, [coreStart, { share, data, dashboard }]] =
|
||||||
await Promise.all([import('../embeddables/job_creation/map'), getStartServices()]);
|
await Promise.all([import('../embeddables/job_creation/map'), getStartServices()]);
|
||||||
await showMapVisToADJobFlyout(
|
await showMapVisToADJobFlyout(embeddable, coreStart, share, data, dashboard);
|
||||||
embeddable,
|
|
||||||
coreStart,
|
|
||||||
share,
|
|
||||||
data,
|
|
||||||
dashboard,
|
|
||||||
isServerless
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return Promise.reject();
|
return Promise.reject();
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||||
* 2.0.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
import { schema, type TypeOf } from '@kbn/config-schema';
|
import { schema } from '@kbn/config-schema';
|
||||||
|
|
||||||
const enabledSchema = schema.maybe(
|
const enabledSchema = schema.maybe(
|
||||||
schema.object({
|
schema.object({
|
||||||
|
@ -17,5 +17,3 @@ export const configSchema = schema.object({
|
||||||
dfa: enabledSchema,
|
dfa: enabledSchema,
|
||||||
nlp: enabledSchema,
|
nlp: enabledSchema,
|
||||||
});
|
});
|
||||||
|
|
||||||
export type ConfigSchema = TypeOf<typeof configSchema>;
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server';
|
import type { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server';
|
||||||
|
import { type ConfigSchema } from '../common/constants/app';
|
||||||
|
import { configSchema } from './config_schema';
|
||||||
import { MlServerPlugin } from './plugin';
|
import { MlServerPlugin } from './plugin';
|
||||||
export type { MlPluginSetup, MlPluginStart } from './plugin';
|
export type { MlPluginSetup, MlPluginStart } from './plugin';
|
||||||
export type {
|
export type {
|
||||||
|
@ -26,10 +28,14 @@ export {
|
||||||
InsufficientMLCapabilities,
|
InsufficientMLCapabilities,
|
||||||
MLPrivilegesUninitialized,
|
MLPrivilegesUninitialized,
|
||||||
} from './shared';
|
} from './shared';
|
||||||
import { configSchema, type ConfigSchema } from './config_schema';
|
|
||||||
|
|
||||||
export const config: PluginConfigDescriptor<ConfigSchema> = {
|
export const config: PluginConfigDescriptor<ConfigSchema> = {
|
||||||
schema: configSchema,
|
schema: configSchema,
|
||||||
|
exposeToBrowser: {
|
||||||
|
ad: true,
|
||||||
|
dfa: true,
|
||||||
|
nlp: true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const plugin = (ctx: PluginInitializerContext<ConfigSchema>) => new MlServerPlugin(ctx);
|
export const plugin = (ctx: PluginInitializerContext<ConfigSchema>) => new MlServerPlugin(ctx);
|
||||||
|
|
|
@ -7,11 +7,11 @@
|
||||||
|
|
||||||
import type { Logger } from '@kbn/core/server';
|
import type { Logger } from '@kbn/core/server';
|
||||||
import type { AlertingPlugin } from '@kbn/alerting-plugin/server';
|
import type { AlertingPlugin } from '@kbn/alerting-plugin/server';
|
||||||
|
import type { MlFeatures } from '../../../common/constants/app';
|
||||||
import { registerAnomalyDetectionAlertType } from './register_anomaly_detection_alert_type';
|
import { registerAnomalyDetectionAlertType } from './register_anomaly_detection_alert_type';
|
||||||
import type { SharedServices } from '../../shared_services';
|
import type { SharedServices } from '../../shared_services';
|
||||||
import { registerJobsMonitoringRuleType } from './register_jobs_monitoring_rule_type';
|
import { registerJobsMonitoringRuleType } from './register_jobs_monitoring_rule_type';
|
||||||
import type { MlServicesProviders } from '../../shared_services/shared_services';
|
import type { MlServicesProviders } from '../../shared_services/shared_services';
|
||||||
import type { MlFeatures } from '../../types';
|
|
||||||
|
|
||||||
export interface RegisterAlertParams {
|
export interface RegisterAlertParams {
|
||||||
alerting: AlertingPlugin['setup'];
|
alerting: AlertingPlugin['setup'];
|
||||||
|
|
|
@ -9,13 +9,13 @@ import { cloneDeep } from 'lodash';
|
||||||
import { firstValueFrom, Observable } from 'rxjs';
|
import { firstValueFrom, Observable } from 'rxjs';
|
||||||
import type { CapabilitiesSwitcher, CoreSetup, Logger } from '@kbn/core/server';
|
import type { CapabilitiesSwitcher, CoreSetup, Logger } from '@kbn/core/server';
|
||||||
import type { ILicense } from '@kbn/licensing-plugin/common/types';
|
import type { ILicense } from '@kbn/licensing-plugin/common/types';
|
||||||
|
import type { MlFeatures } from '../../../common/constants/app';
|
||||||
import { isFullLicense, isMinimumLicense, isMlEnabled } from '../../../common/license';
|
import { isFullLicense, isMinimumLicense, isMlEnabled } from '../../../common/license';
|
||||||
import {
|
import {
|
||||||
type MlCapabilities,
|
type MlCapabilities,
|
||||||
basicLicenseMlCapabilities,
|
basicLicenseMlCapabilities,
|
||||||
featureCapabilities,
|
featureCapabilities,
|
||||||
} from '../../../common/types/capabilities';
|
} from '../../../common/types/capabilities';
|
||||||
import type { MlFeatures } from '../../types';
|
|
||||||
|
|
||||||
export const setupCapabilitiesSwitcher = (
|
export const setupCapabilitiesSwitcher = (
|
||||||
coreSetup: CoreSetup,
|
coreSetup: CoreSetup,
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { CasesSetup } from '@kbn/cases-plugin/server';
|
import type { CasesSetup } from '@kbn/cases-plugin/server';
|
||||||
|
import type { MlFeatures } from '../../common/constants/app';
|
||||||
import {
|
import {
|
||||||
CASE_ATTACHMENT_TYPE_ID_ANOMALY_EXPLORER_CHARTS,
|
CASE_ATTACHMENT_TYPE_ID_ANOMALY_EXPLORER_CHARTS,
|
||||||
CASE_ATTACHMENT_TYPE_ID_ANOMALY_SWIMLANE,
|
CASE_ATTACHMENT_TYPE_ID_ANOMALY_SWIMLANE,
|
||||||
} from '../../common/constants/cases';
|
} from '../../common/constants/cases';
|
||||||
import type { MlFeatures } from '../types';
|
|
||||||
|
|
||||||
export function registerCasesPersistableState(cases: CasesSetup, enabledFeatures: MlFeatures) {
|
export function registerCasesPersistableState(cases: CasesSetup, enabledFeatures: MlFeatures) {
|
||||||
if (enabledFeatures.ad === true) {
|
if (enabledFeatures.ad === true) {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import type { HomeServerPluginSetup } from '@kbn/home-plugin/server';
|
import type { HomeServerPluginSetup } from '@kbn/home-plugin/server';
|
||||||
import type { MlFeatures } from '../types';
|
import type { MlFeatures } from '../../common/constants/app';
|
||||||
|
|
||||||
export function registerSampleDataSetLinks(
|
export function registerSampleDataSetLinks(
|
||||||
home: HomeServerPluginSetup,
|
home: HomeServerPluginSetup,
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {
|
||||||
type MapElements,
|
type MapElements,
|
||||||
} from '@kbn/ml-data-frame-analytics-utils';
|
} from '@kbn/ml-data-frame-analytics-utils';
|
||||||
import { isPopulatedObject } from '@kbn/ml-is-populated-object';
|
import { isPopulatedObject } from '@kbn/ml-is-populated-object';
|
||||||
|
import type { MlFeatures } from '../../../common/constants/app';
|
||||||
import type { ModelService } from '../model_management/models_provider';
|
import type { ModelService } from '../model_management/models_provider';
|
||||||
import { modelsProvider } from '../model_management';
|
import { modelsProvider } from '../model_management';
|
||||||
import {
|
import {
|
||||||
|
@ -36,7 +37,6 @@ import {
|
||||||
isTransformLinkReturnType,
|
isTransformLinkReturnType,
|
||||||
} from './types';
|
} from './types';
|
||||||
import type { MlClient } from '../../lib/ml_client';
|
import type { MlClient } from '../../lib/ml_client';
|
||||||
import type { MlFeatures } from '../../types';
|
|
||||||
import { DEFAULT_TRAINED_MODELS_PAGE_SIZE } from '../../routes/trained_models';
|
import { DEFAULT_TRAINED_MODELS_PAGE_SIZE } from '../../routes/trained_models';
|
||||||
|
|
||||||
export class AnalyticsManager {
|
export class AnalyticsManager {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||||
import numeral from '@elastic/numeral';
|
import numeral from '@elastic/numeral';
|
||||||
import { pick } from 'lodash';
|
import { pick } from 'lodash';
|
||||||
import { isDefined } from '@kbn/ml-is-defined';
|
import { isDefined } from '@kbn/ml-is-defined';
|
||||||
|
import type { MlFeatures } from '../../../common/constants/app';
|
||||||
import type {
|
import type {
|
||||||
MemoryUsageInfo,
|
MemoryUsageInfo,
|
||||||
TrainedModelStatsResponse,
|
TrainedModelStatsResponse,
|
||||||
|
@ -22,7 +23,6 @@ import type {
|
||||||
NodeDeploymentStatsResponse,
|
NodeDeploymentStatsResponse,
|
||||||
NodesOverviewResponse,
|
NodesOverviewResponse,
|
||||||
} from '../../../common/types/trained_models';
|
} from '../../../common/types/trained_models';
|
||||||
import type { MlFeatures } from '../../types';
|
|
||||||
|
|
||||||
// @ts-expect-error numeral missing value
|
// @ts-expect-error numeral missing value
|
||||||
const AD_EXTRA_MEMORY = numeral('10MB').value();
|
const AD_EXTRA_MEMORY = numeral('10MB').value();
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
import { IScopedClusterClient } from '@kbn/core/server';
|
import { IScopedClusterClient } from '@kbn/core/server';
|
||||||
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||||
|
import type { MlFeatures } from '../../../common/constants/app';
|
||||||
import type { MLSavedObjectService } from '../../saved_objects';
|
import type { MLSavedObjectService } from '../../saved_objects';
|
||||||
import type { NotificationItem, NotificationSource } from '../../../common/types/notifications';
|
import type { NotificationItem, NotificationSource } from '../../../common/types/notifications';
|
||||||
import { ML_NOTIFICATION_INDEX_PATTERN } from '../../../common/constants/index_patterns';
|
import { ML_NOTIFICATION_INDEX_PATTERN } from '../../../common/constants/index_patterns';
|
||||||
|
@ -19,7 +20,6 @@ import type {
|
||||||
NotificationsCountResponse,
|
NotificationsCountResponse,
|
||||||
NotificationsSearchResponse,
|
NotificationsSearchResponse,
|
||||||
} from '../../../common/types/notifications';
|
} from '../../../common/types/notifications';
|
||||||
import type { MlFeatures } from '../../types';
|
|
||||||
|
|
||||||
const MAX_NOTIFICATIONS_SIZE = 10000;
|
const MAX_NOTIFICATIONS_SIZE = 10000;
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,16 @@ import type { SpacesPluginSetup } from '@kbn/spaces-plugin/server';
|
||||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/server';
|
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/server';
|
||||||
import type { HomeServerPluginSetup } from '@kbn/home-plugin/server';
|
import type { HomeServerPluginSetup } from '@kbn/home-plugin/server';
|
||||||
import type { CasesSetup } from '@kbn/cases-plugin/server';
|
import type { CasesSetup } from '@kbn/cases-plugin/server';
|
||||||
import type { MlFeatures, PluginsSetup, PluginsStart, RouteInitialization } from './types';
|
import type { PluginsSetup, PluginsStart, RouteInitialization } from './types';
|
||||||
import type { MlCapabilities } from '../common/types/capabilities';
|
import type { MlCapabilities } from '../common/types/capabilities';
|
||||||
import type { ConfigSchema } from './config_schema';
|
|
||||||
import { jsonSchemaRoutes } from './routes/json_schema';
|
import { jsonSchemaRoutes } from './routes/json_schema';
|
||||||
import { notificationsRoutes } from './routes/notifications';
|
import { notificationsRoutes } from './routes/notifications';
|
||||||
import { PLUGIN_ID } from '../common/constants/app';
|
import {
|
||||||
|
type MlFeatures,
|
||||||
|
PLUGIN_ID,
|
||||||
|
type ConfigSchema,
|
||||||
|
initEnabledFeatures,
|
||||||
|
} from '../common/constants/app';
|
||||||
import { initMlServerLog } from './lib/log';
|
import { initMlServerLog } from './lib/log';
|
||||||
import { annotationRoutes } from './routes/annotations';
|
import { annotationRoutes } from './routes/annotations';
|
||||||
import { calendars } from './routes/calendars';
|
import { calendars } from './routes/calendars';
|
||||||
|
@ -102,7 +106,7 @@ export class MlServerPlugin
|
||||||
this.mlLicense = new MlLicense();
|
this.mlLicense = new MlLicense();
|
||||||
this.isMlReady = new Promise((resolve) => (this.setMlReady = resolve));
|
this.isMlReady = new Promise((resolve) => (this.setMlReady = resolve));
|
||||||
this.savedObjectsSyncService = new SavedObjectsSyncService(this.log);
|
this.savedObjectsSyncService = new SavedObjectsSyncService(this.log);
|
||||||
this.initEnabledFeatures(ctx.config.get());
|
initEnabledFeatures(this.enabledFeatures, ctx.config.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
public setup(coreSetup: CoreSetup<PluginsStart>, plugins: PluginsSetup): MlPluginSetup {
|
public setup(coreSetup: CoreSetup<PluginsStart>, plugins: PluginsSetup): MlPluginSetup {
|
||||||
|
@ -240,11 +244,11 @@ export class MlServerPlugin
|
||||||
|
|
||||||
// Register Trained Model Management routes
|
// Register Trained Model Management routes
|
||||||
if (this.enabledFeatures.dfa || this.enabledFeatures.nlp) {
|
if (this.enabledFeatures.dfa || this.enabledFeatures.nlp) {
|
||||||
modelManagementRoutes(routeInit);
|
|
||||||
trainedModelsRoutes(routeInit, plugins.cloud);
|
trainedModelsRoutes(routeInit, plugins.cloud);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register Miscellaneous routes
|
// Register Miscellaneous routes
|
||||||
|
modelManagementRoutes(routeInit);
|
||||||
dataVisualizerRoutes(routeInit);
|
dataVisualizerRoutes(routeInit);
|
||||||
fieldsService(routeInit);
|
fieldsService(routeInit);
|
||||||
indicesRoutes(routeInit);
|
indicesRoutes(routeInit);
|
||||||
|
@ -332,16 +336,4 @@ export class MlServerPlugin
|
||||||
public stop() {
|
public stop() {
|
||||||
this.mlLicense.unsubscribe();
|
this.mlLicense.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
private initEnabledFeatures(config: ConfigSchema) {
|
|
||||||
if (config.ad?.enabled !== undefined) {
|
|
||||||
this.enabledFeatures.ad = config.ad.enabled;
|
|
||||||
}
|
|
||||||
if (config.dfa?.enabled !== undefined) {
|
|
||||||
this.enabledFeatures.dfa = config.dfa.enabled;
|
|
||||||
}
|
|
||||||
if (config.nlp?.enabled !== undefined) {
|
|
||||||
this.enabledFeatures.nlp = config.nlp.enabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,10 @@ import {
|
||||||
JOB_MAP_NODE_TYPES,
|
JOB_MAP_NODE_TYPES,
|
||||||
type DeleteDataFrameAnalyticsWithIndexStatus,
|
type DeleteDataFrameAnalyticsWithIndexStatus,
|
||||||
} from '@kbn/ml-data-frame-analytics-utils';
|
} from '@kbn/ml-data-frame-analytics-utils';
|
||||||
import { ML_INTERNAL_BASE_PATH } from '../../common/constants/app';
|
import { type MlFeatures, ML_INTERNAL_BASE_PATH } from '../../common/constants/app';
|
||||||
import { wrapError } from '../client/error_wrapper';
|
import { wrapError } from '../client/error_wrapper';
|
||||||
import { analyticsAuditMessagesProvider } from '../models/data_frame_analytics/analytics_audit_messages';
|
import { analyticsAuditMessagesProvider } from '../models/data_frame_analytics/analytics_audit_messages';
|
||||||
import type { MlFeatures, RouteInitialization } from '../types';
|
import type { RouteInitialization } from '../types';
|
||||||
import {
|
import {
|
||||||
dataAnalyticsJobConfigSchema,
|
dataAnalyticsJobConfigSchema,
|
||||||
dataAnalyticsJobUpdateSchema,
|
dataAnalyticsJobUpdateSchema,
|
||||||
|
|
|
@ -8,12 +8,11 @@
|
||||||
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||||
import { schema } from '@kbn/config-schema';
|
import { schema } from '@kbn/config-schema';
|
||||||
import type { ErrorType } from '@kbn/ml-error-utils';
|
import type { ErrorType } from '@kbn/ml-error-utils';
|
||||||
import type { MlGetTrainedModelsRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
|
||||||
import { type ElserVersion } from '@kbn/ml-trained-models-utils';
|
|
||||||
import type { CloudSetup } from '@kbn/cloud-plugin/server';
|
import type { CloudSetup } from '@kbn/cloud-plugin/server';
|
||||||
|
import type { ElserVersion } from '@kbn/ml-trained-models-utils';
|
||||||
import { isDefined } from '@kbn/ml-is-defined';
|
import { isDefined } from '@kbn/ml-is-defined';
|
||||||
import { ML_INTERNAL_BASE_PATH } from '../../common/constants/app';
|
import { type MlFeatures, ML_INTERNAL_BASE_PATH } from '../../common/constants/app';
|
||||||
import type { MlFeatures, RouteInitialization } from '../types';
|
import type { RouteInitialization } from '../types';
|
||||||
import { wrapError } from '../client/error_wrapper';
|
import { wrapError } from '../client/error_wrapper';
|
||||||
import {
|
import {
|
||||||
deleteTrainedModelQuerySchema,
|
deleteTrainedModelQuerySchema,
|
||||||
|
@ -101,7 +100,7 @@ export function trainedModelsRoutes(
|
||||||
...getTrainedModelsRequestParams,
|
...getTrainedModelsRequestParams,
|
||||||
...(modelId ? { model_id: modelId } : {}),
|
...(modelId ? { model_id: modelId } : {}),
|
||||||
size: DEFAULT_TRAINED_MODELS_PAGE_SIZE,
|
size: DEFAULT_TRAINED_MODELS_PAGE_SIZE,
|
||||||
} as MlGetTrainedModelsRequest);
|
} as estypes.MlGetTrainedModelsRequest);
|
||||||
// model_type is missing
|
// model_type is missing
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const result = resp.trained_model_configs as TrainedModelConfigResponse[];
|
const result = resp.trained_model_configs as TrainedModelConfigResponse[];
|
||||||
|
|
|
@ -30,6 +30,7 @@ import type { CasesSetup } from '@kbn/cases-plugin/server';
|
||||||
import type { RouteGuard } from './lib/route_guard';
|
import type { RouteGuard } from './lib/route_guard';
|
||||||
import type { ResolveMlCapabilities } from '../common/types/capabilities';
|
import type { ResolveMlCapabilities } from '../common/types/capabilities';
|
||||||
import type { MlLicense } from '../common/license';
|
import type { MlLicense } from '../common/license';
|
||||||
|
import type { MlFeatures } from '../common/constants/app';
|
||||||
|
|
||||||
export interface LicenseCheckResult {
|
export interface LicenseCheckResult {
|
||||||
isAvailable: boolean;
|
isAvailable: boolean;
|
||||||
|
@ -82,5 +83,3 @@ export interface RouteInitialization {
|
||||||
routeGuard: RouteGuard;
|
routeGuard: RouteGuard;
|
||||||
getEnabledFeatures: () => MlFeatures;
|
getEnabledFeatures: () => MlFeatures;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MlFeatures = Record<'ad' | 'dfa' | 'nlp', boolean>;
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue