mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[ML] Adding bucket span estimator to new wizards (#43288)
* [ML] Adding bucket span estimator to new wizards * disabling next button when estimating * fixing population
This commit is contained in:
parent
c65b9752cb
commit
f4b0a9c962
10 changed files with 147 additions and 10 deletions
|
@ -95,11 +95,19 @@ export class JobCreator {
|
|||
return agg !== undefined ? agg : null;
|
||||
}
|
||||
|
||||
public get aggregations(): Aggregation[] {
|
||||
return this._aggs;
|
||||
}
|
||||
|
||||
public getField(index: number): Field | null {
|
||||
const field = this._fields[index];
|
||||
return field !== undefined ? field : null;
|
||||
}
|
||||
|
||||
public get fields(): Field[] {
|
||||
return this._fields;
|
||||
}
|
||||
|
||||
public set bucketSpan(bucketSpan: BucketSpan) {
|
||||
this._job_config.analysis_config.bucket_span = bucketSpan;
|
||||
}
|
||||
|
|
|
@ -5,12 +5,18 @@
|
|||
*/
|
||||
|
||||
import React, { FC, useContext, useEffect, useState } from 'react';
|
||||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
|
||||
import { BucketSpanInput } from './bucket_span_input';
|
||||
import { JobCreatorContext } from '../../../job_creator_context';
|
||||
import { Description } from './description';
|
||||
import { BucketSpanEstimator } from '../bucket_span_estimator';
|
||||
|
||||
export const BucketSpan: FC = () => {
|
||||
interface Props {
|
||||
setIsValid: (proceed: boolean) => void;
|
||||
}
|
||||
|
||||
export const BucketSpan: FC<Props> = ({ setIsValid }) => {
|
||||
const {
|
||||
jobCreator,
|
||||
jobCreatorUpdate,
|
||||
|
@ -20,6 +26,7 @@ export const BucketSpan: FC = () => {
|
|||
} = useContext(JobCreatorContext);
|
||||
const [bucketSpan, setBucketSpan] = useState(jobCreator.bucketSpan);
|
||||
const [validation, setValidation] = useState(jobValidator.bucketSpan);
|
||||
const [estimating, setEstimating] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
jobCreator.bucketSpan = bucketSpan;
|
||||
|
@ -34,13 +41,25 @@ export const BucketSpan: FC = () => {
|
|||
setValidation(jobValidator.bucketSpan);
|
||||
}, [jobValidatorUpdated]);
|
||||
|
||||
useEffect(() => {
|
||||
setIsValid(estimating === false);
|
||||
}, [estimating]);
|
||||
|
||||
return (
|
||||
<Description validation={validation}>
|
||||
<BucketSpanInput
|
||||
setBucketSpan={setBucketSpan}
|
||||
bucketSpan={bucketSpan}
|
||||
isInvalid={validation.valid === false}
|
||||
/>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<BucketSpanInput
|
||||
setBucketSpan={setBucketSpan}
|
||||
bucketSpan={bucketSpan}
|
||||
isInvalid={validation.valid === false}
|
||||
disabled={estimating}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<BucketSpanEstimator setEstimating={setEstimating} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</Description>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -11,11 +11,13 @@ interface Props {
|
|||
bucketSpan: string;
|
||||
setBucketSpan: (bs: string) => void;
|
||||
isInvalid: boolean;
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
export const BucketSpanInput: FC<Props> = ({ bucketSpan, setBucketSpan, isInvalid }) => {
|
||||
export const BucketSpanInput: FC<Props> = ({ bucketSpan, setBucketSpan, isInvalid, disabled }) => {
|
||||
return (
|
||||
<EuiFieldText
|
||||
disabled={disabled}
|
||||
placeholder="Bucket span"
|
||||
value={bucketSpan}
|
||||
onChange={e => setBucketSpan(e.target.value)}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { FC, useEffect } from 'react';
|
||||
import { EuiButton } from '@elastic/eui';
|
||||
|
||||
import { useEstimateBucketSpan, ESTIMATE_STATUS } from './estimate_bucket_span';
|
||||
|
||||
interface Props {
|
||||
setEstimating(estimating: boolean): void;
|
||||
}
|
||||
|
||||
export const BucketSpanEstimator: FC<Props> = ({ setEstimating }) => {
|
||||
const { status, estimateBucketSpan } = useEstimateBucketSpan();
|
||||
|
||||
useEffect(() => {
|
||||
setEstimating(status === ESTIMATE_STATUS.RUNNING);
|
||||
}, [status]);
|
||||
|
||||
return (
|
||||
<EuiButton disabled={status === ESTIMATE_STATUS.RUNNING} onClick={estimateBucketSpan}>
|
||||
Estimate bucket span
|
||||
</EuiButton>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { useContext, useState } from 'react';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { toastNotifications } from 'ui/notify';
|
||||
import { JobCreatorContext } from '../../../job_creator_context';
|
||||
import { EVENT_RATE_FIELD_ID } from '../../../../../../../../common/types/fields';
|
||||
import { isMultiMetricJobCreator, isPopulationJobCreator } from '../../../../../common/job_creator';
|
||||
import { ml } from '../../../../../../../services/ml_api_service';
|
||||
import { useKibanaContext } from '../../../../../../../contexts/kibana';
|
||||
|
||||
export enum ESTIMATE_STATUS {
|
||||
NOT_RUNNING,
|
||||
RUNNING,
|
||||
}
|
||||
|
||||
export function useEstimateBucketSpan() {
|
||||
const { jobCreator, jobCreatorUpdate } = useContext(JobCreatorContext);
|
||||
const kibanaContext = useKibanaContext();
|
||||
|
||||
const [status, setStatus] = useState(ESTIMATE_STATUS.NOT_RUNNING);
|
||||
|
||||
const data = {
|
||||
aggTypes: jobCreator.aggregations.map(a => a.dslName),
|
||||
duration: {
|
||||
start: jobCreator.start,
|
||||
end: jobCreator.end,
|
||||
},
|
||||
fields: jobCreator.fields.map(f => (f.id === EVENT_RATE_FIELD_ID ? null : f.id)),
|
||||
index: kibanaContext.currentIndexPattern.title,
|
||||
query: kibanaContext.combinedQuery,
|
||||
splitField:
|
||||
(isMultiMetricJobCreator(jobCreator) || isPopulationJobCreator(jobCreator)) &&
|
||||
jobCreator.splitField !== null
|
||||
? jobCreator.splitField.id
|
||||
: undefined,
|
||||
timeField: kibanaContext.currentIndexPattern.timeFieldName,
|
||||
};
|
||||
|
||||
async function estimateBucketSpan() {
|
||||
setStatus(ESTIMATE_STATUS.RUNNING);
|
||||
const { name, error, message } = await ml.estimateBucketSpan(data);
|
||||
setStatus(ESTIMATE_STATUS.NOT_RUNNING);
|
||||
if (error === true) {
|
||||
let text = '';
|
||||
if (message !== undefined) {
|
||||
if (typeof message === 'object') {
|
||||
text = message.msg || JSON.stringify(message);
|
||||
} else {
|
||||
text = message;
|
||||
}
|
||||
}
|
||||
toastNotifications.addDanger({
|
||||
title: i18n.translate('xpack.ml.newJob.wizard.estimateBucketSpanError', {
|
||||
defaultMessage: `Bucket span estimation error`,
|
||||
}),
|
||||
text,
|
||||
});
|
||||
} else {
|
||||
jobCreator.bucketSpan = name;
|
||||
jobCreatorUpdate();
|
||||
}
|
||||
}
|
||||
return { status, estimateBucketSpan };
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
export { BucketSpanEstimator } from './bucket_span_estimator';
|
|
@ -45,7 +45,7 @@ export const MultiMetricSettings: FC<Props> = ({ isActive, setIsValid }) => {
|
|||
</EuiFlexGroup>
|
||||
<EuiFlexGroup gutterSize="xl">
|
||||
<EuiFlexItem>
|
||||
<BucketSpan />
|
||||
<BucketSpan setIsValid={setIsValid} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem />
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -36,7 +36,7 @@ export const PopulationSettings: FC<Props> = ({ isActive, setIsValid }) => {
|
|||
<Fragment>
|
||||
<EuiFlexGroup gutterSize="xl">
|
||||
<EuiFlexItem>
|
||||
<BucketSpan />
|
||||
<BucketSpan setIsValid={setIsValid} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<Influencers />
|
||||
|
|
|
@ -51,7 +51,7 @@ export const SingleMetricSettings: FC<Props> = ({ isActive, setIsValid }) => {
|
|||
<Fragment>
|
||||
<EuiFlexGroup gutterSize="xl">
|
||||
<EuiFlexItem>
|
||||
<BucketSpan />
|
||||
<BucketSpan setIsValid={setIsValid} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiFlexGroup>
|
||||
|
|
|
@ -121,6 +121,10 @@ declare interface Ml {
|
|||
end: number
|
||||
): Promise<{ progress: number; isRunning: boolean }>;
|
||||
};
|
||||
|
||||
estimateBucketSpan(
|
||||
data: object
|
||||
): Promise<{ name: string; ms: number; error?: boolean; message?: { msg: string } | string }>;
|
||||
}
|
||||
|
||||
declare const ml: Ml;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue