Skip to content

Commit

Permalink
[Metrics-UI] Port graphql query for snapshot and node details to hapi…
Browse files Browse the repository at this point in the history
…js (elastic#50730)

* Port graphql query for snapshot to hapijs

* fix type

* Remove graphql from node details.

* Use boom for error handling.

* Remove unused imports

* Remove dead code. Merge types

* Fix tests

* Remove unused import

* Rename types

* Go all in on io-ts. Cleanup types

* Fix typecheck
  • Loading branch information
phillipb committed Dec 9, 2019
1 parent a1bce70 commit b1cfc21
Show file tree
Hide file tree
Showing 28 changed files with 947 additions and 844 deletions.
58 changes: 58 additions & 0 deletions x-pack/legacy/plugins/infra/common/http_api/node_details_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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 * as rt from 'io-ts';
import { InventoryMetricRT, ItemTypeRT } from '../inventory_models/types';
import { InfraWrappableRequest } from '../../server/lib/adapters/framework';
import { InfraTimerangeInputRT } from './snapshot_api';

const NodeDetailsDataPointRT = rt.intersection([
rt.type({
timestamp: rt.number,
}),
rt.partial({
value: rt.union([rt.number, rt.null]),
}),
]);

const NodeDetailsDataSeries = rt.type({
id: rt.string,
label: rt.string,
data: rt.array(NodeDetailsDataPointRT),
});

export const NodeDetailsMetricDataRT = rt.intersection([
rt.partial({
id: rt.union([InventoryMetricRT, rt.null]),
}),
rt.type({
series: rt.array(NodeDetailsDataSeries),
}),
]);

export const NodeDetailsMetricDataResponseRT = rt.type({
metrics: rt.array(NodeDetailsMetricDataRT),
});

export const NodeDetailsRequestRT = rt.intersection([
rt.type({
nodeType: ItemTypeRT,
nodeId: rt.string,
metrics: rt.array(InventoryMetricRT),
timerange: InfraTimerangeInputRT,
sourceId: rt.string,
}),
rt.partial({
cloudId: rt.union([rt.string, rt.null]),
}),
]);

// export type NodeDetailsRequest = InfraWrappableRequest<NodesArgs & SourceArgs>;

export type NodeDetailsRequest = rt.TypeOf<typeof NodeDetailsRequestRT>;
export type NodeDetailsWrappedRequest = InfraWrappableRequest<NodeDetailsRequest>;

export type NodeDetailsMetricDataResponse = rt.TypeOf<typeof NodeDetailsMetricDataResponseRT>;
69 changes: 69 additions & 0 deletions x-pack/legacy/plugins/infra/common/http_api/snapshot_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* 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 * as rt from 'io-ts';
import { InfraWrappableRequest } from '../../server/lib/adapters/framework';
import { SnapshotMetricTypeRT, ItemTypeRT } from '../inventory_models/types';

export const SnapshotNodePathRT = rt.intersection([
rt.type({
value: rt.string,
label: rt.string,
}),
rt.partial({
ip: rt.union([rt.string, rt.null]),
}),
]);

const SnapshotNodeMetricOptionalRT = rt.partial({
value: rt.union([rt.number, rt.null]),
average: rt.union([rt.number, rt.null]),
max: rt.union([rt.number, rt.null]),
});

const SnapshotNodeMetricRequiredRT = rt.type({
name: SnapshotMetricTypeRT,
});

export const SnapshotNodeRT = rt.type({
metric: rt.intersection([SnapshotNodeMetricRequiredRT, SnapshotNodeMetricOptionalRT]),
path: rt.array(SnapshotNodePathRT),
});

export const SnapshotNodeResponseRT = rt.type({
nodes: rt.array(SnapshotNodeRT),
});

export const InfraTimerangeInputRT = rt.type({
interval: rt.string,
to: rt.number,
from: rt.number,
});

export const SnapshotRequestRT = rt.intersection([
rt.type({
timerange: InfraTimerangeInputRT,
metric: rt.type({
type: SnapshotMetricTypeRT,
}),
groupBy: rt.array(
rt.partial({
label: rt.union([rt.string, rt.null]),
field: rt.union([rt.string, rt.null]),
})
),
nodeType: ItemTypeRT,
sourceId: rt.string,
}),
rt.partial({
filterQuery: rt.union([rt.string, rt.null]),
}),
]);

export type SnapshotRequest = rt.TypeOf<typeof SnapshotRequestRT>;
export type SnapshotWrappedRequest = InfraWrappableRequest<SnapshotRequest>;
export type SnapshotNode = rt.TypeOf<typeof SnapshotNodeRT>;
export type SnapshotNodeResponse = rt.TypeOf<typeof SnapshotNodeResponseRT>;
38 changes: 33 additions & 5 deletions x-pack/legacy/plugins/infra/public/components/inventory/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,61 @@

import React from 'react';
import { InfraWaffleMapOptions, InfraWaffleMapBounds } from '../../lib/lib';
import { InfraNodeType, InfraSnapshotNode, InfraTimerangeInput } from '../../graphql/types';
import {
InfraNodeType,
InfraTimerangeInput,
InfraSnapshotMetricInput,
InfraSnapshotGroupbyInput,
} from '../../graphql/types';
import { KueryFilterQuery } from '../../store/local/waffle_filter';

import { NodesOverview } from '../nodes_overview';
import { Toolbar } from './toolbars/toolbar';
import { PageContent } from '../page';
import { useSnapshot } from '../../containers/waffle/use_snaphot';

export interface LayoutProps {
options: InfraWaffleMapOptions;
nodeType: InfraNodeType;
nodes: InfraSnapshotNode[];
loading: boolean;
reload: () => void;
onDrilldown: (filter: KueryFilterQuery) => void;
timeRange: InfraTimerangeInput;
onViewChange: (view: string) => void;
view: string;
boundsOverride: InfraWaffleMapBounds;
autoBounds: boolean;

filterQuery: string | null | undefined;
metric: InfraSnapshotMetricInput;
groupBy: InfraSnapshotGroupbyInput[];
sourceId: string;
}

export const Layout = (props: LayoutProps) => {
const { loading, nodes, reload } = useSnapshot(
props.filterQuery,
props.metric,
props.groupBy,
props.nodeType,
props.sourceId,
props.timeRange
);
return (
<>
<Toolbar nodeType={props.nodeType} />
<PageContent>
<NodesOverview {...props} />
<NodesOverview
nodes={nodes}
options={props.options}
nodeType={props.nodeType}
loading={loading}
reload={reload}
onDrilldown={props.onDrilldown}
timeRange={props.timeRange}
onViewChange={props.onViewChange}
view={props.view}
autoBounds={props.autoBounds}
boundsOverride={props.boundsOverride}
/>
</PageContent>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ import { InfraLoadingPanel } from '../loading';
import { Map } from '../waffle/map';
import { ViewSwitcher } from '../waffle/view_switcher';
import { TableView } from './table';
import { SnapshotNode } from '../../../common/http_api/snapshot_api';

interface Props {
options: InfraWaffleMapOptions;
nodeType: InfraNodeType;
nodes: InfraSnapshotNode[];
nodes: SnapshotNode[];
loading: boolean;
reload: () => void;
onDrilldown: (filter: KueryFilterQuery) => void;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* 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 { fold } from 'fp-ts/lib/Either';
import { identity } from 'fp-ts/lib/function';
import { pipe } from 'fp-ts/lib/pipeable';
import { InfraNodeType, InfraTimerangeInput } from '../../graphql/types';
import { throwErrors, createPlainError } from '../../../common/runtime_types';
import { useHTTPRequest } from '../../hooks/use_http_request';
import {
NodeDetailsMetricDataResponseRT,
NodeDetailsMetricDataResponse,
} from '../../../common/http_api/node_details_api';
import { InventoryMetric } from '../../../common/inventory_models/types';

export function useNodeDetails(
metrics: InventoryMetric[],
nodeId: string,
nodeType: InfraNodeType,
sourceId: string,
timerange: InfraTimerangeInput,
cloudId: string
) {
const decodeResponse = (response: any) => {
return pipe(
NodeDetailsMetricDataResponseRT.decode(response),
fold(throwErrors(createPlainError), identity)
);
};

const { error, loading, response, makeRequest } = useHTTPRequest<NodeDetailsMetricDataResponse>(
'/api/metrics/node_details',
'POST',
JSON.stringify({
metrics,
nodeId,
nodeType,
timerange,
cloudId,
sourceId,
decodeResponse,
})
);

return {
error,
loading,
metrics: response ? response.metrics : [],
makeRequest,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@
*/

export * from './with_waffle_filters';
export * from './with_waffle_nodes';
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* 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 { useEffect } from 'react';
import { fold } from 'fp-ts/lib/Either';
import { identity } from 'fp-ts/lib/function';
import { pipe } from 'fp-ts/lib/pipeable';
import {
InfraNodeType,
InfraSnapshotMetricInput,
InfraSnapshotGroupbyInput,
InfraTimerangeInput,
} from '../../graphql/types';
import { throwErrors, createPlainError } from '../../../common/runtime_types';
import { useHTTPRequest } from '../../hooks/use_http_request';
import {
SnapshotNodeResponseRT,
SnapshotNodeResponse,
} from '../../../common/http_api/snapshot_api';

export function useSnapshot(
filterQuery: string | null | undefined,
metric: InfraSnapshotMetricInput,
groupBy: InfraSnapshotGroupbyInput[],
nodeType: InfraNodeType,
sourceId: string,
timerange: InfraTimerangeInput
) {
const decodeResponse = (response: any) => {
return pipe(
SnapshotNodeResponseRT.decode(response),
fold(throwErrors(createPlainError), identity)
);
};

const { error, loading, response, makeRequest } = useHTTPRequest<SnapshotNodeResponse>(
'/api/metrics/snapshot',
'POST',
JSON.stringify({
metric,
groupBy,
nodeType,
timerange,
filterQuery,
sourceId,
decodeResponse,
})
);

useEffect(() => {
(async () => {
await makeRequest();
})();
}, [makeRequest]);

return {
error: (error && error.message) || null,
loading,
nodes: response ? response.nodes : [],
reload: makeRequest,
};
}
Loading

0 comments on commit b1cfc21

Please sign in to comment.