Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add host inventory metrics to ec2 metricset #20171

Merged
merged 14 commits into from
Aug 18, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Added cache and connection_errors metrics to status metricset of MySQL module {issue}16955[16955] {pull}19844[19844]
- Update MySQL dashboard with connection errors and cache metrics {pull}19913[19913] {issue}16955[16955]
- Add cloud.instance.name into aws ec2 metricset. {pull}20077[20077]
- Add host inventory metrics into aws ec2 metricset. {pull}20171[20171]
jsoriano marked this conversation as resolved.
Show resolved Hide resolved

*Packetbeat*

Expand Down
47 changes: 37 additions & 10 deletions x-pack/metricbeat/module/aws/ec2/_meta/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
"ec2": {
"cpu": {
"credit_balance": 144,
"credit_usage": 0.061395,
"credit_usage": 0.05477,
"surplus_credit_balance": 0,
"surplus_credits_charged": 0,
"total": {
"pct": 1.1651199407241788
"pct": 1.166484417714406
}
},
"diskio": {
Expand Down Expand Up @@ -51,16 +51,16 @@
},
"network": {
"in": {
"bytes": 7375.4,
"bytes_per_sec": 24.584666666666667,
"packets": 49,
"packets_per_sec": 0.16333333333333333
"bytes": 6644.4,
"bytes_per_sec": 22.148,
"packets": 44.6,
"packets_per_sec": 0.14866666666666667
},
"out": {
"bytes": 11567,
"bytes_per_sec": 38.556666666666665,
"packets": 44.8,
"packets_per_sec": 0.14933333333333332
"bytes": 6016.6,
"bytes_per_sec": 20.055333333333333,
"packets": 35.4,
"packets_per_sec": 0.118
}
},
"status": {
Expand Down Expand Up @@ -95,6 +95,33 @@
"duration": 115000,
"module": "aws"
},
"host": {
"cpu": {
"pct": 1.166484417714406
},
"disk": {
"read": {
"bytes": 0
}
},
"diskio": {
"write": {
"bytes": 0
}
},
"id": "i-0516ddaca5c1d231f",
"name": "mysql-test",
"network": {
"in": {
"bytes": 6644.4,
"packets": 44.6
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a counter? Why is it a decimal number?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a gauge actually and it's an average value among 5 minutes:

Screen Shot 2020-07-31 at 8 36 46 AM

},
"out": {
"bytes": 6016.6,
"packets": 35.4
}
}
},
"metricset": {
"name": "ec2",
"period": 10000
Expand Down
36 changes: 36 additions & 0 deletions x-pack/metricbeat/module/aws/ec2/ec2.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ func (m *MetricSet) createCloudWatchEvents(getMetricDataResults []cloudwatch.Met
// add cloud.instance.name and host.name into ec2 events
if *tag.Key == "Name" {
events[instanceID].RootFields.Put("cloud.instance.name", *tag.Value)
events[instanceID].RootFields.Put("host.name", *tag.Value)
}
}

Expand Down Expand Up @@ -269,6 +270,10 @@ func (m *MetricSet) createCloudWatchEvents(getMetricDataResults []cloudwatch.Met
return events, errors.Wrap(err, "EventMapping failed")
}

// add host cpu/network/disk fields and host.id
hostFields := addHostFields(resultMetricsetFields, events[instanceID].RootFields, instanceID)
events[instanceID].RootFields.Update(hostFields)

// add rate metrics
calculateRate(resultMetricsetFields, monitoringStates[instanceID])

Expand Down Expand Up @@ -309,6 +314,37 @@ func calculateRate(resultMetricsetFields common.MapStr, monitoringState string)
}
}

func addHostFields(resultMetricsetFields common.MapStr, rootFields common.MapStr, instanceID string) common.MapStr {
hostRootFields := common.MapStr{}
hostRootFields.Put("host.id", instanceID)

// If there is no instance name, use instance ID as the host.name
hostName, err := rootFields.GetValue("host.name")
if err == nil && hostName != nil {
hostRootFields.Put("host.name", hostName)
} else {
hostRootFields.Put("host.name", instanceID)
}

hostFieldTable := map[string]string{
"cpu.total.pct": "host.cpu.pct",
"network.in.bytes": "host.network.in.bytes",
"network.out.bytes": "host.network.out.bytes",
"network.in.packets": "host.network.in.packets",
"network.out.packets": "host.network.out.packets",
"diskio.read.bytes": "host.disk.read.bytes",
"diskio.write.bytes": "host.diskio.write.bytes",
kaiyan-sheng marked this conversation as resolved.
Show resolved Hide resolved
}

for ec2MetricName, hostMetricName := range hostFieldTable {
metricValue, err := resultMetricsetFields.GetValue(ec2MetricName)
if err == nil && metricValue != nil {
hostRootFields.Put(hostMetricName, metricValue)
}
}
return hostRootFields
}

func getInstancesPerRegion(svc ec2iface.ClientAPI) (instanceIDs []string, instancesOutputs map[string]ec2.Instance, err error) {
instancesOutputs = map[string]ec2.Instance{}
output := ec2.DescribeInstancesOutput{NextToken: nil}
Expand Down
79 changes: 77 additions & 2 deletions x-pack/metricbeat/module/aws/ec2/ec2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ func (m *MockEC2Client) DescribeInstancesRequest(input *ec2.DescribeInstancesInp
Key: awssdk.String("helm.sh/chart"),
Value: awssdk.String("foo-chart"),
},
{
Key: awssdk.String("Name"),
Value: awssdk.String("test-instance"),
},
}

instance := ec2.Instance{
Expand Down Expand Up @@ -144,10 +148,15 @@ func TestCreateCloudWatchEventsDedotTags(t *testing.T) {
"cloud": common.MapStr{
"region": regionName,
"provider": "aws",
"instance": common.MapStr{"id": "i-123"},
"instance": common.MapStr{"id": "i-123", "name": "test-instance"},
"machine": common.MapStr{"type": "t2.medium"},
"availability_zone": "us-west-1a",
},
"host": common.MapStr{
"cpu": common.MapStr{"pct": 0.25},
"id": "i-123",
"name": "test-instance",
},
},
MetricSetFields: common.MapStr{
"cpu": common.MapStr{
Expand All @@ -171,6 +180,7 @@ func TestCreateCloudWatchEventsDedotTags(t *testing.T) {
"tags": common.MapStr{
"app_kubernetes_io/name": "foo",
"helm_sh/chart": "foo-chart",
"Name": "test-instance",
},
},
}
Expand Down Expand Up @@ -227,10 +237,15 @@ func TestCreateCloudWatchEventsWithTagsFilter(t *testing.T) {
"cloud": common.MapStr{
"region": regionName,
"provider": "aws",
"instance": common.MapStr{"id": "i-123"},
"instance": common.MapStr{"id": "i-123", "name": "test-instance"},
"machine": common.MapStr{"type": "t2.medium"},
"availability_zone": "us-west-1a",
},
"host": common.MapStr{
"cpu": common.MapStr{"pct": 0.25},
"id": "i-123",
"name": "test-instance",
},
},
MetricSetFields: common.MapStr{
"cpu": common.MapStr{
Expand All @@ -254,6 +269,7 @@ func TestCreateCloudWatchEventsWithTagsFilter(t *testing.T) {
"tags": common.MapStr{
"app_kubernetes_io/name": "foo",
"helm_sh/chart": "foo-chart",
"Name": "test-instance",
},
},
}
Expand Down Expand Up @@ -455,3 +471,62 @@ func TestCalculateRate(t *testing.T) {
assert.Equal(t, c.rateMetricValueDetailed, output)
}
}

func TestCreateCloudWatchEventsWithInstanceName(t *testing.T) {
expectedEvent := mb.Event{
RootFields: common.MapStr{
"cloud": common.MapStr{
"region": regionName,
"provider": "aws",
"instance": common.MapStr{"id": "i-123", "name": "test-instance"},
"machine": common.MapStr{"type": "t2.medium"},
"availability_zone": "us-west-1a",
},
"host": common.MapStr{
"cpu": common.MapStr{"pct": 0.25},
"id": "i-123",
},
},
MetricSetFields: common.MapStr{
"tags": common.MapStr{
"app_kubernetes_io/name": "foo",
"helm_sh/chart": "foo-chart",
"Name": "test-instance",
},
},
}
svcEC2Mock := &MockEC2Client{}
instanceIDs, instancesOutputs, err := getInstancesPerRegion(svcEC2Mock)
assert.NoError(t, err)
assert.Equal(t, 1, len(instanceIDs))
instanceID := instanceIDs[0]
assert.Equal(t, instanceID, instanceID)
timestamp := time.Now()

getMetricDataOutput := []cloudwatch.MetricDataResult{
{
Id: &id1,
Label: &label1,
Values: []float64{0.25},
Timestamps: []time.Time{timestamp},
},
}

metricSet := MetricSet{
&aws.MetricSet{},
}

events, err := metricSet.createCloudWatchEvents(getMetricDataOutput, instancesOutputs, "us-west-1")
assert.NoError(t, err)
assert.Equal(t, 1, len(events))

assert.Equal(t, expectedEvent.MetricSetFields["tags"], events[instanceID].ModuleFields["tags"])

hostID, err := events[instanceID].RootFields.GetValue("host.id")
assert.NoError(t, err)
assert.Equal(t, "i-123", hostID)

instanceName, err := events[instanceID].RootFields.GetValue("cloud.instance.name")
assert.NoError(t, err)
assert.Equal(t, "test-instance", instanceName)
}