[Metrics UI] Add AWS Metricsets to Inventory Models (#49983)
* Adding initial code for EC2 * Removing obsolute files; Adding EC2; * Removing currentTimerange and replacing it with currentTime; Timerange will now be calcuated on the server * Fixing AWS.s3 with Metrics Explorer * Auto calculating timerange and interval based on metricset.period * Adding S3 metricset * Inital addition of RDS metrics * Adding SQS and fixing a few things * Fixing typescript error * Adding RDS; Adjusting fields for S3; adding new formatter * Return 60 seconds by detault * Fixing types * Removing i18n * Fixing tests * Fixing translations * Fixes from merge * Removing IDX from code not covered by #52354 * fixing tests * Adding controls for crossliking; consolidating display name * remove obsolete import * Adding drop_last_bucket_support to TSVB models * Changing type * Fixing value per type * remvoing obsolete translation * Removing duplicate lines * Removing icons from switcher * Reducing boilerplate in Toolbar Items * Changing file name
This commit is contained in:
parent
31a6b5013d
commit
617c8d589a
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -30,5 +30,9 @@ export const sharedSchema = gql`
|
|||
pod
|
||||
container
|
||||
host
|
||||
awsEC2
|
||||
awsS3
|
||||
awsRDS
|
||||
awsSQS
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -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',
|
||||
}
|
||||
|
||||
|
|
|
@ -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<typeof InfraMetadataMachineRT>;
|
|||
export type InfraMetadataHost = rt.TypeOf<typeof InfraMetadataHostRT>;
|
||||
|
||||
export type InfraMetadataOS = rt.TypeOf<typeof InfraMetadataOSRT>;
|
||||
|
||||
export type InfraMetadataNodeType = rt.TypeOf<typeof InfraMetadataNodeTypeRT>;
|
||||
|
|
|
@ -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'],
|
||||
};
|
|
@ -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) => (
|
||||
<React.Fragment>
|
||||
<Section
|
||||
navLabel="AWS EC2"
|
||||
sectionLabel={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.ec2MetricsLayout.overviewSection.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Aws EC2 Overview',
|
||||
}
|
||||
)}
|
||||
metrics={metrics}
|
||||
>
|
||||
<SubSection
|
||||
id="awsEC2CpuUtilization"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.ec2MetricsLayout.cpuUsageSection.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'CPU Usage',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
stacked={true}
|
||||
type="area"
|
||||
formatter="percent"
|
||||
seriesOverrides={{
|
||||
total: { color: theme.eui.euiColorVis1 },
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
<SubSection
|
||||
id="awsEC2NetworkTraffic"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.ec2MetricsLayout.networkTrafficSection.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Network Traffic',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
formatter="bits"
|
||||
formatterTemplate="{{value}}/s"
|
||||
type="area"
|
||||
seriesOverrides={{
|
||||
rx: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.hostMetricsLayout.networkTrafficSection.networkRxRateSeriesLabel',
|
||||
{
|
||||
defaultMessage: 'in',
|
||||
}
|
||||
),
|
||||
},
|
||||
tx: {
|
||||
color: theme.eui.euiColorVis2,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.hostMetricsLayout.networkTrafficSection.networkTxRateSeriesLabel',
|
||||
{
|
||||
defaultMessage: 'out',
|
||||
}
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
<SubSection
|
||||
id="awsEC2DiskIOBytes"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.ec2MetricsLayout.diskIOBytesSection.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Disk IO (Bytes)',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
formatter="bytes"
|
||||
formatterTemplate="{{value}}/s"
|
||||
type="area"
|
||||
seriesOverrides={{
|
||||
write: {
|
||||
color: theme.eui.euiColorVis2,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.ec2MetricsLayout.diskIOBytesSection.writeLabel',
|
||||
{
|
||||
defaultMessage: 'writes',
|
||||
}
|
||||
),
|
||||
},
|
||||
read: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.ec2MetricsLayout.diskIOBytesSection.readLabel',
|
||||
{
|
||||
defaultMessage: 'reads',
|
||||
}
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
</Section>
|
||||
</React.Fragment>
|
||||
));
|
|
@ -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
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
);
|
|
@ -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',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
);
|
|
@ -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',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
);
|
|
@ -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 (
|
||||
<MetricsAndGroupByToolbarItems
|
||||
{...props}
|
||||
metricTypes={metricTypes}
|
||||
groupByFields={groupByFields}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -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',
|
||||
],
|
||||
};
|
|
@ -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) => (
|
||||
<React.Fragment>
|
||||
<Section
|
||||
navLabel="AWS RDS"
|
||||
sectionLabel={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.rdsMetricsLayout.overviewSection.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Aws RDS Overview',
|
||||
}
|
||||
)}
|
||||
metrics={metrics}
|
||||
>
|
||||
<SubSection
|
||||
id="awsRDSCpuTotal"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.rdsMetricsLayout.cpuTotal.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Total CPU Usage',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
type="area"
|
||||
formatter="percent"
|
||||
seriesOverrides={{
|
||||
cpu: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.rdsMetricsLayout.cpuTotal.chartLabel',
|
||||
{ defaultMessage: 'Total' }
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
<SubSection
|
||||
id="awsRDSConnections"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.rdsMetricsLayout.connections.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Connections',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
type="bar"
|
||||
formatter="number"
|
||||
seriesOverrides={{
|
||||
connections: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.rdsMetricsLayout.connections.chartLabel',
|
||||
{ defaultMessage: 'Connections' }
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
<SubSection
|
||||
id="awsRDSQueriesExecuted"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.rdsMetricsLayout.queriesExecuted.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Queries Executed',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
type="bar"
|
||||
formatter="number"
|
||||
seriesOverrides={{
|
||||
queries: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.rdsMetricsLayout.queriesExecuted.chartLabel',
|
||||
{ defaultMessage: 'Queries' }
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
<SubSection
|
||||
id="awsRDSActiveTransactions"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.rdsMetricsLayout.activeTransactions.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Transactions',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
type="bar"
|
||||
formatter="number"
|
||||
seriesOverrides={{
|
||||
active: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.rdsMetricsLayout.active.chartLabel',
|
||||
{ defaultMessage: 'Active' }
|
||||
),
|
||||
},
|
||||
blocked: {
|
||||
color: theme.eui.euiColorVis2,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.rdsMetricsLayout.blocked.chartLabel',
|
||||
{ defaultMessage: 'Blocked' }
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
<SubSection
|
||||
id="awsRDSLatency"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.rdsMetricsLayout.latency.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Latency',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
type="bar"
|
||||
stacked={true}
|
||||
formatter="highPercision"
|
||||
formatterTemplate={'{{value}} ms'}
|
||||
seriesOverrides={{
|
||||
read: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.rdsMetricsLayout.latency.read.chartLabel',
|
||||
{ defaultMessage: 'Read' }
|
||||
),
|
||||
},
|
||||
write: {
|
||||
color: theme.eui.euiColorVis2,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.rdsMetricsLayout.latency.write.chartLabel',
|
||||
{ defaultMessage: 'Write' }
|
||||
),
|
||||
},
|
||||
insert: {
|
||||
color: theme.eui.euiColorVis0,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.rdsMetricsLayout.latency.insert.chartLabel',
|
||||
{ defaultMessage: 'Insert' }
|
||||
),
|
||||
},
|
||||
update: {
|
||||
color: theme.eui.euiColorVis7,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.rdsMetricsLayout.latency.update.chartLabel',
|
||||
{ defaultMessage: 'Update' }
|
||||
),
|
||||
},
|
||||
commit: {
|
||||
color: theme.eui.euiColorVis3,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.rdsMetricsLayout.latency.commit.chartLabel',
|
||||
{ defaultMessage: 'Commit' }
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
</Section>
|
||||
</React.Fragment>
|
||||
));
|
|
@ -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
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
);
|
|
@ -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',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
);
|
|
@ -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',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
);
|
|
@ -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',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
);
|
|
@ -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',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
);
|
|
@ -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 (
|
||||
<MetricsAndGroupByToolbarItems
|
||||
{...props}
|
||||
metricTypes={metricTypes}
|
||||
groupByFields={groupByFields}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -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',
|
||||
],
|
||||
};
|
|
@ -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) => (
|
||||
<React.Fragment>
|
||||
<Section
|
||||
navLabel="AWS S3"
|
||||
sectionLabel={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.s3MetricsLayout.overviewSection.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Aws S3 Overview',
|
||||
}
|
||||
)}
|
||||
metrics={metrics}
|
||||
>
|
||||
<SubSection
|
||||
id="awsS3BucketSize"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.s3MetricsLayout.bucketSize.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Bucket Size',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
type="bar"
|
||||
formatter="bytes"
|
||||
seriesOverrides={{
|
||||
bytes: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.s3MetricsLayout.bucketSize.chartLabel',
|
||||
{ defaultMessage: 'Total Bytes' }
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
<SubSection
|
||||
id="awsS3NumberOfObjects"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.s3MetricsLayout.numberOfObjects.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Number of Objects',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
type="bar"
|
||||
formatter="abbreviatedNumber"
|
||||
seriesOverrides={{
|
||||
objects: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.s3MetricsLayout.numberOfObjects.chartLabel',
|
||||
{ defaultMessage: 'Objects' }
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
<SubSection
|
||||
id="awsS3TotalRequests"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.s3MetricsLayout.totalRequests.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Total Requests',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
type="bar"
|
||||
formatter="abbreviatedNumber"
|
||||
seriesOverrides={{
|
||||
total: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.s3MetricsLayout.totalRequests.chartLabel',
|
||||
{ defaultMessage: 'Requests' }
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
<SubSection
|
||||
id="awsS3DownloadBytes"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.s3MetricsLayout.downloadBytes.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Downloaded Bytes',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
type="bar"
|
||||
formatter="bytes"
|
||||
seriesOverrides={{
|
||||
bytes: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.s3MetricsLayout.downloadBytes.chartLabel',
|
||||
{ defaultMessage: 'Bytes' }
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
<SubSection
|
||||
id="awsS3UploadBytes"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.s3MetricsLayout.uploadBytes.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Uploaded Bytes',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
type="bar"
|
||||
formatter="bytes"
|
||||
seriesOverrides={{
|
||||
bytes: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.s3MetricsLayout.uploadBytes.chartLabel',
|
||||
{ defaultMessage: 'Bytes' }
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
</Section>
|
||||
</React.Fragment>
|
||||
));
|
|
@ -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
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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
|
||||
);
|
|
@ -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'
|
||||
);
|
|
@ -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
|
||||
);
|
|
@ -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'
|
||||
);
|
|
@ -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'
|
||||
);
|
|
@ -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 (
|
||||
<MetricsAndGroupByToolbarItems
|
||||
{...props}
|
||||
metricTypes={metricTypes}
|
||||
groupByFields={groupByFields}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -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',
|
||||
],
|
||||
};
|
|
@ -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) => (
|
||||
<React.Fragment>
|
||||
<Section
|
||||
navLabel="AWS SQS"
|
||||
sectionLabel={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.sqsMetricsLayout.overviewSection.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Aws SQS Overview',
|
||||
}
|
||||
)}
|
||||
metrics={metrics}
|
||||
>
|
||||
<SubSection
|
||||
id="awsSQSMessagesVisible"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.sqsMetricsLayout.messagesVisible.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Messages Available',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
type="bar"
|
||||
formatter="abbreviatedNumber"
|
||||
seriesOverrides={{
|
||||
visible: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.sqsMetricsLayout.messagesVisible.chartLabel',
|
||||
{ defaultMessage: 'Available' }
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
<SubSection
|
||||
id="awsSQSMessagesDelayed"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.sqsMetricsLayout.messagesDelayed.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Messages Delayed',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
type="bar"
|
||||
formatter="abbreviatedNumber"
|
||||
seriesOverrides={{
|
||||
delayed: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.sqsMetricsLayout.messagesDelayed.chartLabel',
|
||||
{ defaultMessage: 'Delayed' }
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
<SubSection
|
||||
id="awsSQSMessagesSent"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.sqsMetricsLayout.messagesSent.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Messages Added',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
type="bar"
|
||||
formatter="abbreviatedNumber"
|
||||
seriesOverrides={{
|
||||
sent: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.sqsMetricsLayout.messagesSent.chartLabel',
|
||||
{ defaultMessage: 'Added' }
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
<SubSection
|
||||
id="awsSQSMessagesEmpty"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.sqsMetricsLayout.messagesEmpty.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Messages Empty',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
type="bar"
|
||||
formatter="abbreviatedNumber"
|
||||
seriesOverrides={{
|
||||
sent: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.sqsMetricsLayout.messagesEmpty.chartLabel',
|
||||
{ defaultMessage: 'Empty' }
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
<SubSection
|
||||
id="awsSQSOldestMessage"
|
||||
label={i18n.translate(
|
||||
'xpack.infra.metricDetailPage.sqsMetricsLayout.oldestMessage.sectionLabel',
|
||||
{
|
||||
defaultMessage: 'Oldest Message',
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChartSectionVis
|
||||
type="bar"
|
||||
formatter="abbreviatedNumber"
|
||||
seriesOverrides={{
|
||||
oldest: {
|
||||
color: theme.eui.euiColorVis1,
|
||||
name: i18n.translate(
|
||||
'xpack.infra.metricDetailPage.sqsMetricsLayout.oldestMessage.chartLabel',
|
||||
{ defaultMessage: 'Age' }
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</SubSection>
|
||||
</Section>
|
||||
</React.Fragment>
|
||||
));
|
|
@ -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
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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'
|
||||
);
|
|
@ -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'
|
||||
);
|
|
@ -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'
|
||||
);
|
|
@ -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'
|
||||
);
|
|
@ -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'
|
||||
);
|
|
@ -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 (
|
||||
<MetricsAndGroupByToolbarItems
|
||||
{...props}
|
||||
metricTypes={metricTypes}
|
||||
groupByFields={groupByFields}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -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',
|
||||
|
|
|
@ -30,4 +30,5 @@ export const metrics: InventoryMetrics = {
|
|||
},
|
||||
snapshot: { cpu, memory, rx, tx },
|
||||
defaultSnapshot: 'cpu',
|
||||
defaultTimeRangeInSeconds: 3600, // 1 hour
|
||||
};
|
||||
|
|
|
@ -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 (
|
||||
<>
|
||||
<EuiFlexItem grow={false}>
|
||||
<WaffleMetricControls
|
||||
metric={props.metric}
|
||||
options={options}
|
||||
onChange={props.changeMetric}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<WaffleGroupByControls
|
||||
options={groupByOptions}
|
||||
groupBy={props.groupBy}
|
||||
nodeType={props.nodeType}
|
||||
onChange={props.changeGroupBy}
|
||||
fields={props.createDerivedIndexPattern('metrics').fields}
|
||||
onChangeCustomOptions={props.changeCustomOptions}
|
||||
customOptions={props.customOptions}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</>
|
||||
<MetricsAndGroupByToolbarItems
|
||||
{...props}
|
||||
metricTypes={metricTypes}
|
||||
groupByFields={groupByFields}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
});
|
|
@ -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',
|
||||
|
|
|
@ -52,4 +52,5 @@ export const metrics: InventoryMetrics = {
|
|||
},
|
||||
snapshot: { count, cpu, load, logRate, memory, rx, tx },
|
||||
defaultSnapshot: 'cpu',
|
||||
defaultTimeRangeInSeconds: 3600, // 1 hour
|
||||
};
|
||||
|
|
|
@ -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 (
|
||||
<>
|
||||
<EuiFlexItem grow={false}>
|
||||
<WaffleMetricControls
|
||||
options={metricOptions}
|
||||
metric={props.metric}
|
||||
onChange={props.changeMetric}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<WaffleGroupByControls
|
||||
options={groupByOptions}
|
||||
groupBy={props.groupBy}
|
||||
nodeType={props.nodeType}
|
||||
onChange={props.changeGroupBy}
|
||||
fields={props.createDerivedIndexPattern('metrics').fields}
|
||||
onChangeCustomOptions={props.changeCustomOptions}
|
||||
customOptions={props.customOptions}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</>
|
||||
<MetricsAndGroupByToolbarItems
|
||||
{...props}
|
||||
metricTypes={metricTypes}
|
||||
groupByFields={groupByFields}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -26,4 +26,5 @@ export const metrics: InventoryMetrics = {
|
|||
},
|
||||
snapshot: { cpu, memory, rx, tx },
|
||||
defaultSnapshot: 'cpu',
|
||||
defaultTimeRangeInSeconds: 3600, // 1 hour
|
||||
};
|
||||
|
|
|
@ -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 (
|
||||
<>
|
||||
<EuiFlexItem grow={false}>
|
||||
<WaffleMetricControls
|
||||
metric={props.metric}
|
||||
options={options}
|
||||
onChange={props.changeMetric}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<WaffleGroupByControls
|
||||
options={groupByOptions}
|
||||
groupBy={props.groupBy}
|
||||
nodeType={props.nodeType}
|
||||
onChange={props.changeGroupBy}
|
||||
fields={props.createDerivedIndexPattern('metrics').fields}
|
||||
onChangeCustomOptions={props.changeCustomOptions}
|
||||
customOptions={props.customOptions}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</>
|
||||
<MetricsAndGroupByToolbarItems
|
||||
{...props}
|
||||
metricTypes={metricTypes}
|
||||
groupByFields={groupByFields}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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 (
|
||||
<>
|
||||
<EuiFlexItem grow={false}>
|
||||
<WaffleMetricControls
|
||||
options={metricOptions}
|
||||
metric={props.metric}
|
||||
onChange={props.changeMetric}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<WaffleGroupByControls
|
||||
options={groupByOptions}
|
||||
groupBy={props.groupBy}
|
||||
nodeType={props.nodeType}
|
||||
onChange={props.changeGroupBy}
|
||||
fields={props.createDerivedIndexPattern('metrics').fields}
|
||||
onChangeCustomOptions={props.changeCustomOptions}
|
||||
customOptions={props.customOptions}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -35,4 +35,5 @@ export const metrics: InventoryMetrics = {
|
|||
count,
|
||||
},
|
||||
defaultSnapshot: 'count',
|
||||
defaultTimeRangeInSeconds: 3600,
|
||||
};
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -30,6 +30,7 @@ export const InventoryFormatterTypeRT = rt.keyof({
|
|||
bytes: null,
|
||||
number: null,
|
||||
percent: null,
|
||||
highPercision: null,
|
||||
});
|
||||
export type InventoryFormatterType = rt.TypeOf<typeof InventoryFormatterTypeRT>;
|
||||
export type InventoryItemType = rt.TypeOf<typeof ItemTypeRT>;
|
||||
|
@ -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<typeof InventoryMetricRT>;
|
||||
|
@ -162,6 +181,8 @@ export const TSVBSeriesRT = rt.intersection([
|
|||
}),
|
||||
]);
|
||||
|
||||
export type TSVBSeries = rt.TypeOf<typeof TSVBSeriesRT>;
|
||||
|
||||
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<typeof SnapshotMetricTypeRT>;
|
||||
|
@ -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[];
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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<Props, {}> {
|
|||
nodeType,
|
||||
reload,
|
||||
view,
|
||||
currentTime,
|
||||
options,
|
||||
timeRange,
|
||||
} = this.props;
|
||||
if (loading) {
|
||||
return (
|
||||
|
@ -152,7 +179,7 @@ export const NodesOverview = class extends React.Component<Props, {}> {
|
|||
nodes={nodes}
|
||||
options={options}
|
||||
formatter={this.formatter}
|
||||
timeRange={timeRange}
|
||||
currentTime={currentTime}
|
||||
onFilter={this.handleDrilldown}
|
||||
/>
|
||||
</TableContainer>
|
||||
|
@ -163,7 +190,7 @@ export const NodesOverview = class extends React.Component<Props, {}> {
|
|||
nodes={nodes}
|
||||
options={options}
|
||||
formatter={this.formatter}
|
||||
timeRange={timeRange}
|
||||
currentTime={currentTime}
|
||||
onFilter={this.handleDrilldown}
|
||||
bounds={bounds}
|
||||
dataBounds={dataBounds}
|
||||
|
|
|
@ -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<Props, State> {
|
||||
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<Props, State> {
|
|||
node={item.node}
|
||||
nodeType={nodeType}
|
||||
closePopover={this.closePopoverFor(uniqueID)}
|
||||
timeRange={timeRange}
|
||||
currentTime={currentTime}
|
||||
isPopoverOpen={this.state.isPopoverOpen.includes(uniqueID)}
|
||||
options={options}
|
||||
popoverPosition="rightCenter"
|
||||
|
|
|
@ -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> = props => {
|
||||
|
@ -41,7 +41,7 @@ export const GroupOfGroups: React.FC<Props> = props => {
|
|||
formatter={props.formatter}
|
||||
bounds={props.bounds}
|
||||
nodeType={props.nodeType}
|
||||
timeRange={props.timeRange}
|
||||
currentTime={props.currentTime}
|
||||
/>
|
||||
))}
|
||||
</Groups>
|
||||
|
|
|
@ -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<Props> = ({
|
||||
|
@ -35,7 +35,7 @@ export const GroupOfNodes: React.FC<Props> = ({
|
|||
isChild = false,
|
||||
bounds,
|
||||
nodeType,
|
||||
timeRange,
|
||||
currentTime,
|
||||
}) => {
|
||||
const width = group.width > 200 ? group.width : 200;
|
||||
return (
|
||||
|
@ -51,7 +51,7 @@ export const GroupOfNodes: React.FC<Props> = ({
|
|||
formatter={formatter}
|
||||
bounds={bounds}
|
||||
nodeType={nodeType}
|
||||
timeRange={timeRange}
|
||||
currentTime={currentTime}
|
||||
/>
|
||||
))}
|
||||
</Nodes>
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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<Props> = ({
|
||||
nodes,
|
||||
options,
|
||||
timeRange,
|
||||
currentTime,
|
||||
onFilter,
|
||||
formatter,
|
||||
bounds,
|
||||
|
@ -59,7 +59,7 @@ export const Map: React.FC<Props> = ({
|
|||
formatter={formatter}
|
||||
bounds={bounds}
|
||||
nodeType={nodeType}
|
||||
timeRange={timeRange}
|
||||
currentTime={currentTime}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ export const Map: React.FC<Props> = ({
|
|||
isChild={false}
|
||||
bounds={bounds}
|
||||
nodeType={nodeType}
|
||||
timeRange={timeRange}
|
||||
currentTime={currentTime}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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<Props, State> {
|
||||
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<Props, State> {
|
|||
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<Props, State> {
|
|||
isPopoverOpen={isPopoverOpen}
|
||||
closePopover={this.closePopover}
|
||||
options={options}
|
||||
timeRange={newTimerange}
|
||||
currentTime={currentTime}
|
||||
popoverPosition="downCenter"
|
||||
>
|
||||
<ConditionalToolTip
|
||||
|
|
|
@ -15,14 +15,15 @@ import { i18n } from '@kbn/i18n';
|
|||
import React from 'react';
|
||||
import { UICapabilities } from 'ui/capabilities';
|
||||
import { injectUICapabilities } from 'ui/capabilities/react';
|
||||
import { InfraNodeType, InfraTimerangeInput } from '../../graphql/types';
|
||||
import { InfraNodeType } from '../../graphql/types';
|
||||
import { InfraWaffleMapNode, InfraWaffleMapOptions } from '../../lib/lib';
|
||||
import { getNodeDetailUrl, getNodeLogsUrl } from '../../pages/link_to';
|
||||
import { createUptimeLink } from './lib/create_uptime_link';
|
||||
import { findInventoryModel } from '../../../common/inventory_models';
|
||||
|
||||
interface Props {
|
||||
options: InfraWaffleMapOptions;
|
||||
timeRange: InfraTimerangeInput;
|
||||
currentTime: number;
|
||||
children: any;
|
||||
node: InfraWaffleMapNode;
|
||||
nodeType: InfraNodeType;
|
||||
|
@ -35,25 +36,21 @@ interface Props {
|
|||
export const NodeContextMenu = injectUICapabilities(
|
||||
({
|
||||
options,
|
||||
timeRange,
|
||||
currentTime,
|
||||
children,
|
||||
node,
|
||||
isPopoverOpen,
|
||||
closePopover,
|
||||
nodeType,
|
||||
|
||||
uiCapabilities,
|
||||
popoverPosition,
|
||||
}: Props) => {
|
||||
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 (
|
||||
<EuiPopover
|
||||
|
|
|
@ -4,8 +4,13 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { EuiPopover, EuiContextMenu, EuiFilterButton, EuiFilterGroup } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
EuiPopover,
|
||||
EuiContextMenu,
|
||||
EuiFilterButton,
|
||||
EuiFilterGroup,
|
||||
EuiContextMenuPanelDescriptor,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import React, { useCallback, useState, useMemo } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
@ -16,6 +21,7 @@ import {
|
|||
InfraSnapshotGroupbyInput,
|
||||
} from '../../graphql/types';
|
||||
import { findInventoryModel } from '../../../common/inventory_models';
|
||||
import { InventoryItemType } from '../../../common/inventory_models/types';
|
||||
|
||||
interface WaffleInventorySwitcherProps {
|
||||
nodeType: InfraNodeType;
|
||||
|
@ -24,6 +30,11 @@ interface WaffleInventorySwitcherProps {
|
|||
changeMetric: (metric: InfraSnapshotMetricInput) => void;
|
||||
}
|
||||
|
||||
const getDisplayNameForType = (type: InventoryItemType) => {
|
||||
const inventoryModel = findInventoryModel(type);
|
||||
return inventoryModel.displayName;
|
||||
};
|
||||
|
||||
export const WaffleInventorySwitcher: React.FC<WaffleInventorySwitcherProps> = ({
|
||||
changeNodeType,
|
||||
changeGroupBy,
|
||||
|
@ -48,44 +59,62 @@ export const WaffleInventorySwitcher: React.FC<WaffleInventorySwitcherProps> = (
|
|||
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<WaffleInventorySwitcherProps> = (
|
|||
withTitle
|
||||
anchorPosition="downLeft"
|
||||
>
|
||||
<EuiContextMenu initialPanelId={0} panels={panels} />
|
||||
<EuiContextMenu initialPanelId="firstPanel" panels={panels} />
|
||||
</EuiPopover>
|
||||
</EuiFilterGroup>
|
||||
);
|
||||
|
|
|
@ -44,7 +44,7 @@ export const WaffleMetricControls = class extends React.PureComponent<Props, Sta
|
|||
}
|
||||
const currentLabel = options.find(o => o.value === metric.type);
|
||||
if (!currentLabel) {
|
||||
return 'null';
|
||||
return null;
|
||||
}
|
||||
const panels: EuiContextMenuPanelDescriptor[] = [
|
||||
{
|
||||
|
|
|
@ -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<SnapshotNodeResponse>(
|
||||
'/api/metrics/snapshot',
|
||||
'POST',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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',
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ export const SnapshotPageContent: React.FC = () => (
|
|||
<WithWaffleFilter indexPattern={createDerivedIndexPattern('metrics')}>
|
||||
{({ filterQueryAsJson, applyFilterQuery }) => (
|
||||
<WithWaffleTime>
|
||||
{({ currentTimeRange, isAutoReloading }) => (
|
||||
{({ currentTime }) => (
|
||||
<WithWaffleOptions>
|
||||
{({
|
||||
metric,
|
||||
|
@ -33,12 +33,12 @@ export const SnapshotPageContent: React.FC = () => (
|
|||
boundsOverride,
|
||||
}) => (
|
||||
<Layout
|
||||
currentTime={currentTime}
|
||||
filterQuery={filterQueryAsJson}
|
||||
metric={metric}
|
||||
groupBy={groupBy}
|
||||
nodeType={nodeType}
|
||||
sourceId={sourceId}
|
||||
timeRange={currentTimeRange}
|
||||
options={{
|
||||
...wafflemap,
|
||||
metric,
|
||||
|
|
|
@ -11,19 +11,22 @@ import { RedirectToLogs } from './redirect_to_logs';
|
|||
import { RedirectToNodeDetail } from './redirect_to_node_detail';
|
||||
import { RedirectToNodeLogs } from './redirect_to_node_logs';
|
||||
import { RedirectToHostDetailViaIP } from './redirect_to_host_detail_via_ip';
|
||||
import { inventoryModels } from '../../../common/inventory_models';
|
||||
|
||||
interface LinkToPageProps {
|
||||
match: RouteMatch<{}>;
|
||||
}
|
||||
|
||||
const ITEM_TYPES = inventoryModels.map(m => m.id).join('|');
|
||||
|
||||
export const LinkToPage: React.FC<LinkToPageProps> = props => (
|
||||
<Switch>
|
||||
<Route
|
||||
path={`${props.match.url}/:sourceId?/:nodeType(host|container|pod)-logs/:nodeId`}
|
||||
path={`${props.match.url}/:sourceId?/:nodeType(${ITEM_TYPES})-logs/:nodeId`}
|
||||
component={RedirectToNodeLogs}
|
||||
/>
|
||||
<Route
|
||||
path={`${props.match.url}/:nodeType(host|container|pod)-detail/:nodeId`}
|
||||
path={`${props.match.url}/:nodeType(${ITEM_TYPES})-detail/:nodeId`}
|
||||
component={RedirectToNodeDetail}
|
||||
/>
|
||||
<Route
|
||||
|
|
|
@ -14,9 +14,10 @@ import { LoadingPage } from '../../components/loading_page';
|
|||
import { replaceLogFilterInQueryString } from '../../containers/logs/with_log_filter';
|
||||
import { replaceLogPositionInQueryString } from '../../containers/logs/with_log_position';
|
||||
import { replaceSourceIdInQueryString } from '../../containers/source_id';
|
||||
import { InfraNodeType } from '../../graphql/types';
|
||||
import { InfraNodeType, SourceConfigurationFields } from '../../graphql/types';
|
||||
import { getFilterFromLocation, getTimeFromLocation } from './query_params';
|
||||
import { useSource } from '../../containers/source/source';
|
||||
import { findInventoryFields } from '../../../common/inventory_models';
|
||||
|
||||
type RedirectToNodeLogsType = RouteComponentProps<{
|
||||
nodeId: string;
|
||||
|
@ -24,6 +25,11 @@ type RedirectToNodeLogsType = RouteComponentProps<{
|
|||
sourceId?: string;
|
||||
}>;
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
};
|
|
@ -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}}') => (
|
||||
|
|
|
@ -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',
|
||||
}
|
||||
|
||||
|
|
|
@ -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<InfraMetricData[]> {
|
||||
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 = <Aggregation>(searchOptions: object) =>
|
||||
this.framework.callWithRequest<{}, Aggregation>(requestContext, 'search', searchOptions);
|
||||
|
||||
|
|
|
@ -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'];
|
||||
|
|
|
@ -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<InfraTimerangeInput> => {
|
||||
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<string | undefined>)
|
||||
.filter(v => v)
|
||||
.map(field =>
|
||||
field!
|
||||
.split(/\./)
|
||||
.slice(0, 2)
|
||||
.join('.')
|
||||
)
|
||||
) as string[];
|
||||
};
|
|
@ -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', {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue