diff --git a/x-pack/legacy/plugins/infra/common/ecs_allowed_list.ts b/x-pack/legacy/plugins/infra/common/ecs_allowed_list.ts index 37b037214bb0..1728cd1fa4b4 100644 --- a/x-pack/legacy/plugins/infra/common/ecs_allowed_list.ts +++ b/x-pack/legacy/plugins/infra/common/ecs_allowed_list.ts @@ -45,6 +45,8 @@ export const DOCKER_ALLOWED_LIST = [ 'docker.container.labels', ]; +export const AWS_S3_ALLOWED_LIST = ['aws.s3']; + export const getAllowedListForPrefix = (prefix: string) => { const firstPart = first(prefix.split(/\./)); const defaultAllowedList = prefix ? [...ECS_ALLOWED_LIST, prefix] : ECS_ALLOWED_LIST; @@ -55,6 +57,10 @@ export const getAllowedListForPrefix = (prefix: string) => { return [...defaultAllowedList, ...PROMETHEUS_ALLOWED_LIST]; case 'kubernetes': return [...defaultAllowedList, ...K8S_ALLOWED_LIST]; + case 'aws': + if (prefix === 'aws.s3_daily_storage') { + return [...defaultAllowedList, ...AWS_S3_ALLOWED_LIST]; + } default: return defaultAllowedList; } diff --git a/x-pack/legacy/plugins/infra/common/graphql/shared/schema.gql.ts b/x-pack/legacy/plugins/infra/common/graphql/shared/schema.gql.ts index fd86e605b874..071313817eff 100644 --- a/x-pack/legacy/plugins/infra/common/graphql/shared/schema.gql.ts +++ b/x-pack/legacy/plugins/infra/common/graphql/shared/schema.gql.ts @@ -30,5 +30,9 @@ export const sharedSchema = gql` pod container host + awsEC2 + awsS3 + awsRDS + awsSQS } `; diff --git a/x-pack/legacy/plugins/infra/common/graphql/types.ts b/x-pack/legacy/plugins/infra/common/graphql/types.ts index 273cbfc1d4f8..0520409800bc 100644 --- a/x-pack/legacy/plugins/infra/common/graphql/types.ts +++ b/x-pack/legacy/plugins/infra/common/graphql/types.ts @@ -552,6 +552,10 @@ export enum InfraNodeType { pod = 'pod', container = 'container', host = 'host', + awsEC2 = 'awsEC2', + awsS3 = 'awsS3', + awsRDS = 'awsRDS', + awsSQS = 'awsSQS', } export enum InfraSnapshotMetricType { @@ -562,6 +566,22 @@ export enum InfraSnapshotMetricType { tx = 'tx', rx = 'rx', logRate = 'logRate', + diskIOReadBytes = 'diskIOReadBytes', + diskIOWriteBytes = 'diskIOWriteBytes', + s3TotalRequests = 's3TotalRequests', + s3NumberOfObjects = 's3NumberOfObjects', + s3BucketSize = 's3BucketSize', + s3DownloadBytes = 's3DownloadBytes', + s3UploadBytes = 's3UploadBytes', + rdsConnections = 'rdsConnections', + rdsQueriesExecuted = 'rdsQueriesExecuted', + rdsActiveTransactions = 'rdsActiveTransactions', + rdsLatency = 'rdsLatency', + sqsMessagesVisible = 'sqsOldestMessage', + sqsMessagesDelayed = 'sqsMessagesDelayed', + sqsMessagesSent = 'sqsMessagesSent', + sqsMessagesEmpty = 'sqsMessagesEmpty', + sqsOldestMessage = 'sqsOldestMessage', } export enum InfraMetric { @@ -602,6 +622,24 @@ export enum InfraMetric { awsNetworkPackets = 'awsNetworkPackets', awsDiskioBytes = 'awsDiskioBytes', awsDiskioOps = 'awsDiskioOps', + awsEC2CpuUtilization = 'awsEC2CpuUtilization', + awsEC2DiskIOBytes = 'awsEC2DiskIOBytes', + awsEC2NetworkTraffic = 'awsEC2NetworkTraffic', + awsS3TotalRequests = 'awsS3TotalRequests', + awsS3NumberOfObjects = 'awsS3NumberOfObjects', + awsS3BucketSize = 'awsS3BucketSize', + awsS3DownloadBytes = 'awsS3DownloadBytes', + awsS3UploadBytes = 'awsS3UploadBytes', + awsRDSCpuTotal = 'awsRDSCpuTotal', + awsRDSConnections = 'awsRDSConnections', + awsRDSQueriesExecuted = 'awsRDSQueriesExecuted', + awsRDSActiveTransactions = 'awsRDSActiveTransactions', + awsRDSLatency = 'awsRDSLatency', + awsSQSMessagesVisible = 'awsSQSMessagesVisible', + awsSQSMessagesDelayed = 'awsSQSMessagesDelayed', + awsSQSMessagesSent = 'awsSQSMessagesSent', + awsSQSMessagesEmpty = 'awsSQSMessagesEmpty', + awsSQSOldestMessage = 'awsSQSOldestMessage', custom = 'custom', } diff --git a/x-pack/legacy/plugins/infra/common/http_api/metadata_api.ts b/x-pack/legacy/plugins/infra/common/http_api/metadata_api.ts index ace61e13193c..7fc3c3e876f0 100644 --- a/x-pack/legacy/plugins/infra/common/http_api/metadata_api.ts +++ b/x-pack/legacy/plugins/infra/common/http_api/metadata_api.ts @@ -5,16 +5,11 @@ */ import * as rt from 'io-ts'; - -export const InfraMetadataNodeTypeRT = rt.keyof({ - host: null, - pod: null, - container: null, -}); +import { ItemTypeRT } from '../../common/inventory_models/types'; export const InfraMetadataRequestRT = rt.type({ nodeId: rt.string, - nodeType: InfraMetadataNodeTypeRT, + nodeType: ItemTypeRT, sourceId: rt.string, }); @@ -96,5 +91,3 @@ export type InfraMetadataMachine = rt.TypeOf; export type InfraMetadataHost = rt.TypeOf; export type InfraMetadataOS = rt.TypeOf; - -export type InfraMetadataNodeType = rt.TypeOf; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/index.ts new file mode 100644 index 000000000000..ba4a6bb22c18 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/index.ts @@ -0,0 +1,30 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { metrics } from './metrics'; +import { InventoryModel } from '../types'; + +export const awsEC2: InventoryModel = { + id: 'awsEC2', + displayName: i18n.translate('xpack.infra.inventoryModels.awsEC2.displayName', { + defaultMessage: 'EC2 Instances', + }), + requiredModules: ['aws'], + crosslinkSupport: { + details: true, + logs: true, + apm: true, + uptime: true, + }, + metrics, + fields: { + id: 'cloud.instance.id', + name: 'cloud.instance.name', + ip: 'aws.ec2.instance.public.ip', + }, + requiredMetrics: ['awsEC2CpuUtilization', 'awsEC2NetworkTraffic', 'awsEC2DiskIOBytes'], +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/layout.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/layout.tsx new file mode 100644 index 000000000000..01009b478951 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/layout.tsx @@ -0,0 +1,116 @@ +/* + * 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 React from 'react'; +import { i18n } from '@kbn/i18n'; +import { LayoutPropsWithTheme } from '../../../public/pages/metrics/types'; +import { Section } from '../../../public/pages/metrics/components/section'; +import { SubSection } from '../../../public/pages/metrics/components/sub_section'; +import { ChartSectionVis } from '../../../public/pages/metrics/components/chart_section_vis'; +import { withTheme } from '../../../../../common/eui_styled_components'; + +export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( + +
+ + + + + + + + + +
+
+)); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/index.ts new file mode 100644 index 000000000000..18b7cca2048a --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/index.ts @@ -0,0 +1,28 @@ +/* + * 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 { cpu } from './snapshot/cpu'; +import { rx } from './snapshot/rx'; +import { tx } from './snapshot/tx'; +import { diskIOReadBytes } from './snapshot/disk_io_read_bytes'; +import { diskIOWriteBytes } from './snapshot/disk_io_write_bytes'; + +import { awsEC2CpuUtilization } from './tsvb/aws_ec2_cpu_utilization'; +import { awsEC2NetworkTraffic } from './tsvb/aws_ec2_network_traffic'; +import { awsEC2DiskIOBytes } from './tsvb/aws_ec2_diskio_bytes'; + +import { InventoryMetrics } from '../../types'; + +export const metrics: InventoryMetrics = { + tsvb: { + awsEC2CpuUtilization, + awsEC2NetworkTraffic, + awsEC2DiskIOBytes, + }, + snapshot: { cpu, rx, tx, diskIOReadBytes, diskIOWriteBytes }, + defaultSnapshot: 'cpu', + defaultTimeRangeInSeconds: 14400, // 4 hours +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/cpu.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/cpu.ts new file mode 100644 index 000000000000..483d9de78491 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/cpu.ts @@ -0,0 +1,27 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const cpu: SnapshotModel = { + cpu_avg: { + avg: { + field: 'aws.ec2.cpu.total.pct', + }, + }, + cpu: { + bucket_script: { + buckets_path: { + cpu: 'cpu_avg', + }, + script: { + source: 'params.cpu / 100', + lang: 'painless', + }, + gap_policy: 'skip', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/disk_io_read_bytes.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/disk_io_read_bytes.ts new file mode 100644 index 000000000000..48e4a9eb59fa --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/disk_io_read_bytes.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const diskIOReadBytes: SnapshotModel = { + diskIOReadBytes: { + avg: { + field: 'aws.ec2.diskio.read.bytes_per_sec', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/disk_io_write_bytes.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/disk_io_write_bytes.ts new file mode 100644 index 000000000000..deadaa8c4a77 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/disk_io_write_bytes.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const diskIOWriteBytes: SnapshotModel = { + diskIOWriteBytes: { + avg: { + field: 'aws.ec2.diskio.write.bytes_per_sec', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/rx.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/rx.ts new file mode 100644 index 000000000000..2b857ce9b338 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/rx.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const rx: SnapshotModel = { + rx: { + avg: { + field: 'aws.ec2.network.in.bytes_per_sec', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/tx.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/tx.ts new file mode 100644 index 000000000000..63c9da8ea188 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/tx.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const tx: SnapshotModel = { + tx: { + avg: { + field: 'aws.ec2.network.in.bytes_per_sec', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_cpu_utilization.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_cpu_utilization.ts new file mode 100644 index 000000000000..a7a06ef1cfc1 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_cpu_utilization.ts @@ -0,0 +1,37 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; + +export const awsEC2CpuUtilization = createTSVBModel( + 'awsEC2CpuUtilization', + ['aws.ec2'], + [ + { + id: 'total', + split_mode: 'everything', + metrics: [ + { + field: 'aws.ec2.cpu.total.pct', + id: 'avg-cpu', + type: 'avg', + }, + { + id: 'convert-to-percent', + script: 'params.avg / 100', + type: 'calculation', + variables: [ + { + field: 'avg-cpu', + id: 'var-avg', + name: 'avg', + }, + ], + }, + ], + }, + ] +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_diskio_bytes.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_diskio_bytes.ts new file mode 100644 index 000000000000..35d165936211 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_diskio_bytes.ts @@ -0,0 +1,41 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; +export const awsEC2DiskIOBytes = createTSVBModel( + 'awsEC2DiskIOBytes', + ['aws.ec2'], + [ + { + id: 'write', + split_mode: 'everything', + metrics: [ + { + field: 'aws.ec2.diskio.write.bytes_per_sec', + id: 'avg-write', + type: 'avg', + }, + ], + }, + { + id: 'read', + split_mode: 'everything', + metrics: [ + { + field: 'aws.ec2.diskio.read.bytes_per_sec', + id: 'avg-read', + type: 'avg', + }, + { + id: 'calculation-rate', + type: 'calculation', + variables: [{ id: 'rate-var', name: 'rate', field: 'avg-read' }], + script: 'params.rate * -1', + }, + ], + }, + ] +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_network_traffic.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_network_traffic.ts new file mode 100644 index 000000000000..ea4b41d0bcd6 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_network_traffic.ts @@ -0,0 +1,41 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; +export const awsEC2NetworkTraffic = createTSVBModel( + 'awsEC2NetworkTraffic', + ['aws.ec2'], + [ + { + id: 'tx', + split_mode: 'everything', + metrics: [ + { + field: 'aws.ec2.network.out.bytes_per_sec', + id: 'avg-tx', + type: 'avg', + }, + ], + }, + { + id: 'rx', + split_mode: 'everything', + metrics: [ + { + field: 'aws.ec2.network.in.bytes_per_sec', + id: 'avg-rx', + type: 'avg', + }, + { + id: 'calculation-rate', + type: 'calculation', + variables: [{ id: 'rate-var', name: 'rate', field: 'avg-rx' }], + script: 'params.rate * -1', + }, + ], + }, + ] +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/toolbar_items.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/toolbar_items.tsx new file mode 100644 index 000000000000..fc09f0761a52 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_ec2/toolbar_items.tsx @@ -0,0 +1,33 @@ +/* + * 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 React from 'react'; +import { ToolbarProps } from '../../../public/components/inventory/toolbars/toolbar'; +import { MetricsAndGroupByToolbarItems } from '../shared/compontents/metrics_and_groupby_toolbar_items'; +import { InfraSnapshotMetricType } from '../../graphql/types'; + +export const AwsEC2ToolbarItems = (props: ToolbarProps) => { + const metricTypes = [ + InfraSnapshotMetricType.cpu, + InfraSnapshotMetricType.rx, + InfraSnapshotMetricType.tx, + InfraSnapshotMetricType.diskIOReadBytes, + InfraSnapshotMetricType.diskIOWriteBytes, + ]; + const groupByFields = [ + 'cloud.availability_zone', + 'cloud.machine.type', + 'aws.ec2.instance.image.id', + 'aws.ec2.instance.state.name', + ]; + return ( + + ); +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/index.ts new file mode 100644 index 000000000000..e81dee504b06 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/index.ts @@ -0,0 +1,35 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { metrics } from './metrics'; +import { InventoryModel } from '../types'; + +export const awsRDS: InventoryModel = { + id: 'awsRDS', + displayName: i18n.translate('xpack.infra.inventoryModels.awsRDS.displayName', { + defaultMessage: 'RDS Databases', + }), + requiredModules: ['aws'], + crosslinkSupport: { + details: true, + logs: true, + apm: false, + uptime: false, + }, + metrics, + fields: { + id: 'aws.rds.db_instance.arn', + name: 'aws.rds.db_instance.identifier', + }, + requiredMetrics: [ + 'awsRDSCpuTotal', + 'awsRDSConnections', + 'awsRDSQueriesExecuted', + 'awsRDSActiveTransactions', + 'awsRDSLatency', + ], +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/layout.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/layout.tsx new file mode 100644 index 000000000000..5f1185666a35 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/layout.tsx @@ -0,0 +1,180 @@ +/* + * 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 React from 'react'; +import { i18n } from '@kbn/i18n'; +import { LayoutPropsWithTheme } from '../../../public/pages/metrics/types'; +import { Section } from '../../../public/pages/metrics/components/section'; +import { SubSection } from '../../../public/pages/metrics/components/sub_section'; +import { ChartSectionVis } from '../../../public/pages/metrics/components/chart_section_vis'; +import { withTheme } from '../../../../../common/eui_styled_components'; + +export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( + +
+ + + + + + + + + + + + + + + +
+
+)); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/index.ts new file mode 100644 index 000000000000..eaded5d8df22 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/index.ts @@ -0,0 +1,38 @@ +/* + * 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 { InventoryMetrics } from '../../types'; + +import { cpu } from './snapshot/cpu'; +import { rdsLatency } from './snapshot/rds_latency'; +import { rdsConnections } from './snapshot/rds_connections'; +import { rdsQueriesExecuted } from './snapshot/rds_queries_executed'; +import { rdsActiveTransactions } from './snapshot/rds_active_transactions'; + +import { awsRDSLatency } from './tsvb/aws_rds_latency'; +import { awsRDSConnections } from './tsvb/aws_rds_connections'; +import { awsRDSCpuTotal } from './tsvb/aws_rds_cpu_total'; +import { awsRDSQueriesExecuted } from './tsvb/aws_rds_queries_executed'; +import { awsRDSActiveTransactions } from './tsvb/aws_rds_active_transactions'; + +export const metrics: InventoryMetrics = { + tsvb: { + awsRDSLatency, + awsRDSConnections, + awsRDSCpuTotal, + awsRDSQueriesExecuted, + awsRDSActiveTransactions, + }, + snapshot: { + cpu, + rdsLatency, + rdsConnections, + rdsQueriesExecuted, + rdsActiveTransactions, + }, + defaultSnapshot: 'cpu', + defaultTimeRangeInSeconds: 14400, // 4 hours +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/cpu.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/cpu.ts new file mode 100644 index 000000000000..e277b3b11958 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/cpu.ts @@ -0,0 +1,27 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const cpu: SnapshotModel = { + cpu_avg: { + avg: { + field: 'aws.rds.cpu.total.pct', + }, + }, + cpu: { + bucket_script: { + buckets_path: { + cpu: 'cpu_avg', + }, + script: { + source: 'params.cpu / 100', + lang: 'painless', + }, + gap_policy: 'skip', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_active_transactions.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_active_transactions.ts new file mode 100644 index 000000000000..be3dba100ba2 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_active_transactions.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const rdsActiveTransactions: SnapshotModel = { + rdsActiveTransactions: { + avg: { + field: 'aws.rds.transactions.active', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_connections.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_connections.ts new file mode 100644 index 000000000000..c7855d5548ee --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_connections.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const rdsConnections: SnapshotModel = { + rdsConnections: { + avg: { + field: 'aws.rds.database_connections', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_latency.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_latency.ts new file mode 100644 index 000000000000..2997b54d2f92 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_latency.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const rdsLatency: SnapshotModel = { + rdsLatency: { + avg: { + field: 'aws.rds.latency.dml', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_queries_executed.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_queries_executed.ts new file mode 100644 index 000000000000..18e6538fb1e1 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_queries_executed.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const rdsQueriesExecuted: SnapshotModel = { + rdsQueriesExecuted: { + avg: { + field: 'aws.rds.queries', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_active_transactions.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_active_transactions.ts new file mode 100644 index 000000000000..026cdeac40c3 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_active_transactions.ts @@ -0,0 +1,36 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; + +export const awsRDSActiveTransactions = createTSVBModel( + 'awsRDSActiveTransactions', + ['aws.rds'], + [ + { + id: 'active', + split_mode: 'everything', + metrics: [ + { + field: 'aws.rds.transactions.active', + id: 'avg', + type: 'avg', + }, + ], + }, + { + id: 'blocked', + split_mode: 'everything', + metrics: [ + { + field: 'aws.rds.transactions.blocked', + id: 'avg', + type: 'avg', + }, + ], + }, + ] +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_connections.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_connections.ts new file mode 100644 index 000000000000..145cc758e4a5 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_connections.ts @@ -0,0 +1,25 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; + +export const awsRDSConnections = createTSVBModel( + 'awsRDSConnections', + ['aws.rds'], + [ + { + id: 'connections', + split_mode: 'everything', + metrics: [ + { + field: 'aws.rds.database_connections', + id: 'avg-conns', + type: 'avg', + }, + ], + }, + ] +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_cpu_total.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_cpu_total.ts new file mode 100644 index 000000000000..9a8eefc859bb --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_cpu_total.ts @@ -0,0 +1,37 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; + +export const awsRDSCpuTotal = createTSVBModel( + 'awsRDSCpuTotal', + ['aws.rds'], + [ + { + id: 'cpu', + split_mode: 'everything', + metrics: [ + { + field: 'aws.rds.cpu.total.pct', + id: 'avg-cpu', + type: 'avg', + }, + { + id: 'convert-to-percent', + script: 'params.avg / 100', + type: 'calculation', + variables: [ + { + field: 'avg-cpu', + id: 'var-avg', + name: 'avg', + }, + ], + }, + ], + }, + ] +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_latency.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_latency.ts new file mode 100644 index 000000000000..80dffeeb717c --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_latency.ts @@ -0,0 +1,68 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; + +export const awsRDSLatency = createTSVBModel( + 'awsRDSLatency', + ['aws.rds'], + [ + { + id: 'read', + split_mode: 'everything', + metrics: [ + { + field: 'aws.rds.latency.read', + id: 'avg', + type: 'avg', + }, + ], + }, + { + id: 'write', + split_mode: 'everything', + metrics: [ + { + field: 'aws.rds.latency.write', + id: 'avg', + type: 'avg', + }, + ], + }, + { + id: 'insert', + split_mode: 'everything', + metrics: [ + { + field: 'aws.rds.latency.insert', + id: 'avg', + type: 'avg', + }, + ], + }, + { + id: 'update', + split_mode: 'everything', + metrics: [ + { + field: 'aws.rds.latency.update', + id: 'avg', + type: 'avg', + }, + ], + }, + { + id: 'commit', + split_mode: 'everything', + metrics: [ + { + field: 'aws.rds.latency.commit', + id: 'avg', + type: 'avg', + }, + ], + }, + ] +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_queries_executed.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_queries_executed.ts new file mode 100644 index 000000000000..4dd1a1e89a21 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_queries_executed.ts @@ -0,0 +1,24 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; +export const awsRDSQueriesExecuted = createTSVBModel( + 'awsRDSQueriesExecuted', + ['aws.rds'], + [ + { + id: 'queries', + split_mode: 'everything', + metrics: [ + { + field: 'aws.rds.queries', + id: 'avg-queries', + type: 'avg', + }, + ], + }, + ] +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/toolbar_items.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/toolbar_items.tsx new file mode 100644 index 000000000000..b60d6292c9c0 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_rds/toolbar_items.tsx @@ -0,0 +1,32 @@ +/* + * 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 React from 'react'; +import { ToolbarProps } from '../../../public/components/inventory/toolbars/toolbar'; +import { InfraSnapshotMetricType } from '../../../public/graphql/types'; +import { MetricsAndGroupByToolbarItems } from '../shared/compontents/metrics_and_groupby_toolbar_items'; + +export const AwsRDSToolbarItems = (props: ToolbarProps) => { + const metricTypes = [ + InfraSnapshotMetricType.cpu, + InfraSnapshotMetricType.rdsConnections, + InfraSnapshotMetricType.rdsQueriesExecuted, + InfraSnapshotMetricType.rdsActiveTransactions, + InfraSnapshotMetricType.rdsLatency, + ]; + const groupByFields = [ + 'cloud.availability_zone', + 'aws.rds.db_instance.class', + 'aws.rds.db_instance.status', + ]; + return ( + + ); +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/index.ts new file mode 100644 index 000000000000..c5de4ed80a1c --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/index.ts @@ -0,0 +1,35 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { metrics } from './metrics'; +import { InventoryModel } from '../types'; + +export const awsS3: InventoryModel = { + id: 'awsS3', + displayName: i18n.translate('xpack.infra.inventoryModels.awsS3.displayName', { + defaultMessage: 'S3 Buckets', + }), + requiredModules: ['aws'], + crosslinkSupport: { + details: true, + logs: true, + apm: false, + uptime: false, + }, + metrics, + fields: { + id: 'aws.s3.bucket.name', + name: 'aws.s3.bucket.name', + }, + requiredMetrics: [ + 'awsS3BucketSize', + 'awsS3NumberOfObjects', + 'awsS3TotalRequests', + 'awsS3DownloadBytes', + 'awsS3UploadBytes', + ], +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/layout.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/layout.tsx new file mode 100644 index 000000000000..80089f15b04b --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/layout.tsx @@ -0,0 +1,143 @@ +/* + * 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 React from 'react'; +import { i18n } from '@kbn/i18n'; +import { LayoutPropsWithTheme } from '../../../public/pages/metrics/types'; +import { Section } from '../../../public/pages/metrics/components/section'; +import { SubSection } from '../../../public/pages/metrics/components/sub_section'; +import { ChartSectionVis } from '../../../public/pages/metrics/components/chart_section_vis'; +import { withTheme } from '../../../../../common/eui_styled_components'; + +export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( + +
+ + + + + + + + + + + + + + + +
+
+)); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/index.ts new file mode 100644 index 000000000000..5aa974c16fee --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/index.ts @@ -0,0 +1,38 @@ +/* + * 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 { InventoryMetrics } from '../../types'; + +import { awsS3BucketSize } from './tsvb/aws_s3_bucket_size'; +import { awsS3TotalRequests } from './tsvb/aws_s3_total_requests'; +import { awsS3NumberOfObjects } from './tsvb/aws_s3_number_of_objects'; +import { awsS3DownloadBytes } from './tsvb/aws_s3_download_bytes'; +import { awsS3UploadBytes } from './tsvb/aws_s3_upload_bytes'; + +import { s3BucketSize } from './snapshot/s3_bucket_size'; +import { s3TotalRequests } from './snapshot/s3_total_requests'; +import { s3NumberOfObjects } from './snapshot/s3_number_of_objects'; +import { s3DownloadBytes } from './snapshot/s3_download_bytes'; +import { s3UploadBytes } from './snapshot/s3_upload_bytes'; + +export const metrics: InventoryMetrics = { + tsvb: { + awsS3BucketSize, + awsS3TotalRequests, + awsS3NumberOfObjects, + awsS3DownloadBytes, + awsS3UploadBytes, + }, + snapshot: { + s3BucketSize, + s3NumberOfObjects, + s3TotalRequests, + s3UploadBytes, + s3DownloadBytes, + }, + defaultSnapshot: 's3BucketSize', + defaultTimeRangeInSeconds: 86400 * 7, // 7 days +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_bucket_size.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_bucket_size.ts new file mode 100644 index 000000000000..a99753a39c97 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_bucket_size.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const s3BucketSize: SnapshotModel = { + s3BucketSize: { + max: { + field: 'aws.s3_daily_storage.bucket.size.bytes', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_download_bytes.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_download_bytes.ts new file mode 100644 index 000000000000..a0b23dadee37 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_download_bytes.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const s3DownloadBytes: SnapshotModel = { + s3DownloadBytes: { + max: { + field: 'aws.s3_request.downloaded.bytes', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_number_of_objects.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_number_of_objects.ts new file mode 100644 index 000000000000..29162a59db47 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_number_of_objects.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const s3NumberOfObjects: SnapshotModel = { + s3NumberOfObjects: { + max: { + field: 'aws.s3_daily_storage.number_of_objects', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_total_requests.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_total_requests.ts new file mode 100644 index 000000000000..bc57c6eb3823 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_total_requests.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const s3TotalRequests: SnapshotModel = { + s3TotalRequests: { + max: { + field: 'aws.s3_request.requests.total', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_upload_bytes.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_upload_bytes.ts new file mode 100644 index 000000000000..977d73254c3c --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_upload_bytes.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const s3UploadBytes: SnapshotModel = { + s3UploadBytes: { + max: { + field: 'aws.s3_request.uploaded.bytes', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_bucket_size.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_bucket_size.ts new file mode 100644 index 000000000000..216f98b9e16b --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_bucket_size.ts @@ -0,0 +1,26 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; + +export const awsS3BucketSize = createTSVBModel( + 'awsS3BucketSize', + ['aws.s3_daily_storage'], + [ + { + id: 'bytes', + split_mode: 'everything', + metrics: [ + { + field: 'aws.s3_daily_storage.bucket.size.bytes', + id: 'max-bytes', + type: 'max', + }, + ], + }, + ], + '>=86400s', + false +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_download_bytes.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_download_bytes.ts new file mode 100644 index 000000000000..15eb3130a5e2 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_download_bytes.ts @@ -0,0 +1,25 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; + +export const awsS3DownloadBytes = createTSVBModel( + 'awsS3DownloadBytes', + ['aws.s3_request'], + [ + { + id: 'bytes', + split_mode: 'everything', + metrics: [ + { + field: 'aws.s3_request.downloaded.bytes', + id: 'max-bytes', + type: 'max', + }, + ], + }, + ], + '>=300s' +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_number_of_objects.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_number_of_objects.ts new file mode 100644 index 000000000000..c108735bc0ef --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_number_of_objects.ts @@ -0,0 +1,26 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; + +export const awsS3NumberOfObjects = createTSVBModel( + 'awsS3NumberOfObjects', + ['aws.s3_daily_storage'], + [ + { + id: 'objects', + split_mode: 'everything', + metrics: [ + { + field: 'aws.s3_daily_storage.number_of_objects', + id: 'max-size', + type: 'max', + }, + ], + }, + ], + '>=86400s', + false +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_total_requests.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_total_requests.ts new file mode 100644 index 000000000000..311067fd96b4 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_total_requests.ts @@ -0,0 +1,26 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; + +export const awsS3TotalRequests = createTSVBModel( + 'awsS3TotalRequests', + ['aws.s3_request'], + [ + { + id: 'total', + split_mode: 'everything', + metrics: [ + { + field: 'aws.s3_request.requests.total', + id: 'max-size', + type: 'max', + }, + ], + }, + ], + '>=300s' +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_upload_bytes.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_upload_bytes.ts new file mode 100644 index 000000000000..ab66b47cfa78 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_upload_bytes.ts @@ -0,0 +1,26 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; + +export const awsS3UploadBytes = createTSVBModel( + 'awsS3UploadBytes', + ['aws.s3_request'], + [ + { + id: 'bytes', + split_mode: 'everything', + metrics: [ + { + field: 'aws.s3_request.uploaded.bytes', + id: 'max-bytes', + type: 'max', + }, + ], + }, + ], + '>=300s' +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/toolbar_items.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/toolbar_items.tsx new file mode 100644 index 000000000000..6764de237118 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_s3/toolbar_items.tsx @@ -0,0 +1,28 @@ +/* + * 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 React from 'react'; +import { ToolbarProps } from '../../../public/components/inventory/toolbars/toolbar'; +import { InfraSnapshotMetricType } from '../../../public/graphql/types'; +import { MetricsAndGroupByToolbarItems } from '../shared/compontents/metrics_and_groupby_toolbar_items'; + +export const AwsS3ToolbarItems = (props: ToolbarProps) => { + const metricTypes = [ + InfraSnapshotMetricType.s3BucketSize, + InfraSnapshotMetricType.s3NumberOfObjects, + InfraSnapshotMetricType.s3TotalRequests, + InfraSnapshotMetricType.s3DownloadBytes, + InfraSnapshotMetricType.s3UploadBytes, + ]; + const groupByFields = ['cloud.region']; + return ( + + ); +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/index.ts new file mode 100644 index 000000000000..d7fb7c7a615b --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/index.ts @@ -0,0 +1,35 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { metrics } from './metrics'; +import { InventoryModel } from '../types'; + +export const awsSQS: InventoryModel = { + id: 'awsSQS', + displayName: i18n.translate('xpack.infra.inventoryModels.awsSQS.displayName', { + defaultMessage: 'SQS Queues', + }), + requiredModules: ['aws'], + crosslinkSupport: { + details: true, + logs: true, + apm: false, + uptime: false, + }, + metrics, + fields: { + id: 'aws.sqs.queue.name', + name: 'aws.sqs.queue.name', + }, + requiredMetrics: [ + 'awsSQSMessagesVisible', + 'awsSQSMessagesDelayed', + 'awsSQSMessagesSent', + 'awsSQSMessagesEmpty', + 'awsSQSOldestMessage', + ], +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/layout.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/layout.tsx new file mode 100644 index 000000000000..40cb0a64d83c --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/layout.tsx @@ -0,0 +1,143 @@ +/* + * 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 React from 'react'; +import { i18n } from '@kbn/i18n'; +import { LayoutPropsWithTheme } from '../../../public/pages/metrics/types'; +import { Section } from '../../../public/pages/metrics/components/section'; +import { SubSection } from '../../../public/pages/metrics/components/sub_section'; +import { ChartSectionVis } from '../../../public/pages/metrics/components/chart_section_vis'; +import { withTheme } from '../../../../../common/eui_styled_components'; + +export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( + +
+ + + + + + + + + + + + + + + +
+
+)); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/index.ts new file mode 100644 index 000000000000..7bc593cc2203 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/index.ts @@ -0,0 +1,38 @@ +/* + * 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 { InventoryMetrics } from '../../types'; + +import { sqsMessagesVisible } from './snapshot/sqs_messages_visible'; +import { sqsMessagesDelayed } from './snapshot/sqs_messages_delayed'; +import { sqsMessagesEmpty } from './snapshot/sqs_messages_empty'; +import { sqsMessagesSent } from './snapshot/sqs_messages_sent'; +import { sqsOldestMessage } from './snapshot/sqs_oldest_message'; + +import { awsSQSMessagesVisible } from './tsvb/aws_sqs_messages_visible'; +import { awsSQSMessagesDelayed } from './tsvb/aws_sqs_messages_delayed'; +import { awsSQSMessagesSent } from './tsvb/aws_sqs_messages_sent'; +import { awsSQSMessagesEmpty } from './tsvb/aws_sqs_messages_empty'; +import { awsSQSOldestMessage } from './tsvb/aws_sqs_oldest_message'; + +export const metrics: InventoryMetrics = { + tsvb: { + awsSQSMessagesVisible, + awsSQSMessagesDelayed, + awsSQSMessagesSent, + awsSQSMessagesEmpty, + awsSQSOldestMessage, + }, + snapshot: { + sqsMessagesVisible, + sqsMessagesDelayed, + sqsMessagesEmpty, + sqsMessagesSent, + sqsOldestMessage, + }, + defaultSnapshot: 'sqsMessagesVisible', + defaultTimeRangeInSeconds: 14400, // 4 hours +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_delayed.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_delayed.ts new file mode 100644 index 000000000000..679f86671725 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_delayed.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const sqsMessagesDelayed: SnapshotModel = { + sqsMessagesDelayed: { + max: { + field: 'aws.sqs.messages.delayed', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_empty.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_empty.ts new file mode 100644 index 000000000000..d80a3f3451e1 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_empty.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const sqsMessagesEmpty: SnapshotModel = { + sqsMessagesEmpty: { + max: { + field: 'aws.sqs.messages.not_visible', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_sent.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_sent.ts new file mode 100644 index 000000000000..3d6934bf3da8 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_sent.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const sqsMessagesSent: SnapshotModel = { + sqsMessagesSent: { + max: { + field: 'aws.sqs.messages.sent', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_visible.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_visible.ts new file mode 100644 index 000000000000..1a78c50cd794 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_visible.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const sqsMessagesVisible: SnapshotModel = { + sqsMessagesVisible: { + avg: { + field: 'aws.sqs.messages.visible', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_oldest_message.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_oldest_message.ts new file mode 100644 index 000000000000..ae780069c8ca --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_oldest_message.ts @@ -0,0 +1,15 @@ +/* + * 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 { SnapshotModel } from '../../../types'; + +export const sqsOldestMessage: SnapshotModel = { + sqsOldestMessage: { + max: { + field: 'aws.sqs.oldest_message_age.sec', + }, + }, +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_delayed.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_delayed.ts new file mode 100644 index 000000000000..469b9ddd3395 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_delayed.ts @@ -0,0 +1,26 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; + +export const awsSQSMessagesDelayed = createTSVBModel( + 'awsSQSMessagesDelayed', + ['aws.sqs'], + [ + { + id: 'delayed', + split_mode: 'everything', + metrics: [ + { + field: 'aws.sqs.messages.delayed', + id: 'avg-delayed', + type: 'avg', + }, + ], + }, + ], + '>=300s' +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_empty.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_empty.ts new file mode 100644 index 000000000000..54c9e503a8c8 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_empty.ts @@ -0,0 +1,26 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; + +export const awsSQSMessagesEmpty = createTSVBModel( + 'awsSQSMessagesEmpty', + ['aws.sqs'], + [ + { + id: 'empty', + split_mode: 'everything', + metrics: [ + { + field: 'aws.sqs.messages.not_visible', + id: 'avg-empty', + type: 'avg', + }, + ], + }, + ], + '>=300s' +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_sent.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_sent.ts new file mode 100644 index 000000000000..98389ef22fbe --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_sent.ts @@ -0,0 +1,26 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; + +export const awsSQSMessagesSent = createTSVBModel( + 'awsSQSMessagesSent', + ['aws.sqs'], + [ + { + id: 'sent', + split_mode: 'everything', + metrics: [ + { + field: 'aws.sqs.messages.sent', + id: 'avg-sent', + type: 'avg', + }, + ], + }, + ], + '>=300s' +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_visible.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_visible.ts new file mode 100644 index 000000000000..c96ab07e4ae7 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_visible.ts @@ -0,0 +1,26 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; + +export const awsSQSMessagesVisible = createTSVBModel( + 'awsSQSMessagesVisible', + ['aws.sqs'], + [ + { + id: 'visible', + split_mode: 'everything', + metrics: [ + { + field: 'aws.sqs.messages.visible', + id: 'avg-visible', + type: 'avg', + }, + ], + }, + ], + '>=300s' +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_oldest_message.ts b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_oldest_message.ts new file mode 100644 index 000000000000..812906386fb6 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_oldest_message.ts @@ -0,0 +1,26 @@ +/* + * 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 { createTSVBModel } from '../../../create_tsvb_model'; + +export const awsSQSOldestMessage = createTSVBModel( + 'awsSQSOldestMessage', + ['aws.sqs'], + [ + { + id: 'oldest', + split_mode: 'everything', + metrics: [ + { + field: 'aws.sqs.oldest_message_age.sec', + id: 'max-oldest', + type: 'max', + }, + ], + }, + ], + '>=300s' +); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/toolbar_items.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/toolbar_items.tsx new file mode 100644 index 000000000000..89d372d6ac21 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/aws_sqs/toolbar_items.tsx @@ -0,0 +1,28 @@ +/* + * 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 React from 'react'; +import { ToolbarProps } from '../../../public/components/inventory/toolbars/toolbar'; +import { MetricsAndGroupByToolbarItems } from '../shared/compontents/metrics_and_groupby_toolbar_items'; +import { InfraSnapshotMetricType } from '../../graphql/types'; + +export const AwsSQSToolbarItems = (props: ToolbarProps) => { + const metricTypes = [ + InfraSnapshotMetricType.sqsMessagesVisible, + InfraSnapshotMetricType.sqsMessagesDelayed, + InfraSnapshotMetricType.sqsMessagesSent, + InfraSnapshotMetricType.sqsMessagesEmpty, + InfraSnapshotMetricType.sqsOldestMessage, + ]; + const groupByFields = ['cloud.region']; + return ( + + ); +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts index 54fe938528d1..af7b6058ff17 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts @@ -4,12 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ +import { i18n } from '@kbn/i18n'; import { metrics } from './metrics'; import { InventoryModel } from '../types'; export const container: InventoryModel = { id: 'container', + displayName: i18n.translate('xpack.infra.inventoryModel.container.displayName', { + defaultMessage: 'Docker Containers', + }), requiredModules: ['docker'], + crosslinkSupport: { + details: true, + logs: true, + apm: true, + uptime: true, + }, + fields: { + id: 'container.id', + name: 'container.name', + ip: 'continaer.ip_address', + }, metrics, requiredMetrics: [ 'containerOverview', diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/container/metrics/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/container/metrics/index.ts index 9e0153c5d6ea..73a10cbadb66 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/container/metrics/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/container/metrics/index.ts @@ -30,4 +30,5 @@ export const metrics: InventoryMetrics = { }, snapshot: { cpu, memory, rx, tx }, defaultSnapshot: 'cpu', + defaultTimeRangeInSeconds: 3600, // 1 hour }; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/container/toolbar_items.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/container/toolbar_items.tsx index ddb3c0491f16..9ed2cbe6dea0 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/container/toolbar_items.tsx +++ b/x-pack/legacy/plugins/infra/common/inventory_models/container/toolbar_items.tsx @@ -4,61 +4,31 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useMemo } from 'react'; -import { EuiFlexItem } from '@elastic/eui'; +import React from 'react'; import { ToolbarProps } from '../../../public/components/inventory/toolbars/toolbar'; -import { WaffleMetricControls } from '../../../public/components/waffle/waffle_metric_controls'; -import { WaffleGroupByControls } from '../../../public/components/waffle/waffle_group_by_controls'; -import { InfraSnapshotMetricType } from '../../../public/graphql/types'; -import { - toMetricOpt, - toGroupByOpt, -} from '../../../public/components/inventory/toolbars/toolbar_wrapper'; +import { MetricsAndGroupByToolbarItems } from '../shared/compontents/metrics_and_groupby_toolbar_items'; +import { InfraSnapshotMetricType } from '../../graphql/types'; export const ContainerToolbarItems = (props: ToolbarProps) => { - const options = useMemo( - () => - [ - InfraSnapshotMetricType.cpu, - InfraSnapshotMetricType.memory, - InfraSnapshotMetricType.rx, - InfraSnapshotMetricType.tx, - ].map(toMetricOpt), - [] - ); - - const groupByOptions = useMemo( - () => - [ - 'host.name', - 'cloud.availability_zone', - 'cloud.machine.type', - 'cloud.project.id', - 'cloud.provider', - 'service.type', - ].map(toGroupByOpt), - [] - ); + const metricTypes = [ + InfraSnapshotMetricType.cpu, + InfraSnapshotMetricType.memory, + InfraSnapshotMetricType.rx, + InfraSnapshotMetricType.tx, + ]; + const groupByFields = [ + 'host.name', + 'cloud.availability_zone', + 'cloud.machine.type', + 'cloud.project.id', + 'cloud.provider', + 'service.type', + ]; return ( - <> - - - - - - - + ); }; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/create_tsvb_model.ts b/x-pack/legacy/plugins/infra/common/inventory_models/create_tsvb_model.ts new file mode 100644 index 000000000000..7036b2236881 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/create_tsvb_model.ts @@ -0,0 +1,24 @@ +/* + * 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 { TSVBMetricModelCreator, TSVBMetricModel, TSVBSeries, InventoryMetric } from './types'; + +export const createTSVBModel = ( + id: InventoryMetric, + requires: string[], + series: TSVBSeries[], + interval = '>=300s', + dropLastBucket = true +): TSVBMetricModelCreator => (timeField, indexPattern): TSVBMetricModel => ({ + id, + requires, + drop_last_bucket: dropLastBucket, + index_pattern: indexPattern, + interval, + time_field: timeField, + type: 'timeseries', + series, +}); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts index 08056e650a32..54d3267eef57 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { i18n } from '@kbn/i18n'; import { metrics } from './metrics'; import { InventoryModel } from '../types'; import { @@ -13,7 +14,21 @@ import { export const host: InventoryModel = { id: 'host', + displayName: i18n.translate('xpack.infra.inventoryModel.host.displayName', { + defaultMessage: 'Hosts', + }), requiredModules: ['system'], + crosslinkSupport: { + details: true, + logs: true, + apm: true, + uptime: true, + }, + fields: { + id: 'host.name', + name: 'host.name', + ip: 'host.ip', + }, metrics, requiredMetrics: [ 'hostSystemOverview', diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/host/metrics/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/host/metrics/index.ts index f4c0150309dd..7f77f23e4fb9 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/host/metrics/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/host/metrics/index.ts @@ -52,4 +52,5 @@ export const metrics: InventoryMetrics = { }, snapshot: { count, cpu, load, logRate, memory, rx, tx }, defaultSnapshot: 'cpu', + defaultTimeRangeInSeconds: 3600, // 1 hour }; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/host/toolbar_items.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/host/toolbar_items.tsx index 8e1bb0dfb481..f8df81a33a8e 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/host/toolbar_items.tsx +++ b/x-pack/legacy/plugins/infra/common/inventory_models/host/toolbar_items.tsx @@ -4,63 +4,32 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useMemo } from 'react'; -import { EuiFlexItem } from '@elastic/eui'; +import React from 'react'; import { ToolbarProps } from '../../../public/components/inventory/toolbars/toolbar'; -import { WaffleMetricControls } from '../../../public/components/waffle/waffle_metric_controls'; -import { WaffleGroupByControls } from '../../../public/components/waffle/waffle_group_by_controls'; -import { InfraSnapshotMetricType } from '../../../public/graphql/types'; -import { - toGroupByOpt, - toMetricOpt, -} from '../../../public/components/inventory/toolbars/toolbar_wrapper'; +import { MetricsAndGroupByToolbarItems } from '../shared/compontents/metrics_and_groupby_toolbar_items'; +import { InfraSnapshotMetricType } from '../../graphql/types'; export const HostToolbarItems = (props: ToolbarProps) => { - const metricOptions = useMemo( - () => - [ - InfraSnapshotMetricType.cpu, - InfraSnapshotMetricType.memory, - InfraSnapshotMetricType.load, - InfraSnapshotMetricType.rx, - InfraSnapshotMetricType.tx, - InfraSnapshotMetricType.logRate, - ].map(toMetricOpt), - [] - ); - - const groupByOptions = useMemo( - () => - [ - 'cloud.availability_zone', - 'cloud.machine.type', - 'cloud.project.id', - 'cloud.provider', - 'service.type', - ].map(toGroupByOpt), - [] - ); - + const metricTypes = [ + InfraSnapshotMetricType.cpu, + InfraSnapshotMetricType.memory, + InfraSnapshotMetricType.load, + InfraSnapshotMetricType.rx, + InfraSnapshotMetricType.tx, + InfraSnapshotMetricType.logRate, + ]; + const groupByFields = [ + 'cloud.availability_zone', + 'cloud.machine.type', + 'cloud.project.id', + 'cloud.provider', + 'service.type', + ]; return ( - <> - - - - - - - + ); }; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/index.ts index 79aad7b2ccf6..d9fd8fa465b7 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/index.ts @@ -7,11 +7,15 @@ import { i18n } from '@kbn/i18n'; import { host } from './host'; import { pod } from './pod'; +import { awsEC2 } from './aws_ec2'; +import { awsS3 } from './aws_s3'; +import { awsRDS } from './aws_rds'; +import { awsSQS } from './aws_sqs'; import { container } from './container'; import { InventoryItemType } from './types'; export { metrics } from './metrics'; -const inventoryModels = [host, pod, container]; +export const inventoryModels = [host, pod, container, awsEC2, awsS3, awsRDS, awsSQS]; export const findInventoryModel = (type: InventoryItemType) => { const model = inventoryModels.find(m => m.id === type); @@ -24,3 +28,38 @@ export const findInventoryModel = (type: InventoryItemType) => { } return model; }; + +interface InventoryFields { + message: string[]; + host: string; + pod: string; + container: string; + timestamp: string; + tiebreaker: string; +} + +const LEGACY_TYPES = ['host', 'pod', 'container']; + +const getFieldByType = (type: InventoryItemType, fields: InventoryFields) => { + switch (type) { + case 'pod': + return fields.pod; + case 'host': + return fields.host; + case 'container': + return fields.container; + } +}; + +export const findInventoryFields = (type: InventoryItemType, fields: InventoryFields) => { + const inventoryModel = findInventoryModel(type); + if (LEGACY_TYPES.includes(type)) { + const id = getFieldByType(type, fields) || inventoryModel.fields.id; + return { + ...inventoryModel.fields, + id, + }; + } else { + return inventoryModel.fields; + } +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/layouts.ts b/x-pack/legacy/plugins/infra/common/inventory_models/layouts.ts index 0c593bec1af3..d9008753adf7 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/layouts.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/layouts.ts @@ -17,6 +17,10 @@ import { ReactNode, FunctionComponent } from 'react'; import { Layout as HostLayout } from './host/layout'; import { Layout as PodLayout } from './pod/layout'; import { Layout as ContainerLayout } from './container/layout'; +import { Layout as AwsEC2Layout } from './aws_ec2/layout'; +import { Layout as AwsS3Layout } from './aws_s3/layout'; +import { Layout as AwsRDSLayout } from './aws_rds/layout'; +import { Layout as AwsSQSLayout } from './aws_sqs/layout'; import { InventoryItemType } from './types'; import { LayoutProps } from '../../public/pages/metrics/types'; @@ -28,6 +32,10 @@ const layouts: Layouts = { host: HostLayout, pod: PodLayout, container: ContainerLayout, + awsEC2: AwsEC2Layout, + awsS3: AwsS3Layout, + awsRDS: AwsRDSLayout, + awsSQS: AwsSQSLayout, }; export const findLayout = (type: InventoryItemType) => { diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/metrics.ts b/x-pack/legacy/plugins/infra/common/inventory_models/metrics.ts index 78dc262b29ba..cadc059fc5ae 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/metrics.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/metrics.ts @@ -8,6 +8,10 @@ import { metrics as hostMetrics } from './host/metrics'; import { metrics as sharedMetrics } from './shared/metrics'; import { metrics as podMetrics } from './pod/metrics'; import { metrics as containerMetrics } from './container/metrics'; +import { metrics as awsEC2Metrics } from './aws_ec2/metrics'; +import { metrics as awsS3Metrics } from './aws_s3/metrics'; +import { metrics as awsRDSMetrics } from './aws_rds/metrics'; +import { metrics as awsSQSMetrics } from './aws_sqs/metrics'; export const metrics = { tsvb: { @@ -15,5 +19,9 @@ export const metrics = { ...sharedMetrics.tsvb, ...podMetrics.tsvb, ...containerMetrics.tsvb, + ...awsEC2Metrics.tsvb, + ...awsS3Metrics.tsvb, + ...awsRDSMetrics.tsvb, + ...awsSQSMetrics.tsvb, }, }; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts index 66ace03abac0..3efc5827b4f2 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts @@ -4,13 +4,28 @@ * you may not use this file except in compliance with the Elastic License. */ +import { i18n } from '@kbn/i18n'; import { metrics } from './metrics'; import { InventoryModel } from '../types'; import { nginx as nginxRequiredMetrics } from '../shared/metrics/required_metrics'; export const pod: InventoryModel = { id: 'pod', + displayName: i18n.translate('xpack.infra.inventoryModel.pod.displayName', { + defaultMessage: 'Kubernetes Pods', + }), requiredModules: ['kubernetes'], + crosslinkSupport: { + details: true, + logs: true, + apm: true, + uptime: true, + }, + fields: { + id: 'kubernetes.pod.uid', + name: 'kubernetes.pod.name', + ip: 'kubernetes.pod.ip', + }, metrics, requiredMetrics: [ 'podOverview', diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/pod/metrics/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/pod/metrics/index.ts index 2aa7ac6b496a..b4420b5532cc 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/pod/metrics/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/pod/metrics/index.ts @@ -26,4 +26,5 @@ export const metrics: InventoryMetrics = { }, snapshot: { cpu, memory, rx, tx }, defaultSnapshot: 'cpu', + defaultTimeRangeInSeconds: 3600, // 1 hour }; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/pod/toolbar_items.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/pod/toolbar_items.tsx index cc0676fc60ae..9ef4a889dc58 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/pod/toolbar_items.tsx +++ b/x-pack/legacy/plugins/infra/common/inventory_models/pod/toolbar_items.tsx @@ -4,54 +4,24 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useMemo } from 'react'; -import { EuiFlexItem } from '@elastic/eui'; +import React from 'react'; import { ToolbarProps } from '../../../public/components/inventory/toolbars/toolbar'; -import { WaffleMetricControls } from '../../../public/components/waffle/waffle_metric_controls'; -import { WaffleGroupByControls } from '../../../public/components/waffle/waffle_group_by_controls'; -import { InfraSnapshotMetricType } from '../../../public/graphql/types'; -import { - toGroupByOpt, - toMetricOpt, -} from '../../../public/components/inventory/toolbars/toolbar_wrapper'; +import { MetricsAndGroupByToolbarItems } from '../shared/compontents/metrics_and_groupby_toolbar_items'; +import { InfraSnapshotMetricType } from '../../graphql/types'; export const PodToolbarItems = (props: ToolbarProps) => { - const options = useMemo( - () => - [ - InfraSnapshotMetricType.cpu, - InfraSnapshotMetricType.memory, - InfraSnapshotMetricType.rx, - InfraSnapshotMetricType.tx, - ].map(toMetricOpt), - [] - ); - - const groupByOptions = useMemo( - () => ['kubernetes.namespace', 'kubernetes.node.name', 'service.type'].map(toGroupByOpt), - [] - ); - + const metricTypes = [ + InfraSnapshotMetricType.cpu, + InfraSnapshotMetricType.memory, + InfraSnapshotMetricType.rx, + InfraSnapshotMetricType.tx, + ]; + const groupByFields = ['kubernetes.namespace', 'kubernetes.node.name', 'service.type']; return ( - <> - - - - - - - + ); }; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/shared/compontents/metrics_and_groupby_toolbar_items.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/shared/compontents/metrics_and_groupby_toolbar_items.tsx new file mode 100644 index 000000000000..c46ad5c6df95 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/shared/compontents/metrics_and_groupby_toolbar_items.tsx @@ -0,0 +1,52 @@ +/* + * 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 React, { useMemo } from 'react'; +import { EuiFlexItem } from '@elastic/eui'; +import { ToolbarProps } from '../../../../public/components/inventory/toolbars/toolbar'; +import { WaffleMetricControls } from '../../../../public/components/waffle/waffle_metric_controls'; +import { WaffleGroupByControls } from '../../../../public/components/waffle/waffle_group_by_controls'; +import { InfraSnapshotMetricType } from '../../../../public/graphql/types'; +import { + toGroupByOpt, + toMetricOpt, +} from '../../../../public/components/inventory/toolbars/toolbar_wrapper'; + +interface Props extends ToolbarProps { + metricTypes: InfraSnapshotMetricType[]; + groupByFields: string[]; +} + +export const MetricsAndGroupByToolbarItems = (props: Props) => { + const metricOptions = useMemo(() => props.metricTypes.map(toMetricOpt), [props.metricTypes]); + + const groupByOptions = useMemo(() => props.groupByFields.map(toGroupByOpt), [ + props.groupByFields, + ]); + + return ( + <> + + + + + + + + ); +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/shared/metrics/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/shared/metrics/index.ts index 6416aa08e858..2bab5c5229c5 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/shared/metrics/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/shared/metrics/index.ts @@ -35,4 +35,5 @@ export const metrics: InventoryMetrics = { count, }, defaultSnapshot: 'count', + defaultTimeRangeInSeconds: 3600, }; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/toolbars.ts b/x-pack/legacy/plugins/infra/common/inventory_models/toolbars.ts index dc3c409ac497..05def078c7f2 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/toolbars.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/toolbars.ts @@ -11,6 +11,10 @@ import { HostToolbarItems } from './host/toolbar_items'; import { ContainerToolbarItems } from './container/toolbar_items'; import { PodToolbarItems } from './pod/toolbar_items'; import { ToolbarProps } from '../../public/components/inventory/toolbars/toolbar'; +import { AwsEC2ToolbarItems } from './aws_ec2/toolbar_items'; +import { AwsS3ToolbarItems } from './aws_s3/toolbar_items'; +import { AwsRDSToolbarItems } from './aws_rds/toolbar_items'; +import { AwsSQSToolbarItems } from './aws_sqs/toolbar_items'; interface Toolbars { [type: string]: ReactNode; @@ -20,6 +24,10 @@ const toolbars: Toolbars = { host: HostToolbarItems, container: ContainerToolbarItems, pod: PodToolbarItems, + awsEC2: AwsEC2ToolbarItems, + awsS3: AwsS3ToolbarItems, + awsRDS: AwsRDSToolbarItems, + awsSQS: AwsSQSToolbarItems, }; export const findToolbar = (type: InventoryItemType) => { diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/types.ts b/x-pack/legacy/plugins/infra/common/inventory_models/types.ts index 93eaf214ad23..e1cbdcb52ff2 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/types.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/types.ts @@ -30,6 +30,7 @@ export const InventoryFormatterTypeRT = rt.keyof({ bytes: null, number: null, percent: null, + highPercision: null, }); export type InventoryFormatterType = rt.TypeOf; export type InventoryItemType = rt.TypeOf; @@ -72,6 +73,24 @@ export const InventoryMetricRT = rt.keyof({ awsNetworkPackets: null, awsDiskioBytes: null, awsDiskioOps: null, + awsEC2CpuUtilization: null, + awsEC2NetworkTraffic: null, + awsEC2DiskIOBytes: null, + awsS3TotalRequests: null, + awsS3NumberOfObjects: null, + awsS3BucketSize: null, + awsS3DownloadBytes: null, + awsS3UploadBytes: null, + awsRDSCpuTotal: null, + awsRDSConnections: null, + awsRDSQueriesExecuted: null, + awsRDSActiveTransactions: null, + awsRDSLatency: null, + awsSQSMessagesVisible: null, + awsSQSMessagesDelayed: null, + awsSQSMessagesSent: null, + awsSQSMessagesEmpty: null, + awsSQSOldestMessage: null, custom: null, }); export type InventoryMetric = rt.TypeOf; @@ -162,6 +181,8 @@ export const TSVBSeriesRT = rt.intersection([ }), ]); +export type TSVBSeries = rt.TypeOf; + export const TSVBMetricModelRT = rt.intersection([ rt.type({ id: InventoryMetricRT, @@ -176,6 +197,7 @@ export const TSVBMetricModelRT = rt.intersection([ filter: rt.string, map_field_to: rt.string, id_type: rt.keyof({ cloud: null, node: null }), + drop_last_bucket: rt.boolean, }), ]); @@ -267,6 +289,22 @@ export const SnapshotMetricTypeRT = rt.keyof({ tx: null, rx: null, logRate: null, + diskIOReadBytes: null, + diskIOWriteBytes: null, + s3TotalRequests: null, + s3NumberOfObjects: null, + s3BucketSize: null, + s3DownloadBytes: null, + s3UploadBytes: null, + rdsConnections: null, + rdsQueriesExecuted: null, + rdsActiveTransactions: null, + rdsLatency: null, + sqsMessagesVisible: null, + sqsMessagesDelayed: null, + sqsMessagesSent: null, + sqsMessagesEmpty: null, + sqsOldestMessage: null, }); export type SnapshotMetricType = rt.TypeOf; @@ -275,11 +313,25 @@ export interface InventoryMetrics { tsvb: { [name: string]: TSVBMetricModelCreator }; snapshot: { [name: string]: SnapshotModel }; defaultSnapshot: SnapshotMetricType; + /** This is used by the inventory view to calculate the appropriate amount of time for the metrics detail page. Some metris like awsS3 require multiple days where others like host only need an hour.*/ + defaultTimeRangeInSeconds: number; } export interface InventoryModel { id: string; + displayName: string; requiredModules: string[]; + fields: { + id: string; + name: string; + ip?: string; + }; + crosslinkSupport: { + details: boolean; + logs: boolean; + apm: boolean; + uptime: boolean; + }; metrics: InventoryMetrics; requiredMetrics: InventoryMetric[]; } diff --git a/x-pack/legacy/plugins/infra/public/components/inventory/layout.tsx b/x-pack/legacy/plugins/infra/public/components/inventory/layout.tsx index 47858624fde0..cb48c99963d1 100644 --- a/x-pack/legacy/plugins/infra/public/components/inventory/layout.tsx +++ b/x-pack/legacy/plugins/infra/public/components/inventory/layout.tsx @@ -8,7 +8,6 @@ import React from 'react'; import { InfraWaffleMapOptions, InfraWaffleMapBounds } from '../../lib/lib'; import { InfraNodeType, - InfraTimerangeInput, InfraSnapshotMetricInput, InfraSnapshotGroupbyInput, } from '../../graphql/types'; @@ -23,7 +22,7 @@ export interface LayoutProps { options: InfraWaffleMapOptions; nodeType: InfraNodeType; onDrilldown: (filter: KueryFilterQuery) => void; - timeRange: InfraTimerangeInput; + currentTime: number; onViewChange: (view: string) => void; view: string; boundsOverride: InfraWaffleMapBounds; @@ -42,7 +41,7 @@ export const Layout = (props: LayoutProps) => { props.groupBy, props.nodeType, props.sourceId, - props.timeRange + props.currentTime ); return ( <> @@ -55,7 +54,7 @@ export const Layout = (props: LayoutProps) => { loading={loading} reload={reload} onDrilldown={props.onDrilldown} - timeRange={props.timeRange} + currentTime={props.currentTime} onViewChange={props.onViewChange} view={props.view} autoBounds={props.autoBounds} diff --git a/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/toolbar_wrapper.tsx b/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/toolbar_wrapper.tsx index 7cb86f6e4d0e..c4721fee4b74 100644 --- a/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/toolbar_wrapper.tsx +++ b/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/toolbar_wrapper.tsx @@ -81,6 +81,54 @@ const ToolbarTranslations = { Count: i18n.translate('xpack.infra.waffle.metricOptions.countText', { defaultMessage: 'Count', }), + DiskIOReadBytes: i18n.translate('xpack.infra.waffle.metricOptions.diskIOReadBytes', { + defaultMessage: 'Disk Reads', + }), + DiskIOWriteBytes: i18n.translate('xpack.infra.waffle.metricOptions.diskIOWriteBytes', { + defaultMessage: 'Disk Writes', + }), + s3BucketSize: i18n.translate('xpack.infra.waffle.metricOptions.s3BucketSize', { + defaultMessage: 'Bucket Size', + }), + s3TotalRequests: i18n.translate('xpack.infra.waffle.metricOptions.s3TotalRequests', { + defaultMessage: 'Total Requests', + }), + s3NumberOfObjects: i18n.translate('xpack.infra.waffle.metricOptions.s3NumberOfObjects', { + defaultMessage: 'Number of Objects', + }), + s3DownloadBytes: i18n.translate('xpack.infra.waffle.metricOptions.s3DownloadBytes', { + defaultMessage: 'Downloads (Bytes)', + }), + s3UploadBytes: i18n.translate('xpack.infra.waffle.metricOptions.s3UploadBytes', { + defaultMessage: 'Uploads (Bytes)', + }), + rdsConnections: i18n.translate('xpack.infra.waffle.metricOptions.rdsConnections', { + defaultMessage: 'Connections', + }), + rdsQueriesExecuted: i18n.translate('xpack.infra.waffle.metricOptions.rdsQueriesExecuted', { + defaultMessage: 'Queries Executed', + }), + rdsActiveTransactions: i18n.translate('xpack.infra.waffle.metricOptions.rdsActiveTransactions', { + defaultMessage: 'Active Transactions', + }), + rdsLatency: i18n.translate('xpack.infra.waffle.metricOptions.rdsLatency', { + defaultMessage: 'Latency', + }), + sqsMessagesVisible: i18n.translate('xpack.infra.waffle.metricOptions.sqsMessagesVisible', { + defaultMessage: 'Messages Available', + }), + sqsMessagesDelayed: i18n.translate('xpack.infra.waffle.metricOptions.sqsMessagesDelayed', { + defaultMessage: 'Messages Delayed', + }), + sqsMessagesSent: i18n.translate('xpack.infra.waffle.metricOptions.sqsMessagesSent', { + defaultMessage: 'Messages Added', + }), + sqsMessagesEmpty: i18n.translate('xpack.infra.waffle.metricOptions.sqsMessagesEmpty', { + defaultMessage: 'Messages Returned Empty', + }), + sqsOldestMessage: i18n.translate('xpack.infra.waffle.metricOptions.sqsOldestMessage', { + defaultMessage: 'Oldest Message', + }), }; export const toGroupByOpt = (field: string) => ({ @@ -126,5 +174,85 @@ export const toMetricOpt = (metric: InfraSnapshotMetricType) => { text: ToolbarTranslations.Count, value: InfraSnapshotMetricType.count, }; + case InfraSnapshotMetricType.diskIOReadBytes: + return { + text: ToolbarTranslations.DiskIOReadBytes, + value: InfraSnapshotMetricType.diskIOReadBytes, + }; + case InfraSnapshotMetricType.diskIOWriteBytes: + return { + text: ToolbarTranslations.DiskIOWriteBytes, + value: InfraSnapshotMetricType.diskIOWriteBytes, + }; + case InfraSnapshotMetricType.s3BucketSize: + return { + text: ToolbarTranslations.s3BucketSize, + value: InfraSnapshotMetricType.s3BucketSize, + }; + case InfraSnapshotMetricType.s3TotalRequests: + return { + text: ToolbarTranslations.s3TotalRequests, + value: InfraSnapshotMetricType.s3TotalRequests, + }; + case InfraSnapshotMetricType.s3NumberOfObjects: + return { + text: ToolbarTranslations.s3NumberOfObjects, + value: InfraSnapshotMetricType.s3NumberOfObjects, + }; + case InfraSnapshotMetricType.s3DownloadBytes: + return { + text: ToolbarTranslations.s3DownloadBytes, + value: InfraSnapshotMetricType.s3DownloadBytes, + }; + case InfraSnapshotMetricType.s3UploadBytes: + return { + text: ToolbarTranslations.s3UploadBytes, + value: InfraSnapshotMetricType.s3UploadBytes, + }; + case InfraSnapshotMetricType.rdsConnections: + return { + text: ToolbarTranslations.rdsConnections, + value: InfraSnapshotMetricType.rdsConnections, + }; + case InfraSnapshotMetricType.rdsQueriesExecuted: + return { + text: ToolbarTranslations.rdsQueriesExecuted, + value: InfraSnapshotMetricType.rdsQueriesExecuted, + }; + case InfraSnapshotMetricType.rdsActiveTransactions: + return { + text: ToolbarTranslations.rdsActiveTransactions, + value: InfraSnapshotMetricType.rdsActiveTransactions, + }; + case InfraSnapshotMetricType.rdsLatency: + return { + text: ToolbarTranslations.rdsLatency, + value: InfraSnapshotMetricType.rdsLatency, + }; + case InfraSnapshotMetricType.sqsMessagesVisible: + return { + text: ToolbarTranslations.sqsMessagesVisible, + value: InfraSnapshotMetricType.sqsMessagesVisible, + }; + case InfraSnapshotMetricType.sqsMessagesDelayed: + return { + text: ToolbarTranslations.sqsMessagesDelayed, + value: InfraSnapshotMetricType.sqsMessagesDelayed, + }; + case InfraSnapshotMetricType.sqsMessagesSent: + return { + text: ToolbarTranslations.sqsMessagesSent, + value: InfraSnapshotMetricType.sqsMessagesSent, + }; + case InfraSnapshotMetricType.sqsMessagesEmpty: + return { + text: ToolbarTranslations.sqsMessagesEmpty, + value: InfraSnapshotMetricType.sqsMessagesEmpty, + }; + case InfraSnapshotMetricType.sqsOldestMessage: + return { + text: ToolbarTranslations.sqsOldestMessage, + value: InfraSnapshotMetricType.sqsOldestMessage, + }; } }; diff --git a/x-pack/legacy/plugins/infra/public/components/nodes_overview/index.tsx b/x-pack/legacy/plugins/infra/public/components/nodes_overview/index.tsx index acddbee8db26..edf1b228b278 100644 --- a/x-pack/legacy/plugins/infra/public/components/nodes_overview/index.tsx +++ b/x-pack/legacy/plugins/infra/public/components/nodes_overview/index.tsx @@ -11,12 +11,7 @@ import { get, max, min } from 'lodash'; import React from 'react'; import euiStyled from '../../../../../common/eui_styled_components'; -import { - InfraSnapshotMetricType, - InfraSnapshotNode, - InfraNodeType, - InfraTimerangeInput, -} from '../../graphql/types'; +import { InfraSnapshotMetricType, InfraSnapshotNode, InfraNodeType } from '../../graphql/types'; import { InfraFormatterType, InfraWaffleMapBounds, InfraWaffleMapOptions } from '../../lib/lib'; import { KueryFilterQuery } from '../../store/local/waffle_filter'; import { createFormatter } from '../../utils/formatters'; @@ -34,7 +29,7 @@ interface Props { loading: boolean; reload: () => void; onDrilldown: (filter: KueryFilterQuery) => void; - timeRange: InfraTimerangeInput; + currentTime: number; onViewChange: (view: string) => void; view: string; boundsOverride: InfraWaffleMapBounds; @@ -67,6 +62,38 @@ const METRIC_FORMATTERS: MetricFormatters = { formatter: InfraFormatterType.abbreviatedNumber, template: '{{value}}/s', }, + [InfraSnapshotMetricType.diskIOReadBytes]: { + formatter: InfraFormatterType.bytes, + template: '{{value}}/s', + }, + [InfraSnapshotMetricType.diskIOWriteBytes]: { + formatter: InfraFormatterType.bytes, + template: '{{value}}/s', + }, + [InfraSnapshotMetricType.s3BucketSize]: { + formatter: InfraFormatterType.bytes, + template: '{{value}}', + }, + [InfraSnapshotMetricType.s3TotalRequests]: { + formatter: InfraFormatterType.abbreviatedNumber, + template: '{{value}}', + }, + [InfraSnapshotMetricType.s3NumberOfObjects]: { + formatter: InfraFormatterType.abbreviatedNumber, + template: '{{value}}', + }, + [InfraSnapshotMetricType.s3UploadBytes]: { + formatter: InfraFormatterType.bytes, + template: '{{value}}', + }, + [InfraSnapshotMetricType.s3DownloadBytes]: { + formatter: InfraFormatterType.bytes, + template: '{{value}}', + }, + [InfraSnapshotMetricType.sqsOldestMessage]: { + formatter: InfraFormatterType.number, + template: '{{value}} seconds', + }, }; const calculateBoundsFromNodes = (nodes: InfraSnapshotNode[]): InfraWaffleMapBounds => { @@ -92,8 +119,8 @@ export const NodesOverview = class extends React.Component { nodeType, reload, view, + currentTime, options, - timeRange, } = this.props; if (loading) { return ( @@ -152,7 +179,7 @@ export const NodesOverview = class extends React.Component { nodes={nodes} options={options} formatter={this.formatter} - timeRange={timeRange} + currentTime={currentTime} onFilter={this.handleDrilldown} /> @@ -163,7 +190,7 @@ export const NodesOverview = class extends React.Component { nodes={nodes} options={options} formatter={this.formatter} - timeRange={timeRange} + currentTime={currentTime} onFilter={this.handleDrilldown} bounds={bounds} dataBounds={dataBounds} diff --git a/x-pack/legacy/plugins/infra/public/components/nodes_overview/table.tsx b/x-pack/legacy/plugins/infra/public/components/nodes_overview/table.tsx index 5b201d2be433..b4abf962bd89 100644 --- a/x-pack/legacy/plugins/infra/public/components/nodes_overview/table.tsx +++ b/x-pack/legacy/plugins/infra/public/components/nodes_overview/table.tsx @@ -10,12 +10,7 @@ import { i18n } from '@kbn/i18n'; import { last } from 'lodash'; import React from 'react'; import { createWaffleMapNode } from '../../containers/waffle/nodes_to_wafflemap'; -import { - InfraSnapshotNode, - InfraSnapshotNodePath, - InfraTimerangeInput, - InfraNodeType, -} from '../../graphql/types'; +import { InfraSnapshotNode, InfraSnapshotNodePath, InfraNodeType } from '../../graphql/types'; import { InfraWaffleMapNode, InfraWaffleMapOptions } from '../../lib/lib'; import { fieldToName } from '../waffle/lib/field_to_display_name'; import { NodeContextMenu } from '../waffle/node_context_menu'; @@ -25,7 +20,7 @@ interface Props { nodeType: InfraNodeType; options: InfraWaffleMapOptions; formatter: (subject: string | number) => string; - timeRange: InfraTimerangeInput; + currentTime: number; onFilter: (filter: string) => void; } @@ -49,7 +44,7 @@ const getGroupPaths = (path: InfraSnapshotNodePath[]) => { export const TableView = class extends React.PureComponent { public readonly state: State = initialState; public render() { - const { nodes, options, formatter, timeRange, nodeType } = this.props; + const { nodes, options, formatter, currentTime, nodeType } = this.props; const columns = [ { field: 'name', @@ -68,7 +63,7 @@ export const TableView = class extends React.PureComponent { node={item.node} nodeType={nodeType} closePopover={this.closePopoverFor(uniqueID)} - timeRange={timeRange} + currentTime={currentTime} isPopoverOpen={this.state.isPopoverOpen.includes(uniqueID)} options={options} popoverPosition="rightCenter" diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/group_of_groups.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/group_of_groups.tsx index 3f456c3c8d40..7a229fbbe02e 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/group_of_groups.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/group_of_groups.tsx @@ -7,7 +7,7 @@ import React from 'react'; import euiStyled from '../../../../../common/eui_styled_components'; -import { InfraNodeType, InfraTimerangeInput } from '../../graphql/types'; +import { InfraNodeType } from '../../graphql/types'; import { InfraWaffleMapBounds, InfraWaffleMapGroupOfGroups, @@ -23,7 +23,7 @@ interface Props { formatter: (val: number) => string; bounds: InfraWaffleMapBounds; nodeType: InfraNodeType; - timeRange: InfraTimerangeInput; + currentTime: number; } export const GroupOfGroups: React.FC = props => { @@ -41,7 +41,7 @@ export const GroupOfGroups: React.FC = props => { formatter={props.formatter} bounds={props.bounds} nodeType={props.nodeType} - timeRange={props.timeRange} + currentTime={props.currentTime} /> ))} diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/group_of_nodes.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/group_of_nodes.tsx index bc7d31a30149..c40c68cbdbf2 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/group_of_nodes.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/group_of_nodes.tsx @@ -7,7 +7,7 @@ import React from 'react'; import euiStyled from '../../../../../common/eui_styled_components'; -import { InfraNodeType, InfraTimerangeInput } from '../../graphql/types'; +import { InfraNodeType } from '../../graphql/types'; import { InfraWaffleMapBounds, InfraWaffleMapGroupOfNodes, @@ -24,7 +24,7 @@ interface Props { isChild: boolean; bounds: InfraWaffleMapBounds; nodeType: InfraNodeType; - timeRange: InfraTimerangeInput; + currentTime: number; } export const GroupOfNodes: React.FC = ({ @@ -35,7 +35,7 @@ export const GroupOfNodes: React.FC = ({ isChild = false, bounds, nodeType, - timeRange, + currentTime, }) => { const width = group.width > 200 ? group.width : 200; return ( @@ -51,7 +51,7 @@ export const GroupOfNodes: React.FC = ({ formatter={formatter} bounds={bounds} nodeType={nodeType} - timeRange={timeRange} + currentTime={currentTime} /> ))} diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/lib/field_to_display_name.ts b/x-pack/legacy/plugins/infra/public/components/waffle/lib/field_to_display_name.ts index b34b2801a50f..7160c8eaa8dd 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/lib/field_to_display_name.ts +++ b/x-pack/legacy/plugins/infra/public/components/waffle/lib/field_to_display_name.ts @@ -10,6 +10,14 @@ interface Lookup { [id: string]: string; } +const availabilityZoneName = i18n.translate('xpack.infra.groupByDisplayNames.availabilityZone', { + defaultMessage: 'Availability zone', +}); + +const machineTypeName = i18n.translate('xpack.infra.groupByDisplayNames.machineType', { + defaultMessage: 'Machine type', +}); + export const fieldToName = (field: string) => { const LOOKUP: Lookup = { 'kubernetes.namespace': i18n.translate('xpack.infra.groupByDisplayNames.kubernetesNamespace', { @@ -21,12 +29,8 @@ export const fieldToName = (field: string) => { 'host.name': i18n.translate('xpack.infra.groupByDisplayNames.hostName', { defaultMessage: 'Host', }), - 'cloud.availability_zone': i18n.translate('xpack.infra.groupByDisplayNames.availabilityZone', { - defaultMessage: 'Availability zone', - }), - 'cloud.machine.type': i18n.translate('xpack.infra.groupByDisplayNames.machineType', { - defaultMessage: 'Machine type', - }), + 'cloud.availability_zone': availabilityZoneName, + 'cloud.machine.type': machineTypeName, 'cloud.project.id': i18n.translate('xpack.infra.groupByDisplayNames.projectID', { defaultMessage: 'Project ID', }), @@ -36,6 +40,32 @@ export const fieldToName = (field: string) => { 'service.type': i18n.translate('xpack.infra.groupByDisplayNames.serviceType', { defaultMessage: 'Service type', }), + 'aws.cloud.availability_zone': availabilityZoneName, + 'aws.cloud.machine.type': machineTypeName, + 'aws.tags': i18n.translate('xpack.infra.groupByDisplayNames.tags', { + defaultMessage: 'Tags', + }), + 'aws.ec2.instance.image.id': i18n.translate('xpack.infra.groupByDisplayNames.image', { + defaultMessage: 'Image', + }), + 'aws.ec2.instance.state.name': i18n.translate('xpack.infra.groupByDisplayNames.state.name', { + defaultMessage: 'State', + }), + 'cloud.region': i18n.translate('xpack.infra.groupByDisplayNames.cloud.region', { + defaultMessage: 'Region', + }), + 'aws.rds.db_instance.class': i18n.translate( + 'xpack.infra.groupByDisplayNames.rds.db_instance.class', + { + defaultMessage: 'Instance Class', + } + ), + 'aws.rds.db_instance.status': i18n.translate( + 'xpack.infra.groupByDisplayNames.rds.db_instance.status', + { + defaultMessage: 'Status', + } + ), }; return LOOKUP[field] || field; }; diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/map.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/map.tsx index ed7db4fe3dfe..6c0209a60f1c 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/map.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/map.tsx @@ -11,7 +11,7 @@ import { isWaffleMapGroupWithGroups, isWaffleMapGroupWithNodes, } from '../../containers/waffle/type_guards'; -import { InfraSnapshotNode, InfraNodeType, InfraTimerangeInput } from '../../graphql/types'; +import { InfraSnapshotNode, InfraNodeType } from '../../graphql/types'; import { InfraWaffleMapBounds, InfraWaffleMapOptions } from '../../lib/lib'; import { AutoSizer } from '../auto_sizer'; import { GroupOfGroups } from './group_of_groups'; @@ -24,7 +24,7 @@ interface Props { nodeType: InfraNodeType; options: InfraWaffleMapOptions; formatter: (subject: string | number) => string; - timeRange: InfraTimerangeInput; + currentTime: number; onFilter: (filter: string) => void; bounds: InfraWaffleMapBounds; dataBounds: InfraWaffleMapBounds; @@ -33,7 +33,7 @@ interface Props { export const Map: React.FC = ({ nodes, options, - timeRange, + currentTime, onFilter, formatter, bounds, @@ -59,7 +59,7 @@ export const Map: React.FC = ({ formatter={formatter} bounds={bounds} nodeType={nodeType} - timeRange={timeRange} + currentTime={currentTime} /> ); } @@ -74,7 +74,7 @@ export const Map: React.FC = ({ isChild={false} bounds={bounds} nodeType={nodeType} - timeRange={timeRange} + currentTime={currentTime} /> ); } diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/node.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/node.tsx index 8f09a3fdca9c..f0770064c3cf 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/node.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/node.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import moment from 'moment'; import { darken, readableColor } from 'polished'; import React from 'react'; @@ -12,7 +11,7 @@ import { i18n } from '@kbn/i18n'; import { ConditionalToolTip } from './conditional_tooltip'; import euiStyled from '../../../../../common/eui_styled_components'; -import { InfraTimerangeInput, InfraNodeType } from '../../graphql/types'; +import { InfraNodeType } from '../../graphql/types'; import { InfraWaffleMapBounds, InfraWaffleMapNode, InfraWaffleMapOptions } from '../../lib/lib'; import { colorFromValue } from './lib/color_from_value'; import { NodeContextMenu } from './node_context_menu'; @@ -30,13 +29,13 @@ interface Props { formatter: (val: number) => string; bounds: InfraWaffleMapBounds; nodeType: InfraNodeType; - timeRange: InfraTimerangeInput; + currentTime: number; } export const Node = class extends React.PureComponent { public readonly state: State = initialState; public render() { - const { nodeType, node, options, squareSize, bounds, formatter, timeRange } = this.props; + const { nodeType, node, options, squareSize, bounds, formatter, currentTime } = this.props; const { isPopoverOpen } = this.state; const { metric } = node; const valueMode = squareSize > 70; @@ -44,12 +43,6 @@ export const Node = class extends React.PureComponent { const rawValue = (metric && metric.value) || 0; const color = colorFromValue(options.legend, rawValue, bounds); const value = formatter(rawValue); - const newTimerange = { - ...timeRange, - from: moment(timeRange.to) - .subtract(1, 'hour') - .valueOf(), - }; const nodeAriaLabel = i18n.translate('xpack.infra.node.ariaLabel', { defaultMessage: '{nodeName}, click to open menu', values: { nodeName: node.name }, @@ -61,7 +54,7 @@ export const Node = class extends React.PureComponent { isPopoverOpen={isPopoverOpen} closePopover={this.closePopover} options={options} - timeRange={newTimerange} + currentTime={currentTime} popoverPosition="downCenter" > { + const inventoryModel = findInventoryModel(nodeType); // Due to the changing nature of the fields between APM and this UI, // We need to have some exceptions until 7.0 & ECS is finalized. Reference // #26620 for the details for these fields. // TODO: This is tech debt, remove it after 7.0 & ECS migration. - const APM_FIELDS = { - [InfraNodeType.host]: 'host.hostname', - [InfraNodeType.container]: 'container.id', - [InfraNodeType.pod]: 'kubernetes.pod.uid', - }; + const apmField = nodeType === InfraNodeType.host ? 'host.hostname' : inventoryModel.fields.id; const nodeLogsMenuItem = { name: i18n.translate('xpack.infra.nodeContextMenu.viewLogsName', { @@ -62,11 +59,12 @@ export const NodeContextMenu = injectUICapabilities( href: getNodeLogsUrl({ nodeType, nodeId: node.id, - time: timeRange.to, + time: currentTime, }), 'data-test-subj': 'viewLogsContextMenuItem', }; + const nodeDetailFrom = currentTime - inventoryModel.metrics.defaultTimeRangeInSeconds * 1000; const nodeDetailMenuItem = { name: i18n.translate('xpack.infra.nodeContextMenu.viewMetricsName', { defaultMessage: 'View metrics', @@ -74,45 +72,47 @@ export const NodeContextMenu = injectUICapabilities( href: getNodeDetailUrl({ nodeType, nodeId: node.id, - from: timeRange.from, - to: timeRange.to, + from: nodeDetailFrom, + to: currentTime, }), }; const apmTracesMenuItem = { name: i18n.translate('xpack.infra.nodeContextMenu.viewAPMTraces', { - defaultMessage: 'View {nodeType} APM traces', - values: { nodeType }, + defaultMessage: 'View APM traces', }), - href: `../app/apm#/traces?_g=()&kuery=${APM_FIELDS[nodeType]}:"${node.id}"`, + href: `../app/apm#/traces?_g=()&kuery=${apmField}:"${node.id}"`, 'data-test-subj': 'viewApmTracesContextMenuItem', }; const uptimeMenuItem = { name: i18n.translate('xpack.infra.nodeContextMenu.viewUptimeLink', { - defaultMessage: 'View {nodeType} in Uptime', - values: { nodeType }, + defaultMessage: 'View in Uptime', }), href: createUptimeLink(options, nodeType, node), }; - const showLogsLink = node.id && uiCapabilities.logs.show; - const showAPMTraceLink = uiCapabilities.apm && uiCapabilities.apm.show; + const showDetail = inventoryModel.crosslinkSupport.details; + const showLogsLink = + inventoryModel.crosslinkSupport.logs && node.id && uiCapabilities.logs.show; + const showAPMTraceLink = + inventoryModel.crosslinkSupport.apm && uiCapabilities.apm && uiCapabilities.apm.show; const showUptimeLink = - [InfraNodeType.pod, InfraNodeType.container].includes(nodeType) || node.ip; + inventoryModel.crosslinkSupport.uptime && + ([InfraNodeType.pod, InfraNodeType.container].includes(nodeType) || node.ip); - const panels: EuiContextMenuPanelDescriptor[] = [ - { - id: 0, - title: '', - items: [ - ...(showLogsLink ? [nodeLogsMenuItem] : []), - nodeDetailMenuItem, - ...(showAPMTraceLink ? [apmTracesMenuItem] : []), - ...(showUptimeLink ? [uptimeMenuItem] : []), - ], - }, + const items = [ + ...(showLogsLink ? [nodeLogsMenuItem] : []), + ...(showDetail ? [nodeDetailMenuItem] : []), + ...(showAPMTraceLink ? [apmTracesMenuItem] : []), + ...(showUptimeLink ? [uptimeMenuItem] : []), ]; + const panels: EuiContextMenuPanelDescriptor[] = [{ id: 0, title: '', items }]; + + // If there is nothing to show then we need to return the child as is + if (items.length === 0) { + return <>{children}; + } return ( void; } +const getDisplayNameForType = (type: InventoryItemType) => { + const inventoryModel = findInventoryModel(type); + return inventoryModel.displayName; +}; + export const WaffleInventorySwitcher: React.FC = ({ changeNodeType, changeGroupBy, @@ -48,44 +59,62 @@ export const WaffleInventorySwitcher: React.FC = ( const goToHost = useCallback(() => goToNodeType('host' as InfraNodeType), [goToNodeType]); const goToK8 = useCallback(() => goToNodeType('pod' as InfraNodeType), [goToNodeType]); const goToDocker = useCallback(() => goToNodeType('container' as InfraNodeType), [goToNodeType]); + const goToAwsEC2 = useCallback(() => goToNodeType('awsEC2' as InfraNodeType), [goToNodeType]); + const goToAwsS3 = useCallback(() => goToNodeType('awsS3' as InfraNodeType), [goToNodeType]); + const goToAwsRDS = useCallback(() => goToNodeType('awsRDS' as InfraNodeType), [goToNodeType]); + const goToAwsSQS = useCallback(() => goToNodeType('awsSQS' as InfraNodeType), [goToNodeType]); const panels = useMemo( - () => [ - { - id: 0, - items: [ - { - name: i18n.translate('xpack.infra.waffle.nodeTypeSwitcher.hostsLabel', { - defaultMessage: 'Hosts', - }), - icon: 'host', - onClick: goToHost, - }, - { - name: 'Kubernetes', - icon: 'kubernetes', - onClick: goToK8, - }, - { - name: 'Docker', - icon: 'docker', - onClick: goToDocker, - }, - ], - }, - ], - [goToDocker, goToHost, goToK8] + () => + [ + { + id: 'firstPanel', + items: [ + { + name: getDisplayNameForType('host'), + onClick: goToHost, + }, + { + name: getDisplayNameForType('pod'), + onClick: goToK8, + }, + { + name: getDisplayNameForType('container'), + onClick: goToDocker, + }, + { + name: 'AWS', + panel: 'awsPanel', + }, + ], + }, + { + id: 'awsPanel', + title: 'AWS', + items: [ + { + name: getDisplayNameForType('awsEC2'), + onClick: goToAwsEC2, + }, + { + name: getDisplayNameForType('awsS3'), + onClick: goToAwsS3, + }, + { + name: getDisplayNameForType('awsRDS'), + onClick: goToAwsRDS, + }, + { + name: getDisplayNameForType('awsSQS'), + onClick: goToAwsSQS, + }, + ], + }, + ] as EuiContextMenuPanelDescriptor[], + [goToAwsEC2, goToAwsRDS, goToAwsS3, goToAwsSQS, goToDocker, goToHost, goToK8] ); + const selectedText = useMemo(() => { - switch (nodeType) { - case InfraNodeType.host: - return i18n.translate('xpack.infra.waffle.nodeTypeSwitcher.hostsLabel', { - defaultMessage: 'Hosts', - }); - case InfraNodeType.pod: - return 'Kubernetes'; - case InfraNodeType.container: - return 'Docker'; - } + return getDisplayNameForType(nodeType); }, [nodeType]); return ( @@ -107,7 +136,7 @@ export const WaffleInventorySwitcher: React.FC = ( withTitle anchorPosition="downLeft" > - + ); diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/waffle_metric_controls.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/waffle_metric_controls.tsx index b0ea6f13f2bb..d5ae6fcf7f7a 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/waffle_metric_controls.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/waffle_metric_controls.tsx @@ -44,7 +44,7 @@ export const WaffleMetricControls = class extends React.PureComponent o.value === metric.type); if (!currentLabel) { - return 'null'; + return null; } const panels: EuiContextMenuPanelDescriptor[] = [ { diff --git a/x-pack/legacy/plugins/infra/public/containers/waffle/use_snaphot.ts b/x-pack/legacy/plugins/infra/public/containers/waffle/use_snaphot.ts index 4c8d41afd36b..63b91bd97776 100644 --- a/x-pack/legacy/plugins/infra/public/containers/waffle/use_snaphot.ts +++ b/x-pack/legacy/plugins/infra/public/containers/waffle/use_snaphot.ts @@ -12,7 +12,6 @@ import { InfraNodeType, InfraSnapshotMetricInput, InfraSnapshotGroupbyInput, - InfraTimerangeInput, } from '../../graphql/types'; import { throwErrors, createPlainError } from '../../../common/runtime_types'; import { useHTTPRequest } from '../../hooks/use_http_request'; @@ -27,7 +26,7 @@ export function useSnapshot( groupBy: InfraSnapshotGroupbyInput[], nodeType: InfraNodeType, sourceId: string, - timerange: InfraTimerangeInput + currentTime: number ) { const decodeResponse = (response: any) => { return pipe( @@ -36,6 +35,12 @@ export function useSnapshot( ); }; + const timerange = { + interval: '1m', + to: currentTime, + from: currentTime - 360 * 1000, + }; + const { error, loading, response, makeRequest } = useHTTPRequest( '/api/metrics/snapshot', 'POST', diff --git a/x-pack/legacy/plugins/infra/public/graphql/introspection.json b/x-pack/legacy/plugins/infra/public/graphql/introspection.json index 64792d606f44..ae8d3dcdd5be 100644 --- a/x-pack/legacy/plugins/infra/public/graphql/introspection.json +++ b/x-pack/legacy/plugins/infra/public/graphql/introspection.json @@ -2129,7 +2129,8 @@ "isDeprecated": false, "deprecationReason": null }, - { "name": "host", "description": "", "isDeprecated": false, "deprecationReason": null } + { "name": "host", "description": "", "isDeprecated": false, "deprecationReason": null }, + { "name": "awsEC2", "description": "", "isDeprecated": false, "deprecationReason": null } ], "possibleTypes": null }, @@ -2191,7 +2192,9 @@ { "name": "memory", "description": "", "isDeprecated": false, "deprecationReason": null }, { "name": "tx", "description": "", "isDeprecated": false, "deprecationReason": null }, { "name": "rx", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "logRate", "description": "", "isDeprecated": false, "deprecationReason": null } + { "name": "logRate", "description": "", "isDeprecated": false, "deprecationReason": null }, + { "name": "diskIOReadBytes", "description": "", "isDeprecated": false, "deprecationReason": null }, + { "name": "diskIOWriteBytes", "description": "", "isDeprecated": false, "deprecationReason": null } ], "possibleTypes": null }, @@ -2585,6 +2588,24 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "awsEC2CpuUtilization", + "description": "", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "awsEC2NetworkTraffic", + "description": "", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "awsEC2DiskIOBytes", + "description": "", + "isDeprecated": false, + "deprecationReason": null + }, { "name": "custom", "description": "", "isDeprecated": false, "deprecationReason": null } ], "possibleTypes": null diff --git a/x-pack/legacy/plugins/infra/public/graphql/types.ts b/x-pack/legacy/plugins/infra/public/graphql/types.ts index 8d0e75523a8e..3715f02bb252 100644 --- a/x-pack/legacy/plugins/infra/public/graphql/types.ts +++ b/x-pack/legacy/plugins/infra/public/graphql/types.ts @@ -554,6 +554,10 @@ export enum InfraNodeType { pod = 'pod', container = 'container', host = 'host', + awsEC2 = 'awsEC2', + awsS3 = 'awsS3', + awsRDS = 'awsRDS', + awsSQS = 'awsSQS', } export enum InfraSnapshotMetricType { @@ -564,6 +568,22 @@ export enum InfraSnapshotMetricType { tx = 'tx', rx = 'rx', logRate = 'logRate', + diskIOReadBytes = 'diskIOReadBytes', + diskIOWriteBytes = 'diskIOWriteBytes', + s3TotalRequests = 's3TotalRequests', + s3NumberOfObjects = 's3NumberOfObjects', + s3BucketSize = 's3BucketSize', + s3DownloadBytes = 's3DownloadBytes', + s3UploadBytes = 's3UploadBytes', + rdsConnections = 'rdsConnections', + rdsQueriesExecuted = 'rdsQueriesExecuted', + rdsActiveTransactions = 'rdsActiveTransactions', + rdsLatency = 'rdsLatency', + sqsMessagesVisible = 'sqsMessagesVisible', + sqsMessagesDelayed = 'sqsMessagesDelayed', + sqsMessagesSent = 'sqsMessagesSent', + sqsMessagesEmpty = 'sqsMessagesEmpty', + sqsOldestMessage = 'sqsOldestMessage', } export enum InfraMetric { @@ -604,6 +624,24 @@ export enum InfraMetric { awsNetworkPackets = 'awsNetworkPackets', awsDiskioBytes = 'awsDiskioBytes', awsDiskioOps = 'awsDiskioOps', + awsEC2CpuUtilization = 'awsEC2CpuUtilization', + awsEC2DiskIOBytes = 'awsEC2DiskIOBytes', + awsEC2NetworkTraffic = 'awsEC2NetworkTraffic', + awsS3TotalRequests = 'awsS3TotalRequests', + awsS3NumberOfObjects = 'awsS3NumberOfObjects', + awsS3BucketSize = 'awsS3BucketSize', + awsS3DownloadBytes = 'awsS3DownloadBytes', + awsS3UploadBytes = 'awsS3UploadBytes', + awsRDSCpuTotal = 'awsRDSCpuTotal', + awsRDSConnections = 'awsRDSConnections', + awsRDSQueriesExecuted = 'awsRDSQueriesExecuted', + awsRDSActiveTransactions = 'awsRDSActiveTransactions', + awsRDSLatency = 'awsRDSLatency', + awsSQSMessagesVisible = 'awsSQSMessagesVisible', + awsSQSMessagesDelayed = 'awsSQSMessagesDelayed', + awsSQSMessagesSent = 'awsSQSMessagesSent', + awsSQSMessagesEmpty = 'awsSQSMessagesEmpty', + awsSQSOldestMessage = 'awsSQSOldestMessage', custom = 'custom', } diff --git a/x-pack/legacy/plugins/infra/public/pages/infrastructure/snapshot/page_content.tsx b/x-pack/legacy/plugins/infra/public/pages/infrastructure/snapshot/page_content.tsx index 04aa0a9188a5..85b551a448d0 100644 --- a/x-pack/legacy/plugins/infra/public/pages/infrastructure/snapshot/page_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/infrastructure/snapshot/page_content.tsx @@ -21,7 +21,7 @@ export const SnapshotPageContent: React.FC = () => ( {({ filterQueryAsJson, applyFilterQuery }) => ( - {({ currentTimeRange, isAutoReloading }) => ( + {({ currentTime }) => ( {({ metric, @@ -33,12 +33,12 @@ export const SnapshotPageContent: React.FC = () => ( boundsOverride, }) => ( ; } +const ITEM_TYPES = inventoryModels.map(m => m.id).join('|'); + export const LinkToPage: React.FC = props => ( ; +const getFieldByNodeType = (nodeType: InfraNodeType, fields: SourceConfigurationFields.Fields) => { + const inventoryFields = findInventoryFields(nodeType, fields); + return inventoryFields.id; +}; + export const RedirectToNodeLogs = ({ match: { params: { nodeId, nodeType, sourceId = 'default' }, @@ -50,7 +56,7 @@ export const RedirectToNodeLogs = ({ return null; } - const nodeFilter = `${configuration.fields[nodeType]}: ${nodeId}`; + const nodeFilter = `${getFieldByNodeType(nodeType, configuration.fields)}: ${nodeId}`; const userFilter = getFilterFromLocation(location); const filter = userFilter ? `(${nodeFilter}) and (${userFilter})` : nodeFilter; diff --git a/x-pack/legacy/plugins/infra/public/utils/formatters/high_precision.ts b/x-pack/legacy/plugins/infra/public/utils/formatters/high_precision.ts new file mode 100644 index 000000000000..391b19d2af91 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/utils/formatters/high_precision.ts @@ -0,0 +1,11 @@ +/* + * 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. + */ + +export const formatHighPercision = (val: number) => { + return Number(val).toLocaleString('en', { + maximumFractionDigits: 5, + }); +}; diff --git a/x-pack/legacy/plugins/infra/public/utils/formatters/index.ts b/x-pack/legacy/plugins/infra/public/utils/formatters/index.ts index efb20e71a9ce..3c60dba74782 100644 --- a/x-pack/legacy/plugins/infra/public/utils/formatters/index.ts +++ b/x-pack/legacy/plugins/infra/public/utils/formatters/index.ts @@ -10,6 +10,7 @@ import { createBytesFormatter } from './bytes'; import { formatNumber } from './number'; import { formatPercent } from './percent'; import { InventoryFormatterType } from '../../../common/inventory_models/types'; +import { formatHighPercision } from './high_precision'; export const FORMATTERS = { number: formatNumber, @@ -21,6 +22,7 @@ export const FORMATTERS = { // bytes in bits formatted string out bits: createBytesFormatter(InfraWaffleMapDataFormat.bitsDecimal), percent: formatPercent, + highPercision: formatHighPercision, }; export const createFormatter = (format: InventoryFormatterType, template: string = '{{value}}') => ( diff --git a/x-pack/legacy/plugins/infra/server/graphql/types.ts b/x-pack/legacy/plugins/infra/server/graphql/types.ts index 8f87979dbde2..88ad5b2f58f2 100644 --- a/x-pack/legacy/plugins/infra/server/graphql/types.ts +++ b/x-pack/legacy/plugins/infra/server/graphql/types.ts @@ -580,6 +580,10 @@ export enum InfraNodeType { pod = 'pod', container = 'container', host = 'host', + awsEC2 = 'awsEC2', + awsS3 = 'awsS3', + awsRDS = 'awsRDS', + awsSQS = 'awsSQS' } export enum InfraSnapshotMetricType { @@ -590,6 +594,22 @@ export enum InfraSnapshotMetricType { tx = 'tx', rx = 'rx', logRate = 'logRate', + diskIOReadBytes = 'diskIOReadBytes', + diskIOWriteBytes = 'diskIOWriteBytes', + s3TotalRequests = 's3TotalRequests', + s3NumberOfObjects = 's3NumberOfObjects', + s3BucketSize = 's3BucketSize', + s3DownloadBytes = 's3DownloadBytes', + s3UploadBytes = 's3UploadBytes', + rdsConnections = 'rdsConnections', + rdsQueriesExecuted = 'rdsQueriesExecuted', + rdsActiveTransactions = 'rdsActiveTransactions', + rdsLatency = 'rdsLatency', + sqsMessagesVisible = 'sqsOldestMessage', + sqsMessagesDelayed = 'sqsMessagesDelayed', + sqsMessagesSent = 'sqsMessagesSent', + sqsMessagesEmpty = 'sqsMessagesEmpty', + sqsOldestMessage = 'sqsOldestMessage', } export enum InfraMetric { @@ -630,6 +650,24 @@ export enum InfraMetric { awsNetworkPackets = 'awsNetworkPackets', awsDiskioBytes = 'awsDiskioBytes', awsDiskioOps = 'awsDiskioOps', + awsEC2CpuUtilization = 'awsEC2CpuUtilization', + awsEC2DiskIOBytes = 'awsEC2DiskIOBytes', + awsEC2NetworkTraffic = 'awsEC2NetworkTraffic', + awsS3TotalRequests = 'awsS3TotalRequests', + awsS3NumberOfObjects = 'awsS3NumberOfObjects', + awsS3BucketSize = 'awsS3BucketSize', + awsS3DownloadBytes = 'awsS3DownloadBytes', + awsS3UploadBytes = 'awsS3UploadBytes', + awsRDSCpuTotal = 'awsRDSCpuTotal', + awsRDSConnections = 'awsRDSConnections', + awsRDSQueriesExecuted = 'awsRDSQueriesExecuted', + awsRDSActiveTransactions = 'awsRDSActiveTransactions', + awsRDSLatency = 'awsRDSLatency', + awsSQSMessagesVisible = 'awsSQSMessagesVisible', + awsSQSMessagesDelayed = 'awsSQSMessagesDelayed', + awsSQSMessagesSent = 'awsSQSMessagesSent', + awsSQSMessagesEmpty = 'awsSQSMessagesEmpty', + awsSQSOldestMessage = 'awsSQSOldestMessage', custom = 'custom', } diff --git a/x-pack/legacy/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts b/x-pack/legacy/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts index db3c516841cd..c4146f5758d8 100644 --- a/x-pack/legacy/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts +++ b/x-pack/legacy/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts @@ -7,11 +7,11 @@ import { i18n } from '@kbn/i18n'; import { flatten, get } from 'lodash'; import { KibanaRequest, RequestHandlerContext } from 'src/core/server'; -import { InfraMetric, InfraMetricData, InfraNodeType } from '../../../graphql/types'; +import { InfraMetric, InfraMetricData } from '../../../graphql/types'; import { KibanaFramework } from '../framework/kibana_framework_adapter'; import { InfraMetricsAdapter, InfraMetricsRequestOptions } from './adapter_types'; import { checkValidNode } from './lib/check_valid_node'; -import { metrics } from '../../../../common/inventory_models'; +import { metrics, findInventoryFields } from '../../../../common/inventory_models'; import { TSVBMetricModelCreator } from '../../../../common/inventory_models/types'; import { calculateMetricInterval } from '../../../utils/calculate_metric_interval'; @@ -27,13 +27,10 @@ export class KibanaMetricsAdapter implements InfraMetricsAdapter { options: InfraMetricsRequestOptions, rawRequest: KibanaRequest // NP_TODO: Temporarily needed until metrics getVisData no longer needs full request ): Promise { - const fields = { - [InfraNodeType.host]: options.sourceConfiguration.fields.host, - [InfraNodeType.container]: options.sourceConfiguration.fields.container, - [InfraNodeType.pod]: options.sourceConfiguration.fields.pod, - }; const indexPattern = `${options.sourceConfiguration.metricAlias},${options.sourceConfiguration.logAlias}`; - const nodeField = fields[options.nodeType]; + const fields = findInventoryFields(options.nodeType, options.sourceConfiguration.fields); + const nodeField = fields.id; + const search = (searchOptions: object) => this.framework.callWithRequest<{}, Aggregation>(requestContext, 'search', searchOptions); diff --git a/x-pack/legacy/plugins/infra/server/lib/constants.ts b/x-pack/legacy/plugins/infra/server/lib/constants.ts index 4f2fa561da0c..0765256c4160 100644 --- a/x-pack/legacy/plugins/infra/server/lib/constants.ts +++ b/x-pack/legacy/plugins/infra/server/lib/constants.ts @@ -4,21 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -import { InfraNodeType } from '../graphql/types'; - -// Used for metadata and snapshots resolvers to find the field that contains -// a displayable name of a node. -// Intentionally not the same as xpack.infra.sources.default.fields.{host,container,pod}. -// TODO: consider moving this to source configuration too. -export const NAME_FIELDS = { - [InfraNodeType.host]: 'host.name', - [InfraNodeType.pod]: 'kubernetes.pod.name', - [InfraNodeType.container]: 'container.name', -}; -export const IP_FIELDS = { - [InfraNodeType.host]: 'host.ip', - [InfraNodeType.pod]: 'kubernetes.pod.ip', - [InfraNodeType.container]: 'container.ip_address', -}; - export const CLOUD_METRICS_MODULES = ['aws']; diff --git a/x-pack/legacy/plugins/infra/server/lib/snapshot/create_timerange_with_interval.ts b/x-pack/legacy/plugins/infra/server/lib/snapshot/create_timerange_with_interval.ts new file mode 100644 index 000000000000..6c27e54a78be --- /dev/null +++ b/x-pack/legacy/plugins/infra/server/lib/snapshot/create_timerange_with_interval.ts @@ -0,0 +1,59 @@ +/* + * 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 { uniq } from 'lodash'; +import { RequestHandlerContext } from 'kibana/server'; +import { InfraSnapshotRequestOptions } from './types'; +import { InfraTimerangeInput } from '../../../public/graphql/types'; +import { getMetricsAggregations } from './query_helpers'; +import { calculateMetricInterval } from '../../utils/calculate_metric_interval'; +import { SnapshotModel, SnapshotModelMetricAggRT } from '../../../common/inventory_models/types'; +import { KibanaFramework } from '../adapters/framework/kibana_framework_adapter'; + +export const createTimeRangeWithInterval = async ( + framework: KibanaFramework, + requestContext: RequestHandlerContext, + options: InfraSnapshotRequestOptions +): Promise => { + const aggregations = getMetricsAggregations(options); + const modules = aggregationsToModules(aggregations); + const interval = + (await calculateMetricInterval( + framework, + requestContext, + { + indexPattern: options.sourceConfiguration.metricAlias, + timestampField: options.sourceConfiguration.fields.timestamp, + timerange: { from: options.timerange.from, to: options.timerange.to }, + }, + modules, + options.nodeType + )) || 60000; + return { + interval: `${interval}s`, + from: options.timerange.to - interval * 5000, // We need at least 5 buckets worth of data + to: options.timerange.to, + }; +}; + +const aggregationsToModules = (aggregations: SnapshotModel): string[] => { + return uniq( + Object.values(aggregations) + .reduce((modules, agg) => { + if (SnapshotModelMetricAggRT.is(agg)) { + return modules.concat(Object.values(agg).map(a => a?.field)); + } + return modules; + }, [] as Array) + .filter(v => v) + .map(field => + field! + .split(/\./) + .slice(0, 2) + .join('.') + ) + ) as string[]; +}; diff --git a/x-pack/legacy/plugins/infra/server/lib/snapshot/query_helpers.ts b/x-pack/legacy/plugins/infra/server/lib/snapshot/query_helpers.ts index 6ebbe8775562..44d32c7b915a 100644 --- a/x-pack/legacy/plugins/infra/server/lib/snapshot/query_helpers.ts +++ b/x-pack/legacy/plugins/infra/server/lib/snapshot/query_helpers.ts @@ -4,11 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { findInventoryModel } from '../../../common/inventory_models/index'; -import { InfraSnapshotRequestOptions } from './snapshot'; -import { NAME_FIELDS } from '../constants'; +import { findInventoryModel, findInventoryFields } from '../../../common/inventory_models/index'; +import { InfraSnapshotRequestOptions } from './types'; import { getIntervalInSeconds } from '../../utils/get_interval_in_seconds'; import { SnapshotModelRT, SnapshotModel } from '../../../common/inventory_models/types'; @@ -21,28 +19,35 @@ interface GroupBySource { }; } +export const getFieldByNodeType = (options: InfraSnapshotRequestOptions) => { + const inventoryFields = findInventoryFields(options.nodeType, options.sourceConfiguration.fields); + return inventoryFields.id; +}; + export const getGroupedNodesSources = (options: InfraSnapshotRequestOptions) => { + const fields = findInventoryFields(options.nodeType, options.sourceConfiguration.fields); const sources: GroupBySource[] = options.groupBy.map(gb => { return { [`${gb.field}`]: { terms: { field: gb.field } } }; }); sources.push({ id: { - terms: { field: options.sourceConfiguration.fields[options.nodeType] }, + terms: { field: fields.id }, }, }); sources.push({ - name: { terms: { field: NAME_FIELDS[options.nodeType], missing_bucket: true } }, + name: { terms: { field: fields.name, missing_bucket: true } }, }); return sources; }; export const getMetricsSources = (options: InfraSnapshotRequestOptions) => { - return [{ id: { terms: { field: options.sourceConfiguration.fields[options.nodeType] } } }]; + const fields = findInventoryFields(options.nodeType, options.sourceConfiguration.fields); + return [{ id: { terms: { field: fields.id } } }]; }; export const getMetricsAggregations = (options: InfraSnapshotRequestOptions): SnapshotModel => { - const model = findInventoryModel(options.nodeType); - const aggregation = get(model, ['metrics', 'snapshot', options.metric.type]); + const inventoryModel = findInventoryModel(options.nodeType); + const aggregation = inventoryModel.metrics.snapshot?.[options.metric.type]; if (!SnapshotModelRT.is(aggregation)) { throw new Error( i18n.translate('xpack.infra.snapshot.missingSnapshotMetricError', { diff --git a/x-pack/legacy/plugins/infra/server/lib/snapshot/response_helpers.ts b/x-pack/legacy/plugins/infra/server/lib/snapshot/response_helpers.ts index 6b18d9489c10..d22f41ff152f 100644 --- a/x-pack/legacy/plugins/infra/server/lib/snapshot/response_helpers.ts +++ b/x-pack/legacy/plugins/infra/server/lib/snapshot/response_helpers.ts @@ -14,8 +14,8 @@ import { InfraNodeType, } from '../../graphql/types'; import { getIntervalInSeconds } from '../../utils/get_interval_in_seconds'; -import { InfraSnapshotRequestOptions } from './snapshot'; -import { IP_FIELDS } from '../constants'; +import { InfraSnapshotRequestOptions } from './types'; +import { findInventoryModel } from '../../../common/inventory_models'; export interface InfraSnapshotNodeMetricsBucket { key: { id: string }; @@ -73,12 +73,13 @@ export const getIPFromBucket = ( nodeType: InfraNodeType, bucket: InfraSnapshotNodeGroupByBucket ): string | null => { - const ip = get( - bucket, - `ip.hits.hits[0]._source.${IP_FIELDS[nodeType]}`, - null - ); - + const inventoryModel = findInventoryModel(nodeType); + if (!inventoryModel.fields.ip) { + return null; + } + const ip = get(bucket, `ip.hits.hits[0]._source.${inventoryModel.fields.ip}`, null) as + | string[] + | null; if (Array.isArray(ip)) { return ip.find(isIPv4) || null; } else if (typeof ip === 'string') { diff --git a/x-pack/legacy/plugins/infra/server/lib/snapshot/snapshot.ts b/x-pack/legacy/plugins/infra/server/lib/snapshot/snapshot.ts index 95769414832c..d1db0ef07b33 100644 --- a/x-pack/legacy/plugins/infra/server/lib/snapshot/snapshot.ts +++ b/x-pack/legacy/plugins/infra/server/lib/snapshot/snapshot.ts @@ -5,14 +5,7 @@ */ import { RequestHandlerContext } from 'src/core/server'; -import { - InfraSnapshotGroupbyInput, - InfraSnapshotMetricInput, - InfraSnapshotNode, - InfraTimerangeInput, - InfraNodeType, - InfraSourceConfiguration, -} from '../../graphql/types'; +import { InfraSnapshotNode } from '../../graphql/types'; import { InfraDatabaseSearchResponse } from '../adapters/framework'; import { KibanaFramework } from '../adapters/framework/kibana_framework_adapter'; import { InfraSources } from '../sources'; @@ -32,18 +25,11 @@ import { InfraSnapshotNodeGroupByBucket, InfraSnapshotNodeMetricsBucket, } from './response_helpers'; -import { IP_FIELDS } from '../constants'; import { getAllCompositeData } from '../../utils/get_all_composite_data'; import { createAfterKeyHandler } from '../../utils/create_afterkey_handler'; - -export interface InfraSnapshotRequestOptions { - nodeType: InfraNodeType; - sourceConfiguration: InfraSourceConfiguration; - timerange: InfraTimerangeInput; - groupBy: InfraSnapshotGroupbyInput[]; - metric: InfraSnapshotMetricInput; - filterQuery: JsonObject | undefined; -} +import { findInventoryModel } from '../../../common/inventory_models'; +import { InfraSnapshotRequestOptions } from './types'; +import { createTimeRangeWithInterval } from './create_timerange_with_interval'; export class InfraSnapshot { constructor(private readonly libs: { sources: InfraSources; framework: KibanaFramework }) {} @@ -56,8 +42,22 @@ export class InfraSnapshot { // in order to page through the results of their respective composite aggregations. // Both chains of requests are supposed to run in parallel, and their results be merged // when they have both been completed. - const groupedNodesPromise = requestGroupedNodes(requestContext, options, this.libs.framework); - const nodeMetricsPromise = requestNodeMetrics(requestContext, options, this.libs.framework); + const timeRangeWithIntervalApplied = await createTimeRangeWithInterval( + this.libs.framework, + requestContext, + options + ); + const optionsWithTimerange = { ...options, timerange: timeRangeWithIntervalApplied }; + const groupedNodesPromise = requestGroupedNodes( + requestContext, + optionsWithTimerange, + this.libs.framework + ); + const nodeMetricsPromise = requestNodeMetrics( + requestContext, + optionsWithTimerange, + this.libs.framework + ); const groupedNodeBuckets = await groupedNodesPromise; const nodeMetricBuckets = await nodeMetricsPromise; @@ -79,6 +79,7 @@ const requestGroupedNodes = async ( options: InfraSnapshotRequestOptions, framework: KibanaFramework ): Promise => { + const inventoryModel = findInventoryModel(options.nodeType); const query = { allowNoIndices: true, index: `${options.sourceConfiguration.logAlias},${options.sourceConfiguration.metricAlias}`, @@ -112,7 +113,7 @@ const requestGroupedNodes = async ( top_hits: { sort: [{ [options.sourceConfiguration.fields.timestamp]: { order: 'desc' } }], _source: { - includes: [IP_FIELDS[options.nodeType]], + includes: inventoryModel.fields.ip ? [inventoryModel.fields.ip] : [], }, size: 1, }, diff --git a/x-pack/legacy/plugins/infra/server/lib/snapshot/types.ts b/x-pack/legacy/plugins/infra/server/lib/snapshot/types.ts new file mode 100644 index 000000000000..778f5045894a --- /dev/null +++ b/x-pack/legacy/plugins/infra/server/lib/snapshot/types.ts @@ -0,0 +1,23 @@ +/* + * 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 { JsonObject } from '../../../common/typed_json'; +import { + InfraNodeType, + InfraSourceConfiguration, + InfraTimerangeInput, + InfraSnapshotGroupbyInput, + InfraSnapshotMetricInput, +} from '../../../public/graphql/types'; + +export interface InfraSnapshotRequestOptions { + nodeType: InfraNodeType; + sourceConfiguration: InfraSourceConfiguration; + timerange: InfraTimerangeInput; + groupBy: InfraSnapshotGroupbyInput[]; + metric: InfraSnapshotMetricInput; + filterQuery: JsonObject | undefined; +} diff --git a/x-pack/legacy/plugins/infra/server/routes/metadata/lib/get_id_field_name.ts b/x-pack/legacy/plugins/infra/server/routes/metadata/lib/get_id_field_name.ts deleted file mode 100644 index 5f6bdd30fa2b..000000000000 --- a/x-pack/legacy/plugins/infra/server/routes/metadata/lib/get_id_field_name.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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 { InfraSourceConfiguration } from '../../../lib/sources'; - -export const getIdFieldName = (sourceConfiguration: InfraSourceConfiguration, nodeType: string) => { - switch (nodeType) { - case 'host': - return sourceConfiguration.fields.host; - case 'container': - return sourceConfiguration.fields.container; - default: - return sourceConfiguration.fields.pod; - } -}; diff --git a/x-pack/legacy/plugins/infra/server/routes/metadata/lib/get_metric_metadata.ts b/x-pack/legacy/plugins/infra/server/routes/metadata/lib/get_metric_metadata.ts index 3bd22062c26a..191339565b81 100644 --- a/x-pack/legacy/plugins/infra/server/routes/metadata/lib/get_metric_metadata.ts +++ b/x-pack/legacy/plugins/infra/server/routes/metadata/lib/get_metric_metadata.ts @@ -12,8 +12,8 @@ import { } from '../../../lib/adapters/framework'; import { KibanaFramework } from '../../../lib/adapters/framework/kibana_framework_adapter'; import { InfraSourceConfiguration } from '../../../lib/sources'; -import { getIdFieldName } from './get_id_field_name'; -import { NAME_FIELDS } from '../../../lib/constants'; +import { findInventoryFields } from '../../../../common/inventory_models'; +import { InventoryItemType } from '../../../../common/inventory_models/types'; export interface InfraMetricsAdapterResponse { id: string; @@ -26,10 +26,9 @@ export const getMetricMetadata = async ( requestContext: RequestHandlerContext, sourceConfiguration: InfraSourceConfiguration, nodeId: string, - nodeType: 'host' | 'pod' | 'container' + nodeType: InventoryItemType ): Promise => { - const idFieldName = getIdFieldName(sourceConfiguration, nodeType); - + const fields = findInventoryFields(nodeType, sourceConfiguration.fields); const metricQuery = { allowNoIndices: true, ignoreUnavailable: true, @@ -40,7 +39,7 @@ export const getMetricMetadata = async ( must_not: [{ match: { 'event.dataset': 'aws.ec2' } }], filter: [ { - match: { [idFieldName]: nodeId }, + match: { [fields.id]: nodeId }, }, ], }, @@ -49,7 +48,7 @@ export const getMetricMetadata = async ( aggs: { nodeName: { terms: { - field: NAME_FIELDS[nodeType], + field: fields.name, size: 1, }, }, diff --git a/x-pack/legacy/plugins/infra/server/routes/metadata/lib/get_node_info.ts b/x-pack/legacy/plugins/infra/server/routes/metadata/lib/get_node_info.ts index 1567b6d1bd1e..4ff0df30abed 100644 --- a/x-pack/legacy/plugins/infra/server/routes/metadata/lib/get_node_info.ts +++ b/x-pack/legacy/plugins/infra/server/routes/metadata/lib/get_node_info.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { first } from 'lodash'; +import { first, set, startsWith } from 'lodash'; import { RequestHandlerContext } from 'src/core/server'; import { KibanaFramework } from '../../../lib/adapters/framework/kibana_framework_adapter'; import { InfraSourceConfiguration } from '../../../lib/sources'; @@ -12,14 +12,15 @@ import { InfraNodeType } from '../../../graphql/types'; import { InfraMetadataInfo } from '../../../../common/http_api/metadata_api'; import { getPodNodeName } from './get_pod_node_name'; import { CLOUD_METRICS_MODULES } from '../../../lib/constants'; -import { getIdFieldName } from './get_id_field_name'; +import { findInventoryFields } from '../../../../common/inventory_models'; +import { InventoryItemType } from '../../../../common/inventory_models/types'; export const getNodeInfo = async ( framework: KibanaFramework, requestContext: RequestHandlerContext, sourceConfiguration: InfraSourceConfiguration, nodeId: string, - nodeType: 'host' | 'pod' | 'container' + nodeType: InventoryItemType ): Promise => { // If the nodeType is a Kubernetes pod then we need to get the node info // from a host record instead of a pod. This is due to the fact that any host @@ -45,6 +46,7 @@ export const getNodeInfo = async ( } return {}; } + const fields = findInventoryFields(nodeType, sourceConfiguration.fields); const params = { allowNoIndices: true, ignoreUnavailable: true, @@ -55,12 +57,18 @@ export const getNodeInfo = async ( _source: ['host.*', 'cloud.*'], query: { bool: { - must_not: CLOUD_METRICS_MODULES.map(module => ({ match: { 'event.module': module } })), - filter: [{ match: { [getIdFieldName(sourceConfiguration, nodeType)]: nodeId } }], + filter: [{ match: { [fields.id]: nodeId } }], }, }, }, }; + if (!CLOUD_METRICS_MODULES.some(m => startsWith(nodeType, m))) { + set( + params, + 'body.query.bool.must_not', + CLOUD_METRICS_MODULES.map(module => ({ match: { 'event.module': module } })) + ); + } const response = await framework.callWithRequest<{ _source: InfraMetadataInfo }, {}>( requestContext, 'search', diff --git a/x-pack/legacy/plugins/infra/server/routes/metadata/lib/get_pod_node_name.ts b/x-pack/legacy/plugins/infra/server/routes/metadata/lib/get_pod_node_name.ts index 47ffc7f83b6b..be6e29a794d0 100644 --- a/x-pack/legacy/plugins/infra/server/routes/metadata/lib/get_pod_node_name.ts +++ b/x-pack/legacy/plugins/infra/server/routes/metadata/lib/get_pod_node_name.ts @@ -8,7 +8,7 @@ import { first, get } from 'lodash'; import { RequestHandlerContext } from 'src/core/server'; import { KibanaFramework } from '../../../lib/adapters/framework/kibana_framework_adapter'; import { InfraSourceConfiguration } from '../../../lib/sources'; -import { getIdFieldName } from './get_id_field_name'; +import { findInventoryFields } from '../../../../common/inventory_models'; export const getPodNodeName = async ( framework: KibanaFramework, @@ -17,6 +17,7 @@ export const getPodNodeName = async ( nodeId: string, nodeType: 'host' | 'pod' | 'container' ): Promise => { + const fields = findInventoryFields(nodeType, sourceConfiguration.fields); const params = { allowNoIndices: true, ignoreUnavailable: true, @@ -28,7 +29,7 @@ export const getPodNodeName = async ( query: { bool: { filter: [ - { match: { [getIdFieldName(sourceConfiguration, nodeType)]: nodeId } }, + { match: { [fields.id]: nodeId } }, { exists: { field: `kubernetes.node.name` } }, ], }, diff --git a/x-pack/legacy/plugins/infra/server/routes/metadata/lib/has_apm_data.ts b/x-pack/legacy/plugins/infra/server/routes/metadata/lib/has_apm_data.ts index ab242804173c..9ca0819d74d4 100644 --- a/x-pack/legacy/plugins/infra/server/routes/metadata/lib/has_apm_data.ts +++ b/x-pack/legacy/plugins/infra/server/routes/metadata/lib/has_apm_data.ts @@ -8,24 +8,25 @@ import { RequestHandlerContext } from 'src/core/server'; import { KibanaFramework } from '../../../lib/adapters/framework/kibana_framework_adapter'; import { InfraSourceConfiguration } from '../../../lib/sources'; -import { getIdFieldName } from './get_id_field_name'; +import { findInventoryFields } from '../../../../common/inventory_models'; +import { InventoryItemType } from '../../../../common/inventory_models/types'; export const hasAPMData = async ( framework: KibanaFramework, requestContext: RequestHandlerContext, sourceConfiguration: InfraSourceConfiguration, nodeId: string, - nodeType: 'host' | 'pod' | 'container' + nodeType: InventoryItemType ) => { const apmIndices = await framework.plugins.apm.getApmIndices( requestContext.core.savedObjects.client ); const apmIndex = apmIndices['apm_oss.transactionIndices'] || 'apm-*'; + const fields = findInventoryFields(nodeType, sourceConfiguration.fields); // There is a bug in APM ECS data where host.name is not set. // This will fixed with: https://github.com/elastic/apm-server/issues/2502 - const nodeFieldName = - nodeType === 'host' ? 'host.hostname' : getIdFieldName(sourceConfiguration, nodeType); + const nodeFieldName = nodeType === 'host' ? 'host.hostname' : fields.id; const params = { allowNoIndices: true, ignoreUnavailable: true, diff --git a/x-pack/legacy/plugins/infra/server/routes/snapshot/index.ts b/x-pack/legacy/plugins/infra/server/routes/snapshot/index.ts index 013a261d2483..ae707bae79b9 100644 --- a/x-pack/legacy/plugins/infra/server/routes/snapshot/index.ts +++ b/x-pack/legacy/plugins/infra/server/routes/snapshot/index.ts @@ -9,12 +9,12 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; import { InfraBackendLibs } from '../../lib/infra_types'; -import { InfraSnapshotRequestOptions } from '../../lib/snapshot'; import { UsageCollector } from '../../usage/usage_collector'; import { parseFilterQuery } from '../../utils/serialized_query'; import { InfraNodeType, InfraSnapshotMetricInput } from '../../../public/graphql/types'; import { SnapshotRequestRT, SnapshotNodeResponseRT } from '../../../common/http_api/snapshot_api'; import { throwErrors } from '../../../common/runtime_types'; +import { InfraSnapshotRequestOptions } from '../../lib/snapshot/types'; const escapeHatch = schema.object({}, { allowUnknowns: true }); diff --git a/x-pack/legacy/plugins/infra/server/utils/calculate_metric_interval.ts b/x-pack/legacy/plugins/infra/server/utils/calculate_metric_interval.ts index 5eb5d424cdd7..6247c0f0298a 100644 --- a/x-pack/legacy/plugins/infra/server/utils/calculate_metric_interval.ts +++ b/x-pack/legacy/plugins/infra/server/utils/calculate_metric_interval.ts @@ -5,6 +5,8 @@ */ import { RequestHandlerContext } from 'src/core/server'; +import { InfraNodeType } from '../graphql/types'; +import { findInventoryModel } from '../../common/inventory_models'; import { KibanaFramework } from '../lib/adapters/framework/kibana_framework_adapter'; interface Options { @@ -24,8 +26,14 @@ export const calculateMetricInterval = async ( framework: KibanaFramework, requestContext: RequestHandlerContext, options: Options, - modules: string[] + modules: string[], + nodeType?: InfraNodeType // TODO: check that this type still makes sense ) => { + let from = options.timerange.from; + if (nodeType) { + const inventoryModel = findInventoryModel(nodeType); + from = options.timerange.to - inventoryModel.metrics.defaultTimeRangeInSeconds * 1000; + } const query = { allowNoIndices: true, index: options.indexPattern, @@ -37,7 +45,7 @@ export const calculateMetricInterval = async ( { range: { [options.timestampField]: { - gte: options.timerange.from, + gte: from, lte: options.timerange.to, format: 'epoch_millis', }, diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 18bfbff786ed..d6e72583e4d2 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -5997,10 +5997,8 @@ "xpack.infra.metricsExplorer.openInTSVB": "ビジュアライザーで開く", "xpack.infra.metricsExplorer.viewNodeDetail": "{name} のメトリックを表示", "xpack.infra.node.ariaLabel": "{nodeName}、クリックしてメニューを開きます", - "xpack.infra.nodeContextMenu.viewAPMTraces": "{nodeType} APM トレースを表示", "xpack.infra.nodeContextMenu.viewLogsName": "ログを表示", "xpack.infra.nodeContextMenu.viewMetricsName": "メトリックを表示", - "xpack.infra.nodeContextMenu.viewUptimeLink": "アップタイムで {nodeType} を表示", "xpack.infra.nodesToWaffleMap.groupsWithGroups.allName": "すべて", "xpack.infra.nodesToWaffleMap.groupsWithNodes.allName": "すべて", "xpack.infra.notFoundPage.noContentFoundErrorTitle": "コンテンツがありません", @@ -6058,7 +6056,6 @@ "xpack.infra.waffle.metricOptions.outboundTrafficText": "送信トラフィック", "xpack.infra.waffle.noDataDescription": "期間またはフィルターを調整してみてください。", "xpack.infra.waffle.noDataTitle": "表示するデータがありません。", - "xpack.infra.waffle.nodeTypeSwitcher.hostsLabel": "すべてのホスト", "xpack.infra.waffle.selectTwoGroupingsTitle": "最大 2 つのグループ分けを選択してください", "xpack.infra.waffle.unableToSelectGroupErrorMessage": "{nodeType} のオプションでグループを選択できません", "xpack.infra.waffle.unableToSelectMetricErrorTitle": "メトリックのオプションまたは値を選択できません", @@ -12727,4 +12724,4 @@ "xpack.licensing.welcomeBanner.licenseIsExpiredDescription.updateYourLicenseLinkText": "ライセンスを更新", "xpack.licensing.welcomeBanner.licenseIsExpiredTitle": "ご使用の {licenseType} ライセンスは期限切れです" } -} \ No newline at end of file +} diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 7f55866c17a1..0f0a45ea1941 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -5999,10 +5999,8 @@ "xpack.infra.metricsExplorer.openInTSVB": "在 Visualize 中打开", "xpack.infra.metricsExplorer.viewNodeDetail": "查看 {name} 的指标", "xpack.infra.node.ariaLabel": "{nodeName},单击打开菜单", - "xpack.infra.nodeContextMenu.viewAPMTraces": "查看 {nodeType} APM 跟踪", "xpack.infra.nodeContextMenu.viewLogsName": "查看日志", "xpack.infra.nodeContextMenu.viewMetricsName": "查看指标", - "xpack.infra.nodeContextMenu.viewUptimeLink": "在 Uptime 中查看 {nodeType}", "xpack.infra.nodesToWaffleMap.groupsWithGroups.allName": "全部", "xpack.infra.nodesToWaffleMap.groupsWithNodes.allName": "全部", "xpack.infra.notFoundPage.noContentFoundErrorTitle": "未找到任何内容", @@ -6060,7 +6058,6 @@ "xpack.infra.waffle.metricOptions.outboundTrafficText": "出站流量", "xpack.infra.waffle.noDataDescription": "尝试调整您的时间或筛选。", "xpack.infra.waffle.noDataTitle": "没有可显示的数据。", - "xpack.infra.waffle.nodeTypeSwitcher.hostsLabel": "主机", "xpack.infra.waffle.selectTwoGroupingsTitle": "选择最多两个分组", "xpack.infra.waffle.unableToSelectGroupErrorMessage": "无法选择 {nodeType} 的分组依据选项", "xpack.infra.waffle.unableToSelectMetricErrorTitle": "无法选择指标选项或指标值。", diff --git a/x-pack/test/api_integration/apis/infra/waffle.ts b/x-pack/test/api_integration/apis/infra/waffle.ts index 41bdb0893299..1f79ad4eee4e 100644 --- a/x-pack/test/api_integration/apis/infra/waffle.ts +++ b/x-pack/test/api_integration/apis/infra/waffle.ts @@ -189,9 +189,9 @@ export default function({ getService }: FtrProviderContext) { expect(firstNode).to.have.property('metric'); expect(firstNode.metric).to.eql({ name: 'cpu', - value: 0.003666666666666667, - avg: 0.00809090909090909, - max: 0.057833333333333334, + value: 0.009285714285714286, + max: 0.009285714285714286, + avg: 0.0015476190476190477, }); } }); @@ -279,9 +279,9 @@ export default function({ getService }: FtrProviderContext) { expect(firstNode).to.have.property('metric'); expect(firstNode.metric).to.eql({ name: 'cpu', - value: 0.003666666666666667, - avg: 0.00809090909090909, - max: 0.057833333333333334, + value: 0.009285714285714286, + max: 0.009285714285714286, + avg: 0.0015476190476190477, }); const secondNode = nodes[1]; expect(secondNode).to.have.property('path'); @@ -291,9 +291,9 @@ export default function({ getService }: FtrProviderContext) { expect(secondNode).to.have.property('metric'); expect(secondNode.metric).to.eql({ name: 'cpu', - value: 0.003666666666666667, - avg: 0.00809090909090909, - max: 0.057833333333333334, + value: 0.009285714285714286, + max: 0.009285714285714286, + avg: 0.0015476190476190477, }); } });