mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[ML] Job service refactor (#191724)
Follow on from dependancy cache removal https://github.com/elastic/kibana/pull/189729 Moving and removing as much as possible out of the `JobService` class. - Moving the job cloning functions to a separate class as they do not require the same dependancies as `JobService` - Removing api basic wrapper functions like `saveNewJob`, `openJob`, `forceStartDatafeeds` etc - Removes toast dependency. This might be controversial, but I think it is unnecessary for these basic job/datafeed loading functions to show a toast if they fail. If we cannot load the basic list of jobs then there is something else very wrong with the system. We also throw the errors, so they will not be lost. It should be up to the calling function to display a toast. Removing this dependency cleans up the code quite a lot. - The `JobCreator` classes no longer use `JobService`
This commit is contained in:
parent
08f70b7037
commit
2d40fa3311
60 changed files with 417 additions and 708 deletions
|
@ -33,7 +33,6 @@ import { withKibana } from '@kbn/kibana-react-plugin/public';
|
|||
|
||||
import { addItemToRecentlyAccessed } from '../../../util/recently_accessed';
|
||||
import { mlJobServiceFactory } from '../../../services/job_service';
|
||||
import { toastNotificationServiceProvider } from '../../../services/toast_notification_service';
|
||||
import { mlTableService } from '../../../services/table_service';
|
||||
import { ANNOTATIONS_TABLE_DEFAULT_QUERY_SIZE } from '../../../../../common/constants/search';
|
||||
import {
|
||||
|
@ -101,10 +100,7 @@ class AnnotationsTableUI extends Component {
|
|||
this.sorting = {
|
||||
sort: { field: 'timestamp', direction: 'asc' },
|
||||
};
|
||||
this.mlJobService = mlJobServiceFactory(
|
||||
toastNotificationServiceProvider(props.kibana.services.notifications.toasts),
|
||||
props.kibana.services.mlServices.mlApi
|
||||
);
|
||||
this.mlJobService = mlJobServiceFactory(props.kibana.services.mlServices.mlApi);
|
||||
}
|
||||
|
||||
getAnnotations() {
|
||||
|
|
|
@ -272,7 +272,7 @@ export const LinksMenuUI = (props: LinksMenuProps) => {
|
|||
if (dataView === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
dataView.getIndexPattern();
|
||||
const field = findMessageField(dataView);
|
||||
if (field !== null) {
|
||||
setMessageField(field);
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
ANOMALY_DETECTION_DEFAULT_TIME_RANGE,
|
||||
ANOMALY_DETECTION_ENABLE_TIME_RANGE,
|
||||
} from '../../../../common/constants/settings';
|
||||
import { useMlJobService } from '../../services/job_service';
|
||||
import { createResultsUrlForJobs } from '../../util/results_url';
|
||||
|
||||
export const useCreateADLinks = () => {
|
||||
const {
|
||||
|
@ -19,13 +19,12 @@ export const useCreateADLinks = () => {
|
|||
http: { basePath },
|
||||
},
|
||||
} = useMlKibana();
|
||||
const mlJobService = useMlJobService();
|
||||
|
||||
const useUserTimeSettings = useUiSettings().get(ANOMALY_DETECTION_ENABLE_TIME_RANGE);
|
||||
const userTimeSettings = useUiSettings().get(ANOMALY_DETECTION_DEFAULT_TIME_RANGE);
|
||||
const createLinkWithUserDefaults = useCallback(
|
||||
(location: any, jobList: any) => {
|
||||
const resultsUrl = mlJobService.createResultsUrlForJobs(
|
||||
(location, jobList) => {
|
||||
const resultsUrl = createResultsUrlForJobs(
|
||||
jobList,
|
||||
location,
|
||||
useUserTimeSettings === true && userTimeSettings !== undefined
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import type { DataFrameAnalyticsConfig } from '@kbn/ml-data-frame-analytics-utils';
|
||||
|
||||
import { createDatafeedId } from '../../../../../common/util/job_utils';
|
||||
import type { JobType } from '../../../../../common/types/saved_objects';
|
||||
import type { Job, Datafeed } from '../../../../../common/types/anomaly_detection_jobs';
|
||||
import type { Filter } from '../../../../../common/types/filters';
|
||||
|
@ -105,7 +106,7 @@ export class JobImportService {
|
|||
const { jobId } = jobIds[i];
|
||||
j.job.job_id = jobId;
|
||||
j.datafeed.job_id = jobId;
|
||||
j.datafeed.datafeed_id = `datafeed-${jobId}`;
|
||||
j.datafeed.datafeed_id = createDatafeedId(jobId);
|
||||
return j;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -81,10 +81,7 @@ class RuleEditorFlyoutUI extends Component {
|
|||
this.partitioningFieldNames = [];
|
||||
this.canGetFilters = checkPermission('canGetFilters');
|
||||
|
||||
this.mlJobService = mlJobServiceFactory(
|
||||
toastNotificationServiceProvider(props.kibana.services.notifications.toasts),
|
||||
props.kibana.services.mlServices.mlApi
|
||||
);
|
||||
this.mlJobService = mlJobServiceFactory(props.kibana.services.mlServices.mlApi);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
|
|
@ -19,10 +19,9 @@ import {
|
|||
EuiButton,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useMlKibana } from '../../../../contexts/kibana';
|
||||
import { useMlApi, useMlKibana } from '../../../../contexts/kibana';
|
||||
import type { MlSummaryJob } from '../../../../../../common/types/anomaly_detection_jobs';
|
||||
import { isManagedJob } from '../../../jobs_utils';
|
||||
import { useMlJobService } from '../../../../services/job_service';
|
||||
import { closeJobs } from '../utils';
|
||||
import { ManagedJobsWarningCallout } from './managed_jobs_warning_callout';
|
||||
|
||||
|
@ -44,7 +43,7 @@ export const CloseJobsConfirmModal: FC<Props> = ({
|
|||
notifications: { toasts },
|
||||
},
|
||||
} = useMlKibana();
|
||||
const mlJobService = useMlJobService();
|
||||
const mlApi = useMlApi();
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [hasManagedJob, setHasManaged] = useState(true);
|
||||
const [jobsToReset, setJobsToReset] = useState<MlSummaryJob[]>([]);
|
||||
|
@ -121,7 +120,7 @@ export const CloseJobsConfirmModal: FC<Props> = ({
|
|||
|
||||
<EuiButton
|
||||
onClick={() => {
|
||||
closeJobs(toasts, mlJobService, jobsToReset, refreshJobs);
|
||||
closeJobs(toasts, mlApi, jobsToReset, refreshJobs);
|
||||
closeModal();
|
||||
}}
|
||||
fill
|
||||
|
|
|
@ -19,10 +19,9 @@ import {
|
|||
EuiButton,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useMlKibana } from '../../../../contexts/kibana';
|
||||
import { useMlApi, useMlKibana } from '../../../../contexts/kibana';
|
||||
import type { MlSummaryJob } from '../../../../../../common/types/anomaly_detection_jobs';
|
||||
import { isManagedJob } from '../../../jobs_utils';
|
||||
import { useMlJobService } from '../../../../services/job_service';
|
||||
import { stopDatafeeds } from '../utils';
|
||||
import { ManagedJobsWarningCallout } from './managed_jobs_warning_callout';
|
||||
|
||||
|
@ -45,7 +44,7 @@ export const StopDatafeedsConfirmModal: FC<Props> = ({
|
|||
notifications: { toasts },
|
||||
},
|
||||
} = useMlKibana();
|
||||
const mlJobService = useMlJobService();
|
||||
const mlApi = useMlApi();
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [hasManagedJob, setHasManaged] = useState(true);
|
||||
const [jobsToStop, setJobsToStop] = useState<MlSummaryJob[]>([]);
|
||||
|
@ -122,7 +121,7 @@ export const StopDatafeedsConfirmModal: FC<Props> = ({
|
|||
|
||||
<EuiButton
|
||||
onClick={() => {
|
||||
stopDatafeeds(toasts, mlJobService, jobsToStop, refreshJobs);
|
||||
stopDatafeeds(toasts, mlApi, jobsToStop, refreshJobs);
|
||||
closeModal();
|
||||
}}
|
||||
fill
|
||||
|
|
|
@ -23,11 +23,10 @@ import {
|
|||
} from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useMlKibana } from '../../../../contexts/kibana';
|
||||
import { useMlApi, useMlKibana } from '../../../../contexts/kibana';
|
||||
import { deleteJobs } from '../utils';
|
||||
import { BLOCKED_JOBS_REFRESH_INTERVAL_MS } from '../../../../../../common/constants/jobs_list';
|
||||
import { DeleteSpaceAwareItemCheckModal } from '../../../../components/delete_space_aware_item_check_modal';
|
||||
import { useMlJobService } from '../../../../services/job_service';
|
||||
import type { MlSummaryJob } from '../../../../../../common/types/anomaly_detection_jobs';
|
||||
import { isManagedJob } from '../../../jobs_utils';
|
||||
import { ManagedJobsWarningCallout } from '../confirm_modals/managed_jobs_warning_callout';
|
||||
|
@ -46,7 +45,7 @@ export const DeleteJobModal: FC<Props> = ({ setShowFunction, unsetShowFunction,
|
|||
notifications: { toasts },
|
||||
},
|
||||
} = useMlKibana();
|
||||
const mlJobService = useMlJobService();
|
||||
const mlApi = useMlApi();
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [adJobs, setAdJobs] = useState<MlSummaryJob[]>([]);
|
||||
|
@ -92,7 +91,7 @@ export const DeleteJobModal: FC<Props> = ({ setShowFunction, unsetShowFunction,
|
|||
setDeleting(true);
|
||||
deleteJobs(
|
||||
toasts,
|
||||
mlJobService,
|
||||
mlApi,
|
||||
jobIds.map((id) => ({ id })),
|
||||
deleteUserAnnotations,
|
||||
deleteAlertingRules
|
||||
|
@ -102,9 +101,7 @@ export const DeleteJobModal: FC<Props> = ({ setShowFunction, unsetShowFunction,
|
|||
closeModal();
|
||||
refreshJobs();
|
||||
}, BLOCKED_JOBS_REFRESH_INTERVAL_MS);
|
||||
// exclude mlJobservice from deps
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [jobIds, deleteUserAnnotations, deleteAlertingRules, closeModal, refreshJobs]);
|
||||
}, [toasts, mlApi, jobIds, deleteUserAnnotations, deleteAlertingRules, closeModal, refreshJobs]);
|
||||
|
||||
if (modalVisible === false || jobIds.length === 0) {
|
||||
return null;
|
||||
|
|
|
@ -13,8 +13,6 @@ import { EuiFieldText, EuiForm, EuiFormRow, EuiSpacer, EuiTitle } from '@elastic
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { context } from '@kbn/kibana-react-plugin/public';
|
||||
|
||||
import { mlJobServiceFactory } from '../../../../../services/job_service';
|
||||
import { toastNotificationServiceProvider } from '../../../../../services/toast_notification_service';
|
||||
import { detectorToString } from '../../../../../util/string_utils';
|
||||
|
||||
export class Detectors extends Component {
|
||||
|
@ -23,13 +21,6 @@ export class Detectors extends Component {
|
|||
constructor(props, constructorContext) {
|
||||
super(props, constructorContext);
|
||||
|
||||
const mlJobService = mlJobServiceFactory(
|
||||
toastNotificationServiceProvider(constructorContext.services.notifications.toasts),
|
||||
constructorContext.services.mlServices.mlApi
|
||||
);
|
||||
|
||||
this.detectors = mlJobService.getJobGroups().map((g) => ({ label: g.id }));
|
||||
|
||||
this.state = {
|
||||
detectors: [],
|
||||
detectorDescriptions: [],
|
||||
|
|
|
@ -25,7 +25,6 @@ export function actionsMenuContent(
|
|||
toastNotifications,
|
||||
application,
|
||||
mlApi,
|
||||
mlJobService,
|
||||
showEditJobFlyout,
|
||||
showDatafeedChartFlyout,
|
||||
showDeleteJobModal,
|
||||
|
@ -77,7 +76,7 @@ export function actionsMenuContent(
|
|||
if (isManagedJob(item)) {
|
||||
showStopDatafeedsConfirmModal([item]);
|
||||
} else {
|
||||
stopDatafeeds(toastNotifications, mlJobService, [item], refreshJobs);
|
||||
stopDatafeeds(toastNotifications, mlApi, [item], refreshJobs);
|
||||
}
|
||||
|
||||
closeMenu(true);
|
||||
|
@ -114,7 +113,7 @@ export function actionsMenuContent(
|
|||
if (isManagedJob(item)) {
|
||||
showCloseJobsConfirmModal([item]);
|
||||
} else {
|
||||
closeJobs(toastNotifications, mlJobService, [item], refreshJobs);
|
||||
closeJobs(toastNotifications, mlApi, [item], refreshJobs);
|
||||
}
|
||||
|
||||
closeMenu(true);
|
||||
|
@ -153,7 +152,7 @@ export function actionsMenuContent(
|
|||
return isJobBlocked(item) === false && canCreateJob;
|
||||
},
|
||||
onClick: (item) => {
|
||||
cloneJob(toastNotifications, application, mlApi, mlJobService, item.id);
|
||||
cloneJob(toastNotifications, application, mlApi, item.id);
|
||||
closeMenu(true);
|
||||
},
|
||||
'data-test-subj': 'mlActionButtonCloneJob',
|
||||
|
|
|
@ -32,8 +32,6 @@ import { i18n } from '@kbn/i18n';
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { AnomalyDetectionJobIdLink } from './job_id_link';
|
||||
import { isManagedJob } from '../../../jobs_utils';
|
||||
import { mlJobServiceFactory } from '../../../../services/job_service';
|
||||
import { toastNotificationServiceProvider } from '../../../../services/toast_notification_service';
|
||||
|
||||
const PAGE_SIZE_OPTIONS = [10, 25, 50];
|
||||
|
||||
|
@ -47,10 +45,6 @@ export class JobsListUI extends Component {
|
|||
};
|
||||
|
||||
this.mlApi = props.kibana.services.mlServices.mlApi;
|
||||
this.mlJobService = mlJobServiceFactory(
|
||||
toastNotificationServiceProvider(props.kibana.services.notifications.toasts),
|
||||
this.mlApi
|
||||
);
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(props) {
|
||||
|
@ -341,7 +335,6 @@ export class JobsListUI extends Component {
|
|||
this.props.kibana.services.notifications.toasts,
|
||||
this.props.kibana.services.application,
|
||||
this.mlApi,
|
||||
this.mlJobService,
|
||||
this.props.showEditJobFlyout,
|
||||
this.props.showDatafeedChartFlyout,
|
||||
this.props.showDeleteJobModal,
|
||||
|
|
|
@ -10,7 +10,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
|
|||
|
||||
import { withKibana } from '@kbn/kibana-react-plugin/public';
|
||||
|
||||
import { checkForAutoStartDatafeed, filterJobs, loadFullJob } from '../utils';
|
||||
import { filterJobs, loadFullJob } from '../utils';
|
||||
import { JobsList } from '../jobs_list';
|
||||
import { JobDetails } from '../job_details';
|
||||
import { JobFilterBar } from '../job_filter_bar';
|
||||
|
@ -37,8 +37,7 @@ import { StopDatafeedsConfirmModal } from '../confirm_modals/stop_datafeeds_conf
|
|||
import { CloseJobsConfirmModal } from '../confirm_modals/close_jobs_confirm_modal';
|
||||
import { AnomalyDetectionEmptyState } from '../anomaly_detection_empty_state';
|
||||
import { removeNodeInfo } from '../../../../../../common/util/job_utils';
|
||||
import { mlJobServiceFactory } from '../../../../services/job_service';
|
||||
import { toastNotificationServiceProvider } from '../../../../services/toast_notification_service';
|
||||
import { jobCloningService } from '../../../../services/job_cloning_service';
|
||||
|
||||
let blockingJobsRefreshTimeout = null;
|
||||
|
||||
|
@ -80,11 +79,6 @@ export class JobsListViewUI extends Component {
|
|||
* @private
|
||||
*/
|
||||
this._isFiltersSet = false;
|
||||
|
||||
this.mlJobService = mlJobServiceFactory(
|
||||
toastNotificationServiceProvider(props.kibana.services.notifications.toasts),
|
||||
props.kibana.services.mlServices.mlApi
|
||||
);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -106,7 +100,7 @@ export class JobsListViewUI extends Component {
|
|||
}
|
||||
|
||||
openAutoStartDatafeedModal() {
|
||||
const job = checkForAutoStartDatafeed(this.mlJobService);
|
||||
const job = jobCloningService.checkForAutoStartDatafeed();
|
||||
if (job !== undefined) {
|
||||
this.showStartDatafeedModal([job]);
|
||||
}
|
||||
|
|
|
@ -16,8 +16,6 @@ import { context } from '@kbn/kibana-react-plugin/public';
|
|||
|
||||
import { checkPermission } from '../../../../capabilities/check_capabilities';
|
||||
import { mlNodesAvailable } from '../../../../ml_nodes_check/check_ml_nodes';
|
||||
import { mlJobServiceFactory } from '../../../../services/job_service';
|
||||
import { toastNotificationServiceProvider } from '../../../../services/toast_notification_service';
|
||||
|
||||
import { isManagedJob } from '../../../jobs_utils';
|
||||
|
||||
|
@ -46,12 +44,8 @@ class MultiJobActionsMenuUI extends Component {
|
|||
this.canResetJob = checkPermission('canResetJob') && mlNodesAvailable();
|
||||
this.canCreateMlAlerts = checkPermission('canCreateMlAlerts');
|
||||
|
||||
this.toastNoticiations = constructorContext.services.notifications.toasts;
|
||||
const mlApi = constructorContext.services.mlServices.mlApi;
|
||||
const toastNotificationService = toastNotificationServiceProvider(
|
||||
constructorContext.services.notifications.toasts
|
||||
);
|
||||
this.mlJobService = mlJobServiceFactory(toastNotificationService, mlApi);
|
||||
this.toastNotifications = constructorContext.services.notifications.toasts;
|
||||
this.mlApi = constructorContext.services.mlServices.mlApi;
|
||||
}
|
||||
|
||||
onButtonClick = () => {
|
||||
|
@ -116,7 +110,7 @@ class MultiJobActionsMenuUI extends Component {
|
|||
if (this.props.jobs.some((j) => isManagedJob(j))) {
|
||||
this.props.showCloseJobsConfirmModal(this.props.jobs);
|
||||
} else {
|
||||
closeJobs(this.toastNotifications, this.mlJobService, this.props.jobs);
|
||||
closeJobs(this.toastNotifications, this.mlApi, this.props.jobs);
|
||||
}
|
||||
|
||||
this.closePopover();
|
||||
|
@ -163,7 +157,12 @@ class MultiJobActionsMenuUI extends Component {
|
|||
if (this.props.jobs.some((j) => isManagedJob(j))) {
|
||||
this.props.showStopDatafeedsConfirmModal(this.props.jobs);
|
||||
} else {
|
||||
stopDatafeeds(this.props.jobs, this.props.refreshJobs);
|
||||
stopDatafeeds(
|
||||
this.toastNotifications,
|
||||
this.mlApi,
|
||||
this.props.jobs,
|
||||
this.props.refreshJobs
|
||||
);
|
||||
}
|
||||
this.closePopover();
|
||||
}}
|
||||
|
|
|
@ -158,8 +158,8 @@ export class GroupSelectorUI extends Component {
|
|||
}
|
||||
|
||||
const tempJobs = newJobs.map((j) => ({ jobId: j.id, groups: j.newGroups }));
|
||||
const ml = this.props.kibana.services.mlServices.mlApi;
|
||||
ml.jobs
|
||||
const mlApi = this.props.kibana.services.mlServices.mlApi;
|
||||
mlApi.jobs
|
||||
.updateGroups(tempJobs)
|
||||
.then((resp) => {
|
||||
let success = true;
|
||||
|
|
|
@ -25,8 +25,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { resetJobs } from '../utils';
|
||||
import type { MlSummaryJob } from '../../../../../../common/types/anomaly_detection_jobs';
|
||||
import { RESETTING_JOBS_REFRESH_INTERVAL_MS } from '../../../../../../common/constants/jobs_list';
|
||||
import { useMlKibana } from '../../../../contexts/kibana';
|
||||
import { useMlJobService } from '../../../../services/job_service';
|
||||
import { useMlApi, useMlKibana } from '../../../../contexts/kibana';
|
||||
import { OpenJobsWarningCallout } from './open_jobs_warning_callout';
|
||||
import { isManagedJob } from '../../../jobs_utils';
|
||||
import { ManagedJobsWarningCallout } from '../confirm_modals/managed_jobs_warning_callout';
|
||||
|
@ -45,7 +44,7 @@ export const ResetJobModal: FC<Props> = ({ setShowFunction, unsetShowFunction, r
|
|||
notifications: { toasts },
|
||||
},
|
||||
} = useMlKibana();
|
||||
const mlJobService = useMlJobService();
|
||||
const mlApi = useMlApi();
|
||||
const [resetting, setResetting] = useState(false);
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [jobIds, setJobIds] = useState<string[]>([]);
|
||||
|
@ -81,14 +80,12 @@ export const ResetJobModal: FC<Props> = ({ setShowFunction, unsetShowFunction, r
|
|||
|
||||
const resetJob = useCallback(async () => {
|
||||
setResetting(true);
|
||||
await resetJobs(toasts, mlJobService, jobIds, deleteUserAnnotations);
|
||||
await resetJobs(toasts, mlApi, jobIds, deleteUserAnnotations);
|
||||
closeModal();
|
||||
setTimeout(() => {
|
||||
refreshJobs();
|
||||
}, RESETTING_JOBS_REFRESH_INTERVAL_MS);
|
||||
// exclude mlJobservice from deps
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [closeModal, deleteUserAnnotations, jobIds, refreshJobs]);
|
||||
}, [closeModal, deleteUserAnnotations, jobIds, mlApi, refreshJobs, toasts]);
|
||||
|
||||
if (modalVisible === false || jobIds.length === 0) {
|
||||
return null;
|
||||
|
|
|
@ -24,9 +24,6 @@ import {
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { context } from '@kbn/kibana-react-plugin/public';
|
||||
|
||||
import { mlJobServiceFactory } from '../../../../services/job_service';
|
||||
import { toastNotificationServiceProvider } from '../../../../services/toast_notification_service';
|
||||
|
||||
import { isManagedJob } from '../../../jobs_utils';
|
||||
|
||||
import { forceStartDatafeeds } from '../utils';
|
||||
|
@ -57,10 +54,7 @@ export class StartDatafeedModal extends Component {
|
|||
this.refreshJobs = this.props.refreshJobs;
|
||||
this.getShowCreateAlertFlyoutFunction = this.props.getShowCreateAlertFlyoutFunction;
|
||||
this.toastNotifications = constructorContext.services.notifications.toasts;
|
||||
this.mlJobService = mlJobServiceFactory(
|
||||
toastNotificationServiceProvider(this.toastNotifications),
|
||||
constructorContext.services.mlServices.mlApi
|
||||
);
|
||||
this.mlApi = constructorContext.services.mlServices.mlApi;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -125,7 +119,7 @@ export class StartDatafeedModal extends Component {
|
|||
? this.state.endTime.valueOf()
|
||||
: this.state.endTime;
|
||||
|
||||
forceStartDatafeeds(this.toastNotifications, this.mlJobService, jobs, start, end, () => {
|
||||
forceStartDatafeeds(this.toastNotifications, this.mlApi, jobs, start, end, () => {
|
||||
if (this.state.createAlert && jobs.length > 0) {
|
||||
this.getShowCreateAlertFlyoutFunction()(jobs.map((job) => job.id));
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import type {
|
|||
CombinedJobWithStats,
|
||||
MlSummaryJob,
|
||||
} from '../../../../../common/types/anomaly_detection_jobs';
|
||||
import type { MlJobService } from '../../../services/job_service';
|
||||
import type { MlApi } from '../../../services/ml_api_service';
|
||||
|
||||
export function loadFullJob(mlApi: MlApi, jobId: string): Promise<CombinedJobWithStats>;
|
||||
|
@ -22,7 +21,7 @@ export function isClosable(jobs: CombinedJobWithStats[]): boolean;
|
|||
export function isResettable(jobs: CombinedJobWithStats[]): boolean;
|
||||
export function forceStartDatafeeds(
|
||||
toastNotifications: ToastsStart,
|
||||
mlJobService: MlJobService,
|
||||
mlApi: MlApi,
|
||||
jobs: CombinedJobWithStats[],
|
||||
start: number | undefined,
|
||||
end: number | undefined,
|
||||
|
@ -30,7 +29,7 @@ export function forceStartDatafeeds(
|
|||
): Promise<void>;
|
||||
export function stopDatafeeds(
|
||||
toastNotifications: ToastsStart,
|
||||
mlJobService: MlJobService,
|
||||
mlApi: MlApi,
|
||||
jobs: CombinedJobWithStats[] | MlSummaryJob[],
|
||||
finish?: () => void
|
||||
): Promise<void>;
|
||||
|
@ -43,18 +42,17 @@ export function cloneJob(
|
|||
toastNotifications: ToastsStart,
|
||||
application: ApplicationStart,
|
||||
mlApi: MlApi,
|
||||
mlJobService: MlJobService,
|
||||
jobId: string
|
||||
): Promise<void>;
|
||||
export function closeJobs(
|
||||
toastNotifications: ToastsStart,
|
||||
mlJobService: MlJobService,
|
||||
mlApi: MlApi,
|
||||
jobs: CombinedJobWithStats[] | MlSummaryJob[],
|
||||
finish?: () => void
|
||||
): Promise<void>;
|
||||
export function deleteJobs(
|
||||
toastNotifications: ToastsStart,
|
||||
mlJobService: MlJobService,
|
||||
mlApi: MlApi,
|
||||
jobs: Array<{ id: string }>,
|
||||
deleteUserAnnotations?: boolean,
|
||||
deleteAlertingRules?: boolean,
|
||||
|
@ -62,7 +60,7 @@ export function deleteJobs(
|
|||
): Promise<void>;
|
||||
export function resetJobs(
|
||||
toastNotifications: ToastsStart,
|
||||
mlJobService: MlJobService,
|
||||
mlApi: MlApi,
|
||||
jobIds: string[],
|
||||
deleteUserAnnotations?: boolean,
|
||||
finish?: () => void
|
||||
|
@ -73,8 +71,3 @@ export function filterJobs(
|
|||
): CombinedJobWithStats[];
|
||||
export function jobProperty(job: CombinedJobWithStats, prop: string): any;
|
||||
export function jobTagFilter(jobs: CombinedJobWithStats[], value: string): CombinedJobWithStats[];
|
||||
export function checkForAutoStartDatafeed(
|
||||
mlJobService: MlJobService
|
||||
):
|
||||
| { id: string; hasDatafeed: boolean; latestTimestampSortValue: number; datafeedId: string }
|
||||
| undefined;
|
||||
|
|
|
@ -14,7 +14,7 @@ import { JOB_STATE, DATAFEED_STATE } from '../../../../../common/constants/state
|
|||
import { JOB_ACTION } from '../../../../../common/constants/job_actions';
|
||||
import { parseInterval } from '../../../../../common/util/parse_interval';
|
||||
import { mlCalendarService } from '../../../services/calendar_service';
|
||||
import { isPopulatedObject } from '@kbn/ml-is-populated-object';
|
||||
import { jobCloningService } from '../../../services/job_cloning_service';
|
||||
import { ML_PAGES } from '../../../../../common/constants/locator';
|
||||
import { PLUGIN_ID } from '../../../../../common/constants/app';
|
||||
import { CREATED_BY_LABEL } from '../../../../../common/constants/new_job';
|
||||
|
@ -82,14 +82,14 @@ export function isResettable(jobs) {
|
|||
|
||||
export function forceStartDatafeeds(
|
||||
toastNotifications,
|
||||
mlJobService,
|
||||
mlApi,
|
||||
jobs,
|
||||
start,
|
||||
end,
|
||||
finish = () => {}
|
||||
) {
|
||||
const datafeedIds = jobs.filter((j) => j.hasDatafeed).map((j) => j.datafeedId);
|
||||
mlJobService
|
||||
mlApi.jobs
|
||||
.forceStartDatafeeds(datafeedIds, start, end)
|
||||
.then((resp) => {
|
||||
showResults(toastNotifications, resp, DATAFEED_STATE.STARTED);
|
||||
|
@ -106,9 +106,9 @@ export function forceStartDatafeeds(
|
|||
});
|
||||
}
|
||||
|
||||
export function stopDatafeeds(toastNotifications, mlJobService, jobs, finish = () => {}) {
|
||||
export function stopDatafeeds(toastNotifications, mlApi, jobs, finish = () => {}) {
|
||||
const datafeedIds = jobs.filter((j) => j.hasDatafeed).map((j) => j.datafeedId);
|
||||
mlJobService
|
||||
mlApi.jobs
|
||||
.stopDatafeeds(datafeedIds)
|
||||
.then((resp) => {
|
||||
showResults(toastNotifications, resp, DATAFEED_STATE.STOPPED);
|
||||
|
@ -214,13 +214,17 @@ function showResults(toastNotifications, resp, action) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function cloneJob(toastNotifications, application, mlApi, mlJobService, jobId) {
|
||||
export async function cloneJob(toastNotifications, application, mlApi, jobId) {
|
||||
try {
|
||||
const [{ job: cloneableJob, datafeed }, originalJob] = await Promise.all([
|
||||
loadJobForCloning(mlApi, jobId),
|
||||
loadFullJob(mlApi, jobId),
|
||||
]);
|
||||
|
||||
const tempJobCloningData = {
|
||||
skipTimeRangeStep: false,
|
||||
};
|
||||
|
||||
const createdBy = originalJob?.custom_settings?.created_by;
|
||||
if (
|
||||
cloneableJob !== undefined &&
|
||||
|
@ -228,9 +232,9 @@ export async function cloneJob(toastNotifications, application, mlApi, mlJobServ
|
|||
createdBy !== CREATED_BY_LABEL.ADVANCED
|
||||
) {
|
||||
// if the job is from a wizards, i.e. contains a created_by property
|
||||
// use tempJobCloningObjects to temporarily store the job
|
||||
mlJobService.tempJobCloningObjects.createdBy = originalJob?.custom_settings?.created_by;
|
||||
mlJobService.tempJobCloningObjects.job = cloneableJob;
|
||||
// use tempJobCloningData to temporarily store the job
|
||||
tempJobCloningData.createdBy = originalJob?.custom_settings?.created_by;
|
||||
tempJobCloningData.job = cloneableJob;
|
||||
|
||||
if (
|
||||
originalJob.data_counts.earliest_record_timestamp !== undefined &&
|
||||
|
@ -256,26 +260,28 @@ export async function cloneJob(toastNotifications, application, mlApi, mlJobServ
|
|||
end = originalJob.data_counts.latest_bucket_timestamp + bucketSpanMs * 2 - 1;
|
||||
}
|
||||
|
||||
mlJobService.tempJobCloningObjects.start = start;
|
||||
mlJobService.tempJobCloningObjects.end = end;
|
||||
tempJobCloningData.start = start;
|
||||
tempJobCloningData.end = end;
|
||||
}
|
||||
} else {
|
||||
// otherwise use the tempJobCloningObjects
|
||||
mlJobService.tempJobCloningObjects.job = cloneableJob;
|
||||
// otherwise tempJobCloningData
|
||||
tempJobCloningData.job = cloneableJob;
|
||||
// resets the createdBy field in case it still retains previous settings
|
||||
mlJobService.tempJobCloningObjects.createdBy = undefined;
|
||||
tempJobCloningData.createdBy = undefined;
|
||||
}
|
||||
if (datafeed !== undefined) {
|
||||
mlJobService.tempJobCloningObjects.datafeed = datafeed;
|
||||
tempJobCloningData.datafeed = datafeed;
|
||||
}
|
||||
|
||||
if (originalJob.calendars) {
|
||||
mlJobService.tempJobCloningObjects.calendars = await mlCalendarService.fetchCalendarsByIds(
|
||||
tempJobCloningData.calendars = await mlCalendarService.fetchCalendarsByIds(
|
||||
mlApi,
|
||||
originalJob.calendars
|
||||
);
|
||||
}
|
||||
|
||||
jobCloningService.stashJobCloningData(tempJobCloningData);
|
||||
|
||||
application.navigateToApp(PLUGIN_ID, { path: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB });
|
||||
} catch (error) {
|
||||
toastNotificationServiceProvider(toastNotifications).displayErrorToast(
|
||||
|
@ -288,9 +294,9 @@ export async function cloneJob(toastNotifications, application, mlApi, mlJobServ
|
|||
}
|
||||
}
|
||||
|
||||
export function closeJobs(toastNotifications, mlJobService, jobs, finish = () => {}) {
|
||||
export function closeJobs(toastNotifications, mlApi, jobs, finish = () => {}) {
|
||||
const jobIds = jobs.map((j) => j.id);
|
||||
mlJobService
|
||||
mlApi.jobs
|
||||
.closeJobs(jobIds)
|
||||
.then((resp) => {
|
||||
showResults(toastNotifications, resp, JOB_STATE.CLOSED);
|
||||
|
@ -309,12 +315,12 @@ export function closeJobs(toastNotifications, mlJobService, jobs, finish = () =>
|
|||
|
||||
export function resetJobs(
|
||||
toastNotifications,
|
||||
mlJobService,
|
||||
mlApi,
|
||||
jobIds,
|
||||
deleteUserAnnotations,
|
||||
finish = () => {}
|
||||
) {
|
||||
mlJobService
|
||||
mlApi.jobs
|
||||
.resetJobs(jobIds, deleteUserAnnotations)
|
||||
.then((resp) => {
|
||||
showResults(toastNotifications, resp, JOB_ACTION.RESET);
|
||||
|
@ -333,14 +339,14 @@ export function resetJobs(
|
|||
|
||||
export function deleteJobs(
|
||||
toastNotifications,
|
||||
mlJobService,
|
||||
mlApi,
|
||||
jobs,
|
||||
deleteUserAnnotations,
|
||||
deleteAlertingRules,
|
||||
finish = () => {}
|
||||
) {
|
||||
const jobIds = jobs.map((j) => j.id);
|
||||
mlJobService
|
||||
mlApi.jobs
|
||||
.deleteJobs(jobIds, deleteUserAnnotations, deleteAlertingRules)
|
||||
.then((resp) => {
|
||||
showResults(toastNotifications, resp, JOB_STATE.DELETED);
|
||||
|
@ -449,24 +455,3 @@ function jobTagFilter(jobs, value) {
|
|||
.find((t) => value.some((t1) => t1 === t));
|
||||
});
|
||||
}
|
||||
// check to see if a job has been stored in mlJobService.tempJobCloningObjects
|
||||
// if it has, return an object with the minimum properties needed for the
|
||||
// start datafeed modal.
|
||||
export function checkForAutoStartDatafeed(mlJobService) {
|
||||
const job = mlJobService.tempJobCloningObjects.job;
|
||||
const datafeed = mlJobService.tempJobCloningObjects.datafeed;
|
||||
if (job !== undefined) {
|
||||
mlJobService.tempJobCloningObjects.job = undefined;
|
||||
mlJobService.tempJobCloningObjects.datafeed = undefined;
|
||||
mlJobService.tempJobCloningObjects.createdBy = undefined;
|
||||
|
||||
const hasDatafeed = isPopulatedObject(datafeed);
|
||||
const datafeedId = hasDatafeed ? datafeed.datafeed_id : '';
|
||||
return {
|
||||
id: job.job_id,
|
||||
hasDatafeed,
|
||||
latestTimestampSortValue: 0,
|
||||
datafeedId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import type { DataView } from '@kbn/data-views-plugin/public';
|
|||
import type { Field, Aggregation, SplitField } from '@kbn/ml-anomaly-utils';
|
||||
import type { SavedSearch } from '@kbn/saved-search-plugin/public';
|
||||
|
||||
import type { MlJobService } from '../../../../services/job_service';
|
||||
import type { MlApi } from '../../../../services/ml_api_service';
|
||||
import { JobCreator } from './job_creator';
|
||||
import type {
|
||||
|
@ -44,13 +43,12 @@ export class AdvancedJobCreator extends JobCreator {
|
|||
|
||||
constructor(
|
||||
mlApi: MlApi,
|
||||
mlJobService: MlJobService,
|
||||
newJobCapsService: NewJobCapsService,
|
||||
indexPattern: DataView,
|
||||
savedSearch: SavedSearch | null,
|
||||
query: object
|
||||
) {
|
||||
super(mlApi, mlJobService, newJobCapsService, indexPattern, savedSearch, query);
|
||||
super(mlApi, newJobCapsService, indexPattern, savedSearch, query);
|
||||
this.createdBy = CREATED_BY_LABEL.ADVANCED;
|
||||
|
||||
this._queryString = JSON.stringify(this._datafeed_config.query);
|
||||
|
|
|
@ -34,7 +34,6 @@ import {
|
|||
DEFAULT_BUCKET_SPAN,
|
||||
DEFAULT_RARE_BUCKET_SPAN,
|
||||
} from '../../../../../../common/constants/new_job';
|
||||
import type { MlJobService } from '../../../../services/job_service';
|
||||
import type { MlApi } from '../../../../services/ml_api_service';
|
||||
import type { NewJobCapsService } from '../../../../services/new_job_capabilities/new_job_capabilities_service';
|
||||
|
||||
|
@ -66,13 +65,12 @@ export class CategorizationJobCreator extends JobCreator {
|
|||
|
||||
constructor(
|
||||
mlApi: MlApi,
|
||||
mlJobService: MlJobService,
|
||||
newJobCapsService: NewJobCapsService,
|
||||
indexPattern: DataView,
|
||||
savedSearch: SavedSearch | null,
|
||||
query: object
|
||||
) {
|
||||
super(mlApi, mlJobService, newJobCapsService, indexPattern, savedSearch, query);
|
||||
super(mlApi, newJobCapsService, indexPattern, savedSearch, query);
|
||||
this.createdBy = CREATED_BY_LABEL.CATEGORIZATION;
|
||||
this._examplesLoader = new CategorizationExamplesLoader(this, indexPattern, query);
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
import type { DataView } from '@kbn/data-views-plugin/public';
|
||||
import type { Field, Aggregation, SplitField, AggFieldPair } from '@kbn/ml-anomaly-utils';
|
||||
import type { SavedSearch } from '@kbn/saved-search-plugin/public';
|
||||
import type { MlJobService } from '../../../../services/job_service';
|
||||
import type { MlApi } from '../../../../services/ml_api_service';
|
||||
import type { NewJobCapsService } from '../../../../services/new_job_capabilities/new_job_capabilities_service';
|
||||
import { JobCreator } from './job_creator';
|
||||
|
@ -32,13 +31,12 @@ export class GeoJobCreator extends JobCreator {
|
|||
|
||||
constructor(
|
||||
mlApi: MlApi,
|
||||
mlJobService: MlJobService,
|
||||
newJobCapsService: NewJobCapsService,
|
||||
indexPattern: DataView,
|
||||
savedSearch: SavedSearch | null,
|
||||
query: object
|
||||
) {
|
||||
super(mlApi, mlJobService, newJobCapsService, indexPattern, savedSearch, query);
|
||||
super(mlApi, newJobCapsService, indexPattern, savedSearch, query);
|
||||
this.createdBy = CREATED_BY_LABEL.GEO;
|
||||
this._wizardInitialized$.next(true);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
import type { RuntimeMappings } from '@kbn/ml-runtime-field-utils';
|
||||
import type { SavedSearch } from '@kbn/saved-search-plugin/public';
|
||||
import { isPopulatedObject } from '@kbn/ml-is-populated-object';
|
||||
import { createDatafeedId } from '../../../../../../common/util/job_utils';
|
||||
import type { MlApi } from '../../../../services/ml_api_service';
|
||||
import type { IndexPatternTitle } from '../../../../../../common/types/kibana';
|
||||
import { getQueryFromSavedSearchObject } from '../../../../util/index_utils';
|
||||
|
@ -36,7 +37,6 @@ import type {
|
|||
} from '../../../../../../common/types/anomaly_detection_jobs';
|
||||
import { combineFieldsAndAggs } from '../../../../../../common/util/fields_utils';
|
||||
import { createEmptyJob, createEmptyDatafeed } from './util/default_configs';
|
||||
import type { MlJobService } from '../../../../services/job_service';
|
||||
import { JobRunner, type ProgressSubscriber } from '../job_runner';
|
||||
import type { CREATED_BY_LABEL } from '../../../../../../common/constants/new_job';
|
||||
import { JOB_TYPE, SHARED_RESULTS_INDEX_NAME } from '../../../../../../common/constants/new_job';
|
||||
|
@ -80,19 +80,16 @@ export class JobCreator {
|
|||
protected _wizardInitialized$ = new BehaviorSubject<boolean>(false);
|
||||
public wizardInitialized$ = this._wizardInitialized$.asObservable();
|
||||
public mlApi: MlApi;
|
||||
public mlJobService: MlJobService;
|
||||
public newJobCapsService: NewJobCapsService;
|
||||
|
||||
constructor(
|
||||
mlApi: MlApi,
|
||||
mlJobService: MlJobService,
|
||||
newJobCapsService: NewJobCapsService,
|
||||
indexPattern: DataView,
|
||||
savedSearch: SavedSearch | null,
|
||||
query: object
|
||||
) {
|
||||
this.mlApi = mlApi;
|
||||
this.mlJobService = mlJobService;
|
||||
this.newJobCapsService = newJobCapsService;
|
||||
this._indexPattern = indexPattern;
|
||||
this._savedSearch = savedSearch;
|
||||
|
@ -241,7 +238,7 @@ export class JobCreator {
|
|||
public set jobId(jobId: JobId) {
|
||||
this._job_config.job_id = jobId;
|
||||
this._datafeed_config.job_id = jobId;
|
||||
this._datafeed_config.datafeed_id = `datafeed-${jobId}`;
|
||||
this._datafeed_config.datafeed_id = createDatafeedId(jobId);
|
||||
|
||||
if (this._useDedicatedIndex) {
|
||||
this._job_config.results_index_name = jobId;
|
||||
|
@ -620,16 +617,13 @@ export class JobCreator {
|
|||
}
|
||||
}
|
||||
|
||||
public async createJob(): Promise<object> {
|
||||
public async createJob() {
|
||||
try {
|
||||
const { success, resp } = await this.mlJobService.saveNewJob(this._job_config);
|
||||
await this.mlApi.addJob({
|
||||
jobId: this._job_config.job_id,
|
||||
job: this._job_config,
|
||||
});
|
||||
await this._updateCalendars();
|
||||
|
||||
if (success === true) {
|
||||
return resp;
|
||||
} else {
|
||||
throw resp;
|
||||
}
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
@ -638,7 +632,14 @@ export class JobCreator {
|
|||
public async createDatafeed(): Promise<object> {
|
||||
try {
|
||||
const tempDatafeed = this._getDatafeedWithFilteredRuntimeMappings();
|
||||
return await this.mlJobService.saveNewDatafeed(tempDatafeed, this._job_config.job_id);
|
||||
const jobId = this._job_config.job_id;
|
||||
const datafeedId = createDatafeedId(jobId);
|
||||
tempDatafeed.job_id = jobId;
|
||||
|
||||
return this.mlApi.addDatafeed({
|
||||
datafeedId,
|
||||
datafeedConfig: tempDatafeed,
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
import type { DataView } from '@kbn/data-views-plugin/public';
|
||||
import type { SavedSearch } from '@kbn/saved-search-plugin/public';
|
||||
import type { MlJobService } from '../../../../services/job_service';
|
||||
import type { MlApi } from '../../../../services/ml_api_service';
|
||||
import type { NewJobCapsService } from '../../../../services/new_job_capabilities/new_job_capabilities_service';
|
||||
import { SingleMetricJobCreator } from './single_metric_job_creator';
|
||||
|
@ -24,7 +23,6 @@ export const jobCreatorFactory =
|
|||
(jobType: JOB_TYPE) =>
|
||||
(
|
||||
mlApi: MlApi,
|
||||
mlJobService: MlJobService,
|
||||
newJobCapsService: NewJobCapsService,
|
||||
indexPattern: DataView,
|
||||
savedSearch: SavedSearch | null,
|
||||
|
@ -57,5 +55,5 @@ export const jobCreatorFactory =
|
|||
jc = SingleMetricJobCreator;
|
||||
break;
|
||||
}
|
||||
return new jc(mlApi, mlJobService, newJobCapsService, indexPattern, savedSearch, query);
|
||||
return new jc(mlApi, newJobCapsService, indexPattern, savedSearch, query);
|
||||
};
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
import type { DataView } from '@kbn/data-views-plugin/public';
|
||||
import type { Field, Aggregation, SplitField, AggFieldPair } from '@kbn/ml-anomaly-utils';
|
||||
import type { SavedSearch } from '@kbn/saved-search-plugin/public';
|
||||
import type { MlJobService } from '../../../../services/job_service';
|
||||
import type { MlApi } from '../../../../services/ml_api_service';
|
||||
import type { NewJobCapsService } from '../../../../services/new_job_capabilities/new_job_capabilities_service';
|
||||
import { JobCreator } from './job_creator';
|
||||
|
@ -31,13 +30,12 @@ export class MultiMetricJobCreator extends JobCreator {
|
|||
|
||||
constructor(
|
||||
mlApi: MlApi,
|
||||
mlJobService: MlJobService,
|
||||
newJobCapsService: NewJobCapsService,
|
||||
indexPattern: DataView,
|
||||
savedSearch: SavedSearch | null,
|
||||
query: object
|
||||
) {
|
||||
super(mlApi, mlJobService, newJobCapsService, indexPattern, savedSearch, query);
|
||||
super(mlApi, newJobCapsService, indexPattern, savedSearch, query);
|
||||
this.createdBy = CREATED_BY_LABEL.MULTI_METRIC;
|
||||
this._wizardInitialized$.next(true);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
import type { DataView } from '@kbn/data-views-plugin/public';
|
||||
import type { Field, Aggregation, SplitField, AggFieldPair } from '@kbn/ml-anomaly-utils';
|
||||
import type { SavedSearch } from '@kbn/saved-search-plugin/public';
|
||||
import type { MlJobService } from '../../../../services/job_service';
|
||||
import type { MlApi } from '../../../../services/ml_api_service';
|
||||
import type { NewJobCapsService } from '../../../../services/new_job_capabilities/new_job_capabilities_service';
|
||||
import { JobCreator } from './job_creator';
|
||||
|
@ -30,13 +29,12 @@ export class PopulationJobCreator extends JobCreator {
|
|||
|
||||
constructor(
|
||||
mlApi: MlApi,
|
||||
mlJobService: MlJobService,
|
||||
newJobCapsService: NewJobCapsService,
|
||||
indexPattern: DataView,
|
||||
savedSearch: SavedSearch | null,
|
||||
query: object
|
||||
) {
|
||||
super(mlApi, mlJobService, newJobCapsService, indexPattern, savedSearch, query);
|
||||
super(mlApi, newJobCapsService, indexPattern, savedSearch, query);
|
||||
this.createdBy = CREATED_BY_LABEL.POPULATION;
|
||||
this._wizardInitialized$.next(true);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import {
|
|||
ML_JOB_AGGREGATION,
|
||||
} from '@kbn/ml-anomaly-utils';
|
||||
import type { SavedSearch } from '@kbn/saved-search-plugin/public';
|
||||
import type { MlJobService } from '../../../../services/job_service';
|
||||
import type { MlApi } from '../../../../services/ml_api_service';
|
||||
import type { NewJobCapsService } from '../../../../services/new_job_capabilities/new_job_capabilities_service';
|
||||
import { JobCreator } from './job_creator';
|
||||
|
@ -38,13 +37,12 @@ export class RareJobCreator extends JobCreator {
|
|||
|
||||
constructor(
|
||||
mlApi: MlApi,
|
||||
mlJobService: MlJobService,
|
||||
newJobCapsService: NewJobCapsService,
|
||||
indexPattern: DataView,
|
||||
savedSearch: SavedSearch | null,
|
||||
query: object
|
||||
) {
|
||||
super(mlApi, mlJobService, newJobCapsService, indexPattern, savedSearch, query);
|
||||
super(mlApi, newJobCapsService, indexPattern, savedSearch, query);
|
||||
this.createdBy = CREATED_BY_LABEL.RARE;
|
||||
this._wizardInitialized$.next(true);
|
||||
this._rareAgg = {} as Aggregation;
|
||||
|
|
|
@ -15,7 +15,6 @@ import {
|
|||
ES_AGGREGATION,
|
||||
} from '@kbn/ml-anomaly-utils';
|
||||
import type { SavedSearch } from '@kbn/saved-search-plugin/public';
|
||||
import type { MlJobService } from '../../../../services/job_service';
|
||||
import type { MlApi } from '../../../../services/ml_api_service';
|
||||
import { parseInterval } from '../../../../../../common/util/parse_interval';
|
||||
import { JobCreator } from './job_creator';
|
||||
|
@ -36,13 +35,12 @@ export class SingleMetricJobCreator extends JobCreator {
|
|||
|
||||
constructor(
|
||||
mlApi: MlApi,
|
||||
mlJobService: MlJobService,
|
||||
newJobCapsService: NewJobCapsService,
|
||||
indexPattern: DataView,
|
||||
savedSearch: SavedSearch | null,
|
||||
query: object
|
||||
) {
|
||||
super(mlApi, mlJobService, newJobCapsService, indexPattern, savedSearch, query);
|
||||
super(mlApi, newJobCapsService, indexPattern, savedSearch, query);
|
||||
this.createdBy = CREATED_BY_LABEL.SINGLE_METRIC;
|
||||
this._wizardInitialized$.next(true);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ import {
|
|||
ML_JOB_AGGREGATION,
|
||||
SPARSE_DATA_AGGREGATIONS,
|
||||
} from '@kbn/ml-anomaly-utils';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { jobCloningService } from '../../../../../services/job_cloning_service';
|
||||
import type {
|
||||
Job,
|
||||
Datafeed,
|
||||
|
@ -28,7 +30,6 @@ import type {
|
|||
import type { NewJobCapsService } from '../../../../../services/new_job_capabilities/new_job_capabilities_service';
|
||||
import type { NavigateToPath } from '../../../../../contexts/kibana';
|
||||
import { ML_PAGES } from '../../../../../../../common/constants/locator';
|
||||
import type { MlJobService } from '../../../../../services/job_service';
|
||||
import type { JobCreatorType } from '..';
|
||||
import { CREATED_BY_LABEL, JOB_TYPE } from '../../../../../../../common/constants/new_job';
|
||||
|
||||
|
@ -237,53 +238,39 @@ export function isSparseDataJob(job: Job, datafeed: Datafeed): boolean {
|
|||
}
|
||||
|
||||
export function convertToMultiMetricJob(
|
||||
mlJobService: MlJobService,
|
||||
jobCreator: JobCreatorType,
|
||||
navigateToPath: NavigateToPath
|
||||
) {
|
||||
jobCreator.createdBy = CREATED_BY_LABEL.MULTI_METRIC;
|
||||
jobCreator.modelPlot = false;
|
||||
mlJobService.stashJobForCloning(jobCreator, true, true);
|
||||
jobCloningService.stashJobForCloning(jobCreator, true, true);
|
||||
navigateToPath(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_CONVERT_TO_MULTI_METRIC, true);
|
||||
}
|
||||
|
||||
export function convertToAdvancedJob(
|
||||
mlJobService: MlJobService,
|
||||
jobCreator: JobCreatorType,
|
||||
navigateToPath: NavigateToPath
|
||||
) {
|
||||
export function convertToAdvancedJob(jobCreator: JobCreatorType, navigateToPath: NavigateToPath) {
|
||||
jobCreator.createdBy = null;
|
||||
mlJobService.stashJobForCloning(jobCreator, true, true);
|
||||
jobCloningService.stashJobForCloning(jobCreator, true, true);
|
||||
navigateToPath(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_CONVERT_TO_ADVANCED, true);
|
||||
}
|
||||
|
||||
export function resetAdvancedJob(
|
||||
mlJobService: MlJobService,
|
||||
jobCreator: JobCreatorType,
|
||||
navigateToPath: NavigateToPath
|
||||
) {
|
||||
export function resetAdvancedJob(jobCreator: JobCreatorType, navigateToPath: NavigateToPath) {
|
||||
jobCreator.createdBy = null;
|
||||
mlJobService.stashJobForCloning(jobCreator, true, false);
|
||||
jobCloningService.stashJobForCloning(jobCreator, true, false);
|
||||
navigateToPath(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB);
|
||||
}
|
||||
|
||||
export function resetJob(
|
||||
mlJobService: MlJobService,
|
||||
jobCreator: JobCreatorType,
|
||||
navigateToPath: NavigateToPath
|
||||
) {
|
||||
export function resetJob(jobCreator: JobCreatorType, navigateToPath: NavigateToPath) {
|
||||
jobCreator.jobId = '';
|
||||
mlJobService.stashJobForCloning(jobCreator, true, true);
|
||||
jobCloningService.stashJobForCloning(jobCreator, true, true);
|
||||
navigateToPath(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB);
|
||||
}
|
||||
|
||||
export function advancedStartDatafeed(
|
||||
mlJobService: MlJobService,
|
||||
jobCreator: JobCreatorType | null,
|
||||
navigateToPath: NavigateToPath
|
||||
) {
|
||||
if (jobCreator !== null) {
|
||||
mlJobService.stashJobForCloning(jobCreator, false, false);
|
||||
jobCloningService.stashJobForCloning(jobCreator, false, false);
|
||||
}
|
||||
navigateToPath('/jobs');
|
||||
}
|
||||
|
@ -350,3 +337,13 @@ export function collectAggs(o: any, aggFields: Field[]) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function cloneDatafeed(datafeed: Datafeed) {
|
||||
const tempDatafeed = cloneDeep(datafeed);
|
||||
|
||||
// remove parts of the datafeed config which should not be copied
|
||||
tempDatafeed.datafeed_id = '';
|
||||
tempDatafeed.job_id = '';
|
||||
|
||||
return tempDatafeed;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import type { MlApi } from '../../../../services/ml_api_service';
|
||||
import type { MlJobService } from '../../../../services/job_service';
|
||||
import type { JobCreator } from '../job_creator';
|
||||
import type { DatafeedId, JobId } from '../../../../../../common/types/anomaly_detection_jobs';
|
||||
import { DATAFEED_STATE } from '../../../../../../common/constants/states';
|
||||
|
@ -23,7 +22,6 @@ export type JobAssignmentSubscriber = (assigned: boolean) => void;
|
|||
|
||||
export class JobRunner {
|
||||
private _mlApi: MlApi;
|
||||
private _mlJobService: MlJobService;
|
||||
private _jobId: JobId;
|
||||
private _datafeedId: DatafeedId;
|
||||
private _start: number = 0;
|
||||
|
@ -45,7 +43,6 @@ export class JobRunner {
|
|||
|
||||
constructor(jobCreator: JobCreator) {
|
||||
this._mlApi = jobCreator.mlApi;
|
||||
this._mlJobService = jobCreator.mlJobService;
|
||||
this._jobId = jobCreator.jobId;
|
||||
this._datafeedId = jobCreator.datafeedId;
|
||||
this._start = jobCreator.start;
|
||||
|
@ -72,7 +69,7 @@ export class JobRunner {
|
|||
|
||||
private async openJob(): Promise<void> {
|
||||
try {
|
||||
const { node }: { node?: string } = await this._mlJobService.openJob(this._jobId);
|
||||
const { node }: { node?: string } = await this._mlApi.openJob({ jobId: this._jobId });
|
||||
this._jobAssignedToNode = node !== undefined && node.length > 0;
|
||||
this._jobAssignedToNode$.next(this._jobAssignedToNode);
|
||||
} catch (error) {
|
||||
|
@ -96,12 +93,11 @@ export class JobRunner {
|
|||
pollProgress === true ? this._subscribers.map((s) => this._progress$.subscribe(s)) : [];
|
||||
|
||||
await this.openJob();
|
||||
const { started } = await this._mlJobService.startDatafeed(
|
||||
this._datafeedId,
|
||||
this._jobId,
|
||||
const { started } = await this._mlApi.startDatafeed({
|
||||
datafeedId: this._datafeedId,
|
||||
start,
|
||||
end
|
||||
);
|
||||
end,
|
||||
});
|
||||
|
||||
this._datafeedState = DATAFEED_STATE.STARTED;
|
||||
this._percentageComplete = 0;
|
||||
|
|
|
@ -22,7 +22,6 @@ import { FilterStateStore } from '@kbn/es-query';
|
|||
import type { ErrorType } from '@kbn/ml-error-utils';
|
||||
import type { DataViewsContract } from '@kbn/data-views-plugin/public';
|
||||
import type { MlApi } from '../../../services/ml_api_service';
|
||||
import type { MlJobService } from '../../../services/job_service';
|
||||
import type { Job, Datafeed } from '../../../../../common/types/anomaly_detection_jobs';
|
||||
import { getFiltersForDSLQuery } from '../../../../../common/util/job_utils';
|
||||
import type { CREATED_BY_LABEL } from '../../../../../common/constants/new_job';
|
||||
|
@ -57,8 +56,7 @@ export class QuickJobCreatorBase {
|
|||
protected readonly kibanaConfig: IUiSettingsClient,
|
||||
protected readonly timeFilter: TimefilterContract,
|
||||
protected readonly dashboardService: DashboardStart,
|
||||
protected readonly mlApi: MlApi,
|
||||
protected readonly mlJobService: MlJobService
|
||||
protected readonly mlApi: MlApi
|
||||
) {}
|
||||
|
||||
protected async putJobAndDataFeed({
|
||||
|
|
|
@ -20,7 +20,6 @@ import type { LensApi } from '@kbn/lens-plugin/public';
|
|||
import type { JobCreatorType } from '../common/job_creator';
|
||||
import { createEmptyJob, createEmptyDatafeed } from '../common/job_creator/util/default_configs';
|
||||
import type { MlApi } from '../../../services/ml_api_service';
|
||||
import type { MlJobService } from '../../../services/job_service';
|
||||
import {
|
||||
CREATED_BY_LABEL,
|
||||
DEFAULT_BUCKET_SPAN,
|
||||
|
@ -34,6 +33,7 @@ import {
|
|||
} from './utils';
|
||||
import { VisualizationExtractor } from './visualization_extractor';
|
||||
import { QuickJobCreatorBase, type CreateState } from '../job_from_dashboard';
|
||||
import { jobCloningService } from '../../../services/job_cloning_service';
|
||||
|
||||
export class QuickLensJobCreator extends QuickJobCreatorBase {
|
||||
constructor(
|
||||
|
@ -42,10 +42,9 @@ export class QuickLensJobCreator extends QuickJobCreatorBase {
|
|||
kibanaConfig: IUiSettingsClient,
|
||||
timeFilter: TimefilterContract,
|
||||
dashboardService: DashboardStart,
|
||||
mlApi: MlApi,
|
||||
mlJobService: MlJobService
|
||||
mlApi: MlApi
|
||||
) {
|
||||
super(dataViews, kibanaConfig, timeFilter, dashboardService, mlApi, mlJobService);
|
||||
super(dataViews, kibanaConfig, timeFilter, dashboardService, mlApi);
|
||||
}
|
||||
|
||||
public async createAndSaveJob(
|
||||
|
@ -116,7 +115,7 @@ export class QuickLensJobCreator extends QuickJobCreatorBase {
|
|||
// add job config and start and end dates to the
|
||||
// job cloning stash, so they can be used
|
||||
// by the new job wizards
|
||||
this.mlJobService.stashJobForCloning(
|
||||
jobCloningService.stashJobForCloning(
|
||||
{
|
||||
jobConfig,
|
||||
datafeedConfig,
|
||||
|
|
|
@ -15,7 +15,6 @@ import type { DashboardStart } from '@kbn/dashboard-plugin/public';
|
|||
import type { DataViewsContract } from '@kbn/data-views-plugin/public';
|
||||
import { QuickLensJobCreator } from './quick_create_job';
|
||||
import type { MlApi } from '../../../services/ml_api_service';
|
||||
import type { MlJobService } from '../../../services/job_service';
|
||||
|
||||
import { getDefaultQuery, getRisonValue } from '../utils/new_job_utils';
|
||||
|
||||
|
@ -26,7 +25,6 @@ interface Dependencies {
|
|||
timeFilter: TimefilterContract;
|
||||
dashboardService: DashboardStart;
|
||||
mlApi: MlApi;
|
||||
mlJobService: MlJobService;
|
||||
}
|
||||
export async function resolver(
|
||||
deps: Dependencies,
|
||||
|
@ -37,7 +35,7 @@ export async function resolver(
|
|||
filtersRisonString: string,
|
||||
layerIndexRisonString: string
|
||||
) {
|
||||
const { dataViews, lens, mlApi, mlJobService, timeFilter, kibanaConfig, dashboardService } = deps;
|
||||
const { dataViews, lens, mlApi, timeFilter, kibanaConfig, dashboardService } = deps;
|
||||
if (lensSavedObjectRisonString === undefined) {
|
||||
throw new Error('Cannot create visualization');
|
||||
}
|
||||
|
@ -59,8 +57,7 @@ export async function resolver(
|
|||
kibanaConfig,
|
||||
timeFilter,
|
||||
dashboardService,
|
||||
mlApi,
|
||||
mlJobService
|
||||
mlApi
|
||||
);
|
||||
await jobCreator.createAndStashADJob(vis, from, to, query, filters, layerIndex);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/public'
|
|||
import type { DashboardStart } from '@kbn/dashboard-plugin/public';
|
||||
import type { MapApi } from '@kbn/maps-plugin/public';
|
||||
import type { MlApi } from '../../../services/ml_api_service';
|
||||
import type { MlJobService } from '../../../services/job_service';
|
||||
import {
|
||||
CREATED_BY_LABEL,
|
||||
JOB_TYPE,
|
||||
|
@ -25,6 +24,7 @@ import { getJobsItemsFromEmbeddable } from './utils';
|
|||
import type { CreateState } from '../job_from_dashboard';
|
||||
import { QuickJobCreatorBase } from '../job_from_dashboard';
|
||||
import { getDefaultQuery } from '../utils/new_job_utils';
|
||||
import { jobCloningService } from '../../../services/job_cloning_service';
|
||||
|
||||
interface VisDescriptor {
|
||||
dashboard: { query: Query; filters: Filter[] };
|
||||
|
@ -43,10 +43,9 @@ export class QuickGeoJobCreator extends QuickJobCreatorBase {
|
|||
kibanaConfig: IUiSettingsClient,
|
||||
timeFilter: TimefilterContract,
|
||||
dashboardService: DashboardStart,
|
||||
mlApi: MlApi,
|
||||
mlJobService: MlJobService
|
||||
mlApi: MlApi
|
||||
) {
|
||||
super(dataViews, kibanaConfig, timeFilter, dashboardService, mlApi, mlJobService);
|
||||
super(dataViews, kibanaConfig, timeFilter, dashboardService, mlApi);
|
||||
}
|
||||
|
||||
public async createAndSaveGeoJob({
|
||||
|
@ -145,7 +144,7 @@ export class QuickGeoJobCreator extends QuickJobCreatorBase {
|
|||
// add job config and start and end dates to the
|
||||
// job cloning stash, so they can be used
|
||||
// by the new job wizards
|
||||
this.mlJobService.stashJobForCloning(
|
||||
jobCloningService.stashJobForCloning(
|
||||
{
|
||||
jobConfig,
|
||||
datafeedConfig,
|
||||
|
|
|
@ -10,7 +10,6 @@ import type { TimefilterContract } from '@kbn/data-plugin/public';
|
|||
import type { DashboardStart } from '@kbn/dashboard-plugin/public';
|
||||
import type { DataViewsContract } from '@kbn/data-views-plugin/public';
|
||||
import type { MlApi } from '../../../services/ml_api_service';
|
||||
import type { MlJobService } from '../../../services/job_service';
|
||||
import { QuickGeoJobCreator } from './quick_create_job';
|
||||
|
||||
import { getDefaultQuery, getRisonValue } from '../utils/new_job_utils';
|
||||
|
@ -21,7 +20,6 @@ interface Dependencies {
|
|||
timeFilter: TimefilterContract;
|
||||
dashboardService: DashboardStart;
|
||||
mlApi: MlApi;
|
||||
mlJobService: MlJobService;
|
||||
}
|
||||
export async function resolver(
|
||||
deps: Dependencies,
|
||||
|
@ -34,7 +32,7 @@ export async function resolver(
|
|||
toRisonString: string,
|
||||
layerRisonString?: string
|
||||
) {
|
||||
const { dataViews, kibanaConfig, timeFilter, dashboardService, mlApi, mlJobService } = deps;
|
||||
const { dataViews, kibanaConfig, timeFilter, dashboardService, mlApi } = deps;
|
||||
const defaultLayer = { query: getDefaultQuery(), filters: [] };
|
||||
|
||||
const dashboard = getRisonValue<typeof defaultLayer>(dashboardRisonString, defaultLayer);
|
||||
|
@ -57,8 +55,7 @@ export async function resolver(
|
|||
kibanaConfig,
|
||||
timeFilter,
|
||||
dashboardService,
|
||||
mlApi,
|
||||
mlJobService
|
||||
mlApi
|
||||
);
|
||||
|
||||
await jobCreator.createAndStashGeoJob(
|
||||
|
|
|
@ -17,9 +17,9 @@ import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/type
|
|||
import { CREATED_BY_LABEL, DEFAULT_BUCKET_SPAN } from '../../../../../common/constants/new_job';
|
||||
import { type CreateState, QuickJobCreatorBase } from '../job_from_dashboard/quick_create_job_base';
|
||||
import type { MlApi } from '../../../services/ml_api_service';
|
||||
import type { MlJobService } from '../../../services/job_service';
|
||||
import { createEmptyDatafeed, createEmptyJob } from '../common/job_creator/util/default_configs';
|
||||
import type { JobCreatorType } from '../common/job_creator';
|
||||
import { jobCloningService } from '../../../services/job_cloning_service';
|
||||
|
||||
export const CATEGORIZATION_TYPE = {
|
||||
COUNT: ML_JOB_AGGREGATION.COUNT,
|
||||
|
@ -36,10 +36,9 @@ export class QuickCategorizationJobCreator extends QuickJobCreatorBase {
|
|||
timeFilter: TimefilterContract,
|
||||
dashboardService: DashboardStart,
|
||||
private data: DataPublicPluginStart,
|
||||
mlApi: MlApi,
|
||||
mlJobService: MlJobService
|
||||
mlApi: MlApi
|
||||
) {
|
||||
super(dataViews, kibanaConfig, timeFilter, dashboardService, mlApi, mlJobService);
|
||||
super(dataViews, kibanaConfig, timeFilter, dashboardService, mlApi);
|
||||
}
|
||||
|
||||
public async createAndSaveJob(
|
||||
|
@ -119,7 +118,7 @@ export class QuickCategorizationJobCreator extends QuickJobCreatorBase {
|
|||
// add job config and start and end dates to the
|
||||
// job cloning stash, so they can be used
|
||||
// by the new job wizards
|
||||
this.mlJobService.stashJobForCloning(
|
||||
jobCloningService.stashJobForCloning(
|
||||
{
|
||||
jobConfig,
|
||||
datafeedConfig,
|
||||
|
|
|
@ -15,7 +15,6 @@ import {
|
|||
CATEGORIZATION_TYPE,
|
||||
} from './quick_create_job';
|
||||
import type { MlApi } from '../../../services/ml_api_service';
|
||||
import type { MlJobService } from '../../../services/job_service';
|
||||
|
||||
import { getDefaultDatafeedQuery, getRisonValue } from '../utils/new_job_utils';
|
||||
|
||||
|
@ -25,7 +24,6 @@ interface Dependencies {
|
|||
dashboardService: DashboardStart;
|
||||
data: DataPublicPluginStart;
|
||||
mlApi: MlApi;
|
||||
mlJobService: MlJobService;
|
||||
}
|
||||
export async function resolver(
|
||||
deps: Dependencies,
|
||||
|
@ -38,7 +36,7 @@ export async function resolver(
|
|||
toRisonString: string,
|
||||
queryRisonString: string
|
||||
) {
|
||||
const { mlApi, mlJobService, timeFilter, kibanaConfig, dashboardService, data } = deps;
|
||||
const { mlApi, timeFilter, kibanaConfig, dashboardService, data } = deps;
|
||||
|
||||
const query = getRisonValue<QueryDslQueryContainer>(queryRisonString, getDefaultDatafeedQuery());
|
||||
const from = getRisonValue<string>(fromRisonString, '');
|
||||
|
@ -59,8 +57,7 @@ export async function resolver(
|
|||
timeFilter,
|
||||
dashboardService,
|
||||
data,
|
||||
mlApi,
|
||||
mlJobService
|
||||
mlApi
|
||||
);
|
||||
await jobCreator.createAndStashADJob(
|
||||
categorizationType,
|
||||
|
|
|
@ -27,7 +27,6 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
|
||||
import { extractErrorMessage } from '@kbn/ml-error-utils';
|
||||
|
||||
import { useMlJobService } from '../../../../../../../services/job_service';
|
||||
import { JobCreatorContext } from '../../../job_creator_context';
|
||||
import type { AdvancedJobCreator } from '../../../../../common/job_creator';
|
||||
import { resetAdvancedJob } from '../../../../../common/job_creator/util/general';
|
||||
|
@ -63,7 +62,6 @@ export const ChangeDataViewModal: FC<Props> = ({ onClose }) => {
|
|||
|
||||
const { jobCreator: jc } = useContext(JobCreatorContext);
|
||||
const jobCreator = jc as AdvancedJobCreator;
|
||||
const mlJobService = useMlJobService();
|
||||
|
||||
const [validating, setValidating] = useState(false);
|
||||
const [step, setStep] = useState(STEP.PICK_DATA_VIEW);
|
||||
|
@ -121,9 +119,8 @@ export const ChangeDataViewModal: FC<Props> = ({ onClose }) => {
|
|||
const applyDataView = useCallback(() => {
|
||||
const newIndices = newDataViewTitle.split(',');
|
||||
jobCreator.indices = newIndices;
|
||||
resetAdvancedJob(mlJobService, jobCreator, navigateToPath);
|
||||
resetAdvancedJob(jobCreator, navigateToPath);
|
||||
// exclude mlJobService from deps
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [jobCreator, newDataViewTitle, navigateToPath]);
|
||||
|
||||
return (
|
||||
|
|
|
@ -10,7 +10,6 @@ import React, { Fragment, useContext } from 'react';
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui';
|
||||
|
||||
import { useMlJobService } from '../../../../../../../services/job_service';
|
||||
import { useNavigateToPath } from '../../../../../../../contexts/kibana';
|
||||
|
||||
import { convertToMultiMetricJob } from '../../../../../common/job_creator/util/general';
|
||||
|
@ -26,11 +25,10 @@ interface Props {
|
|||
|
||||
export const SingleMetricSettings: FC<Props> = ({ setIsValid }) => {
|
||||
const { jobCreator } = useContext(JobCreatorContext);
|
||||
const mlJobService = useMlJobService();
|
||||
const navigateToPath = useNavigateToPath();
|
||||
|
||||
const convertToMultiMetric = () => {
|
||||
convertToMultiMetricJob(mlJobService, jobCreator, navigateToPath);
|
||||
convertToMultiMetricJob(jobCreator, navigateToPath);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -18,13 +18,13 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { createResultsUrl } from '../../../../../util/results_url';
|
||||
import { useMlKibana, useNavigateToPath } from '../../../../../contexts/kibana';
|
||||
import { PreviousButton } from '../wizard_nav';
|
||||
import type { StepProps } from '../step_types';
|
||||
import { WIZARD_STEPS } from '../step_types';
|
||||
import { JobCreatorContext } from '../job_creator_context';
|
||||
import type { JobRunner } from '../../../common/job_runner';
|
||||
import { useMlJobService } from '../../../../../services/job_service';
|
||||
import { JsonEditorFlyout, EDITOR_MODE } from '../common/json_editor_flyout';
|
||||
import { isSingleMetricJobCreator, isAdvancedJobCreator } from '../../../common/job_creator';
|
||||
import { JobDetails } from './components/job_details';
|
||||
|
@ -49,7 +49,6 @@ export const SummaryStep: FC<StepProps> = ({ setCurrentStep, isCurrentStep }) =>
|
|||
http: { basePath },
|
||||
},
|
||||
} = useMlKibana();
|
||||
const mlJobService = useMlJobService();
|
||||
|
||||
const navigateToPath = useNavigateToPath();
|
||||
|
||||
|
@ -108,7 +107,7 @@ export const SummaryStep: FC<StepProps> = ({ setCurrentStep, isCurrentStep }) =>
|
|||
try {
|
||||
await jobCreator.createJob();
|
||||
await jobCreator.createDatafeed();
|
||||
advancedStartDatafeed(mlJobService, showStartModal ? jobCreator : null, navigateToPath);
|
||||
advancedStartDatafeed(showStartModal ? jobCreator : null, navigateToPath);
|
||||
} catch (error) {
|
||||
handleJobCreationError(error);
|
||||
}
|
||||
|
@ -126,7 +125,7 @@ export const SummaryStep: FC<StepProps> = ({ setCurrentStep, isCurrentStep }) =>
|
|||
}
|
||||
|
||||
function viewResults() {
|
||||
const url = mlJobService.createResultsUrl(
|
||||
const url = createResultsUrl(
|
||||
[jobCreator.jobId],
|
||||
jobCreator.start,
|
||||
jobCreator.end,
|
||||
|
@ -136,11 +135,11 @@ export const SummaryStep: FC<StepProps> = ({ setCurrentStep, isCurrentStep }) =>
|
|||
}
|
||||
|
||||
function clickResetJob() {
|
||||
resetJob(mlJobService, jobCreator, navigateToPath);
|
||||
resetJob(jobCreator, navigateToPath);
|
||||
}
|
||||
|
||||
const convertToAdvanced = () => {
|
||||
convertToAdvancedJob(mlJobService, jobCreator, navigateToPath);
|
||||
convertToAdvancedJob(jobCreator, navigateToPath);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -7,17 +7,16 @@
|
|||
|
||||
import type { ApplicationStart } from '@kbn/core/public';
|
||||
import type { DataViewsContract } from '@kbn/data-views-plugin/public';
|
||||
import type { MlJobService } from '../../../../services/job_service';
|
||||
import { jobCloningService } from '../../../../services/job_cloning_service';
|
||||
import type { Job, Datafeed } from '../../../../../../common/types/anomaly_detection_jobs';
|
||||
import { CREATED_BY_LABEL, JOB_TYPE } from '../../../../../../common/constants/new_job';
|
||||
|
||||
export async function preConfiguredJobRedirect(
|
||||
mlJobService: MlJobService,
|
||||
dataViewsService: DataViewsContract,
|
||||
basePath: string,
|
||||
navigateToUrl: ApplicationStart['navigateToUrl']
|
||||
) {
|
||||
const { createdBy, job, datafeed } = mlJobService.tempJobCloningObjects;
|
||||
const { createdBy, job, datafeed } = jobCloningService;
|
||||
|
||||
if (job && datafeed) {
|
||||
const dataViewId = await getDataViewIdFromDatafeed(job, datafeed, dataViewsService);
|
||||
|
|
|
@ -13,9 +13,10 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import { getTimeFilterRange, useTimefilter } from '@kbn/ml-date-picker';
|
||||
import { EVENT_RATE_FIELD_ID } from '@kbn/ml-anomaly-utils';
|
||||
import { useTimeBuckets } from '@kbn/ml-time-buckets';
|
||||
import { jobCloningService } from '../../../../services/job_cloning_service';
|
||||
import { Wizard } from './wizard';
|
||||
import { WIZARD_STEPS } from '../components/step_types';
|
||||
import { getJobCreatorTitle } from '../../common/job_creator/util/general';
|
||||
import { cloneDatafeed, getJobCreatorTitle } from '../../common/job_creator/util/general';
|
||||
import {
|
||||
jobCreatorFactory,
|
||||
isAdvancedJobCreator,
|
||||
|
@ -35,7 +36,6 @@ import { JobValidator } from '../../common/job_validator';
|
|||
import { useDataSource } from '../../../../contexts/ml';
|
||||
import { useMlApi, useMlKibana } from '../../../../contexts/kibana';
|
||||
import type { ExistingJobsAndGroups } from '../../../../services/job_service';
|
||||
import { useMlJobService } from '../../../../services/job_service';
|
||||
import { useNewJobCapsService } from '../../../../services/new_job_capabilities/new_job_capabilities_service';
|
||||
import { getNewJobDefaults } from '../../../../services/ml_server_info';
|
||||
import { useToastNotificationService } from '../../../../services/toast_notification_service';
|
||||
|
@ -57,7 +57,6 @@ export const Page: FC<PageProps> = ({ existingJobsAndGroups, jobType }) => {
|
|||
services: { maps: mapsPlugin, uiSettings },
|
||||
} = useMlKibana();
|
||||
const mlApi = useMlApi();
|
||||
const mlJobService = useMlJobService();
|
||||
const newJobCapsService = useNewJobCapsService();
|
||||
|
||||
const chartInterval = useTimeBuckets(uiSettings);
|
||||
|
@ -66,7 +65,6 @@ export const Page: FC<PageProps> = ({ existingJobsAndGroups, jobType }) => {
|
|||
() =>
|
||||
jobCreatorFactory(jobType)(
|
||||
mlApi,
|
||||
mlJobService,
|
||||
newJobCapsService,
|
||||
dataSourceContext.selectedDataView,
|
||||
dataSourceContext.selectedSavedSearch,
|
||||
|
@ -88,53 +86,36 @@ export const Page: FC<PageProps> = ({ existingJobsAndGroups, jobType }) => {
|
|||
? WIZARD_STEPS.ADVANCED_CONFIGURE_DATAFEED
|
||||
: WIZARD_STEPS.TIME_RANGE;
|
||||
|
||||
let autoSetTimeRange = mlJobService.tempJobCloningObjects.autoSetTimeRange;
|
||||
mlJobService.tempJobCloningObjects.autoSetTimeRange = false;
|
||||
let autoSetTimeRange = jobCloningService.autoSetTimeRange;
|
||||
|
||||
if (
|
||||
mlJobService.tempJobCloningObjects.job !== undefined &&
|
||||
mlJobService.tempJobCloningObjects.datafeed !== undefined
|
||||
) {
|
||||
if (jobCloningService.job !== undefined && jobCloningService.datafeed !== undefined) {
|
||||
// cloning a job
|
||||
const clonedJob = mlJobService.tempJobCloningObjects.job;
|
||||
const clonedDatafeed = mlJobService.cloneDatafeed(mlJobService.tempJobCloningObjects.datafeed);
|
||||
const clonedJob = jobCloningService.job;
|
||||
const clonedDatafeed = cloneDatafeed(jobCloningService.datafeed);
|
||||
|
||||
initCategorizationSettings();
|
||||
jobCreator.cloneFromExistingJob(clonedJob, clonedDatafeed);
|
||||
|
||||
// if we're not skipping the time range, this is a standard job clone, so wipe the jobId
|
||||
if (mlJobService.tempJobCloningObjects.skipTimeRangeStep === false) {
|
||||
if (jobCloningService.skipTimeRangeStep === false) {
|
||||
jobCreator.jobId = '';
|
||||
} else if (jobType !== JOB_TYPE.ADVANCED) {
|
||||
firstWizardStep = WIZARD_STEPS.PICK_FIELDS;
|
||||
}
|
||||
|
||||
mlJobService.tempJobCloningObjects.skipTimeRangeStep = false;
|
||||
mlJobService.tempJobCloningObjects.job = undefined;
|
||||
mlJobService.tempJobCloningObjects.datafeed = undefined;
|
||||
mlJobService.tempJobCloningObjects.createdBy = undefined;
|
||||
|
||||
if (
|
||||
mlJobService.tempJobCloningObjects.start !== undefined &&
|
||||
mlJobService.tempJobCloningObjects.end !== undefined
|
||||
) {
|
||||
if (jobCloningService.start !== undefined && jobCloningService.end !== undefined) {
|
||||
// auto select the start and end dates for the time range picker
|
||||
jobCreator.setTimeRange(
|
||||
mlJobService.tempJobCloningObjects.start,
|
||||
mlJobService.tempJobCloningObjects.end
|
||||
);
|
||||
mlJobService.tempJobCloningObjects.start = undefined;
|
||||
mlJobService.tempJobCloningObjects.end = undefined;
|
||||
jobCreator.setTimeRange(jobCloningService.start, jobCloningService.end);
|
||||
} else {
|
||||
// if not start and end times are set and this is an advanced job,
|
||||
// auto set the time range based on the index
|
||||
autoSetTimeRange = autoSetTimeRange || isAdvancedJobCreator(jobCreator);
|
||||
}
|
||||
|
||||
if (mlJobService.tempJobCloningObjects.calendars) {
|
||||
jobCreator.calendars = mlJobService.tempJobCloningObjects.calendars;
|
||||
mlJobService.tempJobCloningObjects.calendars = undefined;
|
||||
if (jobCloningService.calendars) {
|
||||
jobCreator.calendars = jobCloningService.calendars;
|
||||
}
|
||||
jobCloningService.clearJobCloningData();
|
||||
} else {
|
||||
// creating a new job
|
||||
jobCreator.bucketSpan = DEFAULT_BUCKET_SPAN;
|
||||
|
|
|
@ -15,7 +15,6 @@ import type { MlRoute, PageProps } from '../../router';
|
|||
import { createPath, PageLoader } from '../../router';
|
||||
import { useRouteResolver } from '../../use_resolver';
|
||||
import { resolver } from '../../../jobs/new_job/job_from_lens';
|
||||
import { useMlJobService } from '../../../services/job_service';
|
||||
|
||||
export const fromLensRouteFactory = (): MlRoute => ({
|
||||
path: createPath(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_FROM_LENS),
|
||||
|
@ -44,7 +43,6 @@ const PageWrapper: FC<PageProps> = ({ location }) => {
|
|||
lens,
|
||||
},
|
||||
} = useMlKibana();
|
||||
const mlJobService = useMlJobService();
|
||||
|
||||
const { context } = useRouteResolver('full', ['canCreateJob'], {
|
||||
redirect: () =>
|
||||
|
@ -53,7 +51,6 @@ const PageWrapper: FC<PageProps> = ({ location }) => {
|
|||
dataViews,
|
||||
lens,
|
||||
mlApi,
|
||||
mlJobService,
|
||||
timeFilter,
|
||||
kibanaConfig,
|
||||
dashboardService,
|
||||
|
|
|
@ -15,7 +15,6 @@ import type { MlRoute, PageProps } from '../../router';
|
|||
import { createPath, PageLoader } from '../../router';
|
||||
import { useRouteResolver } from '../../use_resolver';
|
||||
import { resolver } from '../../../jobs/new_job/job_from_map';
|
||||
import { useMlJobService } from '../../../services/job_service';
|
||||
|
||||
export const fromMapRouteFactory = (): MlRoute => ({
|
||||
path: createPath(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_FROM_MAP),
|
||||
|
@ -50,12 +49,11 @@ const PageWrapper: FC<PageProps> = ({ location }) => {
|
|||
mlServices: { mlApi },
|
||||
},
|
||||
} = useMlKibana();
|
||||
const mlJobService = useMlJobService();
|
||||
|
||||
const { context } = useRouteResolver('full', ['canCreateJob'], {
|
||||
redirect: () =>
|
||||
resolver(
|
||||
{ dataViews, mlApi, mlJobService, timeFilter, kibanaConfig, dashboardService },
|
||||
{ dataViews, mlApi, timeFilter, kibanaConfig, dashboardService },
|
||||
dashboard,
|
||||
dataViewId,
|
||||
embeddable,
|
||||
|
|
|
@ -15,7 +15,6 @@ import type { MlRoute, PageProps } from '../../router';
|
|||
import { createPath, PageLoader } from '../../router';
|
||||
import { useRouteResolver } from '../../use_resolver';
|
||||
import { resolver } from '../../../jobs/new_job/job_from_pattern_analysis';
|
||||
import { useMlJobService } from '../../../services/job_service';
|
||||
|
||||
export const fromPatternAnalysisRouteFactory = (): MlRoute => ({
|
||||
path: createPath(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_FROM_PATTERN_ANALYSIS),
|
||||
|
@ -44,14 +43,12 @@ const PageWrapper: FC<PageProps> = ({ location }) => {
|
|||
mlServices: { mlApi },
|
||||
},
|
||||
} = useMlKibana();
|
||||
const mlJobService = useMlJobService();
|
||||
|
||||
const { context } = useRouteResolver('full', ['canCreateJob'], {
|
||||
redirect: () =>
|
||||
resolver(
|
||||
{
|
||||
mlApi,
|
||||
mlJobService,
|
||||
timeFilter: data.query.timefilter.timefilter,
|
||||
kibanaConfig,
|
||||
dashboardService,
|
||||
|
|
|
@ -21,7 +21,6 @@ import { basicResolvers } from '../../resolvers';
|
|||
import { preConfiguredJobRedirect } from '../../../jobs/new_job/pages/index_or_search';
|
||||
import { getBreadcrumbWithUrlForApp } from '../../breadcrumbs';
|
||||
import { NavigateToPageButton } from '../../components/navigate_to_page_button';
|
||||
import { useMlJobService } from '../../../services/job_service';
|
||||
|
||||
enum MODE {
|
||||
NEW_JOB,
|
||||
|
@ -219,12 +218,11 @@ const PageWrapper: FC<IndexOrSearchPageProps> = ({ nextStepPath, mode, extraButt
|
|||
data: { dataViews: dataViewsService },
|
||||
},
|
||||
} = useMlKibana();
|
||||
const mlJobService = useMlJobService();
|
||||
|
||||
const newJobResolvers = {
|
||||
...basicResolvers(),
|
||||
preConfiguredJobRedirect: () =>
|
||||
preConfiguredJobRedirect(mlJobService, dataViewsService, basePath.get(), navigateToUrl),
|
||||
preConfiguredJobRedirect(dataViewsService, basePath.get(), navigateToUrl),
|
||||
};
|
||||
|
||||
const { context } = useRouteResolver(
|
||||
|
|
|
@ -17,11 +17,9 @@ import { useMlApi, useMlKibana, useNavigateToPath } from '../../../contexts/kiba
|
|||
import type { MlRoute, PageProps } from '../../router';
|
||||
import { createPath, PageLoader } from '../../router';
|
||||
import { useRouteResolver } from '../../use_resolver';
|
||||
import { mlJobServiceFactory } from '../../../services/job_service';
|
||||
import { getBreadcrumbWithUrlForApp } from '../../breadcrumbs';
|
||||
import { useCreateADLinks } from '../../../components/custom_hooks/use_create_ad_links';
|
||||
import { DataSourceContextProvider } from '../../../contexts/ml';
|
||||
import { useToastNotificationService } from '../../../services/toast_notification_service';
|
||||
|
||||
const Page = dynamic(async () => ({
|
||||
default: (await import('../../../jobs/new_job/recognize')).Page,
|
||||
|
@ -56,12 +54,10 @@ export const checkViewOrCreateRouteFactory = (): MlRoute => ({
|
|||
const PageWrapper: FC<PageProps> = ({ location }) => {
|
||||
const { id } = parse(location.search, { sort: false });
|
||||
const mlApi = useMlApi();
|
||||
const toastNotificationService = useToastNotificationService();
|
||||
|
||||
const { context, results } = useRouteResolver('full', ['canGetJobs'], {
|
||||
...basicResolvers(),
|
||||
existingJobsAndGroups: () =>
|
||||
mlJobServiceFactory(toastNotificationService, mlApi).getJobAndGroupIds(),
|
||||
existingJobsAndGroups: () => mlApi.jobs.getAllJobAndGroupIds(),
|
||||
});
|
||||
|
||||
return (
|
||||
|
|
|
@ -19,8 +19,6 @@ import type { MlRoute, PageProps } from '../../router';
|
|||
import { createPath, PageLoader } from '../../router';
|
||||
import { useRouteResolver } from '../../use_resolver';
|
||||
import { JOB_TYPE } from '../../../../../common/constants/new_job';
|
||||
import { mlJobServiceFactory } from '../../../services/job_service';
|
||||
import { useToastNotificationService } from '../../../services/toast_notification_service';
|
||||
import {
|
||||
loadNewJobCapabilities,
|
||||
ANOMALY_DETECTOR,
|
||||
|
@ -210,8 +208,6 @@ const PageWrapper: FC<WizardPageProps> = ({ location, jobType }) => {
|
|||
mlServices: { mlApi },
|
||||
},
|
||||
} = useMlKibana();
|
||||
const toastNotificationService = useToastNotificationService();
|
||||
|
||||
const { context, results } = useRouteResolver('full', ['canGetJobs', 'canCreateJob'], {
|
||||
...basicResolvers(),
|
||||
// TODO useRouteResolver should be responsible for the redirect
|
||||
|
@ -225,8 +221,7 @@ const PageWrapper: FC<WizardPageProps> = ({ location, jobType }) => {
|
|||
savedSearchService,
|
||||
ANOMALY_DETECTOR
|
||||
),
|
||||
existingJobsAndGroups: () =>
|
||||
mlJobServiceFactory(toastNotificationService, mlApi).getJobAndGroupIds(),
|
||||
existingJobsAndGroups: () => mlApi.jobs.getAllJobAndGroupIds(),
|
||||
});
|
||||
|
||||
return (
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* 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 { isPopulatedObject } from '@kbn/ml-is-populated-object';
|
||||
import type { JobCreator } from '../jobs/new_job/common/job_creator/job_creator';
|
||||
|
||||
interface TempJobCloningData {
|
||||
createdBy: any;
|
||||
datafeed: any;
|
||||
job: any;
|
||||
skipTimeRangeStep: boolean;
|
||||
start?: any;
|
||||
end?: any;
|
||||
calendars: any;
|
||||
autoSetTimeRange?: boolean;
|
||||
}
|
||||
|
||||
export class JobCloningService {
|
||||
// tempJobCloningData -> used to pass a job object between the job management page and
|
||||
// and the advanced wizard.
|
||||
// if populated when loading the advanced wizard, the job is used for cloning.
|
||||
// if populated when loading the job management page, the start datafeed modal
|
||||
// is automatically opened.
|
||||
private tempJobCloningData: TempJobCloningData = {
|
||||
createdBy: undefined,
|
||||
datafeed: undefined,
|
||||
job: undefined,
|
||||
skipTimeRangeStep: false,
|
||||
start: undefined,
|
||||
end: undefined,
|
||||
calendars: undefined,
|
||||
autoSetTimeRange: false,
|
||||
};
|
||||
|
||||
public getJobCloningData(): Readonly<TempJobCloningData> {
|
||||
return this.tempJobCloningData;
|
||||
}
|
||||
|
||||
clearJobCloningData() {
|
||||
this.tempJobCloningData = {
|
||||
createdBy: undefined,
|
||||
datafeed: undefined,
|
||||
job: undefined,
|
||||
skipTimeRangeStep: false,
|
||||
start: undefined,
|
||||
end: undefined,
|
||||
calendars: undefined,
|
||||
autoSetTimeRange: false,
|
||||
};
|
||||
}
|
||||
|
||||
stashJobForCloning(
|
||||
jobCreator: JobCreator,
|
||||
skipTimeRangeStep: boolean,
|
||||
includeTimeRange: boolean,
|
||||
autoSetTimeRange: boolean = false
|
||||
) {
|
||||
const tempJobCloningData: TempJobCloningData = {
|
||||
job: jobCreator.jobConfig,
|
||||
datafeed: jobCreator.datafeedConfig,
|
||||
createdBy: jobCreator.createdBy ?? undefined,
|
||||
// skip over the time picker step of the wizard
|
||||
skipTimeRangeStep,
|
||||
calendars: jobCreator.calendars,
|
||||
...(includeTimeRange === true && autoSetTimeRange === false
|
||||
? // auto select the start and end dates of the time picker
|
||||
{
|
||||
start: jobCreator.start,
|
||||
end: jobCreator.end,
|
||||
}
|
||||
: { autoSetTimeRange: true }),
|
||||
};
|
||||
|
||||
this.tempJobCloningData = tempJobCloningData;
|
||||
}
|
||||
|
||||
public checkForAutoStartDatafeed() {
|
||||
const job = this.tempJobCloningData.job;
|
||||
const datafeed = this.tempJobCloningData.datafeed;
|
||||
if (job !== undefined) {
|
||||
this.tempJobCloningData.job = undefined;
|
||||
this.tempJobCloningData.datafeed = undefined;
|
||||
this.tempJobCloningData.createdBy = undefined;
|
||||
|
||||
const hasDatafeed = isPopulatedObject(datafeed);
|
||||
const datafeedId = hasDatafeed ? datafeed.datafeed_id : '';
|
||||
return {
|
||||
id: job.job_id,
|
||||
hasDatafeed,
|
||||
latestTimestampSortValue: 0,
|
||||
datafeedId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public stashJobCloningData(config: TempJobCloningData) {
|
||||
this.tempJobCloningData = config;
|
||||
}
|
||||
|
||||
public get createdBy() {
|
||||
return this.tempJobCloningData.createdBy;
|
||||
}
|
||||
public get datafeed() {
|
||||
return this.tempJobCloningData.datafeed;
|
||||
}
|
||||
public get job() {
|
||||
return this.tempJobCloningData.job;
|
||||
}
|
||||
public get skipTimeRangeStep() {
|
||||
return this.tempJobCloningData.skipTimeRangeStep;
|
||||
}
|
||||
public get start() {
|
||||
return this.tempJobCloningData.start;
|
||||
}
|
||||
public get end() {
|
||||
return this.tempJobCloningData.end;
|
||||
}
|
||||
public get calendars() {
|
||||
return this.tempJobCloningData.calendars;
|
||||
}
|
||||
public get autoSetTimeRange() {
|
||||
return this.tempJobCloningData.autoSetTimeRange;
|
||||
}
|
||||
}
|
||||
|
||||
export const jobCloningService = new JobCloningService();
|
|
@ -5,12 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { TimeRange } from '@kbn/data-plugin/common/query/timefilter/types';
|
||||
import type { CombinedJob, Datafeed, Job } from '../../../common/types/anomaly_detection_jobs';
|
||||
import type { Calendar } from '../../../common/types/calendars';
|
||||
import type { ToastNotificationService } from './toast_notification_service';
|
||||
import type { CombinedJob } from '../../../common/types/anomaly_detection_jobs';
|
||||
import type { MlApi } from './ml_api_service';
|
||||
import type { JobCreatorType } from '../jobs/new_job/common/job_creator';
|
||||
|
||||
export interface ExistingJobsAndGroups {
|
||||
jobIds: string[];
|
||||
|
@ -19,50 +15,13 @@ export interface ExistingJobsAndGroups {
|
|||
|
||||
export declare interface MlJobService {
|
||||
jobs: CombinedJob[];
|
||||
createResultsUrlForJobs: (jobs: any[], target: string, timeRange?: TimeRange) => string;
|
||||
tempJobCloningObjects: {
|
||||
createdBy?: string;
|
||||
datafeed?: Datafeed;
|
||||
job?: Job;
|
||||
skipTimeRangeStep: boolean;
|
||||
start?: number;
|
||||
end?: number;
|
||||
calendars: Calendar[] | undefined;
|
||||
autoSetTimeRange?: boolean;
|
||||
};
|
||||
skipTimeRangeStep: boolean;
|
||||
saveNewJob(job: Job): Promise<any>;
|
||||
cloneDatafeed(Datafeed: Datafeed): Datafeed;
|
||||
openJob(jobId: string): Promise<any>;
|
||||
saveNewDatafeed(datafeedConfig: any, jobId: string): Promise<any>;
|
||||
startDatafeed(
|
||||
datafeedId: string,
|
||||
jobId: string,
|
||||
start: number | undefined,
|
||||
end: number | undefined
|
||||
): Promise<any>;
|
||||
forceStartDatafeeds(
|
||||
dIds: string[],
|
||||
start: number | undefined,
|
||||
end: number | undefined
|
||||
): Promise<any>;
|
||||
createResultsUrl(jobId: string[], start: number, end: number, location: string): string;
|
||||
getJobAndGroupIds(): Promise<ExistingJobsAndGroups>;
|
||||
getJob(jobId: string): CombinedJob;
|
||||
loadJobsWrapper(): Promise<CombinedJob[]>;
|
||||
customUrlsByJob: Record<string, any[]>;
|
||||
detectorsByJob: Record<string, any>;
|
||||
stashJobForCloning(
|
||||
jobCreator: JobCreatorType,
|
||||
skipTimeRangeStep: boolean = false,
|
||||
includeTimeRange: boolean = false,
|
||||
autoSetTimeRange: boolean = false
|
||||
): void;
|
||||
}
|
||||
|
||||
export const mlJobServiceFactory: (
|
||||
toastNotificationService: ToastNotificationService,
|
||||
mlApi: MlApi
|
||||
) => MlJobService;
|
||||
export const mlJobServiceFactory: (mlApi: MlApi) => MlJobService;
|
||||
|
||||
export const useMlJobService: () => MlJobService;
|
||||
|
|
|
@ -5,42 +5,21 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { cloneDeep, each, find, get, isNumber } from 'lodash';
|
||||
import moment from 'moment';
|
||||
|
||||
import { validateTimeRange, TIME_FORMAT } from '@kbn/ml-date-utils';
|
||||
import { cloneDeep, each, find, get } from 'lodash';
|
||||
|
||||
import { parseInterval } from '../../../common/util/parse_interval';
|
||||
import { createDatafeedId } from '../../../common/util/job_utils';
|
||||
|
||||
import { isWebUrl } from '../util/url_utils';
|
||||
import { useMlApi } from '../contexts/kibana';
|
||||
|
||||
import { useToastNotificationService } from './toast_notification_service';
|
||||
|
||||
let jobs = [];
|
||||
let datafeedIds = {};
|
||||
|
||||
class JobService {
|
||||
constructor(toastNotificationService, ml) {
|
||||
this.toastNotificationService = toastNotificationService;
|
||||
constructor(ml) {
|
||||
this.ml = ml;
|
||||
|
||||
// tempJobCloningObjects -> used to pass a job object between the job management page and
|
||||
// and the advanced wizard.
|
||||
// if populated when loading the advanced wizard, the job is used for cloning.
|
||||
// if populated when loading the job management page, the start datafeed modal
|
||||
// is automatically opened.
|
||||
this.tempJobCloningObjects = {
|
||||
createdBy: undefined,
|
||||
datafeed: undefined,
|
||||
job: undefined,
|
||||
skipTimeRangeStep: false,
|
||||
start: undefined,
|
||||
end: undefined,
|
||||
calendars: undefined,
|
||||
autoSetTimeRange: false,
|
||||
};
|
||||
|
||||
this.jobs = [];
|
||||
|
||||
// Provide ready access to widely used basic job properties.
|
||||
|
@ -112,7 +91,6 @@ class JobService {
|
|||
|
||||
function error(err) {
|
||||
console.log('jobService error getting list of jobs:', err);
|
||||
this.toastNotificationService.displayErrorToast(err);
|
||||
reject({ jobs, err });
|
||||
}
|
||||
});
|
||||
|
@ -168,7 +146,7 @@ class JobService {
|
|||
}
|
||||
}
|
||||
|
||||
const datafeedId = this.getDatafeedId(jobId);
|
||||
const datafeedId = createDatafeedId(jobId);
|
||||
|
||||
this.loadDatafeeds(datafeedId).then((datafeedsResp) => {
|
||||
for (let i = 0; i < jobs.length; i++) {
|
||||
|
@ -195,7 +173,6 @@ class JobService {
|
|||
|
||||
function error(err) {
|
||||
console.log('JobService error getting list of jobs:', err);
|
||||
this.toastNotificationService.displayErrorToast(err);
|
||||
reject({ jobs, err });
|
||||
}
|
||||
});
|
||||
|
@ -235,56 +212,11 @@ class JobService {
|
|||
|
||||
function error(err) {
|
||||
console.log('loadDatafeeds error getting list of datafeeds:', err);
|
||||
this.toastNotificationService.displayErrorToast(err);
|
||||
reject({ jobs, err });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateSingleJobDatafeedState(jobId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const datafeedId = this.getDatafeedId(jobId);
|
||||
|
||||
this.ml
|
||||
.getDatafeedStats({ datafeedId })
|
||||
.then((resp) => {
|
||||
// console.log('updateSingleJobCounts controller query response:', resp);
|
||||
const datafeeds = resp.datafeeds;
|
||||
let state = 'UNKNOWN';
|
||||
if (datafeeds && datafeeds.length) {
|
||||
state = datafeeds[0].state;
|
||||
}
|
||||
resolve(state);
|
||||
})
|
||||
.catch((resp) => {
|
||||
reject(resp);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
saveNewJob(job) {
|
||||
// run then and catch through the same check
|
||||
function func(resp) {
|
||||
console.log('Response for job query:', resp);
|
||||
const success = checkSaveResponse(resp, job);
|
||||
return { success, job, resp };
|
||||
}
|
||||
|
||||
// return the promise chain
|
||||
return this.ml.addJob({ jobId: job.job_id, job }).then(func).catch(func);
|
||||
}
|
||||
|
||||
cloneDatafeed(datafeed) {
|
||||
const tempDatafeed = cloneDeep(datafeed);
|
||||
|
||||
// remove parts of the datafeed config which should not be copied
|
||||
if (tempDatafeed) {
|
||||
delete tempDatafeed.datafeed_id;
|
||||
delete tempDatafeed.job_id;
|
||||
}
|
||||
return tempDatafeed;
|
||||
}
|
||||
|
||||
// find a job based on the id
|
||||
getJob(jobId) {
|
||||
const job = find(jobs, (j) => {
|
||||
|
@ -293,175 +225,6 @@ class JobService {
|
|||
|
||||
return job;
|
||||
}
|
||||
|
||||
openJob(jobId) {
|
||||
return this.ml.openJob({ jobId });
|
||||
}
|
||||
|
||||
closeJob(jobId) {
|
||||
return this.ml.closeJob({ jobId });
|
||||
}
|
||||
|
||||
saveNewDatafeed(datafeedConfig, jobId) {
|
||||
const datafeedId = `datafeed-${jobId}`;
|
||||
datafeedConfig.job_id = jobId;
|
||||
|
||||
return this.ml.addDatafeed({
|
||||
datafeedId,
|
||||
datafeedConfig,
|
||||
});
|
||||
}
|
||||
|
||||
// start the datafeed for a given job
|
||||
// refresh the job state on start success
|
||||
startDatafeed(datafeedId, jobId, start, end) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// if the end timestamp is a number, add one ms to it to make it
|
||||
// inclusive of the end of the data
|
||||
if (isNumber(end)) {
|
||||
end++;
|
||||
}
|
||||
|
||||
this.ml
|
||||
.startDatafeed({
|
||||
datafeedId,
|
||||
start,
|
||||
end,
|
||||
})
|
||||
.then((resp) => {
|
||||
resolve(resp);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log('jobService error starting datafeed:', err);
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
forceStartDatafeeds(dIds, start, end) {
|
||||
return this.ml.jobs.forceStartDatafeeds(dIds, start, end);
|
||||
}
|
||||
|
||||
stopDatafeeds(dIds) {
|
||||
return this.ml.jobs.stopDatafeeds(dIds);
|
||||
}
|
||||
|
||||
deleteJobs(jIds, deleteUserAnnotations, deleteAlertingRules) {
|
||||
return this.ml.jobs.deleteJobs(jIds, deleteUserAnnotations, deleteAlertingRules);
|
||||
}
|
||||
|
||||
closeJobs(jIds) {
|
||||
return this.ml.jobs.closeJobs(jIds);
|
||||
}
|
||||
|
||||
resetJobs(jIds, deleteUserAnnotations) {
|
||||
return this.ml.jobs.resetJobs(jIds, deleteUserAnnotations);
|
||||
}
|
||||
|
||||
validateDetector(detector) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (detector) {
|
||||
this.ml
|
||||
.validateDetector({ detector })
|
||||
.then((resp) => {
|
||||
resolve(resp);
|
||||
})
|
||||
.catch((resp) => {
|
||||
reject(resp);
|
||||
});
|
||||
} else {
|
||||
reject({});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getDatafeedId(jobId) {
|
||||
let datafeedId = datafeedIds[jobId];
|
||||
if (datafeedId === undefined) {
|
||||
datafeedId = `datafeed-${jobId}`;
|
||||
}
|
||||
return datafeedId;
|
||||
}
|
||||
|
||||
// get the list of job group ids as well as how many jobs are in each group
|
||||
getJobGroups() {
|
||||
const groups = [];
|
||||
const tempGroups = {};
|
||||
this.jobs.forEach((job) => {
|
||||
if (Array.isArray(job.groups)) {
|
||||
job.groups.forEach((group) => {
|
||||
if (tempGroups[group] === undefined) {
|
||||
tempGroups[group] = [job];
|
||||
} else {
|
||||
tempGroups[group].push(job);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
each(tempGroups, (js, id) => {
|
||||
groups.push({ id, jobs: js });
|
||||
});
|
||||
return groups;
|
||||
}
|
||||
|
||||
createResultsUrlForJobs(jobsList, resultsPage, timeRange) {
|
||||
return createResultsUrlForJobs(jobsList, resultsPage, timeRange);
|
||||
}
|
||||
|
||||
createResultsUrl(jobIds, from, to, resultsPage) {
|
||||
return createResultsUrl(jobIds, from, to, resultsPage);
|
||||
}
|
||||
|
||||
async getJobAndGroupIds() {
|
||||
try {
|
||||
return await this.ml.jobs.getAllJobAndGroupIds();
|
||||
} catch (error) {
|
||||
return {
|
||||
jobIds: [],
|
||||
groupIds: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
stashJobForCloning(jobCreator, skipTimeRangeStep, includeTimeRange, autoSetTimeRange) {
|
||||
const tempJobCloningObjects = {
|
||||
job: jobCreator.jobConfig,
|
||||
datafeed: jobCreator.datafeedConfig,
|
||||
createdBy: jobCreator.createdBy ?? undefined,
|
||||
// skip over the time picker step of the wizard
|
||||
skipTimeRangeStep,
|
||||
calendars: jobCreator.calendars,
|
||||
...(includeTimeRange === true && autoSetTimeRange === false
|
||||
? // auto select the start and end dates of the time picker
|
||||
{
|
||||
start: jobCreator.start,
|
||||
end: jobCreator.end,
|
||||
}
|
||||
: { autoSetTimeRange: true }),
|
||||
};
|
||||
|
||||
this.tempJobCloningObjects = tempJobCloningObjects;
|
||||
}
|
||||
}
|
||||
|
||||
// private function used to check the job saving response
|
||||
function checkSaveResponse(resp, origJob) {
|
||||
if (resp) {
|
||||
if (resp.job_id) {
|
||||
if (resp.job_id === origJob.job_id) {
|
||||
console.log('checkSaveResponse(): save successful');
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (resp.errorCode) {
|
||||
console.log('checkSaveResponse(): save failed', resp);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log('checkSaveResponse(): response is empty');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function processBasicJobInfo(localJobService, jobsList) {
|
||||
|
@ -521,90 +284,16 @@ function processBasicJobInfo(localJobService, jobsList) {
|
|||
return processedJobsList;
|
||||
}
|
||||
|
||||
function createResultsUrlForJobs(jobsList, resultsPage, userTimeRange) {
|
||||
let from = undefined;
|
||||
let to = undefined;
|
||||
let mode = 'absolute';
|
||||
const jobIds = jobsList.map((j) => j.id);
|
||||
|
||||
// if the custom default time filter is set and enabled in advanced settings
|
||||
// if time is either absolute date or proper datemath format
|
||||
if (validateTimeRange(userTimeRange)) {
|
||||
from = userTimeRange.from;
|
||||
to = userTimeRange.to;
|
||||
// if both pass datemath's checks but are not technically absolute dates, use 'quick'
|
||||
// e.g. "now-15m" "now+1d"
|
||||
const fromFieldAValidDate = moment(userTimeRange.from).isValid();
|
||||
const toFieldAValidDate = moment(userTimeRange.to).isValid();
|
||||
if (!fromFieldAValidDate && !toFieldAValidDate) {
|
||||
return createResultsUrl(jobIds, from, to, resultsPage, 'quick');
|
||||
}
|
||||
} else {
|
||||
// if time range is specified but with incorrect format
|
||||
// change back to the default time range but alert the user
|
||||
// that the advanced setting config is invalid
|
||||
if (userTimeRange) {
|
||||
mode = 'invalid';
|
||||
}
|
||||
|
||||
if (jobsList.length === 1) {
|
||||
from = jobsList[0].earliestTimestampMs;
|
||||
to = jobsList[0].latestResultsTimestampMs; // Will be max(latest source data, latest bucket results)
|
||||
} else {
|
||||
const jobsWithData = jobsList.filter((j) => j.earliestTimestampMs !== undefined);
|
||||
if (jobsWithData.length > 0) {
|
||||
from = Math.min(...jobsWithData.map((j) => j.earliestTimestampMs));
|
||||
to = Math.max(...jobsWithData.map((j) => j.latestResultsTimestampMs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fromString = moment(from).format(TIME_FORMAT); // Defaults to 'now' if 'from' is undefined
|
||||
const toString = moment(to).format(TIME_FORMAT); // Defaults to 'now' if 'to' is undefined
|
||||
|
||||
return createResultsUrl(jobIds, fromString, toString, resultsPage, mode);
|
||||
}
|
||||
|
||||
function createResultsUrl(jobIds, start, end, resultsPage, mode = 'absolute') {
|
||||
const idString = jobIds.map((j) => `'${j}'`).join(',');
|
||||
let from;
|
||||
let to;
|
||||
let path = '';
|
||||
|
||||
if (resultsPage !== undefined) {
|
||||
path += resultsPage;
|
||||
}
|
||||
|
||||
if (mode === 'quick') {
|
||||
from = start;
|
||||
to = end;
|
||||
} else {
|
||||
from = moment(start).toISOString();
|
||||
to = moment(end).toISOString();
|
||||
}
|
||||
|
||||
path += `?_g=(ml:(jobIds:!(${idString}))`;
|
||||
path += `,refreshInterval:(display:Off,pause:!t,value:0),time:(from:'${from}'`;
|
||||
path += `,to:'${to}'`;
|
||||
if (mode === 'invalid') {
|
||||
path += `,mode:invalid`;
|
||||
}
|
||||
path += "))&_a=(query:(query_string:(analyze_wildcard:!t,query:'*')))";
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
// This is to retain the singleton behavior of the previous direct instantiation and export.
|
||||
let mlJobService;
|
||||
export const mlJobServiceFactory = (toastNotificationService, mlApi) => {
|
||||
export const mlJobServiceFactory = (mlApi) => {
|
||||
if (mlJobService) return mlJobService;
|
||||
|
||||
mlJobService = new JobService(toastNotificationService, mlApi);
|
||||
mlJobService = new JobService(mlApi);
|
||||
return mlJobService;
|
||||
};
|
||||
|
||||
export const useMlJobService = () => {
|
||||
const toastNotificationService = useToastNotificationService();
|
||||
const mlApi = useMlApi();
|
||||
return mlJobServiceFactory(toastNotificationService, mlApi);
|
||||
return mlJobServiceFactory(mlApi);
|
||||
};
|
||||
|
|
|
@ -11,6 +11,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
|||
|
||||
import type { RuntimeMappings } from '@kbn/ml-runtime-field-utils';
|
||||
|
||||
import { isNumber } from 'lodash';
|
||||
import { ML_INTERNAL_BASE_PATH } from '../../../../common/constants/app';
|
||||
import type {
|
||||
MlServerDefaults,
|
||||
|
@ -299,6 +300,12 @@ export function mlApiProvider(httpService: HttpService) {
|
|||
start?: number;
|
||||
end?: number;
|
||||
}) {
|
||||
// if the end timestamp is a number, add one ms to it to make it
|
||||
// inclusive of the end of the data
|
||||
if (isNumber(end)) {
|
||||
end++;
|
||||
}
|
||||
|
||||
const body = JSON.stringify({
|
||||
...(start !== undefined ? { start } : {}),
|
||||
...(end !== undefined ? { end } : {}),
|
||||
|
|
|
@ -160,7 +160,7 @@ export class TimeSeriesExplorer extends React.Component {
|
|||
this.mlApi = constructorContext.services.mlServices.mlApi;
|
||||
this.mlForecastService = forecastServiceFactory(this.mlApi);
|
||||
this.mlIndexUtils = indexServiceFactory(this.dataViewsService);
|
||||
this.mlJobService = mlJobServiceFactory(this.toastNotificationService, this.mlApi);
|
||||
this.mlJobService = mlJobServiceFactory(this.mlApi);
|
||||
this.mlResultsService = mlResultsServiceProvider(this.mlApi);
|
||||
this.mlTimeSeriesExplorer = timeSeriesExplorerServiceFactory(
|
||||
constructorContext.services.uiSettings,
|
||||
|
|
|
@ -17,7 +17,6 @@ import { HttpService } from '../services/http_service';
|
|||
import { mlApiProvider } from '../services/ml_api_service';
|
||||
import { mlUsageCollectionProvider } from '../services/usage_collection';
|
||||
import { mlJobServiceFactory } from '../services/job_service';
|
||||
import { toastNotificationServiceProvider } from '../services/toast_notification_service';
|
||||
import { indexServiceFactory } from './index_service';
|
||||
|
||||
/**
|
||||
|
@ -30,8 +29,7 @@ export function getMlGlobalServices(
|
|||
) {
|
||||
const httpService = new HttpService(coreStart.http);
|
||||
const mlApi = mlApiProvider(httpService);
|
||||
const toastNotificationService = toastNotificationServiceProvider(coreStart.notifications.toasts);
|
||||
const mlJobService = mlJobServiceFactory(toastNotificationService, mlApi);
|
||||
const mlJobService = mlJobServiceFactory(mlApi);
|
||||
// Note on the following services:
|
||||
// - `mlIndexUtils` is just instantiated here to be passed on to `mlFieldFormatService`,
|
||||
// but it's not being made available as part of global services. Since it's just
|
||||
|
|
95
x-pack/plugins/ml/public/application/util/results_url.ts
Normal file
95
x-pack/plugins/ml/public/application/util/results_url.ts
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import moment from 'moment';
|
||||
|
||||
import { validateTimeRange, TIME_FORMAT } from '@kbn/ml-date-utils';
|
||||
import type { TimeRange } from '@kbn/es-query';
|
||||
import type { MlSummaryJob } from '../../../common';
|
||||
|
||||
export function createResultsUrlForJobs(
|
||||
jobsList: MlSummaryJob[],
|
||||
resultsPage: string,
|
||||
userTimeRange: TimeRange
|
||||
) {
|
||||
let from;
|
||||
let to;
|
||||
let mode = 'absolute';
|
||||
const jobIds = jobsList.map((j) => j.id);
|
||||
|
||||
// if the custom default time filter is set and enabled in advanced settings
|
||||
// if time is either absolute date or proper datemath format
|
||||
if (validateTimeRange(userTimeRange)) {
|
||||
from = userTimeRange.from;
|
||||
to = userTimeRange.to;
|
||||
// if both pass datemath's checks but are not technically absolute dates, use 'quick'
|
||||
// e.g. "now-15m" "now+1d"
|
||||
const fromFieldAValidDate = moment(userTimeRange.from).isValid();
|
||||
const toFieldAValidDate = moment(userTimeRange.to).isValid();
|
||||
if (!fromFieldAValidDate && !toFieldAValidDate) {
|
||||
return createResultsUrl(jobIds, from, to, resultsPage, 'quick');
|
||||
}
|
||||
} else {
|
||||
// if time range is specified but with incorrect format
|
||||
// change back to the default time range but alert the user
|
||||
// that the advanced setting config is invalid
|
||||
if (userTimeRange) {
|
||||
mode = 'invalid';
|
||||
}
|
||||
|
||||
if (jobsList.length === 1) {
|
||||
from = jobsList[0].earliestTimestampMs;
|
||||
to = jobsList[0].latestResultsTimestampMs; // Will be max(latest source data, latest bucket results)
|
||||
} else {
|
||||
const jobsWithData = jobsList.filter((j) => j.earliestTimestampMs !== undefined);
|
||||
if (jobsWithData.length > 0) {
|
||||
from = Math.min(...jobsWithData.map((j) => j.earliestTimestampMs!));
|
||||
to = Math.max(...jobsWithData.map((j) => j.latestResultsTimestampMs!));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fromString = moment(from).format(TIME_FORMAT); // Defaults to 'now' if 'from' is undefined
|
||||
const toString = moment(to).format(TIME_FORMAT); // Defaults to 'now' if 'to' is undefined
|
||||
|
||||
return createResultsUrl(jobIds, fromString, toString, resultsPage, mode);
|
||||
}
|
||||
|
||||
export function createResultsUrl(
|
||||
jobIds: string[],
|
||||
start: number | string,
|
||||
end: number | string,
|
||||
resultsPage: string,
|
||||
mode = 'absolute'
|
||||
) {
|
||||
const idString = jobIds.map((j) => `'${j}'`).join(',');
|
||||
let from;
|
||||
let to;
|
||||
let path = '';
|
||||
|
||||
if (resultsPage !== undefined) {
|
||||
path += resultsPage;
|
||||
}
|
||||
|
||||
if (mode === 'quick') {
|
||||
from = start;
|
||||
to = end;
|
||||
} else {
|
||||
from = moment(start).toISOString();
|
||||
to = moment(end).toISOString();
|
||||
}
|
||||
|
||||
path += `?_g=(ml:(jobIds:!(${idString}))`;
|
||||
path += `,refreshInterval:(display:Off,pause:!t,value:0),time:(from:'${from}'`;
|
||||
path += `,to:'${to}'`;
|
||||
if (mode === 'invalid') {
|
||||
path += `,mode:invalid`;
|
||||
}
|
||||
path += "))&_a=(query:(query_string:(analyze_wildcard:!t,query:'*')))";
|
||||
|
||||
return path;
|
||||
}
|
|
@ -22,7 +22,6 @@ export const getAnomalyChartsServiceDependencies = async (
|
|||
{ mlApiProvider },
|
||||
{ mlJobServiceFactory },
|
||||
{ mlResultsServiceProvider },
|
||||
{ toastNotificationServiceProvider },
|
||||
] = await Promise.all([
|
||||
await import('../../application/services/anomaly_detector_service'),
|
||||
await import('../../application/services/field_format_service_factory'),
|
||||
|
@ -30,13 +29,11 @@ export const getAnomalyChartsServiceDependencies = async (
|
|||
await import('../../application/services/ml_api_service'),
|
||||
await import('../../application/services/job_service'),
|
||||
await import('../../application/services/results_service'),
|
||||
await import('../../application/services/toast_notification_service'),
|
||||
]);
|
||||
const httpService = new HttpService(coreStart.http);
|
||||
const anomalyDetectorService = new AnomalyDetectorService(httpService);
|
||||
const mlApi = mlApiProvider(httpService);
|
||||
const toastNotificationService = toastNotificationServiceProvider(coreStart.notifications.toasts);
|
||||
const mlJobService = mlJobServiceFactory(toastNotificationService, mlApi);
|
||||
const mlJobService = mlJobServiceFactory(mlApi);
|
||||
const mlResultsService = mlResultsServiceProvider(mlApi);
|
||||
const anomalyExplorerService = new AnomalyExplorerChartsService(
|
||||
pluginsStart.data.query.timefilter.timefilter,
|
||||
|
|
|
@ -34,8 +34,6 @@ import {
|
|||
} from '../../../../application/jobs/new_job/job_from_pattern_analysis';
|
||||
import { useMlFromLensKibanaContext } from '../../common/context';
|
||||
import { JobDetails, type CreateADJobParams } from '../../common/job_details';
|
||||
import { mlJobServiceFactory } from '../../../../application/services/job_service';
|
||||
import { toastNotificationServiceProvider } from '../../../../application/services/toast_notification_service';
|
||||
|
||||
interface Props {
|
||||
dataView: DataView;
|
||||
|
@ -51,13 +49,9 @@ export const CreateJob: FC<Props> = ({ dataView, field, query, timeRange }) => {
|
|||
share,
|
||||
uiSettings,
|
||||
dashboardService,
|
||||
notifications: { toasts },
|
||||
mlServices: { mlApi },
|
||||
},
|
||||
} = useMlFromLensKibanaContext();
|
||||
const toastNotificationService = toastNotificationServiceProvider(toasts);
|
||||
const mlJobService = mlJobServiceFactory(toastNotificationService, mlApi);
|
||||
|
||||
const [categorizationType, setCategorizationType] = useState<CategorizationType>(
|
||||
CATEGORIZATION_TYPE.COUNT
|
||||
);
|
||||
|
@ -96,10 +90,9 @@ export const CreateJob: FC<Props> = ({ dataView, field, query, timeRange }) => {
|
|||
data.query.timefilter.timefilter,
|
||||
dashboardService,
|
||||
data,
|
||||
mlApi,
|
||||
mlJobService
|
||||
mlApi
|
||||
),
|
||||
[dashboardService, data, mlApi, mlJobService, uiSettings]
|
||||
[dashboardService, data, mlApi, uiSettings]
|
||||
);
|
||||
|
||||
function createADJobInWizard() {
|
||||
|
|
|
@ -19,8 +19,6 @@ import { JOB_TYPE } from '../../../../../../common/constants/new_job';
|
|||
import { useMlFromLensKibanaContext } from '../../../common/context';
|
||||
import type { CreateADJobParams } from '../../../common/job_details';
|
||||
import { JobDetails } from '../../../common/job_details';
|
||||
import { mlJobServiceFactory } from '../../../../../application/services/job_service';
|
||||
import { toastNotificationServiceProvider } from '../../../../../application/services/toast_notification_service';
|
||||
|
||||
interface Props {
|
||||
layer: LayerResult;
|
||||
|
@ -36,12 +34,9 @@ export const CompatibleLayer: FC<Props> = ({ layer, layerIndex, embeddable }) =>
|
|||
uiSettings,
|
||||
lens,
|
||||
dashboardService,
|
||||
notifications: { toasts },
|
||||
mlServices: { mlApi },
|
||||
},
|
||||
} = useMlFromLensKibanaContext();
|
||||
const toastNotificationService = toastNotificationServiceProvider(toasts);
|
||||
const mlJobService = mlJobServiceFactory(toastNotificationService, mlApi);
|
||||
|
||||
const quickJobCreator = useMemo(
|
||||
() =>
|
||||
|
@ -51,8 +46,7 @@ export const CompatibleLayer: FC<Props> = ({ layer, layerIndex, embeddable }) =>
|
|||
uiSettings,
|
||||
data.query.timefilter.timefilter,
|
||||
dashboardService,
|
||||
mlApi,
|
||||
mlJobService
|
||||
mlApi
|
||||
),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[data, uiSettings]
|
||||
|
|
|
@ -29,8 +29,6 @@ import {
|
|||
import { useMlFromLensKibanaContext } from '../../../common/context';
|
||||
import type { CreateADJobParams } from '../../../common/job_details';
|
||||
import { JobDetails } from '../../../common/job_details';
|
||||
import { mlJobServiceFactory } from '../../../../../application/services/job_service';
|
||||
import { toastNotificationServiceProvider } from '../../../../../application/services/toast_notification_service';
|
||||
|
||||
interface DropDownLabel {
|
||||
label: string;
|
||||
|
@ -53,12 +51,9 @@ export const CompatibleLayer: FC<Props> = ({ embeddable, layer, layerIndex }) =>
|
|||
share,
|
||||
uiSettings,
|
||||
dashboardService,
|
||||
notifications: { toasts },
|
||||
mlServices: { mlApi },
|
||||
},
|
||||
} = useMlFromLensKibanaContext();
|
||||
const toastNotificationService = toastNotificationServiceProvider(toasts);
|
||||
const mlJobService = mlJobServiceFactory(toastNotificationService, mlApi);
|
||||
|
||||
const quickJobCreator = useMemo(
|
||||
() =>
|
||||
|
@ -67,8 +62,7 @@ export const CompatibleLayer: FC<Props> = ({ embeddable, layer, layerIndex }) =>
|
|||
uiSettings,
|
||||
data.query.timefilter.timefilter,
|
||||
dashboardService,
|
||||
mlApi,
|
||||
mlJobService
|
||||
mlApi
|
||||
),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[data, uiSettings]
|
||||
|
|
|
@ -50,7 +50,7 @@ export const getMlServices = async (
|
|||
const anomalyDetectorService = new AnomalyDetectorService(httpService);
|
||||
const mlApi = mlApiProvider(httpService);
|
||||
const toastNotificationService = toastNotificationServiceProvider(coreStart.notifications.toasts);
|
||||
const mlJobService = mlJobServiceFactory(toastNotificationService, mlApi);
|
||||
const mlJobService = mlJobServiceFactory(mlApi);
|
||||
const mlResultsService = mlResultsServiceProvider(mlApi);
|
||||
const mlTimeSeriesSearchService = timeSeriesSearchServiceFactory(mlResultsService, mlApi);
|
||||
const mlTimeSeriesExplorerService = timeSeriesExplorerServiceFactory(
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
getSingleMetricViewerJobErrorMessage,
|
||||
parseTimeIntervalForJob,
|
||||
isJobWithGeoData,
|
||||
createDatafeedId,
|
||||
} from '../../../common/util/job_utils';
|
||||
import { JOB_STATE, DATAFEED_STATE } from '../../../common/constants/states';
|
||||
import type { JobAction } from '../../../common/constants/job_actions';
|
||||
|
@ -626,7 +627,7 @@ export function jobsProvider(
|
|||
}
|
||||
|
||||
async function getLookBackProgress(jobId: string, start: number, end: number) {
|
||||
const datafeedId = `datafeed-${jobId}`;
|
||||
const datafeedId = createDatafeedId(jobId);
|
||||
const [body, isRunning] = await Promise.all([
|
||||
mlClient.getJobStats({ job_id: jobId }),
|
||||
isDatafeedRunning(datafeedId),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue