Skip to content

Commit cf03c92

Browse files
[ML] Use indices options in anomaly detection job wizards (#91830) (#94755)
* [ML] WIP Datafeed preview refactor * adding indices options to ad job creation searches * update datafeed preview schema * updating types * recalculating wizard time range on JSON edit save * updating endpoint docs * fixing types * more type fixes * fixing missing runtime fields * using isPopulatedObject * adding indices options schema * fixing test * fixing schema Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: James Gowdy <jgowdy@elastic.co>
1 parent 524ab01 commit cf03c92

File tree

45 files changed

+490
-289
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+490
-289
lines changed

x-pack/plugins/ml/common/types/anomaly_detection_jobs/datafeed.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export type Aggregation = Record<
4545
}
4646
>;
4747

48-
interface IndicesOptions {
48+
export interface IndicesOptions {
4949
expand_wildcards?: 'all' | 'open' | 'closed' | 'hidden' | 'none';
5050
ignore_unavailable?: boolean;
5151
allow_no_indices?: boolean;

x-pack/plugins/ml/common/types/job_service.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
* 2.0.
66
*/
77

8-
import { Job, JobStats } from './anomaly_detection_jobs';
8+
import { Job, JobStats, IndicesOptions } from './anomaly_detection_jobs';
9+
import { RuntimeMappings } from './fields';
10+
import { ES_AGGREGATION } from '../constants/aggregation_types';
911

1012
export interface MlJobsResponse {
1113
jobs: Job[];
@@ -23,3 +25,18 @@ export interface JobsExistResponse {
2325
isGroup: boolean;
2426
};
2527
}
28+
29+
export interface BucketSpanEstimatorData {
30+
aggTypes: Array<ES_AGGREGATION | null>;
31+
duration: {
32+
start: number;
33+
end: number;
34+
};
35+
fields: Array<string | null>;
36+
index: string;
37+
query: any;
38+
splitField: string | undefined;
39+
timeField: string | undefined;
40+
runtimeMappings: RuntimeMappings | undefined;
41+
indicesOptions: IndicesOptions | undefined;
42+
}

x-pack/plugins/ml/public/application/components/model_snapshots/revert_model_snapshot_flyout/chart_loader.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ export function chartLoaderProvider(mlResultsService: MlResultsService) {
2929
job.data_description.time_field,
3030
job.data_counts.earliest_record_timestamp,
3131
job.data_counts.latest_record_timestamp,
32-
intervalMs
32+
intervalMs,
33+
job.datafeed_config.indices_options
3334
);
3435
if (resp.error !== undefined) {
3536
throw resp.error;

x-pack/plugins/ml/public/application/jobs/new_job/common/chart_loader/chart_loader.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import memoizeOne from 'memoize-one';
99
import { isEqual } from 'lodash';
1010
import { IndexPatternTitle } from '../../../../../../common/types/kibana';
11+
import { IndicesOptions } from '../../../../../../common/types/anomaly_detection_jobs';
1112
import {
1213
Field,
1314
SplitField,
@@ -56,7 +57,8 @@ export class ChartLoader {
5657
splitField: SplitField,
5758
splitFieldValue: SplitFieldValue,
5859
intervalMs: number,
59-
runtimeMappings: RuntimeMappings | null
60+
runtimeMappings: RuntimeMappings | null,
61+
indicesOptions?: IndicesOptions
6062
): Promise<LineChartData> {
6163
if (this._timeFieldName !== '') {
6264
if (aggFieldPairsCanBeCharted(aggFieldPairs) === false) {
@@ -77,7 +79,8 @@ export class ChartLoader {
7779
aggFieldPairNames,
7880
splitFieldName,
7981
splitFieldValue,
80-
runtimeMappings ?? undefined
82+
runtimeMappings ?? undefined,
83+
indicesOptions
8184
);
8285

8386
return resp.results;
@@ -91,7 +94,8 @@ export class ChartLoader {
9194
aggFieldPairs: AggFieldPair[],
9295
splitField: SplitField,
9396
intervalMs: number,
94-
runtimeMappings: RuntimeMappings | null
97+
runtimeMappings: RuntimeMappings | null,
98+
indicesOptions?: IndicesOptions
9599
): Promise<LineChartData> {
96100
if (this._timeFieldName !== '') {
97101
if (aggFieldPairsCanBeCharted(aggFieldPairs) === false) {
@@ -111,7 +115,8 @@ export class ChartLoader {
111115
this._query,
112116
aggFieldPairNames,
113117
splitFieldName,
114-
runtimeMappings ?? undefined
118+
runtimeMappings ?? undefined,
119+
indicesOptions
115120
);
116121

117122
return resp.results;
@@ -122,7 +127,8 @@ export class ChartLoader {
122127
async loadEventRateChart(
123128
start: number,
124129
end: number,
125-
intervalMs: number
130+
intervalMs: number,
131+
indicesOptions?: IndicesOptions
126132
): Promise<LineChartPoint[]> {
127133
if (this._timeFieldName !== '') {
128134
const resp = await getEventRateData(
@@ -131,7 +137,8 @@ export class ChartLoader {
131137
this._timeFieldName,
132138
start,
133139
end,
134-
intervalMs * 3
140+
intervalMs * 3,
141+
indicesOptions
135142
);
136143
if (resp.error !== undefined) {
137144
throw resp.error;
@@ -147,14 +154,16 @@ export class ChartLoader {
147154

148155
async loadFieldExampleValues(
149156
field: Field,
150-
runtimeMappings: RuntimeMappings | null
157+
runtimeMappings: RuntimeMappings | null,
158+
indicesOptions?: IndicesOptions
151159
): Promise<string[]> {
152160
const { results } = await getCategoryFields(
153161
this._indexPatternTitle,
154162
field.name,
155163
10,
156164
this._query,
157-
runtimeMappings ?? undefined
165+
runtimeMappings ?? undefined,
166+
indicesOptions
158167
);
159168
return results;
160169
}

x-pack/plugins/ml/public/application/jobs/new_job/common/chart_loader/searches.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { get } from 'lodash';
99

1010
import { ml } from '../../../../services/ml_api_service';
1111
import { RuntimeMappings } from '../../../../../../common/types/fields';
12+
import { IndicesOptions } from '../../../../../../common/types/anomaly_detection_jobs';
1213

1314
interface CategoryResults {
1415
success: boolean;
@@ -20,7 +21,8 @@ export function getCategoryFields(
2021
fieldName: string,
2122
size: number,
2223
query: any,
23-
runtimeMappings?: RuntimeMappings
24+
runtimeMappings?: RuntimeMappings,
25+
indicesOptions?: IndicesOptions
2426
): Promise<CategoryResults> {
2527
return new Promise((resolve, reject) => {
2628
ml.esSearch({
@@ -38,6 +40,7 @@ export function getCategoryFields(
3840
},
3941
...(runtimeMappings !== undefined ? { runtime_mappings: runtimeMappings } : {}),
4042
},
43+
...(indicesOptions ?? {}),
4144
})
4245
.then((resp: any) => {
4346
const catFields = get(resp, ['aggregations', 'catFields', 'buckets'], []);

x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -177,16 +177,13 @@ export class AdvancedJobCreator extends JobCreator {
177177
// load the start and end times for the selected index
178178
// and apply them to the job creator
179179
public async autoSetTimeRange() {
180-
try {
181-
const { start, end } = await ml.getTimeFieldRange({
182-
index: this._indexPatternTitle,
183-
timeFieldName: this.timeFieldName,
184-
query: this.query,
185-
});
186-
this.setTimeRange(start.epoch, end.epoch);
187-
} catch (error) {
188-
throw Error(error);
189-
}
180+
const { start, end } = await ml.getTimeFieldRange({
181+
index: this._indexPatternTitle,
182+
timeFieldName: this.timeFieldName,
183+
query: this.query,
184+
indicesOptions: this.datafeedConfig.indices_options,
185+
});
186+
this.setTimeRange(start.epoch, end.epoch);
190187
}
191188

192189
public cloneFromExistingJob(job: Job, datafeed: Datafeed) {

x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ export class CategorizationExamplesLoader {
5151
this._jobCreator.start,
5252
this._jobCreator.end,
5353
analyzer,
54-
this._jobCreator.runtimeMappings ?? undefined
54+
this._jobCreator.runtimeMappings ?? undefined,
55+
this._jobCreator.datafeedConfig.indices_options
5556
);
5657
return resp;
5758
}

x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/results_loader.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,8 @@ export class ResultsLoader {
256256
if (this._jobCreator.splitField !== null) {
257257
const fieldValues = await this._chartLoader.loadFieldExampleValues(
258258
this._jobCreator.splitField,
259-
this._jobCreator.runtimeMappings
259+
this._jobCreator.runtimeMappings,
260+
this._jobCreator.datafeedConfig.indices_options
260261
);
261262
if (fieldValues.length > 0) {
262263
this._detectorSplitFieldFilters = {

x-pack/plugins/ml/public/application/jobs/new_job/pages/components/common/json_editor_flyout/json_editor_flyout.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ import { CombinedJob, Datafeed } from '../../../../../../../../common/types/anom
2525
import { ML_EDITOR_MODE, MLJobEditor } from '../../../../../jobs_list/components/ml_job_editor';
2626
import { isValidJson } from '../../../../../../../../common/util/validation_utils';
2727
import { JobCreatorContext } from '../../job_creator_context';
28+
import { isAdvancedJobCreator } from '../../../../common/job_creator';
2829
import { DatafeedPreview } from '../datafeed_preview_flyout';
30+
import { useToastNotificationService } from '../../../../../../services/toast_notification_service';
2931

3032
export enum EDITOR_MODE {
3133
HIDDEN,
@@ -40,6 +42,7 @@ interface Props {
4042
}
4143
export const JsonEditorFlyout: FC<Props> = ({ isDisabled, jobEditorMode, datafeedEditorMode }) => {
4244
const { jobCreator, jobCreatorUpdate, jobCreatorUpdated } = useContext(JobCreatorContext);
45+
const { displayErrorToast } = useToastNotificationService();
4346
const [showJsonFlyout, setShowJsonFlyout] = useState(false);
4447
const [showChangedIndicesWarning, setShowChangedIndicesWarning] = useState(false);
4548

@@ -120,10 +123,23 @@ export const JsonEditorFlyout: FC<Props> = ({ isDisabled, jobEditorMode, datafee
120123
setSaveable(valid);
121124
}
122125

123-
function onSave() {
126+
async function onSave() {
124127
const jobConfig = JSON.parse(jobConfigString);
125128
const datafeedConfig = JSON.parse(collapseLiteralStrings(datafeedConfigString));
126129
jobCreator.cloneFromExistingJob(jobConfig, datafeedConfig);
130+
if (isAdvancedJobCreator(jobCreator)) {
131+
try {
132+
await jobCreator.autoSetTimeRange();
133+
} catch (error) {
134+
const title = i18n.translate(
135+
'xpack.ml.newJob.wizard.jsonFlyout.autoSetJobCreatorTimeRange.error',
136+
{
137+
defaultMessage: `Error retrieving beginning and end times of index`,
138+
}
139+
);
140+
displayErrorToast(error, title);
141+
}
142+
}
127143
jobCreatorUpdate();
128144
setShowJsonFlyout(false);
129145
}

x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/bucket_span_estimator/estimate_bucket_span.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ import { useContext, useState } from 'react';
99

1010
import { JobCreatorContext } from '../../../job_creator_context';
1111
import { EVENT_RATE_FIELD_ID } from '../../../../../../../../../common/types/fields';
12+
import { BucketSpanEstimatorData } from '../../../../../../../../../common/types/job_service';
1213
import {
1314
isMultiMetricJobCreator,
1415
isPopulationJobCreator,
1516
isAdvancedJobCreator,
1617
} from '../../../../../common/job_creator';
17-
import { ml, BucketSpanEstimatorData } from '../../../../../../../services/ml_api_service';
18+
import { ml } from '../../../../../../../services/ml_api_service';
1819
import { useMlContext } from '../../../../../../../contexts/ml';
1920
import { getToastNotificationService } from '../../../../../../../services/toast_notification_service';
2021

@@ -41,6 +42,7 @@ export function useEstimateBucketSpan() {
4142
splitField: undefined,
4243
timeField: mlContext.currentIndexPattern.timeFieldName,
4344
runtimeMappings: jobCreator.runtimeMappings ?? undefined,
45+
indicesOptions: jobCreator.datafeedConfig.indices_options,
4446
};
4547

4648
if (

0 commit comments

Comments
 (0)