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 resource metric integration test #453

Open
wants to merge 65 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 56 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
3609cd7
Create config file
varunch77 Jan 13, 2025
1952125
Move config file
varunch77 Jan 13, 2025
edd5418
Add resource test
varunch77 Jan 13, 2025
80975df
Write logs
varunch77 Jan 13, 2025
02c34c2
Attempt at checking entity information in logs
varunch77 Jan 13, 2025
2f93774
Revert to validating logs
varunch77 Jan 14, 2025
a9c2c82
Pause deletion of logs for testing
varunch77 Jan 14, 2025
01c488a
Edit config file
varunch77 Jan 14, 2025
044f757
Revert config change
varunch77 Jan 14, 2025
5dbad82
Update config file again
varunch77 Jan 14, 2025
50e7764
Add memory info to config file
varunch77 Jan 14, 2025
dc78832
Reduce append dimensions in config
varunch77 Jan 14, 2025
8e71d15
Update config
varunch77 Jan 14, 2025
c763050
Revert config to minimal version
varunch77 Jan 14, 2025
49c83fa
Another config change
varunch77 Jan 14, 2025
db541b5
Change namespace
varunch77 Jan 14, 2025
5689ad1
Update agent config
varunch77 Jan 17, 2025
a937887
Use default namespace
varunch77 Jan 17, 2025
ad88aec
Merge branch 'main' into resource-metric-integ-test
varunch77 Jan 17, 2025
ce01fa6
Codify curl command
varunch77 Jan 17, 2025
31ea8fb
Unhardcode instance id
varunch77 Jan 17, 2025
b8a54e2
Codify curl command
varunch77 Jan 17, 2025
aa8f340
validate request response
varunch77 Jan 17, 2025
ac08ce5
print type of response
varunch77 Jan 17, 2025
17a05f2
print type
varunch77 Jan 17, 2025
92445d2
Validate request response
varunch77 Jan 17, 2025
cb15441
Add missing packages
varunch77 Jan 17, 2025
aeb11ba
Update packages
varunch77 Jan 17, 2025
7b412b1
Fix package
varunch77 Jan 17, 2025
2f07084
Fix small errors
varunch77 Jan 17, 2025
6e07fec
Add print statements
varunch77 Jan 17, 2025
2b75825
Add print statements
varunch77 Jan 17, 2025
8b61efd
Remove instanceType
varunch77 Jan 17, 2025
8f10cff
Edit comments
varunch77 Jan 17, 2025
8fa2b80
Merge branch 'main' into resource-metric-integ-test
varunch77 Jan 21, 2025
44fca67
Get rid of logs
varunch77 Jan 22, 2025
6907b5d
Move out of logs folder
varunch77 Jan 23, 2025
6738efd
Import fix
varunch77 Jan 23, 2025
5bca823
Fix copy path file
varunch77 Jan 23, 2025
fd57b84
Run linter
varunch77 Jan 23, 2025
43e16ac
use consts
varunch77 Jan 23, 2025
efaef1a
Remove config file copy
varunch77 Jan 23, 2025
d44c45c
Run linter
varunch77 Jan 23, 2025
ccff2e8
Print entity again
varunch77 Jan 23, 2025
1cedc10
Print entire response
varunch77 Jan 23, 2025
1bc7930
Print
varunch77 Jan 23, 2025
4b3de9f
print reponse
varunch77 Jan 23, 2025
d5bc869
print
varunch77 Jan 23, 2025
f4de16c
fully print out body
varunch77 Jan 23, 2025
023da57
print
varunch77 Jan 23, 2025
32c0502
print
varunch77 Jan 23, 2025
de05cbc
Use helper functions to validate entity
varunch77 Jan 23, 2025
bf32e2d
MCreate helper function for making api call
varunch77 Jan 23, 2025
2192042
Fix errors
varunch77 Jan 23, 2025
c91c12f
Add forgotten file
varunch77 Jan 23, 2025
1c5bba2
Run linter
varunch77 Jan 23, 2025
6101dfe
Use test case structure
varunch77 Jan 24, 2025
c160ac4
Run linter
varunch77 Jan 24, 2025
4106a3a
Remove old version of test function
varunch77 Jan 24, 2025
564f56a
Merge branch 'main' into resource-metric-integ-test
varunch77 Jan 24, 2025
19b1659
Add test to metric_value_benchmark suite
varunch77 Jan 24, 2025
2e1c551
remove unussed const
varunch77 Jan 24, 2025
14e278e
Update imports
varunch77 Jan 24, 2025
0b3ff93
fix import
varunch77 Jan 24, 2025
ae22da3
remove config file path
varunch77 Jan 24, 2025
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
2 changes: 1 addition & 1 deletion test/e2e/jmx/jmx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
//------------------------------------------------------------------------------

var (
env *environment.MetaData
env *environment.MetaData
varunch77 marked this conversation as resolved.
Show resolved Hide resolved
)

//------------------------------------------------------------------------------
Expand Down
60 changes: 60 additions & 0 deletions test/entity/entity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
package entity

import (
"encoding/json"
"fmt"
"log"
"net/http"
"path/filepath"
"strings"
"testing"
Expand All @@ -16,10 +18,12 @@ import (

"github.com/aws/amazon-cloudwatch-agent-test/environment"
"github.com/aws/amazon-cloudwatch-agent-test/util/awsservice"
"github.com/aws/amazon-cloudwatch-agent-test/util/common"
)

const (
sleepForFlush = 240 * time.Second
region = "us-west-2"

entityType = "@entity.KeyAttributes.Type"
entityName = "@entity.KeyAttributes.Name"
Expand Down Expand Up @@ -237,6 +241,62 @@ func TestPutLogEventEntityEKS(t *testing.T) {
}
}

func TestResourceMetrics(t *testing.T) {
instanceId := awsservice.GetInstanceId()
configPath := "resources/config_metrics_resource.json"

// start agent and write metrics
common.StartAgent(configPath, true, false)
time.Sleep(sleepForFlush)
common.StopAgent()

// build ListEntitiesForMetric request:
requestBody := []byte(fmt.Sprintf(`{
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I think would be nice to turn these into test case input, then in the future if someone else to implement a new test, they can just write an additional case instead of copying this entire boilerplate code. For example: https://github.com/aws/amazon-cloudwatch-agent-test/pull/453/files#diff-13510c6aa10605c1f76162fde322c3a4da1cf75441a3a93cb340fbb9d36c480dR186

"Namespace": "CWAgent",
"MetricName": "cpu_usage_idle",
"Dimensions": [
{"Name": "InstanceId", "Value": "%s"},
{"Name": "cpu", "Value": "cpu-total"}
]
}`, instanceId))
req, err := common.BuildListEntitiesForMetricRequest(requestBody, region)
assert.NoError(t, err, "Error building ListEntitiesForMetric request")

// send the request
client := &http.Client{}
resp, err := client.Do(req)
assert.NoError(t, err, "Error sending the request")
defer resp.Body.Close()

// parse and verify the response
var response struct {
Entities []struct {
KeyAttributes struct {
Type string `json:"Type"`
ResourceType string `json:"ResourceType"`
Identifier string `json:"Identifier"`
} `json:"KeyAttributes"`
} `json:"Entities"`
}

err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err, "Error parsing JSON response")

// Verify the KeyAttributes
expectedEntity := expectedEntity{
entityType: "AWS::Resource",
platformType: "AWS::EC2::Instance",
instanceId: instanceId,
}
assert.NotEmpty(t, response.Entities, "No entities found in the response")

entity := response.Entities[0]
validator := NewEntityValidator("EC2", expectedEntity)
validator.ValidateField(entityType, entity.KeyAttributes.Type, t)
validator.ValidateField(entityPlatform, entity.KeyAttributes.ResourceType, t)
validator.ValidateField(entityInstanceId, entity.KeyAttributes.Identifier, t)
}

// ValidateLogEntity performs the entity validation for PutLogEvents.
func ValidateLogEntity(t *testing.T, logGroup, logStream string, end *time.Time, queryString string, expectedEntity expectedEntity, entityPlatformType string) {
log.Printf("Checking log group/stream: %s/%s", logGroup, logStream)
Expand Down
32 changes: 32 additions & 0 deletions test/entity/resources/config_metrics_resource.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"agent": {
"metrics_collection_interval": 10,
"run_as_user": "root",
"debug": true
},
"metrics": {
"metrics_collected": {
"cpu": {
"resources": [
"*"
],
"measurement": [
"cpu_usage_idle",
"cpu_usage_nice",
"cpu_usage_guest"
],
"metrics_collection_interval": 10
},
"memory": {
"metrics_collection_interval": 10,
"measurement": [
"mem_used",
"mem_free"
]
}
},
"append_dimensions": {
"InstanceId": "${aws:InstanceId}"
}
}
}
56 changes: 56 additions & 0 deletions util/common/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"bytes"
"context"
"crypto/rand"
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"errors"
Expand All @@ -23,6 +24,8 @@ import (
"collectd.org/exec"
"collectd.org/network"
"github.com/DataDog/datadog-go/statsd"
v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/prozz/aws-embedded-metrics-golang/emf"
)

Expand Down Expand Up @@ -350,3 +353,56 @@ func SendEMFMetrics(metricPerInterval int, metricLogGroup, metricNamespace strin
}

}

// This function builds and signs an ListEntitiesForMetric call, essentially trying to replicate this curl command:
//
// curl -i -X POST monitoring.us-west-2.amazonaws.com -H 'Content-Type: application/json' \
// -H 'Content-Encoding: amz-1.0' \
// --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
// -H "x-amz-security-token: $AWS_SESSION_TOKEN" \
// --aws-sigv4 "aws:amz:us-west-2:monitoring" \
// -H 'X-Amz-Target: com.amazonaws.cloudwatch.v2013_01_16.CloudWatchVersion20130116.ListEntitiesForMetric' \
// -d '{
// // sample request body:
// "Namespace": "CWAgent",
// "MetricName": "cpu_usage_idle",
// "Dimensions": [{"Name": "InstanceId", "Value": "i-0123456789012"}, { "Name": "cpu", "Value": "cpu-total"}]
// }'
func BuildListEntitiesForMetricRequest(body []byte, region string) (*http.Request, error) {
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(region))
if err != nil {
return nil, err
}
signer := v4.NewSigner()
h := sha256.New()

h.Write(body)
payloadHash := hex.EncodeToString(h.Sum(nil))

// build the request
req, err := http.NewRequest("POST", "https://monitoring."+region+".amazonaws.com/", bytes.NewReader(body))
if err != nil {
return nil, err
}

// set headers
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Amz-Target", "com.amazonaws.cloudwatch.v2013_01_16.CloudWatchVersion20130116.ListEntitiesForMetric")
req.Header.Set("Content-Encoding", "amz-1.0")

// set creds
credentials, err := cfg.Credentials.Retrieve(context.TODO())
if err != nil {
return nil, err
}

req.Header.Set("x-amz-security-token", credentials.SessionToken)

// sign the request
err = signer.SignHTTP(context.TODO(), credentials, req, payloadHash, "monitoring", region, time.Now())
if err != nil {
return nil, err
}

return req, nil
}
Loading