Closed

Description
When constructing a MetricDatum for CloudWatch, it seems that setting the timestamp on any datum in the request will result in errors upon attempting to submit the data to CloudWatch via the CloudWatchClient.PutMetricData(...) function.
It looks like the issue is that the output format generated by the CloudWatchClient does not match the specification here:
https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_PutMetricData.html
The code below generates the following request body:
Action=PutMetricData
&Namespace=MyMetricTest
&MetricData.member.1.MetricName=MyMetricName
&MetricData.member.1.Timestamp=1.44409e+012
&MetricData.member.1.Value=100
&Version=2010-08-01
But according to the specification, it looks like it should actually be generating this request body instead (the timestamp is required to be ISO 8601 formatted):
Action=PutMetricData
&Namespace=MyMetricTest
&MetricData.member.1.MetricName=MyMetricName
&MetricData.member.1.Timestamp=2015-10-05T16:40:00Z
&MetricData.member.1.Value=100
&Version=2010-08-01
Here is a code snippet to fully reproduce the issue:
#include <iostream>
#include "aws/core/auth/AWSCredentialsProvider.h"
#include "aws/monitoring/CloudWatchClient.h"
#include "aws/monitoring/model/PutMetricDataRequest.h"
using namespace Aws;
using namespace Aws::Auth;
using namespace Aws::CloudWatch;
using namespace Aws::CloudWatch::Model;
using namespace Aws::Http;
using namespace Aws::Client;
using namespace std::chrono;
long long GetMillisSinceEpoch(const std::chrono::time_point<std::chrono::system_clock>& timePoint)
{
return duration_cast<std::chrono::milliseconds>(timePoint.time_since_epoch()).count();
}
long long GetMillisSinceEpoch()
{
return GetMillisSinceEpoch(system_clock::now());
}
int main()
{
/*
This code results in the following output:
ERROR: MalformedInput::Unable to parse ExceptionName: MalformedInput Message: timestamp must follow ISO8601
Transmission failure
*/
const char* accessKey = "MY_ACCESS_KEY";
const char* secretKey = "MY_SECRET_KEY";
AWSCredentials basicCreds(accessKey,secretKey);
CloudWatchClient client = CloudWatchClient(basicCreds);
PutMetricDataRequest request;
request.SetNamespace("MyMetricTest");
MetricDatum datum;
datum.SetMetricName("MyMetricName");
datum.SetValue(100.0);
//This line is the problem!
//(it's also not clear from the documentation what this "double" value actually represents)
datum.SetTimestamp(static_cast<double>(GetMillisSinceEpoch()));
Aws::Vector<MetricDatum> metrics;
metrics.push_back(datum);
request.SetMetricData(metrics);
char requestDump[4096];
request.GetBody()->getline(requestDump, 4096);
std::cout << "REQUEST = " << requestDump << std::endl;
PutMetricDataOutcome outcome = client.PutMetricData(request);
if (!outcome.IsSuccess())
{
std::cout << "ERROR: " << outcome.GetError().GetExceptionName() << "::" << outcome.GetError().GetMessage() << std::endl;
}
std::cout << "Transmission " << (outcome.IsSuccess() ? "success" : "failure") << std::endl;
char dummy[256];
std::cin.getline(dummy, 256);
}
Metadata
Metadata
Assignees
Labels
No labels