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