[Metrics UI] Optimizations for Snapshot and Inventory Metadata (#83596)

* [Metrics UI] Add time range to inventory metadata request

* Adding optimizations for snapshot request

* Adding sorting to dataset request

* Only query inventory metadata for AWS

* moving check inside getCloudMetadata

* removing unused deps
This commit is contained in:
Chris Cowan 2020-11-18 18:14:22 -07:00 committed by GitHub
parent f2d97a9fe2
commit a04cb37f2b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 69 additions and 20 deletions

View file

@ -21,6 +21,7 @@ export const InventoryMetaResponseRT = rt.type({
export const InventoryMetaRequestRT = rt.type({ export const InventoryMetaRequestRT = rt.type({
sourceId: rt.string, sourceId: rt.string,
nodeType: ItemTypeRT, nodeType: ItemTypeRT,
currentTime: rt.number,
}); });
export type InventoryMetaRequest = rt.TypeOf<typeof InventoryMetaRequestRT>; export type InventoryMetaRequest = rt.TypeOf<typeof InventoryMetaRequestRT>;

View file

@ -124,7 +124,7 @@ export const Layout = () => {
<> <>
<TopActionContainer ref={topActionMeasureRef}> <TopActionContainer ref={topActionMeasureRef}>
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center" gutterSize="m"> <EuiFlexGroup justifyContent="spaceBetween" alignItems="center" gutterSize="m">
<Toolbar nodeType={nodeType} /> <Toolbar nodeType={nodeType} currentTime={currentTime} />
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<IntervalLabel intervalAsString={intervalAsString} /> <IntervalLabel intervalAsString={intervalAsString} />
</EuiFlexItem> </EuiFlexItem>

View file

@ -54,11 +54,12 @@ const wrapToolbarItems = (
interface Props { interface Props {
nodeType: InventoryItemType; nodeType: InventoryItemType;
currentTime: number;
} }
export const Toolbar = ({ nodeType }: Props) => { export const Toolbar = ({ nodeType, currentTime }: Props) => {
const { sourceId } = useSourceContext(); const { sourceId } = useSourceContext();
const { accounts, regions } = useInventoryMeta(sourceId, nodeType); const { accounts, regions } = useInventoryMeta(sourceId, nodeType, currentTime);
const ToolbarItems = findToolbar(nodeType); const ToolbarItems = findToolbar(nodeType);
return wrapToolbarItems(ToolbarItems, accounts, regions); return wrapToolbarItems(ToolbarItems, accounts, regions);
}; };

View file

@ -15,7 +15,11 @@ import {
} from '../../../../../common/http_api/inventory_meta_api'; } from '../../../../../common/http_api/inventory_meta_api';
import { InventoryItemType } from '../../../../../common/inventory_models/types'; import { InventoryItemType } from '../../../../../common/inventory_models/types';
export function useInventoryMeta(sourceId: string, nodeType: InventoryItemType) { export function useInventoryMeta(
sourceId: string,
nodeType: InventoryItemType,
currentTime: number
) {
const decodeResponse = (response: any) => { const decodeResponse = (response: any) => {
return pipe( return pipe(
InventoryMetaResponseRT.decode(response), InventoryMetaResponseRT.decode(response),
@ -29,6 +33,7 @@ export function useInventoryMeta(sourceId: string, nodeType: InventoryItemType)
JSON.stringify({ JSON.stringify({
sourceId, sourceId,
nodeType, nodeType,
currentTime,
}), }),
decodeResponse decodeResponse
); );

View file

@ -44,7 +44,7 @@ export function useSnapshot(
interval: '1m', interval: '1m',
to: currentTime, to: currentTime,
from: currentTime - 1200 * 1000, from: currentTime - 1200 * 1000,
lookbackSize: 20, lookbackSize: 5,
}; };
const { error, loading, response, makeRequest } = useHTTPRequest<SnapshotNodeResponse>( const { error, loading, response, makeRequest } = useHTTPRequest<SnapshotNodeResponse>(

View file

@ -33,7 +33,7 @@ export const initInventoryMetaRoute = (libs: InfraBackendLibs) => {
}, },
async (requestContext, request, response) => { async (requestContext, request, response) => {
try { try {
const { sourceId, nodeType } = pipe( const { sourceId, nodeType, currentTime } = pipe(
InventoryMetaRequestRT.decode(request.body), InventoryMetaRequestRT.decode(request.body),
fold(throwErrors(Boom.badRequest), identity) fold(throwErrors(Boom.badRequest), identity)
); );
@ -42,11 +42,13 @@ export const initInventoryMetaRoute = (libs: InfraBackendLibs) => {
requestContext.core.savedObjects.client, requestContext.core.savedObjects.client,
sourceId sourceId
); );
const awsMetadata = await getCloudMetadata( const awsMetadata = await getCloudMetadata(
framework, framework,
requestContext, requestContext,
configuration, configuration,
nodeType nodeType,
currentTime
); );
return response.ok({ return response.ok({

View file

@ -25,9 +25,18 @@ export const getCloudMetadata = async (
framework: KibanaFramework, framework: KibanaFramework,
req: RequestHandlerContext, req: RequestHandlerContext,
sourceConfiguration: InfraSourceConfiguration, sourceConfiguration: InfraSourceConfiguration,
nodeType: InventoryItemType nodeType: InventoryItemType,
currentTime: number
): Promise<CloudMetaData> => { ): Promise<CloudMetaData> => {
const model = findInventoryModel(nodeType); const model = findInventoryModel(nodeType);
// Only run this for AWS modules, eventually we might have more.
if (model.requiredModule !== 'aws') {
return {
accounts: [],
projects: [],
regions: [],
};
}
const metricQuery = { const metricQuery = {
allowNoIndices: true, allowNoIndices: true,
@ -36,7 +45,18 @@ export const getCloudMetadata = async (
body: { body: {
query: { query: {
bool: { bool: {
must: [{ match: { 'event.module': model.requiredModule } }], must: [
{
range: {
[sourceConfiguration.fields.timestamp]: {
gte: currentTime - 86400000, // 24 hours ago
lte: currentTime,
format: 'epoch_millis',
},
},
},
{ match: { 'event.module': model.requiredModule } },
],
}, },
}, },
size: 0, size: 0,

View file

@ -34,7 +34,8 @@ export const findIntervalForMetrics = async (
const modules = await Promise.all( const modules = await Promise.all(
fields.map( fields.map(
async (field) => await getDatasetForField(client, field as string, options.indexPattern) async (field) =>
await getDatasetForField(client, field as string, options.indexPattern, options.timerange)
) )
); );

View file

@ -17,7 +17,8 @@ interface EventDatasetHit {
export const getDatasetForField = async ( export const getDatasetForField = async (
client: ESSearchClient, client: ESSearchClient,
field: string, field: string,
indexPattern: string indexPattern: string,
timerange: { field: string; to: number; from: number }
) => { ) => {
const params = { const params = {
allowNoIndices: true, allowNoIndices: true,
@ -25,9 +26,25 @@ export const getDatasetForField = async (
terminateAfter: 1, terminateAfter: 1,
index: indexPattern, index: indexPattern,
body: { body: {
query: { exists: { field } }, query: {
bool: {
filter: [
{ exists: { field } },
{
range: {
[timerange.field]: {
gte: timerange.from,
lte: timerange.to,
format: 'epoch_millis',
},
},
},
],
},
},
size: 1, size: 1,
_source: ['event.dataset'], _source: ['event.dataset'],
sort: [{ [timerange.field]: { order: 'desc' } }],
}, },
}; };

View file

@ -75,7 +75,10 @@ const aggregationsToModules = async (
const fields = await Promise.all( const fields = await Promise.all(
uniqueFields.map( uniqueFields.map(
async (field) => async (field) =>
await getDatasetForField(client, field as string, options.sourceConfiguration.metricAlias) await getDatasetForField(client, field as string, options.sourceConfiguration.metricAlias, {
...options.timerange,
field: options.sourceConfiguration.fields.timestamp,
})
) )
); );
return fields.filter((f) => f) as string[]; return fields.filter((f) => f) as string[];

View file

@ -23,12 +23,11 @@ export const getNodes = async (
snapshotRequest snapshotRequest
); );
const metricsApiResponse = await queryAllData(client, metricsApiRequest); const metricsApiResponse = await queryAllData(client, metricsApiRequest);
return copyMissingMetrics( const snapshotResponse = transformMetricsApiResponseToSnapshotResponse(
transformMetricsApiResponseToSnapshotResponse( metricsApiRequest,
metricsApiRequest, snapshotRequest,
snapshotRequest, source,
source, metricsApiResponse
metricsApiResponse
)
); );
return copyMissingMetrics(snapshotResponse);
}; };