import { i18n } from '@kbn/i18n' ; import { Job , Datafeed , Detector } from '../../../../../../../common/types/anomaly_detection_jobs' ; import { newJobCapsService } from '../../../../../services/new_job_capabilities/new_job_capabilities_service' ; import { NavigateToPath } from '../../../../../contexts/kibana' ; import { ML_JOB_AGGREGATION , SPARSE_DATA_AGGREGATIONS , } from '../../../../../../../common/constants/aggregation_types' ; import { MLCATEGORY , DOC_COUNT , _DOC_COUNT , } from '../../../../../../../common/constants/field_types' ; import { ES_FIELD_TYPES } from '../../../../../../../../../../src/plugins/data/public' ; import { EVENT_RATE_FIELD_ID , Field , AggFieldPair , mlCategory , } from '../../../../../../../common/types/fields' ; import { mlJobService } from '../../../../../services/job_service' ; import { JobCreatorType } from '../index' ; import { CREATED_BY_LABEL , JOB_TYPE } from '../../../../../../../common/constants/new_job' ; const getFieldByIdFactory = ( additionalFields ) => ( id ) => { let field = newJobCapsService . getFieldById ( id ) ; if ( field === null ) { if ( id === MLCATEGORY ) { field = mlCategory ; } else if ( additionalFields . length ) { field = additionalFields . find ( ( f ) => f . id === id ) || null ; } } return field ; } ; export function getRichDetectors ( job , datafeed , additionalFields , advanced = false ) { const detectors = advanced ? getDetectorsAdvanced ( job , datafeed ) : getDetectors ( job , datafeed ) ; const getFieldById = getFieldByIdFactory ( additionalFields ) ; return detectors . map ( ( d ) => { let field = null ; let byField = null ; let overField = null ; let partitionField = null ; if ( d . field_name !== undefined ) { field = getFieldById ( d . field_name ) ; } if ( d . by_field_name !== undefined ) { byField = getFieldById ( d . by_field_name ) ; } if ( d . over_field_name !== undefined ) { overField = getFieldById ( d . over_field_name ) ; } if ( d . partition_field_name !== undefined ) { partitionField = getFieldById ( d . partition_field_name ) ; } return { agg : newJobCapsService . getAggById ( d . function ) , field , byField , overField , partitionField , excludeFrequent : d . exclude_frequent ?? null , description : d . detector_description ?? null , useNull : d . use_null ?? null , } ; } ) ; } export function createFieldOptions ( fields , additionalFields ) { return [ ... fields . filter ( ( f ) => f . id !== EVENT_RATE_FIELD_ID ) . map ( ( f ) => ( { label : f . name , } ) ) , ... additionalFields . filter ( ( f ) => fields . some ( ( f2 ) => f2 . id === f . id ) === false ) . map ( ( f ) => ( { label : f . id , } ) ) , ] . sort ( ( a , b ) => a . label . localeCompare ( b . label ) ) ; } export function createMlcategoryFieldOption ( categorizationFieldName ) { if ( categorizationFieldName === null ) { return [ ] ; } return [ { label : MLCATEGORY , } , ] ; } export function createDocCountFieldOption ( usingAggregations ) { return usingAggregations ? [ { label : DOC_COUNT , } , ] : [ { label : _DOC_COUNT , } , ] ; } function getDetectorsAdvanced ( job , datafeed ) { return processFieldlessAggs ( job . analysis_config . detectors ) ; } function getDetectors ( job , datafeed ) { let detectors = job . analysis_config . detectors ; const sparseData = isSparseDataJob ( job , datafeed ) ; if ( datafeed . aggregations !== undefined && job . analysis_config . detectors [ 0 ] . function === ML_JOB_AGGREGATION . NON_ZERO_COUNT && sparseData === false ) { const field = datafeed ?. aggregations ?. buckets ?. aggregations ?. dc_region ?. cardinality ?. field as string ; if ( field !== undefined ) { detectors = [ { function : ML_JOB_AGGREGATION . DISTINCT_COUNT , field_name : field , } , ] ; } } else { detectors = processFieldlessAggs ( detectors ) ; detectors = detectors . map ( ( d ) => { switch ( d . function ) { case ML_JOB_AGGREGATION . NON_ZERO_COUNT : return { ... d , field_name : EVENT_RATE_FIELD_ID , function : ML_JOB_AGGREGATION . COUNT } ; case ML_JOB_AGGREGATION . HIGH_NON_ZERO_COUNT : return { ... d , field_name : EVENT_RATE_FIELD_ID , function : ML_JOB_AGGREGATION . HIGH_COUNT } ; case ML_JOB_AGGREGATION . LOW_NON_ZERO_COUNT : return { ... d , field_name : EVENT_RATE_FIELD_ID , function : ML_JOB_AGGREGATION . LOW_COUNT } ; case ML_JOB_AGGREGATION . NON_NULL_SUM : return { ... d , function : ML_JOB_AGGREGATION . SUM } ; case ML_JOB_AGGREGATION . HIGH_NON_NULL_SUM : return { ... d , function : ML_JOB_AGGREGATION . HIGH_SUM } ; case ML_JOB_AGGREGATION . LOW_NON_NULL_SUM : return { ... d , function : ML_JOB_AGGREGATION . LOW_SUM } ; default : return d ; } } ) ; } return detectors ; } function processFieldlessAggs ( detectors ) { return detectors . map ( ( d ) => { switch ( d . function ) { case ML_JOB_AGGREGATION . COUNT : case ML_JOB_AGGREGATION . HIGH_COUNT : case ML_JOB_AGGREGATION . LOW_COUNT : case ML_JOB_AGGREGATION . NON_ZERO_COUNT : case ML_JOB_AGGREGATION . HIGH_NON_ZERO_COUNT : case ML_JOB_AGGREGATION . LOW_NON_ZERO_COUNT : case ML_JOB_AGGREGATION . RARE : case ML_JOB_AGGREGATION . FREQ_RARE : case ML_JOB_AGGREGATION . TIME_OF_DAY : case ML_JOB_AGGREGATION . TIME_OF_WEEK : return { ... d , field_name : EVENT_RATE_FIELD_ID } ; default : return d ; } } ) ; } export function isSparseDataJob ( job , datafeed ) { const detectors = job . analysis_config . detectors ; const distinctCountField = datafeed ?. aggregations ?. buckets ?. aggregations ?. dc_region ?. cardinality ?. field as string ; if ( distinctCountField === undefined ) { for ( const detector of detectors ) { if ( SPARSE_DATA_AGGREGATIONS . includes ( detector . function as ML_JOB_AGGREGATION ) ) { return true ; } } } return false ; } function stashJobForCloning ( jobCreator , skipTimeRangeStep = false , includeTimeRange = false ) { mlJobService . tempJobCloningObjects . job = jobCreator . jobConfig ; mlJobService . tempJobCloningObjects . datafeed = jobCreator . datafeedConfig ; mlJobService . tempJobCloningObjects . createdBy = jobCreator . createdBy ?? undefined ; mlJobService . tempJobCloningObjects . skipTimeRangeStep = skipTimeRangeStep ; if ( includeTimeRange === true ) { mlJobService . tempJobCloningObjects . start = jobCreator . start ; mlJobService . tempJobCloningObjects . end = jobCreator . end ; } mlJobService . tempJobCloningObjects . calendars = jobCreator . calendars ; } export function convertToMultiMetricJob ( jobCreator , navigateToPath ) { jobCreator . createdBy = CREATED_BY_LABEL . MULTI_METRIC ; jobCreator . modelPlot = false ; stashJobForCloning ( jobCreator , true , true ) ; navigateToPath ( `jobs/new_job/${ JOB_TYPE . MULTI_METRIC }` , true ) ; } export function convertToAdvancedJob ( jobCreator , navigateToPath ) { jobCreator . createdBy = null ; stashJobForCloning ( jobCreator , true , true ) ; navigateToPath ( `jobs/new_job/${ JOB_TYPE . ADVANCED }` , true ) ; } export function resetAdvancedJob ( jobCreator , navigateToPath ) { jobCreator . createdBy = null ; stashJobForCloning ( jobCreator , true , false ) ; navigateToPath ( '/jobs/new_job' ) ; } export function resetJob ( jobCreator , navigateToPath ) { jobCreator . jobId = '' ; stashJobForCloning ( jobCreator , true , true ) ; navigateToPath ( '/jobs/new_job' ) ; } export function advancedStartDatafeed ( jobCreator , navigateToPath ) { if ( jobCreator !== null ) { stashJobForCloning ( jobCreator , false , false ) ; } navigateToPath ( '/jobs' ) ; } export function aggFieldPairsCanBeCharted ( afs ) { return afs . some ( ( a ) => a . agg . dslName === null ) === false ; } export function getJobCreatorTitle ( jobCreator ) { switch ( jobCreator . type ) { case JOB_TYPE . SINGLE_METRIC : return i18n . translate ( 'xpack.ml.newJob.wizard.jobCreatorTitle.singleMetric' , { defaultMessage : 'Single metric' , } ) ; case JOB_TYPE . MULTI_METRIC : return i18n . translate ( 'xpack.ml.newJob.wizard.jobCreatorTitle.multiMetric' , { defaultMessage : 'Multi-metric' , } ) ; case JOB_TYPE . POPULATION : return i18n . translate ( 'xpack.ml.newJob.wizard.jobCreatorTitle.population' , { defaultMessage : 'Population' , } ) ; case JOB_TYPE . ADVANCED : return i18n . translate ( 'xpack.ml.newJob.wizard.jobCreatorTitle.advanced' , { defaultMessage : 'Advanced' , } ) ; case JOB_TYPE . CATEGORIZATION : return i18n . translate ( 'xpack.ml.newJob.wizard.jobCreatorTitle.categorization' , { defaultMessage : 'Categorization' , } ) ; case JOB_TYPE . RARE : return i18n . translate ( 'xpack.ml.newJob.wizard.jobCreatorTitle.rare' , { defaultMessage : 'Rare' , } ) ; default : return '' ; } } export function collectAggs ( o , aggFields ) { for ( const i in o ) { if ( o [ i ] !== null && typeof o [ i ] === 'object' ) { if ( i === 'aggregations' || i === 'aggs' ) { Object . keys ( o [ i ] ) . forEach ( ( k ) => { if ( k !== 'aggregations' && k !== 'aggs' ) { aggFields . push ( { id : k , name : k , type : ES_FIELD_TYPES . KEYWORD , aggregatable : true , } ) ; } } ) ; } collectAggs ( o [ i ] , aggFields ) ; } } }