@@ -77,6 +77,7 @@ import { formikToDetectorName } from '../FeatureAnywhereContextMenu/CreateAnomal
77
77
import { DEFAULT_DATA } from '../../../../../src/plugins/data/common' ;
78
78
import { AppState } from '../../redux/reducers' ;
79
79
import { v4 as uuidv4 } from 'uuid' ;
80
+ import { getPathsPerDataType } from '../../redux/reducers/mapper' ;
80
81
81
82
export interface GeneratedParameters {
82
83
categoryField : string ;
@@ -107,8 +108,7 @@ function SuggestAnomalyDetector({
107
108
const indexPatternId = dataset . id ;
108
109
// indexName could be a index pattern or a concrete index
109
110
const indexName = dataset . title ;
110
- const timeFieldName = dataset . timeFieldName ;
111
- if ( ! indexPatternId || ! indexName || ! timeFieldName ) {
111
+ if ( ! indexPatternId || ! indexName ) {
112
112
notifications . toasts . addDanger (
113
113
'Cannot extract complete index info from the context'
114
114
) ;
@@ -135,11 +135,12 @@ function SuggestAnomalyDetector({
135
135
) ;
136
136
const categoricalFields = getCategoryFields ( indexDataTypes ) ;
137
137
138
- const dateFields = get ( indexDataTypes , 'date' , [ ] ) as string [ ] ;
139
- const dateNanoFields = get ( indexDataTypes , 'date_nanos' , [ ] ) as string [ ] ;
140
- const allDateFields = dateFields . concat ( dateNanoFields ) ;
141
-
138
+ // const dateFields = get(indexDataTypes, 'date', []) as string[];
139
+ // const dateNanoFields = get(indexDataTypes, 'date_nanos', []) as string[];
140
+ // const allDateFields = dateFields.concat(dateNanoFields);
141
+ const [ allDateFields , setAllDateFields ] = useState < string [ ] > ( [ ] ) ;
142
142
const [ feedbackResult , setFeedbackResult ] = useState < boolean | undefined > ( undefined ) ;
143
+ const [ timeFieldName , setTimeFieldName ] = useState ( dataset . timeFieldName || '' ) ;
143
144
144
145
// let LLM to generate parameters for creating anomaly detector
145
146
async function getParameters ( ) {
@@ -166,6 +167,16 @@ function SuggestAnomalyDetector({
166
167
initialDetectorValue . categoryFieldEnabled = ! ! generatedParameters . categoryField ;
167
168
initialDetectorValue . categoryField = initialDetectorValue . categoryFieldEnabled ? [ generatedParameters . categoryField ] : [ ] ;
168
169
170
+ // if the dataset has no time field, then we find a root level field from the mapping, or we use the first one as the default time field
171
+ if ( ! timeFieldName ) {
172
+ if ( generatedParameters . dateFields . length == 0 ) {
173
+ throw new Error ( 'Cannot find any date type fields!' ) ;
174
+ }
175
+ const defaultTimeField = generatedParameters . dateFields . find ( dateField => ! dateField . includes ( '.' ) ) || generatedParameters . dateFields [ 0 ] ;
176
+ setTimeFieldName ( defaultTimeField ) ;
177
+ initialDetectorValue . timeField = defaultTimeField ;
178
+ }
179
+
169
180
setIsLoading ( false ) ;
170
181
setButtonName ( 'Create detector' ) ;
171
182
setCategoryFieldEnabled ( ! ! generatedParameters . categoryField ) ;
@@ -183,7 +194,7 @@ function SuggestAnomalyDetector({
183
194
const rawAggregationMethods = rawGeneratedParameters [ 'aggregationMethod' ] ;
184
195
const rawDataFields = rawGeneratedParameters [ 'dateFields' ] ;
185
196
if ( ! rawAggregationFields || ! rawAggregationMethods || ! rawDataFields ) {
186
- throw new Error ( 'Cannot find aggregation field, aggregation method or data fields!' ) ;
197
+ throw new Error ( 'Cannot find aggregation field, aggregation method or date fields!' ) ;
187
198
}
188
199
const aggregationFields =
189
200
rawAggregationFields . split ( ',' ) ;
@@ -196,19 +207,21 @@ function SuggestAnomalyDetector({
196
207
}
197
208
198
209
const featureList = aggregationFields . map ( ( field : string , index : number ) => {
199
- const method = aggregationMethods [ index ] ;
210
+ let method = aggregationMethods [ index ] ;
200
211
if ( ! field || ! method ) {
201
212
throw new Error ( 'The generated aggregation field or aggregation method is empty!' ) ;
202
213
}
214
+ // for the count aggregation method, display name and actual name are different, need to convert the display name to actual name
215
+ method = method . replace ( 'count' , 'value_count' ) ;
203
216
const aggregationOption = {
204
217
label : field ,
205
218
} ;
206
219
const feature : FeaturesFormikValues = {
207
- featureName : `feature_${ field } ` ,
220
+ featureName : `feature_${ field } ` . substring ( 0 , 64 ) ,
208
221
featureType : FEATURE_TYPE . SIMPLE ,
209
222
featureEnabled : true ,
210
223
aggregationQuery : '' ,
211
- aggregationBy : aggregationMethods [ index ] ,
224
+ aggregationBy : method ,
212
225
aggregationOf : [ aggregationOption ] ,
213
226
} ;
214
227
return feature ;
@@ -223,8 +236,31 @@ function SuggestAnomalyDetector({
223
236
224
237
useEffect ( ( ) => {
225
238
async function fetchData ( ) {
226
- await dispatch ( getMappings ( indexName , dataSourceId ) ) ;
227
- await getParameters ( ) ;
239
+ await dispatch ( getMappings ( indexName , dataSourceId ) )
240
+ . then ( async ( result : any ) => {
241
+ const indexDataTypes = getPathsPerDataType ( result . response . mappings ) ;
242
+ const dateFields = get ( indexDataTypes , 'date' , [ ] ) as string [ ] ;
243
+ const dateNanoFields = get ( indexDataTypes , 'date_nanos' , [ ] ) as string [ ] ;
244
+ const allDateFields = dateFields . concat ( dateNanoFields ) ;
245
+ setAllDateFields ( allDateFields ) ;
246
+ if ( allDateFields . length == 0 ) {
247
+ notifications . toasts . addDanger (
248
+ 'Cannot find any date type fields!'
249
+ ) ;
250
+ } else {
251
+ await getParameters ( ) ;
252
+ }
253
+ } )
254
+ . catch ( ( err : any ) => {
255
+ notifications . toasts . addDanger (
256
+ prettifyErrorMessage (
257
+ getErrorMessage (
258
+ err ,
259
+ 'There was a problem getting the index mapping'
260
+ )
261
+ )
262
+ ) ;
263
+ } ) ;
228
264
}
229
265
fetchData ( ) ;
230
266
} , [ ] ) ;
0 commit comments