Skip to content

Commit 085f8a1

Browse files
committed
Revert "[Metrics UI] Add ability to override datafeeds and job config for partition field (#78875)"
This reverts commit ee7672a.
1 parent fd7dd41 commit 085f8a1

7 files changed

Lines changed: 444 additions & 247 deletions

File tree

x-pack/plugins/infra/public/containers/ml/infra_ml_module_types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ export interface ModuleDescriptor<JobType extends string> {
3333
partitionField?: string
3434
) => Promise<SetupMlModuleResponsePayload>;
3535
cleanUpModule: (spaceId: string, sourceId: string) => Promise<DeleteJobsResponsePayload>;
36-
validateSetupIndices?: (
36+
validateSetupIndices: (
3737
indices: string[],
3838
timestampField: string
3939
) => Promise<ValidationIndicesResponsePayload>;
40-
validateSetupDatasets?: (
40+
validateSetupDatasets: (
4141
indices: string[],
4242
timestampField: string,
4343
startTime: number,
Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { isEqual } from 'lodash';
8+
import { useCallback, useEffect, useMemo, useState } from 'react';
9+
import { usePrevious } from 'react-use';
10+
import {
11+
combineDatasetFilters,
12+
DatasetFilter,
13+
filterDatasetFilter,
14+
isExampleDataIndex,
15+
} from '../../../common/infra_ml';
16+
import {
17+
AvailableIndex,
18+
ValidationIndicesError,
19+
ValidationUIError,
20+
} from '../../components/logging/log_analysis_setup/initial_configuration_step';
21+
import { useTrackedPromise } from '../../utils/use_tracked_promise';
22+
import { ModuleDescriptor, ModuleSourceConfiguration } from './infra_ml_module_types';
23+
24+
type SetupHandler = (
25+
indices: string[],
26+
startTime: number | undefined,
27+
endTime: number | undefined,
28+
datasetFilter: DatasetFilter
29+
) => void;
30+
31+
interface AnalysisSetupStateArguments<JobType extends string> {
32+
cleanUpAndSetUpModule: SetupHandler;
33+
moduleDescriptor: ModuleDescriptor<JobType>;
34+
setUpModule: SetupHandler;
35+
sourceConfiguration: ModuleSourceConfiguration;
36+
}
37+
38+
const fourWeeksInMs = 86400000 * 7 * 4;
39+
40+
export const useAnalysisSetupState = <JobType extends string>({
41+
cleanUpAndSetUpModule,
42+
moduleDescriptor: { validateSetupDatasets, validateSetupIndices },
43+
setUpModule,
44+
sourceConfiguration,
45+
}: AnalysisSetupStateArguments<JobType>) => {
46+
const [startTime, setStartTime] = useState<number | undefined>(Date.now() - fourWeeksInMs);
47+
const [endTime, setEndTime] = useState<number | undefined>(undefined);
48+
49+
const isTimeRangeValid = useMemo(
50+
() => (startTime != null && endTime != null ? startTime < endTime : true),
51+
[endTime, startTime]
52+
);
53+
54+
const [validatedIndices, setValidatedIndices] = useState<AvailableIndex[]>(
55+
sourceConfiguration.indices.map((indexName) => ({
56+
name: indexName,
57+
validity: 'unknown' as const,
58+
}))
59+
);
60+
61+
const updateIndicesWithValidationErrors = useCallback(
62+
(validationErrors: ValidationIndicesError[]) =>
63+
setValidatedIndices((availableIndices) =>
64+
availableIndices.map((previousAvailableIndex) => {
65+
const indexValiationErrors = validationErrors.filter(
66+
({ index }) => index === previousAvailableIndex.name
67+
);
68+
69+
if (indexValiationErrors.length > 0) {
70+
return {
71+
validity: 'invalid',
72+
name: previousAvailableIndex.name,
73+
errors: indexValiationErrors,
74+
};
75+
} else if (previousAvailableIndex.validity === 'valid') {
76+
return {
77+
...previousAvailableIndex,
78+
validity: 'valid',
79+
errors: [],
80+
};
81+
} else {
82+
return {
83+
validity: 'valid',
84+
name: previousAvailableIndex.name,
85+
isSelected: !isExampleDataIndex(previousAvailableIndex.name),
86+
availableDatasets: [],
87+
datasetFilter: {
88+
type: 'includeAll' as const,
89+
},
90+
};
91+
}
92+
})
93+
),
94+
[]
95+
);
96+
97+
const updateIndicesWithAvailableDatasets = useCallback(
98+
(availableDatasets: Array<{ indexName: string; datasets: string[] }>) =>
99+
setValidatedIndices((availableIndices) =>
100+
availableIndices.map((previousAvailableIndex) => {
101+
if (previousAvailableIndex.validity !== 'valid') {
102+
return previousAvailableIndex;
103+
}
104+
105+
const availableDatasetsForIndex = availableDatasets.filter(
106+
({ indexName }) => indexName === previousAvailableIndex.name
107+
);
108+
const newAvailableDatasets = availableDatasetsForIndex.flatMap(
109+
({ datasets }) => datasets
110+
);
111+
112+
// filter out datasets that have disappeared if this index' datasets were updated
113+
const newDatasetFilter: DatasetFilter =
114+
availableDatasetsForIndex.length > 0
115+
? filterDatasetFilter(previousAvailableIndex.datasetFilter, (dataset) =>
116+
newAvailableDatasets.includes(dataset)
117+
)
118+
: previousAvailableIndex.datasetFilter;
119+
120+
return {
121+
...previousAvailableIndex,
122+
availableDatasets: newAvailableDatasets,
123+
datasetFilter: newDatasetFilter,
124+
};
125+
})
126+
),
127+
[]
128+
);
129+
130+
const validIndexNames = useMemo(
131+
() => validatedIndices.filter((index) => index.validity === 'valid').map((index) => index.name),
132+
[validatedIndices]
133+
);
134+
135+
const selectedIndexNames = useMemo(
136+
() =>
137+
validatedIndices
138+
.filter((index) => index.validity === 'valid' && index.isSelected)
139+
.map((i) => i.name),
140+
[validatedIndices]
141+
);
142+
143+
const datasetFilter = useMemo(
144+
() =>
145+
validatedIndices
146+
.flatMap((validatedIndex) =>
147+
validatedIndex.validity === 'valid'
148+
? validatedIndex.datasetFilter
149+
: { type: 'includeAll' as const }
150+
)
151+
.reduce(combineDatasetFilters, { type: 'includeAll' as const }),
152+
[validatedIndices]
153+
);
154+
155+
const [validateIndicesRequest, validateIndices] = useTrackedPromise(
156+
{
157+
cancelPreviousOn: 'resolution',
158+
createPromise: async () => {
159+
return await validateSetupIndices(
160+
sourceConfiguration.indices,
161+
sourceConfiguration.timestampField
162+
);
163+
},
164+
onResolve: ({ data: { errors } }) => {
165+
updateIndicesWithValidationErrors(errors);
166+
},
167+
onReject: () => {
168+
setValidatedIndices([]);
169+
},
170+
},
171+
[sourceConfiguration.indices, sourceConfiguration.timestampField]
172+
);
173+
174+
const [validateDatasetsRequest, validateDatasets] = useTrackedPromise(
175+
{
176+
cancelPreviousOn: 'resolution',
177+
createPromise: async () => {
178+
if (validIndexNames.length === 0) {
179+
return { data: { datasets: [] } };
180+
}
181+
182+
return await validateSetupDatasets(
183+
validIndexNames,
184+
sourceConfiguration.timestampField,
185+
startTime ?? 0,
186+
endTime ?? Date.now()
187+
);
188+
},
189+
onResolve: ({ data: { datasets } }) => {
190+
updateIndicesWithAvailableDatasets(datasets);
191+
},
192+
},
193+
[validIndexNames, sourceConfiguration.timestampField, startTime, endTime]
194+
);
195+
196+
const setUp = useCallback(() => {
197+
return setUpModule(selectedIndexNames, startTime, endTime, datasetFilter);
198+
}, [setUpModule, selectedIndexNames, startTime, endTime, datasetFilter]);
199+
200+
const cleanUpAndSetUp = useCallback(() => {
201+
return cleanUpAndSetUpModule(selectedIndexNames, startTime, endTime, datasetFilter);
202+
}, [cleanUpAndSetUpModule, selectedIndexNames, startTime, endTime, datasetFilter]);
203+
204+
const isValidating = useMemo(
205+
() => validateIndicesRequest.state === 'pending' || validateDatasetsRequest.state === 'pending',
206+
[validateDatasetsRequest.state, validateIndicesRequest.state]
207+
);
208+
209+
const validationErrors = useMemo<ValidationUIError[]>(() => {
210+
if (isValidating) {
211+
return [];
212+
}
213+
214+
return [
215+
// validate request status
216+
...(validateIndicesRequest.state === 'rejected' ||
217+
validateDatasetsRequest.state === 'rejected'
218+
? [{ error: 'NETWORK_ERROR' as const }]
219+
: []),
220+
// validation request results
221+
...validatedIndices.reduce<ValidationUIError[]>((errors, index) => {
222+
return index.validity === 'invalid' && selectedIndexNames.includes(index.name)
223+
? [...errors, ...index.errors]
224+
: errors;
225+
}, []),
226+
// index count
227+
...(selectedIndexNames.length === 0 ? [{ error: 'TOO_FEW_SELECTED_INDICES' as const }] : []),
228+
// time range
229+
...(!isTimeRangeValid ? [{ error: 'INVALID_TIME_RANGE' as const }] : []),
230+
];
231+
}, [
232+
isValidating,
233+
validateIndicesRequest.state,
234+
validateDatasetsRequest.state,
235+
validatedIndices,
236+
selectedIndexNames,
237+
isTimeRangeValid,
238+
]);
239+
240+
const prevStartTime = usePrevious(startTime);
241+
const prevEndTime = usePrevious(endTime);
242+
const prevValidIndexNames = usePrevious(validIndexNames);
243+
244+
useEffect(() => {
245+
if (!isTimeRangeValid) {
246+
return;
247+
}
248+
249+
validateIndices();
250+
}, [isTimeRangeValid, validateIndices]);
251+
252+
useEffect(() => {
253+
if (!isTimeRangeValid) {
254+
return;
255+
}
256+
257+
if (
258+
startTime !== prevStartTime ||
259+
endTime !== prevEndTime ||
260+
!isEqual(validIndexNames, prevValidIndexNames)
261+
) {
262+
validateDatasets();
263+
}
264+
}, [
265+
endTime,
266+
isTimeRangeValid,
267+
prevEndTime,
268+
prevStartTime,
269+
prevValidIndexNames,
270+
startTime,
271+
validIndexNames,
272+
validateDatasets,
273+
]);
274+
275+
return {
276+
cleanUpAndSetUp,
277+
datasetFilter,
278+
endTime,
279+
isValidating,
280+
selectedIndexNames,
281+
setEndTime,
282+
setStartTime,
283+
setUp,
284+
startTime,
285+
validatedIndices,
286+
setValidatedIndices,
287+
validationErrors,
288+
};
289+
};

0 commit comments

Comments
 (0)