Skip to content

Commit 262c43b

Browse files
committed
feat: add gzip compression tracking to User-Agent metrics
- Add test to verify 'L' metric appears in User-Agent when gzip compression is used - Enable compression in test setup and mock client - Validate business metrics tracking for request compression feature update logic for compression unit test
1 parent a8fddd7 commit 262c43b

File tree

6 files changed

+146
-1
lines changed

6 files changed

+146
-1
lines changed

cmake/sdksCommon.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ list(APPEND SDK_TEST_PROJECT_LIST "kinesis:tests/aws-cpp-sdk-kinesis-integration
101101
list(APPEND SDK_TEST_PROJECT_LIST "lambda:tests/aws-cpp-sdk-lambda-integration-tests")
102102
list(APPEND SDK_TEST_PROJECT_LIST "logs:tests/aws-cpp-sdk-logs-integration-tests,tests/aws-cpp-sdk-logs-unit-tests")
103103
list(APPEND SDK_TEST_PROJECT_LIST "mediastore-data:tests/aws-cpp-sdk-mediastore-data-integration-tests")
104-
list(APPEND SDK_TEST_PROJECT_LIST "monitoring:tests/aws-cpp-sdk-monitoring-integration-tests")
104+
list(APPEND SDK_TEST_PROJECT_LIST "monitoring:tests/aws-cpp-sdk-monitoring-integration-tests,tests/aws-cpp-sdk-monitoring-unit-tests")
105105
list(APPEND SDK_TEST_PROJECT_LIST "rds:tests/aws-cpp-sdk-rds-integration-tests")
106106
list(APPEND SDK_TEST_PROJECT_LIST "redshift:tests/aws-cpp-sdk-redshift-integration-tests")
107107
list(APPEND SDK_TEST_PROJECT_LIST "s3:tests/aws-cpp-sdk-s3-integration-tests")

src/aws-cpp-sdk-core/include/aws/core/client/UserAgent.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ enum class UserAgentFeature {
3131
ACCOUNT_ID_MODE_DISABLED,
3232
ACCOUNT_ID_MODE_REQUIRED,
3333
RESOLVED_ACCOUNT_ID,
34+
GZIP_REQUEST_COMPRESSION,
3435
};
3536

3637
class AWS_CORE_API UserAgent {

src/aws-cpp-sdk-core/source/client/AWSClient.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,9 @@ void AWSClient::BuildHttpRequest(const Aws::AmazonWebServiceRequest& request, co
910910
if (compressOutcome.IsSuccess()) {
911911
Aws::String compressionAlgorithmId = Aws::Client::GetCompressionAlgorithmId(selectedCompressionAlgorithm);
912912
AppendHeaderValueToRequest(httpRequest, CONTENT_ENCODING_HEADER, compressionAlgorithmId);
913+
if (selectedCompressionAlgorithm == Aws::Client::CompressionAlgorithm::GZIP) {
914+
request.AddUserAgentFeature(Aws::Client::UserAgentFeature::GZIP_REQUEST_COMPRESSION);
915+
}
913916
AddContentBodyToRequest(
914917
httpRequest, compressOutcome.GetResult(),
915918
request.ShouldComputeContentMd5(),

src/aws-cpp-sdk-core/source/client/UserAgent.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const std::pair<UserAgentFeature, const char*> BUSINESS_METRIC_MAPPING[] = {
4141
{UserAgentFeature::ACCOUNT_ID_MODE_DISABLED , "Q"},
4242
{UserAgentFeature::ACCOUNT_ID_MODE_REQUIRED, "R"},
4343
{UserAgentFeature::RESOLVED_ACCOUNT_ID, "T"},
44+
{UserAgentFeature::GZIP_REQUEST_COMPRESSION, "L"},
4445
};
4546

4647
Aws::String BusinessMetricForFeature(UserAgentFeature feature) {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
add_project(aws-cpp-sdk-monitoring-unit-tests
2+
"Unit Tests for the CloudWatch Monitoring Client"
3+
aws-cpp-sdk-monitoring
4+
testing-resources
5+
aws_test_main
6+
aws-cpp-sdk-core)
7+
8+
add_definitions(-DRESOURCES_DIR="${CMAKE_CURRENT_SOURCE_DIR}/resources")
9+
10+
if(MSVC AND BUILD_SHARED_LIBS)
11+
add_definitions(-DGTEST_LINKED_AS_SHARED_LIBRARY=1)
12+
endif()
13+
14+
enable_testing()
15+
16+
if(PLATFORM_ANDROID AND BUILD_SHARED_LIBS)
17+
add_library(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/CloudWatchUnitTest.cpp)
18+
else()
19+
add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/CloudWatchUnitTest.cpp)
20+
endif()
21+
22+
set_compiler_flags(${PROJECT_NAME})
23+
set_compiler_warnings(${PROJECT_NAME})
24+
25+
target_link_libraries(${PROJECT_NAME} ${PROJECT_LIBS})
26+
27+
if(MSVC AND BUILD_SHARED_LIBS)
28+
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "/DELAYLOAD:aws-cpp-sdk-monitoring.dll /DELAYLOAD:aws-cpp-sdk-core.dll")
29+
target_link_libraries(${PROJECT_NAME} delayimp.lib)
30+
endif()
31+
32+
include(GoogleTest)
33+
gtest_add_tests(TARGET ${PROJECT_NAME})
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/**
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
6+
#include <aws/core/auth/AWSCredentials.h>
7+
#include <aws/core/http/standard/StandardHttpRequest.h>
8+
#include <aws/core/http/standard/StandardHttpResponse.h>
9+
#include <aws/core/utils/Outcome.h>
10+
#include <aws/monitoring/CloudWatchClient.h>
11+
#include <aws/monitoring/model/PutMetricDataRequest.h>
12+
#include <aws/testing/AwsCppSdkGTestSuite.h>
13+
#include <aws/testing/AwsTestHelpers.h>
14+
#include <aws/testing/mocks/http/MockHttpClient.h>
15+
#include <aws/core/utils/StringUtils.h>
16+
#include <gtest/gtest.h>
17+
#include <algorithm>
18+
#include <iostream>
19+
20+
using namespace Aws::Auth;
21+
using namespace Aws::Http;
22+
using namespace Aws::Client;
23+
using namespace Aws::CloudWatch;
24+
using namespace Aws::CloudWatch::Model;
25+
26+
const char* LOG_TAG = "CloudWatchTest";
27+
28+
class CloudWatchTest : public Aws::Testing::AwsCppSdkGTestSuite {
29+
protected:
30+
std::shared_ptr<MockHttpClient> m_mockHttpClient;
31+
std::shared_ptr<MockHttpClientFactory> m_mockHttpClientFactory;
32+
33+
void SetUp() {
34+
m_mockHttpClient = Aws::MakeShared<MockHttpClient>(LOG_TAG);
35+
m_mockHttpClientFactory = Aws::MakeShared<MockHttpClientFactory>(LOG_TAG);
36+
m_mockHttpClientFactory->SetClient(m_mockHttpClient);
37+
SetHttpClientFactory(m_mockHttpClientFactory);
38+
}
39+
40+
void TearDown() {
41+
m_mockHttpClient->Reset();
42+
m_mockHttpClient = nullptr;
43+
m_mockHttpClientFactory = nullptr;
44+
Aws::Http::CleanupHttp();
45+
Aws::Http::InitHttp();
46+
}
47+
};
48+
49+
TEST_F(CloudWatchTest, TestUserAgentCompressionTracking) {
50+
#ifndef ENABLED_ZLIB_REQUEST_COMPRESSION
51+
GTEST_SKIP() << "ZLIB compression not available in this build";
52+
#endif
53+
// Setup mock response with proper CloudWatch XML
54+
std::shared_ptr<HttpRequest> requestTmp =
55+
CreateHttpRequest(Aws::Http::URI("dummy"), Aws::Http::HttpMethod::HTTP_POST, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod);
56+
auto successResponse = Aws::MakeShared<Standard::StandardHttpResponse>(LOG_TAG, requestTmp);
57+
successResponse->SetResponseCode(HttpResponseCode::OK);
58+
successResponse->GetResponseBody() << "<PutMetricDataResponse><ResponseMetadata><RequestId>test-request-id</RequestId></ResponseMetadata></PutMetricDataResponse>";
59+
m_mockHttpClient->AddResponseToReturn(successResponse);
60+
61+
// Create client with compression enabled
62+
Aws::Client::ClientConfigurationInitValues cfgInit;
63+
cfgInit.shouldDisableIMDS = true;
64+
Aws::Client::ClientConfiguration clientConfig(cfgInit);
65+
clientConfig.region = Aws::Region::US_EAST_1;
66+
clientConfig.requestCompressionConfig.useRequestCompression = UseRequestCompression::ENABLE;
67+
clientConfig.requestCompressionConfig.requestMinCompressionSizeBytes = 10240;
68+
69+
AWSCredentials credentials{"mock", "credentials"};
70+
CloudWatchClient client(credentials, clientConfig);
71+
72+
// Create request with large payload to trigger compression
73+
PutMetricDataRequest request;
74+
request.SetNamespace("TestNamespace");
75+
76+
// Add large metric data to trigger compression
77+
MetricDatum metricDatum;
78+
metricDatum.SetMetricName("TestMetric");
79+
metricDatum.SetValue(123.45);
80+
metricDatum.SetTimestamp(Aws::Utils::DateTime::Now());
81+
82+
// Create large metadata to exceed compression threshold
83+
Aws::String largeValue(20000, 'A'); // 20KB value to exceed compression threshold
84+
Dimension dimension;
85+
dimension.SetName("LargeDimension");
86+
dimension.SetValue(largeValue);
87+
metricDatum.AddDimensions(dimension);
88+
89+
request.AddMetricData(metricDatum);
90+
91+
auto outcome = client.PutMetricData(request);
92+
AWS_ASSERT_SUCCESS(outcome);
93+
94+
// Verify User-Agent contains compression metric
95+
auto lastRequest = m_mockHttpClient->GetMostRecentHttpRequest();
96+
EXPECT_TRUE(lastRequest.HasUserAgent());
97+
const auto& userAgent = lastRequest.GetUserAgent();
98+
EXPECT_TRUE(!userAgent.empty());
99+
100+
const auto userAgentParsed = Aws::Utils::StringUtils::Split(userAgent, ' ');
101+
102+
// Check for gzip compression business metric (L) in user agent
103+
auto businessMetrics = std::find_if(userAgentParsed.begin(), userAgentParsed.end(),
104+
[](const Aws::String& value) { return value.find("m/") != Aws::String::npos && value.find("L") != Aws::String::npos; });
105+
106+
EXPECT_TRUE(businessMetrics != userAgentParsed.end());
107+
}

0 commit comments

Comments
 (0)