in src/cdi/cloudwatch_sdk_metrics.cpp [327:425]
CdiReturnStatus UserMetrics::Send(const CloudWatchTransferStats* stats_ptr)
{
CdiReturnStatus rs = kCdiStatusOk;
// Create CloudWatchClient dynamically, otherwise AWS-SDK can generate broken pipe exceptions.
Aws::Client::ClientConfiguration client_config;
// Set region and create an instance of the CloudWatchClient.
client_config.region = m_region_str;
Aws::CloudWatch::CloudWatchClient cw(client_config);
PutMetricDataRequest request;
request.SetNamespace(m_namespace_str);
const Aws::Utils::DateTime timestamp(static_cast<int64_t>(stats_ptr->timestamp_in_ms_since_epoch));
const char* direction_str = stats_ptr->is_receiver ? "Rx" : "Tx";
const char* connection_str = stats_ptr->dimension_connection_str;
const bool high_resolution = stats_ptr->high_resolution;
AddDatum(request, connection_str, direction_str, high_resolution, timestamp, "DroppedPayloads",
stats_ptr->count_based_delta_stats.delta_num_payloads_dropped, StandardUnit::Count);
AddDatum(request, connection_str, direction_str, high_resolution, timestamp, "LatePayloads",
stats_ptr->count_based_delta_stats.delta_num_payloads_late, StandardUnit::Count);
AddDatum(request, connection_str, direction_str, high_resolution, timestamp, "Disconnections",
stats_ptr->count_based_delta_stats.delta_dropped_connection_count, StandardUnit::Count);
AddDatum(request, connection_str, direction_str, high_resolution, timestamp, "Connected",
stats_ptr->connected, StandardUnit::None);
AddDatum(request, connection_str, direction_str, high_resolution, timestamp, "CpuUtilization",
stats_ptr->cpu_utilization / 100, StandardUnit::Percent);
AddDatum(request, connection_str, direction_str, high_resolution, timestamp, "ProbeRetries",
stats_ptr->count_based_delta_stats.delta_probe_command_retry_count, StandardUnit::Count);
AddDatum(request, connection_str, direction_str, high_resolution, timestamp, "BytesTransferred",
stats_ptr->count_based_delta_stats.delta_num_bytes_transferred, StandardUnit::Bytes);
AddDatum(request, connection_str, direction_str, high_resolution, timestamp, "PayloadTimeP50",
stats_ptr->payload_time_interval_stats.transfer_time_P50, StandardUnit::Microseconds);
AddDatum(request, connection_str, direction_str, high_resolution, timestamp, "PayloadTimeP90",
stats_ptr->payload_time_interval_stats.transfer_time_P90, StandardUnit::Microseconds);
AddDatum(request, connection_str, direction_str, high_resolution, timestamp, "PayloadTimeP99",
stats_ptr->payload_time_interval_stats.transfer_time_P99, StandardUnit::Microseconds);
if (0 != stats_ptr->payload_time_interval_stats.transfer_count) {
AddDatum(request, connection_str, direction_str, high_resolution, timestamp, "PayloadTime",
stats_ptr->payload_time_interval_stats.transfer_count,
stats_ptr->payload_time_interval_stats.transfer_time_min,
stats_ptr->payload_time_interval_stats.transfer_time_max,
stats_ptr->payload_time_interval_stats.transfer_time_sum,
StandardUnit::Microseconds);
}
PutMetricDataOutcome outcome;
try {
outcome = cw.PutMetricData(request);
} catch (...) {
// Should never get here, but just to be safe catch all exceptions.
CDI_LOG_THREAD(kLogError, "PutMetricData() failed. Caught an unexpected exception.");
rs = kCdiStatusCloudWatchThrottling;
}
if (kCdiStatusOk == rs && !outcome.IsSuccess()) {
auto error = outcome.GetError();
Aws::CloudWatch::CloudWatchErrors err_type = error.GetErrorType();
if (err_type == Aws::CloudWatch::CloudWatchErrors::THROTTLING) {
// NOTE: Default limits for PutMetricData() are: 40 KB for HTTP POST requests. PutMetricData can handle
// 150 transactions per second (TPS), which is the maximum number of operation requests you can make per
// second without being throttled. You can request a quota increase through AWS.
CDI_LOG_THREAD(kLogInfo, "PutMetricData() is being throttling by AWS-SDK. Message[%s].",
outcome.GetError().GetMessage().c_str());
rs = kCdiStatusCloudWatchThrottling;
} else if (err_type == Aws::CloudWatch::CloudWatchErrors::INVALID_CLIENT_TOKEN_ID ||
err_type == Aws::CloudWatch::CloudWatchErrors::INVALID_ACCESS_KEY_ID ||
err_type == Aws::CloudWatch::CloudWatchErrors::SIGNATURE_DOES_NOT_MATCH ||
err_type == Aws::CloudWatch::CloudWatchErrors::MISSING_AUTHENTICATION_TOKEN) {
// In testing, if the access key is wrong, INVALID_CLIENT_TOKEN_ID is returned. If the secret key is wrong,
// SIGNATURE_DOES_NOT_MATCH is returned. Added INVALID_ACCESS_KEY_ID to this list too.
CDI_LOG_THREAD(kLogError, "PutMetricData() failed. Check credentials. ErrorType[%d] Message[%s].",
err_type, outcome.GetError().GetMessage().c_str());
rs = kCdiStatusCloudWatchInvalidCredentials;
} else if (err_type == Aws::CloudWatch::CloudWatchErrors::INVALID_PARAMETER_COMBINATION ||
err_type == Aws::CloudWatch::CloudWatchErrors::INVALID_QUERY_PARAMETER ||
err_type == Aws::CloudWatch::CloudWatchErrors::INVALID_PARAMETER_VALUE ||
err_type == Aws::CloudWatch::CloudWatchErrors::VALIDATION ||
err_type == Aws::CloudWatch::CloudWatchErrors::MISSING_PARAMETER ||
err_type == Aws::CloudWatch::CloudWatchErrors::MISSING_REQUIRED_PARAMETER ||
err_type == Aws::CloudWatch::CloudWatchErrors::MALFORMED_QUERY_STRING ||
err_type == Aws::CloudWatch::CloudWatchErrors::MISSING_ACTION ||
err_type == Aws::CloudWatch::CloudWatchErrors::INVALID_ACTION) {
CDI_LOG_THREAD(kLogError, "PutMetricData() failed. ErrorType[%d] Message[%s].", err_type,
outcome.GetError().GetMessage().c_str());
rs = kCdiStatusFatal;
} else {
CDI_LOG_THREAD(kLogError,
"PutMetricData() failed. Throttling due to unexpected error. ErrorType[%d] Message[%s].",
err_type,
outcome.GetError().GetMessage().c_str());
rs = kCdiStatusCloudWatchThrottling;
}
}
return rs;
}