From 3461d6a3394ec112182fc2ff9181ede016f1b58c Mon Sep 17 00:00:00 2001 From: Marco Magdy Date: Tue, 11 Dec 2018 07:19:11 -0800 Subject: [PATCH] Add User-Agent information (#11) * Add User-Agent information Send a user-agent http header when talking to Lambda's http server. This is important for collecting usage metrics. --- CMakeLists.txt | 17 +++++++--- ci/codebuild/build-cpp-sdk.sh | 2 +- include/aws/lambda-runtime/version.h | 41 ++++++++++++++++++++++++ src/runtime.cpp | 20 +++++++++--- src/version.cpp.in | 48 ++++++++++++++++++++++++++++ tests/CMakeLists.txt | 7 ++-- tests/version_tests.cpp | 22 +++++++++++++ 7 files changed, 143 insertions(+), 14 deletions(-) create mode 100644 include/aws/lambda-runtime/version.h create mode 100644 src/version.cpp.in create mode 100644 tests/version_tests.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 598306f..9ddf898 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 11) project(aws-lambda-runtime - VERSION 0.1 + VERSION 0.1.0 LANGUAGES CXX) option(ENABLE_TESTS "Enables building the test project, requires AWS C++ SDK." OFF) @@ -26,6 +26,7 @@ check_cxx_compiler_flag("-Wl,-flto" LTO_CAPABLE) add_library(${PROJECT_NAME} "src/logging.cpp" "src/runtime.cpp" + "${CMAKE_CURRENT_BINARY_DIR}/version.cpp" ) target_include_directories(${PROJECT_NAME} PUBLIC @@ -51,11 +52,11 @@ target_compile_options(${PROJECT_NAME} PRIVATE "-Wno-sign-conversion") if (LOG_VERBOSITY) - target_compile_definitions(${PROJECT_NAME} PRIVATE "-DAWS_LAMBDA_LOG=${LOG_VERBOSITY}") + target_compile_definitions(${PROJECT_NAME} PRIVATE "AWS_LAMBDA_LOG=${LOG_VERBOSITY}") elseif(CMAKE_BUILD_TYPE STREQUAL Debug) - target_compile_definitions(${PROJECT_NAME} PRIVATE "-DAWS_LAMBDA_LOG=3") + target_compile_definitions(${PROJECT_NAME} PRIVATE "AWS_LAMBDA_LOG=3") else () - target_compile_definitions(${PROJECT_NAME} PRIVATE "-DAWS_LAMBDA_LOG=0") + target_compile_definitions(${PROJECT_NAME} PRIVATE "AWS_LAMBDA_LOG=0") endif() if ((BUILD_SHARED_LIBS) AND (LTO_CAPABLE)) @@ -69,8 +70,14 @@ if (ENABLE_TESTS) add_subdirectory(tests) endif() +#versioning +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/src/version.cpp.in" + "${CMAKE_CURRENT_BINARY_DIR}/version.cpp" + NEWLINE_STYLE LF) + # installation -install(FILES "include/aws/lambda-runtime/runtime.h" +install(FILES "include/aws/lambda-runtime/runtime.h" "include/aws/lambda-runtime/version.h" DESTINATION "include/aws/lambda-runtime") install(FILES "include/aws/logging/logging.h" diff --git a/ci/codebuild/build-cpp-sdk.sh b/ci/codebuild/build-cpp-sdk.sh index 4871923..93ae7eb 100755 --- a/ci/codebuild/build-cpp-sdk.sh +++ b/ci/codebuild/build-cpp-sdk.sh @@ -11,7 +11,7 @@ cmake .. -GNinja -DBUILD_ONLY="lambda" \ -DCMAKE_BUILD_TYPE=Release \ -DENABLE_UNITY_BUILD=ON \ -DBUILD_SHARED_LIBS=ON \ - -DAUTORUN_UNIT_TESTS=OFF \ + -DENABLE_TESTING=OFF \ -DCMAKE_INSTALL_PREFIX=/install $@ ninja ninja install diff --git a/include/aws/lambda-runtime/version.h b/include/aws/lambda-runtime/version.h new file mode 100644 index 0000000..eafcbde --- /dev/null +++ b/include/aws/lambda-runtime/version.h @@ -0,0 +1,41 @@ +#pragma once +/* + * Copyright 2018-present Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +namespace aws { +namespace lambda_runtime { + +/** + * Returns the major component of the library version. + */ +unsigned get_version_major(); + +/** + * Returns the minor component of the library version. + */ +unsigned get_version_minor(); + +/** + * Returns the patch component of the library version. + */ +unsigned get_version_patch(); + +/** + * Returns the semantic version of the library in the form Major.Minor.Patch + */ +char const* get_version(); + +} // namespace lambda_runtime +} // namespace aws diff --git a/src/runtime.cpp b/src/runtime.cpp index 5df6d67..0af68b2 100644 --- a/src/runtime.cpp +++ b/src/runtime.cpp @@ -14,6 +14,7 @@ */ #include "aws/lambda-runtime/runtime.h" +#include "aws/lambda-runtime/version.h" #include "aws/lambda-runtime/outcome.h" #include "aws/logging/logging.h" #include "aws/http/response.h" @@ -26,7 +27,7 @@ #include #include // for strtoul -#define LAMBDA_RUNTIME_API __attribute__((visibility("default"))) +#define AWS_LAMBDA_RUNTIME_API __attribute__((visibility("default"))) namespace aws { namespace lambda_runtime { @@ -105,6 +106,12 @@ static size_t write_header(char* ptr, size_t size, size_t nmemb, void* userdata) return size * nmemb; } +static std::string const& get_user_agent_header() +{ + static std::string user_agent = std::string("User-Agent: AWS_Lambda_Cpp/") + get_version(); + return user_agent; +} + static size_t read_data(char* buffer, size_t size, size_t nitems, void* userdata) { auto const limit = size * nitems; @@ -243,9 +250,13 @@ runtime::next_outcome runtime::get_next() curl_easy_setopt(m_curl_handle, CURLOPT_WRITEDATA, &resp); curl_easy_setopt(m_curl_handle, CURLOPT_HEADERDATA, &resp); + curl_slist* headers = nullptr; + headers = curl_slist_append(headers, get_user_agent_header().c_str()); + logging::log_debug(LOG_TAG, "Making request to %s", m_endpoints[Endpoints::NEXT].c_str()); CURLcode curl_code = curl_easy_perform(m_curl_handle); logging::log_debug(LOG_TAG, "Completed request to %s", m_endpoints[Endpoints::NEXT].c_str()); + curl_slist_free_all(headers); if (curl_code != CURLE_OK) { logging::log_debug(LOG_TAG, "CURL returned error code %d - %s", curl_code, curl_easy_strerror(curl_code)); @@ -343,6 +354,7 @@ runtime::post_outcome runtime::do_post( headers = curl_slist_append(headers, "Expect:"); headers = curl_slist_append(headers, "transfer-encoding:"); + headers = curl_slist_append(headers, get_user_agent_header().c_str()); auto const& payload = handler_response.get_payload(); logging::log_debug( LOG_TAG, "calculating content length... %s", ("content-length: " + std::to_string(payload.length())).c_str()); @@ -398,7 +410,7 @@ static bool handle_post_outcome(runtime::post_outcome const& o, std::string cons return false; } -LAMBDA_RUNTIME_API +AWS_LAMBDA_RUNTIME_API void run_handler(std::function const& handler) { logging::log_info(LOG_TAG, "Initializing the C++ Lambda Runtime."); @@ -501,7 +513,7 @@ static std::string json_escape(std::string const& in) return out; } -LAMBDA_RUNTIME_API +AWS_LAMBDA_RUNTIME_API invocation_response invocation_response::success(std::string const& payload, std::string const& content_type) { invocation_response r; @@ -511,7 +523,7 @@ invocation_response invocation_response::success(std::string const& payload, std return r; } -LAMBDA_RUNTIME_API +AWS_LAMBDA_RUNTIME_API invocation_response invocation_response::failure(std::string const& error_message, std::string const& error_type) { invocation_response r; diff --git a/src/version.cpp.in b/src/version.cpp.in new file mode 100644 index 0000000..cb91ad4 --- /dev/null +++ b/src/version.cpp.in @@ -0,0 +1,48 @@ +/* + * Copyright 2018-present Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#define AWS_LAMBDA_RUNTIME_API __attribute__((visibility("default"))) + +namespace aws { +namespace lambda_runtime { + +/* clang-format off */ +AWS_LAMBDA_RUNTIME_API +unsigned get_version_major() +{ + return @PROJECT_VERSION_MAJOR@; +} + +AWS_LAMBDA_RUNTIME_API +unsigned get_version_minor() +{ + return @PROJECT_VERSION_MINOR@; +} + +AWS_LAMBDA_RUNTIME_API +unsigned get_version_patch() +{ + return @PROJECT_VERSION_PATCH@; +} +/* clang-format on */ + +AWS_LAMBDA_RUNTIME_API +char const* get_version() +{ + return "@PROJECT_VERSION@"; +} + +} // namespace lambda_runtime +} // namespace aws diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f1dabad..26a6d1c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,13 +4,12 @@ find_package(GTest REQUIRED) add_executable(${PROJECT_NAME} main.cpp - runtime_tests.cpp) + runtime_tests.cpp + version_tests.cpp) target_link_libraries(${PROJECT_NAME} PRIVATE ${AWSSDK_LINK_LIBRARIES} aws-lambda-runtime GTest::GTest) -# gtest_discover_tests(${PROJECT_NAME}) Can't use this until CMake 3.10 :( -# gtest_add_tests(TARGET ${PROJECT_NAME} runtime_tests.cpp) -GTEST_ADD_TESTS(${PROJECT_NAME} "" AUTO) +gtest_discover_tests(${PROJECT_NAME}) # requires CMake 3.10 or later add_subdirectory(resources) diff --git a/tests/version_tests.cpp b/tests/version_tests.cpp new file mode 100644 index 0000000..5a2cc98 --- /dev/null +++ b/tests/version_tests.cpp @@ -0,0 +1,22 @@ +#include +#include + +using namespace aws::lambda_runtime; + +TEST(VersionTests, get_version_major) +{ + auto version = get_version_major(); + ASSERT_EQ(0, version); +} + +TEST(VersionTests, get_version_minor) +{ + auto version = get_version_minor(); + ASSERT_GE(version, 1); +} + +TEST(VersionTests, get_version_patch) +{ + auto version = get_version_patch(); + ASSERT_GE(version, 0); +}