diff --git a/x-pack/plugins/infra/public/components/metrics/index.tsx b/x-pack/plugins/infra/public/components/metrics/index.tsx
index 8a0bdb8e8443..f2f0a634a3fe 100644
--- a/x-pack/plugins/infra/public/components/metrics/index.tsx
+++ b/x-pack/plugins/infra/public/components/metrics/index.tsx
@@ -18,7 +18,8 @@ interface Props {
metrics: InfraMetricData[];
layouts: InfraMetricLayout[];
loading: boolean;
- nodeName: string;
+ nodeId: string;
+ label: string;
onChangeRangeTime?: (time: metricTimeActions.MetricRangeTimeState) => void;
intl: InjectedIntl;
}
@@ -41,15 +42,10 @@ export const Metrics = injectI18n(
);
}
diff --git a/x-pack/plugins/infra/public/components/waffle/group_of_nodes.tsx b/x-pack/plugins/infra/public/components/waffle/group_of_nodes.tsx
index f81203dfab4d..c84dc3934693 100644
--- a/x-pack/plugins/infra/public/components/waffle/group_of_nodes.tsx
+++ b/x-pack/plugins/infra/public/components/waffle/group_of_nodes.tsx
@@ -43,7 +43,7 @@ export const GroupOfNodes: React.SFC = ({
{group.nodes.map(node => (
{
- const nodeName = node.path.length > 0 ? node.path[node.path.length - 1].value : undefined;
- const nodeLogsUrl = nodeName
+ const nodeId = node.path.length > 0 ? node.path[node.path.length - 1].value : undefined;
+ const nodeLogsUrl = nodeId
? getNodeLogsUrl({
nodeType,
- nodeName,
+ nodeId,
time: timeRange.to,
})
: undefined;
- const nodeDetailUrl = nodeName
+ const nodeDetailUrl = nodeId
? getNodeDetailUrl({
nodeType,
- nodeName,
+ nodeId,
from: timeRange.from,
to: timeRange.to,
})
@@ -76,7 +76,7 @@ export const NodeContextMenu = injectI18n(
return (
{({ data, error, loading }) => {
const metadata = data && data.source && data.source.metadataByNode;
- const filteredLayouts = getFilteredLayouts(layouts, metadata);
+ const filteredLayouts = (metadata && getFilteredLayouts(layouts, metadata.features)) || [];
return children({
+ name: (metadata && metadata.name) || '',
filteredLayouts,
error: error && error.message,
loading,
@@ -58,7 +60,7 @@ export const WithMetadata = ({
const getFilteredLayouts = (
layouts: InfraMetricLayout[],
- metadata: Array | undefined
+ metadata: Array | undefined
): InfraMetricLayout[] => {
if (!metadata) {
return layouts;
diff --git a/x-pack/plugins/infra/public/containers/waffle/nodes_to_wafflemap.ts b/x-pack/plugins/infra/public/containers/waffle/nodes_to_wafflemap.ts
index 4b924afe27ac..56f2ffa0bc5d 100644
--- a/x-pack/plugins/infra/public/containers/waffle/nodes_to_wafflemap.ts
+++ b/x-pack/plugins/infra/public/containers/waffle/nodes_to_wafflemap.ts
@@ -51,7 +51,7 @@ function findOrCreateGroupWithNodes(
? i18n.translate('xpack.infra.nodesToWaffleMap.groupsWithNodes.allName', {
defaultMessage: 'All',
})
- : last(path).value,
+ : last(path).label,
count: 0,
width: 0,
squareSize: 0,
@@ -75,7 +75,7 @@ function findOrCreateGroupWithGroups(
? i18n.translate('xpack.infra.nodesToWaffleMap.groupsWithGroups.allName', {
defaultMessage: 'All',
})
- : last(path).value,
+ : last(path).label,
count: 0,
width: 0,
squareSize: 0,
@@ -84,10 +84,12 @@ function findOrCreateGroupWithGroups(
}
function createWaffleMapNode(node: InfraNode): InfraWaffleMapNode {
+ const nodePathItem = last(node.path);
return {
- id: node.path.map(p => p.value).join('/'),
+ pathId: node.path.map(p => p.value).join('/'),
path: node.path,
- name: last(node.path).value,
+ id: nodePathItem.value,
+ name: nodePathItem.label,
metric: node.metric,
};
}
diff --git a/x-pack/plugins/infra/public/containers/waffle/waffle_nodes.gql_query.ts b/x-pack/plugins/infra/public/containers/waffle/waffle_nodes.gql_query.ts
index 8da5b160603e..51b67086a4bf 100644
--- a/x-pack/plugins/infra/public/containers/waffle/waffle_nodes.gql_query.ts
+++ b/x-pack/plugins/infra/public/containers/waffle/waffle_nodes.gql_query.ts
@@ -20,6 +20,7 @@ export const waffleNodesQuery = gql`
nodes(path: $path, metric: $metric) {
path {
value
+ label
}
metric {
name
diff --git a/x-pack/plugins/infra/public/graphql/introspection.json b/x-pack/plugins/infra/public/graphql/introspection.json
index 7cb84b92bab9..328064987fa9 100644
--- a/x-pack/plugins/infra/public/graphql/introspection.json
+++ b/x-pack/plugins/infra/public/graphql/introspection.json
@@ -114,7 +114,7 @@
"description": "A hierarchy of metadata entries by node",
"args": [
{
- "name": "nodeName",
+ "name": "nodeId",
"description": "",
"type": {
"kind": "NON_NULL",
@@ -137,11 +137,7 @@
"type": {
"kind": "NON_NULL",
"name": null,
- "ofType": {
- "kind": "LIST",
- "name": null,
- "ofType": { "kind": "OBJECT", "name": "InfraNodeMetadata", "ofType": null }
- }
+ "ofType": { "kind": "OBJECT", "name": "InfraNodeMetadata", "ofType": null }
},
"isDeprecated": false,
"deprecationReason": null
@@ -775,6 +771,61 @@
"kind": "OBJECT",
"name": "InfraNodeMetadata",
"description": "One metadata entry for a node.",
+ "fields": [
+ {
+ "name": "id",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "SCALAR", "name": "ID", "ofType": null }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "features",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "OBJECT", "name": "InfraNodeFeature", "ofType": null }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "InfraNodeFeature",
+ "description": "",
"fields": [
{
"name": "name",
@@ -1542,6 +1593,18 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "displayName",
+ "description": "",
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
diff --git a/x-pack/plugins/infra/public/graphql/types.ts b/x-pack/plugins/infra/public/graphql/types.ts
index 7c67f7963b74..343b8f0ae0ff 100644
--- a/x-pack/plugins/infra/public/graphql/types.ts
+++ b/x-pack/plugins/infra/public/graphql/types.ts
@@ -23,7 +23,7 @@ export interface InfraSource {
/** The status of the source */
status: InfraSourceStatus;
/** A hierarchy of metadata entries by node */
- metadataByNode: (InfraNodeMetadata | null)[];
+ metadataByNode: InfraNodeMetadata;
/** A consecutive span of log entries surrounding a point in time */
logEntriesAround: InfraLogEntryInterval;
/** A consecutive span of log entries within an interval */
@@ -89,6 +89,14 @@ export interface InfraIndexField {
}
/** One metadata entry for a node. */
export interface InfraNodeMetadata {
+ id: string;
+
+ name: string;
+
+ features: InfraNodeFeature[];
+}
+
+export interface InfraNodeFeature {
name: string;
source: string;
@@ -175,6 +183,8 @@ export interface InfraNode {
export interface InfraNodePath {
value: string;
+
+ label: string;
}
export interface InfraNodeMetric {
@@ -252,7 +262,7 @@ export interface SourceQueryArgs {
id: string;
}
export interface MetadataByNodeInfraSourceArgs {
- nodeName: string;
+ nodeId: string;
nodeType: InfraNodeType;
}
@@ -416,7 +426,7 @@ export namespace MetadataQuery {
id: string;
- metadataByNode: (MetadataByNode | null)[];
+ metadataByNode: MetadataByNode;
};
export type MetadataByNode = {
@@ -424,6 +434,14 @@ export namespace MetadataQuery {
name: string;
+ features: Features[];
+ };
+
+ export type Features = {
+ __typename?: 'InfraNodeFeature';
+
+ name: string;
+
source: string;
};
}
@@ -517,6 +535,8 @@ export namespace WaffleNodesQuery {
__typename?: 'InfraNodePath';
value: string;
+
+ label: string;
};
export type Metric = {
diff --git a/x-pack/plugins/infra/public/lib/lib.ts b/x-pack/plugins/infra/public/lib/lib.ts
index 2ef59fbaeb6c..9d215247d116 100644
--- a/x-pack/plugins/infra/public/lib/lib.ts
+++ b/x-pack/plugins/infra/public/lib/lib.ts
@@ -100,6 +100,7 @@ export interface InfraField {
export type InfraWaffleData = InfraWaffleMapGroup[];
export interface InfraWaffleMapNode {
+ pathId: string;
id: string;
name: string;
path: InfraNodePath[];
diff --git a/x-pack/plugins/infra/public/pages/link_to/link_to.tsx b/x-pack/plugins/infra/public/pages/link_to/link_to.tsx
index e00013a35474..073c335bd156 100644
--- a/x-pack/plugins/infra/public/pages/link_to/link_to.tsx
+++ b/x-pack/plugins/infra/public/pages/link_to/link_to.tsx
@@ -21,11 +21,11 @@ export class LinkToPage extends React.Component {
return (
diff --git a/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_detail.tsx b/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_detail.tsx
index bf70e06a629c..d9f62f48a8a8 100644
--- a/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_detail.tsx
+++ b/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_detail.tsx
@@ -12,13 +12,13 @@ import { InfraNodeType } from '../../graphql/types';
import { getFromFromLocation, getToFromLocation } from './query_params';
type RedirectToNodeDetailProps = RouteComponentProps<{
- nodeName: string;
+ nodeId: string;
nodeType: InfraNodeType;
}>;
export const RedirectToNodeDetail = ({
match: {
- params: { nodeName, nodeType },
+ params: { nodeId, nodeType },
},
location,
}: RedirectToNodeDetailProps) => {
@@ -27,20 +27,20 @@ export const RedirectToNodeDetail = ({
getToFromLocation(location)
)('');
- return ;
+ return ;
};
export const getNodeDetailUrl = ({
nodeType,
- nodeName,
+ nodeId,
to,
from,
}: {
nodeType: InfraNodeType;
- nodeName: string;
+ nodeId: string;
to?: number;
from?: number;
}) => {
const args = to && from ? `?to=${to}&from=${from}` : '';
- return `#/link-to/${nodeType}-detail/${nodeName}${args}`;
+ return `#/link-to/${nodeType}-detail/${nodeId}${args}`;
};
diff --git a/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.tsx b/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.tsx
index 5f444e3afdd3..772a01fea485 100644
--- a/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.tsx
+++ b/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.tsx
@@ -17,7 +17,7 @@ import { InfraNodeType } from '../../graphql/types';
import { getTimeFromLocation } from './query_params';
type RedirectToNodeLogsType = RouteComponentProps<{
- nodeName: string;
+ nodeId: string;
nodeType: InfraNodeType;
}>;
@@ -28,7 +28,7 @@ interface RedirectToNodeLogsProps extends RedirectToNodeLogsType {
export const RedirectToNodeLogs = injectI18n(
({
match: {
- params: { nodeName, nodeType },
+ params: { nodeId, nodeType },
},
location,
intl,
@@ -52,7 +52,7 @@ export const RedirectToNodeLogs = injectI18n(
}
const searchString = compose(
- replaceLogFilterInQueryString(`${configuredFields[nodeType]}: ${nodeName}`),
+ replaceLogFilterInQueryString(`${configuredFields[nodeType]}: ${nodeId}`),
replaceLogPositionInQueryString(getTimeFromLocation(location))
)('');
@@ -63,11 +63,11 @@ export const RedirectToNodeLogs = injectI18n(
);
export const getNodeLogsUrl = ({
- nodeName,
+ nodeId,
nodeType,
time,
}: {
- nodeName: string;
+ nodeId: string;
nodeType: InfraNodeType;
time?: number;
-}) => [`#/link-to/${nodeType}-logs/`, nodeName, ...(time ? [`?time=${time}`] : [])].join('');
+}) => [`#/link-to/${nodeType}-logs/`, nodeId, ...(time ? [`?time=${time}`] : [])].join('');
diff --git a/x-pack/plugins/infra/public/pages/metrics/index.tsx b/x-pack/plugins/infra/public/pages/metrics/index.tsx
index 7e1c138587d9..20e559f6e844 100644
--- a/x-pack/plugins/infra/public/pages/metrics/index.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/index.tsx
@@ -63,7 +63,7 @@ export const MetricDetail = withTheme(
public render() {
const { intl } = this.props;
- const nodeName = this.props.match.params.node;
+ const nodeId = this.props.match.params.node;
const nodeType = this.props.match.params.type as InfraNodeType;
const layoutCreator = layoutCreators[nodeType];
if (!layoutCreator) {
@@ -82,40 +82,40 @@ export const MetricDetail = withTheme(
);
}
const layouts = layoutCreator(this.props.theme);
- const breadcrumbs = [{ text: nodeName }];
return (
-
- }
- breadcrumbs={breadcrumbs}
- />
-
-
-
- {({ sourceId }) => (
-
- {({
- currentTimeRange,
- isAutoReloading,
- setRangeTime,
- startMetricsAutoReload,
- stopMetricsAutoReload,
- }) => (
-
- {({ filteredLayouts, loading: metadataLoading }) => {
- return (
+
+ {({ sourceId }) => (
+
+ {({
+ currentTimeRange,
+ isAutoReloading,
+ setRangeTime,
+ startMetricsAutoReload,
+ stopMetricsAutoReload,
+ }) => (
+
+ {({ name, filteredLayouts, loading: metadataLoading }) => {
+ const breadcrumbs = [{ text: name }];
+ return (
+
+ }
+ breadcrumbs={breadcrumbs}
+ />
+
+
{({ metrics, error, loading }) => {
if (error) {
@@ -126,7 +126,7 @@ export const MetricDetail = withTheme(
@@ -139,7 +139,7 @@ export const MetricDetail = withTheme(
- {nodeName}
+ {name}
- );
- }}
-
- )}
-
+
+
+ );
+ }}
+
)}
-
-
-
+
+ )}
+
);
}
diff --git a/x-pack/plugins/infra/server/graphql/metadata/resolvers.ts b/x-pack/plugins/infra/server/graphql/metadata/resolvers.ts
index 618932d6433e..8d1b386af548 100644
--- a/x-pack/plugins/infra/server/graphql/metadata/resolvers.ts
+++ b/x-pack/plugins/infra/server/graphql/metadata/resolvers.ts
@@ -23,7 +23,7 @@ export const createMetadataResolvers = (libs: {
} => ({
InfraSource: {
async metadataByNode(source, args, { req }) {
- const result = await libs.metadata.getMetadata(req, source.id, args.nodeName, args.nodeType);
+ const result = await libs.metadata.getMetadata(req, source.id, args.nodeId, args.nodeType);
return result;
},
},
diff --git a/x-pack/plugins/infra/server/graphql/metadata/schema.gql.ts b/x-pack/plugins/infra/server/graphql/metadata/schema.gql.ts
index 1a0e40d8f0b8..8944e309d463 100644
--- a/x-pack/plugins/infra/server/graphql/metadata/schema.gql.ts
+++ b/x-pack/plugins/infra/server/graphql/metadata/schema.gql.ts
@@ -9,12 +9,18 @@ import gql from 'graphql-tag';
export const metadataSchema = gql`
"One metadata entry for a node."
type InfraNodeMetadata {
+ id: ID!
+ name: String!
+ features: [InfraNodeFeature!]!
+ }
+
+ type InfraNodeFeature {
name: String!
source: String!
}
extend type InfraSource {
"A hierarchy of metadata entries by node"
- metadataByNode(nodeName: String!, nodeType: InfraNodeType!): [InfraNodeMetadata]!
+ metadataByNode(nodeId: String!, nodeType: InfraNodeType!): InfraNodeMetadata!
}
`;
diff --git a/x-pack/plugins/infra/server/graphql/nodes/schema.gql.ts b/x-pack/plugins/infra/server/graphql/nodes/schema.gql.ts
index 33de32f10080..cbad4e93b158 100644
--- a/x-pack/plugins/infra/server/graphql/nodes/schema.gql.ts
+++ b/x-pack/plugins/infra/server/graphql/nodes/schema.gql.ts
@@ -14,6 +14,7 @@ export const nodesSchema: any = gql`
type InfraNodePath {
value: String!
+ label: String
}
type InfraNode {
diff --git a/x-pack/plugins/infra/server/graphql/types.ts b/x-pack/plugins/infra/server/graphql/types.ts
index 9747790fb17c..c7d974e7e512 100644
--- a/x-pack/plugins/infra/server/graphql/types.ts
+++ b/x-pack/plugins/infra/server/graphql/types.ts
@@ -51,7 +51,7 @@ export interface InfraSource {
/** The status of the source */
status: InfraSourceStatus;
/** A hierarchy of metadata entries by node */
- metadataByNode: (InfraNodeMetadata | null)[];
+ metadataByNode: InfraNodeMetadata;
/** A consecutive span of log entries surrounding a point in time */
logEntriesAround: InfraLogEntryInterval;
/** A consecutive span of log entries within an interval */
@@ -117,6 +117,14 @@ export interface InfraIndexField {
}
/** One metadata entry for a node. */
export interface InfraNodeMetadata {
+ id: string;
+
+ name: string;
+
+ features: InfraNodeFeature[];
+}
+
+export interface InfraNodeFeature {
name: string;
source: string;
@@ -203,6 +211,8 @@ export interface InfraNode {
export interface InfraNodePath {
value: string;
+
+ label: string;
}
export interface InfraNodeMetric {
@@ -280,7 +290,7 @@ export interface SourceQueryArgs {
id: string;
}
export interface MetadataByNodeInfraSourceArgs {
- nodeName: string;
+ nodeId: string;
nodeType: InfraNodeType;
}
@@ -461,7 +471,7 @@ export namespace InfraSourceResolvers {
/** The status of the source */
status?: StatusResolver;
/** A hierarchy of metadata entries by node */
- metadataByNode?: MetadataByNodeResolver<(InfraNodeMetadata | null)[], TypeParent, Context>;
+ metadataByNode?: MetadataByNodeResolver;
/** A consecutive span of log entries surrounding a point in time */
logEntriesAround?: LogEntriesAroundResolver;
/** A consecutive span of log entries within an interval */
@@ -490,12 +500,12 @@ export namespace InfraSourceResolvers {
Context = InfraContext
> = Resolver;
export type MetadataByNodeResolver<
- R = (InfraNodeMetadata | null)[],
+ R = InfraNodeMetadata,
Parent = InfraSource,
Context = InfraContext
> = Resolver;
export interface MetadataByNodeArgs {
- nodeName: string;
+ nodeId: string;
nodeType: InfraNodeType;
}
@@ -746,6 +756,32 @@ export namespace InfraIndexFieldResolvers {
/** One metadata entry for a node. */
export namespace InfraNodeMetadataResolvers {
export interface Resolvers {
+ id?: IdResolver;
+
+ name?: NameResolver;
+
+ features?: FeaturesResolver;
+ }
+
+ export type IdResolver = Resolver<
+ R,
+ Parent,
+ Context
+ >;
+ export type NameResolver<
+ R = string,
+ Parent = InfraNodeMetadata,
+ Context = InfraContext
+ > = Resolver;
+ export type FeaturesResolver<
+ R = InfraNodeFeature[],
+ Parent = InfraNodeMetadata,
+ Context = InfraContext
+ > = Resolver;
+}
+
+export namespace InfraNodeFeatureResolvers {
+ export interface Resolvers {
name?: NameResolver;
source?: SourceResolver;
@@ -753,12 +789,12 @@ export namespace InfraNodeMetadataResolvers {
export type NameResolver<
R = string,
- Parent = InfraNodeMetadata,
+ Parent = InfraNodeFeature,
Context = InfraContext
> = Resolver;
export type SourceResolver<
R = string,
- Parent = InfraNodeMetadata,
+ Parent = InfraNodeFeature,
Context = InfraContext
> = Resolver;
}
@@ -1012,6 +1048,8 @@ export namespace InfraNodeResolvers {
export namespace InfraNodePathResolvers {
export interface Resolvers {
value?: ValueResolver;
+
+ label?: DisplayNameResolver;
}
export type ValueResolver = Resolver<
@@ -1019,6 +1057,11 @@ export namespace InfraNodePathResolvers {
Parent,
Context
>;
+ export type DisplayNameResolver<
+ R = string,
+ Parent = InfraNodePath,
+ Context = InfraContext
+ > = Resolver;
}
export namespace InfraNodeMetricResolvers {
diff --git a/x-pack/plugins/infra/server/lib/adapters/metadata/adapter_types.ts b/x-pack/plugins/infra/server/lib/adapters/metadata/adapter_types.ts
index e7aece48c7cd..fed6589e8ba8 100644
--- a/x-pack/plugins/infra/server/lib/adapters/metadata/adapter_types.ts
+++ b/x-pack/plugins/infra/server/lib/adapters/metadata/adapter_types.ts
@@ -7,17 +7,23 @@
import { InfraSourceConfiguration } from '../../sources';
import { InfraFrameworkRequest, InfraMetadataAggregationBucket } from '../framework';
+export interface InfraMetricsAdapterResponse {
+ id: string;
+ name?: string;
+ buckets: InfraMetadataAggregationBucket[];
+}
+
export interface InfraMetadataAdapter {
getMetricMetadata(
req: InfraFrameworkRequest,
sourceConfiguration: InfraSourceConfiguration,
- nodeName: string,
+ nodeId: string,
nodeType: string
- ): Promise;
+ ): Promise;
getLogMetadata(
req: InfraFrameworkRequest,
sourceConfiguration: InfraSourceConfiguration,
- nodeName: string,
+ nodeId: string,
nodeType: string
- ): Promise;
+ ): Promise;
}
diff --git a/x-pack/plugins/infra/server/lib/adapters/metadata/elasticsearch_metadata_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/metadata/elasticsearch_metadata_adapter.ts
index 7972154124ee..e35438e66376 100644
--- a/x-pack/plugins/infra/server/lib/adapters/metadata/elasticsearch_metadata_adapter.ts
+++ b/x-pack/plugins/infra/server/lib/adapters/metadata/elasticsearch_metadata_adapter.ts
@@ -4,14 +4,15 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import { first, get } from 'lodash';
import { InfraSourceConfiguration } from '../../sources';
import {
InfraBackendFrameworkAdapter,
InfraFrameworkRequest,
- InfraMetadataAggregationBucket,
InfraMetadataAggregationResponse,
} from '../framework';
-import { InfraMetadataAdapter } from './adapter_types';
+import { NAME_FIELDS } from '../nodes/constants';
+import { InfraMetadataAdapter, InfraMetricsAdapterResponse } from './adapter_types';
export class ElasticsearchMetadataAdapter implements InfraMetadataAdapter {
private framework: InfraBackendFrameworkAdapter;
@@ -22,9 +23,9 @@ export class ElasticsearchMetadataAdapter implements InfraMetadataAdapter {
public async getMetricMetadata(
req: InfraFrameworkRequest,
sourceConfiguration: InfraSourceConfiguration,
- nodeName: string,
+ nodeId: string,
nodeType: 'host' | 'container' | 'pod'
- ): Promise {
+ ): Promise {
const idFieldName = getIdFieldName(sourceConfiguration, nodeType);
const metricQuery = {
index: sourceConfiguration.metricAlias,
@@ -32,11 +33,12 @@ export class ElasticsearchMetadataAdapter implements InfraMetadataAdapter {
query: {
bool: {
filter: {
- term: { [idFieldName]: nodeName },
+ term: { [idFieldName]: nodeId },
},
},
},
- size: 0,
+ size: 1,
+ _source: [NAME_FIELDS[nodeType]],
aggs: {
metrics: {
terms: {
@@ -61,17 +63,26 @@ export class ElasticsearchMetadataAdapter implements InfraMetadataAdapter {
{ metrics?: InfraMetadataAggregationResponse }
>(req, 'search', metricQuery);
- return response.aggregations && response.aggregations.metrics
- ? response.aggregations.metrics.buckets
- : [];
+ const buckets =
+ response.aggregations && response.aggregations.metrics
+ ? response.aggregations.metrics.buckets
+ : [];
+
+ const sampleDoc = first(response.hits.hits);
+
+ return {
+ id: nodeId,
+ name: get(sampleDoc, `_source.${NAME_FIELDS[nodeType]}`),
+ buckets,
+ };
}
public async getLogMetadata(
req: InfraFrameworkRequest,
sourceConfiguration: InfraSourceConfiguration,
- nodeName: string,
+ nodeId: string,
nodeType: 'host' | 'container' | 'pod'
- ): Promise {
+ ): Promise {
const idFieldName = getIdFieldName(sourceConfiguration, nodeType);
const logQuery = {
index: sourceConfiguration.logAlias,
@@ -79,11 +90,12 @@ export class ElasticsearchMetadataAdapter implements InfraMetadataAdapter {
query: {
bool: {
filter: {
- term: { [idFieldName]: nodeName },
+ term: { [idFieldName]: nodeId },
},
},
},
- size: 0,
+ size: 1,
+ _source: [NAME_FIELDS[nodeType]],
aggs: {
metrics: {
terms: {
@@ -108,9 +120,18 @@ export class ElasticsearchMetadataAdapter implements InfraMetadataAdapter {
{ metrics?: InfraMetadataAggregationResponse }
>(req, 'search', logQuery);
- return response.aggregations && response.aggregations.metrics
- ? response.aggregations.metrics.buckets
- : [];
+ const buckets =
+ response.aggregations && response.aggregations.metrics
+ ? response.aggregations.metrics.buckets
+ : [];
+
+ const sampleDoc = first(response.hits.hits);
+
+ return {
+ id: nodeId,
+ name: get(sampleDoc, `_source.${NAME_FIELDS[nodeType]}`),
+ buckets,
+ };
}
}
diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/constants.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/constants.ts
index 75d8464e8efe..53adf25a8b06 100644
--- a/x-pack/plugins/infra/server/lib/adapters/nodes/constants.ts
+++ b/x-pack/plugins/infra/server/lib/adapters/nodes/constants.ts
@@ -4,6 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import { InfraNodeType } from '../../../graphql/types';
// TODO: Make NODE_REQUEST_PARTITION_SIZE configurable from kibana.yml
export const NODE_REQUEST_PARTITION_SIZE = 75;
export const NODE_REQUEST_PARTITION_FACTOR = 1.2;
+export const NAME_FIELDS = {
+ [InfraNodeType.host]: 'host.name',
+ [InfraNodeType.pod]: 'kubernetes.pod.name',
+ [InfraNodeType.container]: 'docker.container.name',
+};
diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_node_item.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_node_item.ts
index 41c24ed13407..5a5bdabdfded 100644
--- a/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_node_item.ts
+++ b/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_node_item.ts
@@ -4,12 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { last } from 'lodash';
+import { get, last } from 'lodash';
import { isNumber } from 'lodash';
import moment from 'moment';
import { InfraNode, InfraNodeMetric } from '../../../../graphql/types';
import { InfraBucket, InfraNodeRequestOptions } from '../adapter_types';
+import { NAME_FIELDS } from '../constants';
import { getBucketSizeInSeconds } from './get_bucket_size_in_seconds';
// TODO: Break these function into seperate files and expand beyond just documnet count
@@ -57,8 +58,9 @@ export function createNodeItem(
node: InfraBucket,
bucket: InfraBucket
): InfraNode {
+ const nodeDoc = get(node, ['nodeDetails', 'hits', 'hits', 0]);
return {
metric: createNodeMetrics(options, node, bucket),
- path: [{ value: node.key }],
+ path: [{ value: node.key, label: get(nodeDoc, `_source.${NAME_FIELDS[options.nodeType]}`) }],
} as InfraNode;
}
diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/lib/extract_group_paths.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/lib/extract_group_paths.ts
index 924687ac0e86..1ea42536b86a 100644
--- a/x-pack/plugins/infra/server/lib/adapters/nodes/lib/extract_group_paths.ts
+++ b/x-pack/plugins/infra/server/lib/adapters/nodes/lib/extract_group_paths.ts
@@ -28,8 +28,8 @@ export function extractGroupPaths(
(b: InfraBucket): InfraNode => {
const innerNode = createNodeItem(options, node, b);
const nodePath = [
- { value: bucket.key.toString() },
- { value: b.key.toString() },
+ { value: bucket.key.toString(), label: bucket.key.toString() },
+ { value: b.key.toString(), label: b.key.toString() },
].concat(innerNode.path);
return {
...innerNode,
@@ -40,7 +40,7 @@ export function extractGroupPaths(
);
}
const nodeItem = createNodeItem(options, node, bucket);
- const path = [{ value: key }].concat(nodeItem.path);
+ const path = [{ value: key, label: key }].concat(nodeItem.path);
return acc.concat({
...nodeItem,
path,
diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/processors/common/group_by_processor.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/processors/common/group_by_processor.ts
index a1196b15f121..38d489a15199 100644
--- a/x-pack/plugins/infra/server/lib/adapters/nodes/processors/common/group_by_processor.ts
+++ b/x-pack/plugins/infra/server/lib/adapters/nodes/processors/common/group_by_processor.ts
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { cloneDeep, set } from 'lodash';
+import { cloneDeep, get, set } from 'lodash';
import { InfraPathFilterInput, InfraPathInput } from '../../../../../graphql/types';
import {
@@ -18,7 +18,7 @@ export const groupByProcessor = (options: InfraProcesorRequestOptions) => {
return (doc: InfraESSearchBody) => {
const result = cloneDeep(doc);
const { groupBy } = options.nodeOptions;
- let aggs = {};
+ let aggs = get(result, 'aggs.waffle.aggs.nodes.aggs', {});
set(result, 'aggs.waffle.aggs.nodes.aggs', aggs);
groupBy.forEach((grouping: InfraPathInput, index: number) => {
if (isGroupByTerms(grouping)) {
@@ -49,7 +49,7 @@ export const groupByProcessor = (options: InfraProcesorRequestOptions) => {
),
},
};
- set(aggs, `${grouping.id}`, filtersAgg);
+ set(aggs, `path_${index}`, filtersAgg);
aggs = filtersAgg.aggs;
}
});
diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/processors/common/nodes_processor.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/processors/common/nodes_processor.ts
index b161e4b04b50..cf416346df28 100644
--- a/x-pack/plugins/infra/server/lib/adapters/nodes/processors/common/nodes_processor.ts
+++ b/x-pack/plugins/infra/server/lib/adapters/nodes/processors/common/nodes_processor.ts
@@ -7,7 +7,11 @@
import { cloneDeep, set } from 'lodash';
import { InfraESSearchBody, InfraNodeType, InfraProcesorRequestOptions } from '../../adapter_types';
-import { NODE_REQUEST_PARTITION_FACTOR, NODE_REQUEST_PARTITION_SIZE } from '../../constants';
+import {
+ NAME_FIELDS,
+ NODE_REQUEST_PARTITION_FACTOR,
+ NODE_REQUEST_PARTITION_SIZE,
+} from '../../constants';
const nodeTypeToField = (options: InfraProcesorRequestOptions): string => {
const { fields } = options.nodeOptions.sourceConfiguration;
@@ -22,6 +26,7 @@ const nodeTypeToField = (options: InfraProcesorRequestOptions): string => {
};
export const nodesProcessor = (options: InfraProcesorRequestOptions) => {
+ const { fields } = options.nodeOptions.sourceConfiguration;
return (doc: InfraESSearchBody) => {
const result = cloneDeep(doc);
const field = nodeTypeToField(options);
@@ -35,6 +40,16 @@ export const nodesProcessor = (options: InfraProcesorRequestOptions) => {
order: { _key: 'asc' },
size: NODE_REQUEST_PARTITION_SIZE * NODE_REQUEST_PARTITION_FACTOR,
});
+
+ set(result, 'aggs.waffle.aggs.nodes.aggs', {
+ nodeDetails: {
+ top_hits: {
+ size: 1,
+ _source: { includes: [NAME_FIELDS[options.nodeType]] },
+ sort: [{ [fields.timestamp]: { order: 'desc' } }],
+ },
+ },
+ });
return result;
};
};
diff --git a/x-pack/plugins/infra/server/lib/adapters/sources/configuration_sources_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/sources/configuration_sources_adapter.ts
index 4b8956b5f998..4870def3a87d 100644
--- a/x-pack/plugins/infra/server/lib/adapters/sources/configuration_sources_adapter.ts
+++ b/x-pack/plugins/infra/server/lib/adapters/sources/configuration_sources_adapter.ts
@@ -49,10 +49,10 @@ export class InfraConfigurationSourcesAdapter implements InfraSourcesAdapter {
}
const DEFAULT_FIELDS = {
- container: 'docker.container.name',
- host: 'beat.hostname',
+ container: 'docker.container.id',
+ host: 'host.name',
message: ['message', '@message'],
- pod: 'kubernetes.pod.name',
+ pod: 'kubernetes.pod.uid',
tiebreaker: '_doc',
timestamp: '@timestamp',
};
diff --git a/x-pack/plugins/infra/server/lib/domains/metadata_domain/metadata_domain.ts b/x-pack/plugins/infra/server/lib/domains/metadata_domain/metadata_domain.ts
index 9453061f590e..5c30a7189a8b 100644
--- a/x-pack/plugins/infra/server/lib/domains/metadata_domain/metadata_domain.ts
+++ b/x-pack/plugins/infra/server/lib/domains/metadata_domain/metadata_domain.ts
@@ -17,30 +17,32 @@ export class InfraMetadataDomain {
public async getMetadata(
req: InfraFrameworkRequest,
sourceId: string,
- nodeName: string,
+ nodeId: string,
nodeType: string
) {
const sourceConfiguration = await this.libs.sources.getConfiguration(sourceId);
const metricsPromise = this.adapter.getMetricMetadata(
req,
sourceConfiguration,
- nodeName,
+ nodeId,
nodeType
);
- const logsPromise = this.adapter.getLogMetadata(req, sourceConfiguration, nodeName, nodeType);
+ const logsPromise = this.adapter.getLogMetadata(req, sourceConfiguration, nodeId, nodeType);
const metrics = await metricsPromise;
const logs = await logsPromise;
- const metricMetadata = pickMetadata(metrics).map(entry => {
+ const metricMetadata = pickMetadata(metrics.buckets).map(entry => {
return { name: entry, source: 'metrics' };
});
- const logMetadata = pickMetadata(logs).map(entry => {
+ const logMetadata = pickMetadata(logs.buckets).map(entry => {
return { name: entry, source: 'logs' };
});
- return metricMetadata.concat(logMetadata);
+ const id = metrics.id || logs.id;
+ const name = metrics.name || logs.name || id;
+ return { id, name, features: metricMetadata.concat(logMetadata) };
}
}
diff --git a/x-pack/test/api_integration/apis/infra/metadata.ts b/x-pack/test/api_integration/apis/infra/metadata.ts
index 4714fd7f60b0..15289a15b700 100644
--- a/x-pack/test/api_integration/apis/infra/metadata.ts
+++ b/x-pack/test/api_integration/apis/infra/metadata.ts
@@ -30,7 +30,12 @@ const metadataTests: KbnTestProvider = ({ getService }) => {
})
.then(resp => {
const metadata = resp.data.source.metadataByNode;
- expect(metadata.length).to.be(14);
+ if (metadata) {
+ expect(metadata.features.length).to.be(14);
+ expect(metadata.name).to.equal('demo-stack-nginx-01');
+ } else {
+ throw new Error('Metadata should never be empty');
+ }
});
});
});
diff --git a/x-pack/test/api_integration/apis/infra/sources.ts b/x-pack/test/api_integration/apis/infra/sources.ts
index a3822c6b72ff..2c7820e8a277 100644
--- a/x-pack/test/api_integration/apis/infra/sources.ts
+++ b/x-pack/test/api_integration/apis/infra/sources.ts
@@ -33,9 +33,9 @@ const sourcesTests: KbnTestProvider = ({ getService }) => {
// shipped default values
expect(sourceConfiguration.metricAlias).to.be('metricbeat-*');
expect(sourceConfiguration.logAlias).to.be('filebeat-*');
- expect(sourceConfiguration.fields.container).to.be('docker.container.name');
- expect(sourceConfiguration.fields.host).to.be('beat.hostname');
- expect(sourceConfiguration.fields.pod).to.be('kubernetes.pod.name');
+ expect(sourceConfiguration.fields.container).to.be('docker.container.id');
+ expect(sourceConfiguration.fields.host).to.be('host.name');
+ expect(sourceConfiguration.fields.pod).to.be('kubernetes.pod.uid');
// test data in x-pack/test/functional/es_archives/infra/data.json.gz
expect(sourceStatus.indexFields.length).to.be(1765);