import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey' ; import { ES_FIELD_TYPES } from '@kbn/field-types' ; import type { ElasticsearchClient } from 'src/core/server' ; import type { CorrelationsParams } from '../../../../common/correlations/types' ; import { FIELD_PREFIX_TO_EXCLUDE_AS_CANDIDATE , FIELDS_TO_ADD_AS_CANDIDATE , FIELDS_TO_EXCLUDE_AS_CANDIDATE , POPULATED_DOC_COUNT_SAMPLE_SIZE , } from '../../../../common/correlations/constants' ; import { hasPrefixToInclude } from '../../../../common/correlations/utils' ; import { getQueryWithParams } from './get_query_with_params' ; import { getRequestBase } from './get_request_base' ; const SUPPORTED_ES_FIELD_TYPES = [ ES_FIELD_TYPES . KEYWORD , ES_FIELD_TYPES . IP , ES_FIELD_TYPES . BOOLEAN , ] ; export const shouldBeExcluded = ( fieldName ) => { return ( FIELDS_TO_EXCLUDE_AS_CANDIDATE . has ( fieldName ) || FIELD_PREFIX_TO_EXCLUDE_AS_CANDIDATE . some ( ( prefix ) => fieldName . startsWith ( prefix ) ) ) ; } ; export const getRandomDocsRequest = ( params ) : estypes . SearchRequest => ( { ... getRequestBase ( params ) , body : { fields : [ '*' ] , _source : false , query : { function_score : { query : getQueryWithParams ( { params } ) , random_score : { } , } , } , size : POPULATED_DOC_COUNT_SAMPLE_SIZE , } , } ) ; export const fetchTransactionDurationFieldCandidates = async ( esClient , params ) : Promise < { fieldCandidates : string [ ] ; } > => { const { index } = params ; const respMapping = await esClient . fieldCaps ( { index , fields : '*' , } ) ; const finalFieldCandidates = new Set ( FIELDS_TO_ADD_AS_CANDIDATE ) ; const acceptableFields = new Set ( ) ; Object . entries ( respMapping . body . fields ) . forEach ( ( [ key , value ] ) => { const fieldTypes = Object . keys ( value ) as ES_FIELD_TYPES [ ] ; const isSupportedType = fieldTypes . some ( ( type ) => SUPPORTED_ES_FIELD_TYPES . includes ( type ) ) ; if ( hasPrefixToInclude ( key ) && isSupportedType ) { finalFieldCandidates . add ( key ) ; } if ( isSupportedType ) { acceptableFields . add ( key ) ; } } ) ; const resp = await esClient . search ( getRandomDocsRequest ( params ) ) ; const sampledDocs = resp . body . hits . hits . map ( ( d ) => d . fields ?? { } ) ; [ ... new Set ( sampledDocs . map ( Object . keys ) . flat ( 1 ) ) ] . forEach ( ( field ) => { if ( acceptableFields . has ( field ) && ! shouldBeExcluded ( field ) ) { finalFieldCandidates . add ( field ) ; } } ) ; return { fieldCandidates : [ ... finalFieldCandidates ] , } ; } ;