-
Notifications
You must be signed in to change notification settings - Fork 8.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Infra UI] Convert terms aggregation to composite for field selection filtering #47500
Changes from 5 commits
a44c0e2
3e7d171
aec5d16
4456cf1
29d999c
817ef1a
4c2f71b
cab55e3
239d2a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { set } from 'lodash'; | ||
import { | ||
InfraSnapshotGroupbyInput, | ||
InfraSnapshotMetricInput, | ||
|
@@ -12,7 +13,11 @@ import { | |
InfraNodeType, | ||
InfraSourceConfiguration, | ||
} from '../../graphql/types'; | ||
import { InfraBackendFrameworkAdapter, InfraFrameworkRequest } from '../adapters/framework'; | ||
import { | ||
InfraBackendFrameworkAdapter, | ||
InfraFrameworkRequest, | ||
InfraDatabaseSearchResponse, | ||
} from '../adapters/framework'; | ||
import { InfraSources } from '../sources'; | ||
|
||
import { JsonObject } from '../../../common/typed_json'; | ||
|
@@ -31,6 +36,7 @@ import { | |
InfraSnapshotNodeMetricsBucket, | ||
} from './response_helpers'; | ||
import { IP_FIELDS } from '../constants'; | ||
import { getAllCompositeData } from '../../utils/get_all_composite_data'; | ||
|
||
export interface InfraSnapshotRequestOptions { | ||
nodeType: InfraNodeType; | ||
|
@@ -63,6 +69,24 @@ export class InfraSnapshot { | |
} | ||
} | ||
|
||
// This is used by the getAllCompositeData to select the bucket to return. | ||
const bucketSelector = ( | ||
response: InfraDatabaseSearchResponse<{}, InfraSnapshotAggregationResponse> | ||
) => (response.aggregations && response.aggregations.nodes.buckets) || []; | ||
|
||
// This is used by getAllCompositeData to add the after key to the subsequent requests | ||
const handleAfterKey = ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As the two uses of
check and the merging of the |
||
options: object, | ||
response: InfraDatabaseSearchResponse<{}, InfraSnapshotAggregationResponse> | ||
) => { | ||
if (!response.aggregations) { | ||
return options; | ||
} | ||
const newOptions = { ...options }; | ||
set(newOptions, 'body.aggregations.nodes.composite.after', response.aggregations.nodes.after_key); | ||
return newOptions; | ||
}; | ||
|
||
const requestGroupedNodes = async ( | ||
request: InfraFrameworkRequest, | ||
options: InfraSnapshotRequestOptions, | ||
|
@@ -112,11 +136,10 @@ const requestGroupedNodes = async ( | |
}, | ||
}; | ||
|
||
return await getAllCompositeAggregationData<InfraSnapshotNodeGroupByBucket>( | ||
framework, | ||
request, | ||
query | ||
); | ||
return await getAllCompositeData< | ||
InfraSnapshotAggregationResponse, | ||
InfraSnapshotNodeGroupByBucket | ||
>(framework, request, query, bucketSelector, handleAfterKey); | ||
}; | ||
|
||
const requestNodeMetrics = async ( | ||
|
@@ -174,12 +197,10 @@ const requestNodeMetrics = async ( | |
}, | ||
}, | ||
}; | ||
|
||
return await getAllCompositeAggregationData<InfraSnapshotNodeMetricsBucket>( | ||
framework, | ||
request, | ||
query | ||
); | ||
return await getAllCompositeData< | ||
InfraSnapshotAggregationResponse, | ||
InfraSnapshotNodeMetricsBucket | ||
>(framework, request, query, bucketSelector, handleAfterKey); | ||
}; | ||
|
||
// buckets can be InfraSnapshotNodeGroupByBucket[] or InfraSnapshotNodeMetricsBucket[] | ||
|
@@ -191,46 +212,6 @@ interface InfraSnapshotAggregationResponse { | |
}; | ||
} | ||
|
||
const getAllCompositeAggregationData = async <BucketType>( | ||
framework: InfraBackendFrameworkAdapter, | ||
request: InfraFrameworkRequest, | ||
query: any, | ||
previousBuckets: BucketType[] = [] | ||
): Promise<BucketType[]> => { | ||
const response = await framework.callWithRequest<{}, InfraSnapshotAggregationResponse>( | ||
request, | ||
'search', | ||
query | ||
); | ||
|
||
// Nothing available, return the previous buckets. | ||
if (response.hits.total.value === 0) { | ||
return previousBuckets; | ||
} | ||
|
||
// if ES doesn't return an aggregations key, something went seriously wrong. | ||
if (!response.aggregations) { | ||
throw new Error('Whoops!, `aggregations` key must always be returned.'); | ||
} | ||
|
||
const currentBuckets = response.aggregations.nodes.buckets; | ||
|
||
// if there are no currentBuckets then we are finished paginating through the results | ||
if (currentBuckets.length === 0) { | ||
return previousBuckets; | ||
} | ||
|
||
// There is possibly more data, concat previous and current buckets and call ourselves recursively. | ||
const newQuery = { ...query }; | ||
newQuery.body.aggregations.nodes.composite.after = response.aggregations.nodes.after_key; | ||
return getAllCompositeAggregationData( | ||
framework, | ||
request, | ||
query, | ||
previousBuckets.concat(currentBuckets) | ||
); | ||
}; | ||
|
||
const mergeNodeBuckets = ( | ||
nodeGroupByBuckets: InfraSnapshotNodeGroupByBucket[], | ||
nodeMetricsBuckets: InfraSnapshotNodeMetricsBucket[], | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { | ||
InfraBackendFrameworkAdapter, | ||
InfraFrameworkRequest, | ||
InfraDatabaseSearchResponse, | ||
} from '../lib/adapters/framework'; | ||
|
||
export const getAllCompositeData = async < | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice 👍 |
||
Aggregation = undefined, | ||
Bucket = {}, | ||
Options extends object = {} | ||
>( | ||
framework: InfraBackendFrameworkAdapter, | ||
request: InfraFrameworkRequest, | ||
options: Options, | ||
bucketSelector: (response: InfraDatabaseSearchResponse<{}, Aggregation>) => Bucket[], | ||
onAfterKey: (options: Options, response: InfraDatabaseSearchResponse<{}, Aggregation>) => Options, | ||
previousBuckets: Bucket[] = [] | ||
): Promise<Bucket[]> => { | ||
const response = await framework.callWithRequest<{}, Aggregation>(request, 'search', options); | ||
|
||
// Nothing available, return the previous buckets. | ||
if (response.hits.total.value === 0) { | ||
return previousBuckets; | ||
} | ||
|
||
// if ES doesn't return an aggregations key, something went seriously wrong. | ||
if (!response.aggregations) { | ||
throw new Error('Whoops!, `aggregations` key must always be returned.'); | ||
} | ||
|
||
const currentBuckets = bucketSelector(response); | ||
|
||
// if there are no currentBuckets then we are finished paginating through the results | ||
if (currentBuckets.length === 0) { | ||
return previousBuckets; | ||
} | ||
|
||
// There is possibly more data, concat previous and current buckets and call ourselves recursively. | ||
const newOptions = onAfterKey(options, response); | ||
return getAllCompositeData( | ||
framework, | ||
request, | ||
newOptions, | ||
bucketSelector, | ||
onAfterKey, | ||
previousBuckets.concat(currentBuckets) | ||
); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love comments, but I'm not sure we need these given the parameters for
getAllCompositeData()
are fully typed and explain themselves?