import type { TermsEnumRequest , TermsEnumResponse , } from '@elastic/elasticsearch/lib/api/typesWithBodyKey' ; import { ValuesType } from 'utility-types' ; import { withApmSpan } from '../../../../utils/with_apm_span' ; import { Profile } from '../../../../../typings/es_schemas/ui/profile' ; import { ElasticsearchClient , KibanaRequest , } from '../../../../../../../../src/core/server' ; import { ESSearchRequest , InferSearchResponseOf , } from '../../../../../../../../src/core/types/elasticsearch' ; import { unwrapEsResponse } from '../../../../../../observability/server' ; import { ProcessorEvent } from '../../../../../common/processor_event' ; import { APMError } from '../../../../../typings/es_schemas/ui/apm_error' ; import { Metric } from '../../../../../typings/es_schemas/ui/metric' ; import { Span } from '../../../../../typings/es_schemas/ui/span' ; import { Transaction } from '../../../../../typings/es_schemas/ui/transaction' ; import { ApmIndicesConfig } from '../../../../routes/settings/apm_indices/get_apm_indices' ; import { callAsyncWithDebug , getDebugBody , getDebugTitle , } from '../call_async_with_debug' ; import { cancelEsRequestOnAbort } from '../cancel_es_request_on_abort' ; import { addFilterToExcludeLegacyData } from './add_filter_to_exclude_legacy_data' ; import { unpackProcessorEvents } from './unpack_processor_events' ; export type APMEventESSearchRequest = Omit < ESSearchRequest , 'index' > & { apm : { events : ProcessorEvent [ ] ; includeLegacyData ? : boolean ; } ; } ; export type APMEventESTermsEnumRequest = Omit < TermsEnumRequest , 'index' > & { apm : { events : ProcessorEvent [ ] ; } ; } ; type TypeOfProcessorEvent < T extends ProcessorEvent > = { error : APMError ; transaction : Transaction ; span : Span ; metric : Metric ; profile : Profile ; } [ T ] ; type TypedSearchResponse < TParams extends APMEventESSearchRequest > = InferSearchResponseOf < TypeOfProcessorEvent < ValuesType < TParams [ 'apm' ] [ 'events' ] > > , TParams > ; export interface APMEventClientConfig { esClient : ElasticsearchClient ; debug : boolean ; request : KibanaRequest ; indices : ApmIndicesConfig ; options : { includeFrozen : boolean ; } ; } export class APMEventClient { private readonly esClient : ElasticsearchClient ; private readonly debug : boolean ; private readonly request : KibanaRequest ; private readonly indices : ApmIndicesConfig ; private readonly includeFrozen : boolean ; constructor ( config ) { this . esClient = config . esClient ; this . debug = config . debug ; this . request = config . request ; this . indices = config . indices ; this . includeFrozen = config . options . includeFrozen ; } async search < TParams extends APMEventESSearchRequest > ( operationName , params ) { const withProcessorEventFilter = unpackProcessorEvents ( params , this . indices ) ; const { includeLegacyData = false } = params . apm ; const withPossibleLegacyDataFilter = ! includeLegacyData ? addFilterToExcludeLegacyData ( withProcessorEventFilter ) : withProcessorEventFilter ; const searchParams = { ... withPossibleLegacyDataFilter , ... ( this . includeFrozen ? { ignore_throttled : false } : { } ) , ignore_unavailable : true , preference : 'any' , } ; const requestType = 'search' ; return callAsyncWithDebug ( { cb : ( ) => { const searchPromise = withApmSpan ( operationName , ( ) => { const controller = new AbortController ( ) ; return cancelEsRequestOnAbort ( this . esClient . search ( searchParams , { signal : controller . signal } ) , this . request , controller ) ; } ) ; return unwrapEsResponse ( searchPromise ) ; } , getDebugMessage : ( ) => ( { body : getDebugBody ( { params : searchParams , requestType , operationName , } ) , title : getDebugTitle ( this . request ) , } ) , isCalledWithInternalUser : false , debug : this . debug , request : this . request , requestType , operationName , requestParams : searchParams , } ) ; } async termsEnum ( operationName , params ) { const requestType = 'terms_enum' ; const { index } = unpackProcessorEvents ( params , this . indices ) ; return callAsyncWithDebug ( { cb : ( ) => { const { apm , ... rest } = params ; const termsEnumPromise = withApmSpan ( operationName , ( ) => { const controller = new AbortController ( ) ; return cancelEsRequestOnAbort ( this . esClient . termsEnum ( { index : Array . isArray ( index ) ? index . join ( ',' ) : index , ... rest , } , { signal : controller . signal } ) , this . request , controller ) ; } ) ; return unwrapEsResponse ( termsEnumPromise ) ; } , getDebugMessage : ( ) => ( { body : getDebugBody ( { params , requestType , operationName , } ) , title : getDebugTitle ( this . request ) , } ) , isCalledWithInternalUser : false , debug : this . debug , request : this . request , requestType , operationName , requestParams : params , } ) ; } }