[ML] Converting single to multi metric job (#42532)

* [ML] Converting single to multi metric job

* removing summary_count_field_name from copied job

* changes based on review
This commit is contained in:
James Gowdy 2019-08-12 18:35:04 +01:00 committed by GitHub
parent 042307e48d
commit 516b25c458
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 83 additions and 35 deletions

View file

@ -149,7 +149,14 @@ function showResults(resp, action) {
export function cloneJob(jobId) {
loadFullJob(jobId)
.then((job) => {
mlJobService.currentJob = job;
if(job.custom_settings && job.custom_settings.created_by) {
// if the job is from a wizards, i.e. contains a created_by property
// use tempJobCloningObjects to temporarily store the job
mlJobService.tempJobCloningObjects.job = job;
} else {
// otherwise use the currentJob
mlJobService.currentJob = job;
}
window.location.href = `#/jobs/new_job`;
})
.catch((error) => {

View file

@ -23,7 +23,12 @@ export function preConfiguredJobRedirect(AppState, Private, courier) {
let redirectUrl = getWizardUrlFromAppState(appState);
if (redirectUrl === null) {
// no settings in appState
const job = mlJobService.currentJob;
let job;
if(mlJobService.currentJob !== undefined) {
job = mlJobService.currentJob;
} else if(mlJobService.tempJobCloningObjects.job !== undefined) {
job = mlJobService.tempJobCloningObjects.job;
}
if (job) {
loadIndexPatterns(Private, courier)
.then(() => {

View file

@ -12,7 +12,7 @@ import { Aggregation, Field } from '../../../../../common/types/fields';
import { createEmptyJob, createEmptyDatafeed } from './util/default_configs';
import { mlJobService } from '../../../../services/job_service';
import { JobRunner, ProgressSubscriber } from '../job_runner';
import { JOB_TYPE } from './util/constants';
import { JOB_TYPE, CREATED_BY_LABEL } from './util/constants';
export class JobCreator {
protected _type: JOB_TYPE = JOB_TYPE.SINGLE_METRIC;
@ -341,12 +341,12 @@ export class JobCreator {
return null;
}
public set createdBy(createdBy: string | null) {
public set createdBy(createdBy: CREATED_BY_LABEL | null) {
this._setCustomSetting('created_by', createdBy);
}
public get createdBy(): string | null {
return this._getCustomSetting('created_by') as string | null;
public get createdBy(): CREATED_BY_LABEL | null {
return this._getCustomSetting('created_by') as CREATED_BY_LABEL | null;
}
public get formattedJobJson() {

View file

@ -5,9 +5,14 @@
*/
import React, { Fragment, FC, useContext, useEffect, useState } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui';
import { JobCreatorContext } from '../../../job_creator_context';
import { BucketSpan } from '../bucket_span';
import { CREATED_BY_LABEL } from '../../../../../common/job_creator/util/constants';
import { mlJobService } from '../../../../../../../services/job_service';
interface Props {
isActive: boolean;
setIsValid: (proceed: boolean) => void;
@ -27,5 +32,37 @@ export const SingleMetricSettings: FC<Props> = ({ isActive, setIsValid }) => {
setBucketSpan(jobCreator.bucketSpan);
}, [jobCreatorUpdated]);
return <Fragment>{isActive && <BucketSpan />}</Fragment>;
const convertToMultiMetricJob = () => {
jobCreator.createdBy = CREATED_BY_LABEL.MULTI_METRIC;
mlJobService.tempJobCloningObjects.job = {
...jobCreator.jobConfig,
datafeed_config: jobCreator.datafeedConfig,
};
delete mlJobService.tempJobCloningObjects.job.datafeed_config.aggregations;
delete mlJobService.tempJobCloningObjects.job.analysis_config.summary_count_field_name;
mlJobService.tempJobCloningObjects.skipTimeRangeStep = true;
window.location.href = window.location.href.replace('single_metric', 'multi_metric');
};
return (
<Fragment>
{isActive && (
<Fragment>
<EuiFlexGroup gutterSize="xl">
<EuiFlexItem>
<BucketSpan />
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiButtonEmpty onClick={convertToMultiMetricJob}>
Convert to multi metric job
</EuiButtonEmpty>
</EuiFlexItem>
</EuiFlexGroup>
</Fragment>
)}
</Fragment>
);
};

View file

@ -65,7 +65,7 @@ export const SplitCards: FC<Props> = memo(
marginBottom: `-${SPACING}px`,
marginLeft: `${sideMargin}px`,
marginRight: `${sideMargin}px`,
...(animate ? { transition: 'margin 0.2s' } : {}),
...(animate ? { transition: 'margin 0.5s' } : {}),
};
return (
<div key={fieldName} ref={ref => storePanels(ref, marginBottom)} style={style}>

View file

@ -18,8 +18,6 @@ import { EventRateChart } from '../charts/event_rate_chart';
import { LineChartPoint } from '../../../common/chart_loader';
import { TimeRangePicker } from './time_range_picker';
import { GetTimeFieldRangeResponse } from '../../../../../services/ml_api_service';
import { mlJobService } from '../../../../../services/job_service';
import { ml } from '../../../../../services/ml_api_service';
export interface TimeRange {
start: number;
@ -82,28 +80,6 @@ export const TimeRangeStep: FC<StepProps> = ({ setCurrentStep, isCurrentStep })
});
}
useEffect(() => {
if (mlJobService.currentJob !== undefined) {
(async (index: string, timeFieldName: string | undefined, query: object) => {
const resp = await ml.getTimeFieldRange({
index,
timeFieldName,
query,
});
setTimeRange({
start: resp.start.epoch,
end: resp.end.epoch,
});
// wipe the cloning job
mlJobService.currentJob = undefined;
})(
kibanaContext.currentIndexPattern.title,
kibanaContext.currentIndexPattern.timeFieldName,
kibanaContext.combinedQuery
);
}
}, []);
return (
<Fragment>
{isCurrentStep && (

View file

@ -51,10 +51,16 @@ export const Page: FC<PageProps> = ({ existingJobsAndGroups, jobType }) => {
const { from, to } = getTimeFilterRange();
jobCreator.setTimeRange(from, to);
if (mlJobService.currentJob !== undefined) {
const clonedJob = mlJobService.cloneJob(mlJobService.currentJob);
let skipTimeRangeStep = false;
if (mlJobService.tempJobCloningObjects.job !== undefined) {
const clonedJob = mlJobService.cloneJob(mlJobService.tempJobCloningObjects.job);
const { job, datafeed } = expandCombinedJobConfig(clonedJob);
jobCreator.cloneFromExistingJob(job, datafeed);
skipTimeRangeStep = mlJobService.tempJobCloningObjects.skipTimeRangeStep;
mlJobService.tempJobCloningObjects.skipTimeRangeStep = false;
mlJobService.tempJobCloningObjects.job = undefined;
} else {
jobCreator.bucketSpan = DEFAULT_BUCKET_SPAN;
@ -89,7 +95,6 @@ export const Page: FC<PageProps> = ({ existingJobsAndGroups, jobType }) => {
useEffect(() => {
return () => {
jobCreator.forceStopRefreshPolls();
mlJobService.currentJob = undefined;
};
});
@ -105,6 +110,7 @@ export const Page: FC<PageProps> = ({ existingJobsAndGroups, jobType }) => {
chartInterval={chartInterval}
jobValidator={jobValidator}
existingJobsAndGroups={existingJobsAndGroups}
skipTimeRangeStep={skipTimeRangeStep}
/>
</EuiPageContentBody>
</EuiPageBody>

View file

@ -39,6 +39,7 @@ interface Props {
chartInterval: MlTimeBuckets;
jobValidator: JobValidator;
existingJobsAndGroups: ExistingJobsAndGroups;
skipTimeRangeStep: boolean;
}
export const Wizard: FC<Props> = ({
@ -48,6 +49,7 @@ export const Wizard: FC<Props> = ({
chartInterval,
jobValidator,
existingJobsAndGroups,
skipTimeRangeStep = false,
}) => {
const [jobCreatorUpdated, setJobCreatorUpdate] = useReducer<(s: number) => number>(s => s + 1, 0);
const jobCreatorUpdate = () => setJobCreatorUpdate(jobCreatorUpdated);
@ -102,6 +104,10 @@ export const Wizard: FC<Props> = ({
useEffect(() => {
jobCreator.subscribeToProgress(setProgress);
if (skipTimeRangeStep) {
setCurrentStep(WIZARD_STEPS.PICK_FIELDS);
}
}, []);
// disable the step links if the job is running

View file

@ -11,6 +11,11 @@ export interface ExistingJobsAndGroups {
declare interface JobService {
currentJob: any;
tempJobCloningObjects: {
job: any;
skipTimeRangeStep: boolean;
};
skipTimeRangeStep: boolean;
saveNewJob(job: any): Promise<any>;
cloneJob(job: any): any;
openJob(jobId: string): Promise<any>;

View file

@ -30,6 +30,12 @@ class JobService {
// if populated when loading the job management page, the start datafeed modal
// is automatically opened.
this.currentJob = undefined;
this.tempJobCloningObjects = {
job: undefined,
skipTimeRangeStep: false,
};
this.jobs = [];
// Provide ready access to widely used basic job properties.