From 8b418fee835d89a7978e9471cbce07194d0a70a2 Mon Sep 17 00:00:00 2001 From: WenTao Ou Date: Fri, 13 Dec 2024 21:41:46 +0800 Subject: [PATCH 01/12] [TEST] Change `is_called_` and `got_response_` to use atomic (#3204) --- ext/test/http/curl_http_test.cc | 55 ++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/ext/test/http/curl_http_test.cc b/ext/test/http/curl_http_test.cc index 137c9b7f9b..1b4289f400 100644 --- a/ext/test/http/curl_http_test.cc +++ b/ext/test/http/curl_http_test.cc @@ -33,7 +33,7 @@ class CustomEventHandler : public http_client::EventHandler public: void OnResponse(http_client::Response & /* response */) noexcept override { - got_response_ = true; + got_response_.store(true, std::memory_order_release); } void OnEvent(http_client::SessionState state, nostd::string_view /* reason */) noexcept override { @@ -41,16 +41,20 @@ class CustomEventHandler : public http_client::EventHandler { case http_client::SessionState::ConnectFailed: case http_client::SessionState::SendFailed: { - is_called_ = true; + is_called_.store(true, std::memory_order_release); break; } default: break; } } + + CustomEventHandler() : is_called_(false), got_response_(false) {} + ~CustomEventHandler() override = default; - bool is_called_ = false; - bool got_response_ = false; + + std::atomic is_called_; + std::atomic got_response_; }; class GetEventHandler : public CustomEventHandler @@ -59,8 +63,8 @@ class GetEventHandler : public CustomEventHandler { ASSERT_EQ(200, response.GetStatusCode()); ASSERT_EQ(response.GetBody().size(), 0); - is_called_ = true; - got_response_ = true; + is_called_.store(true, std::memory_order_release); + got_response_.store(true, std::memory_order_release); } }; @@ -71,8 +75,8 @@ class PostEventHandler : public CustomEventHandler ASSERT_EQ(200, response.GetStatusCode()); std::string body(response.GetBody().begin(), response.GetBody().end()); ASSERT_EQ(body, "{'k1':'v1', 'k2':'v2', 'k3':'v3'}"); - is_called_ = true; - got_response_ = true; + is_called_.store(true, std::memory_order_release); + got_response_.store(true, std::memory_order_release); } }; @@ -87,8 +91,8 @@ class FinishInCallbackHandler : public CustomEventHandler { ASSERT_EQ(200, response.GetStatusCode()); ASSERT_EQ(response.GetBody().size(), 0); - is_called_ = true; - got_response_ = true; + is_called_.store(true, std::memory_order_release); + got_response_.store(true, std::memory_order_release); if (session_) { @@ -249,8 +253,8 @@ TEST_F(BasicCurlHttpTests, SendGetRequest) session->SendRequest(handler); ASSERT_TRUE(waitForRequests(30, 1)); session->FinishSession(); - ASSERT_TRUE(handler->is_called_); - ASSERT_TRUE(handler->got_response_); + ASSERT_TRUE(handler->is_called_.load(std::memory_order_acquire)); + ASSERT_TRUE(handler->got_response_.load(std::memory_order_acquire)); } TEST_F(BasicCurlHttpTests, SendPostRequest) @@ -272,8 +276,8 @@ TEST_F(BasicCurlHttpTests, SendPostRequest) session->SendRequest(handler); ASSERT_TRUE(waitForRequests(30, 1)); session->FinishSession(); - ASSERT_TRUE(handler->is_called_); - ASSERT_TRUE(handler->got_response_); + ASSERT_TRUE(handler->is_called_.load(std::memory_order_acquire)); + ASSERT_TRUE(handler->got_response_.load(std::memory_order_acquire)); session_manager->CancelAllSessions(); session_manager->FinishAllSessions(); @@ -291,8 +295,8 @@ TEST_F(BasicCurlHttpTests, RequestTimeout) auto handler = std::make_shared(); session->SendRequest(handler); session->FinishSession(); - ASSERT_TRUE(handler->is_called_); - ASSERT_FALSE(handler->got_response_); + ASSERT_TRUE(handler->is_called_.load(std::memory_order_acquire)); + ASSERT_FALSE(handler->got_response_.load(std::memory_order_acquire)); } TEST_F(BasicCurlHttpTests, CurlHttpOperations) @@ -408,8 +412,8 @@ TEST_F(BasicCurlHttpTests, SendGetRequestAsync) sessions[i]->FinishSession(); ASSERT_FALSE(sessions[i]->IsSessionActive()); - ASSERT_TRUE(handlers[i]->is_called_); - ASSERT_TRUE(handlers[i]->got_response_); + ASSERT_TRUE(handlers[i]->is_called_.load(std::memory_order_acquire)); + ASSERT_TRUE(handlers[i]->got_response_.load(std::memory_order_acquire)); } http_client.WaitBackgroundThreadExit(); @@ -437,7 +441,8 @@ TEST_F(BasicCurlHttpTests, SendGetRequestAsyncTimeout) // Lock mtx_requests to prevent response, we will check IsSessionActive() in the end std::unique_lock lock_requests(mtx_requests); sessions[i]->SendRequest(handlers[i]); - ASSERT_TRUE(sessions[i]->IsSessionActive() || handlers[i]->is_called_); + ASSERT_TRUE(sessions[i]->IsSessionActive() || + handlers[i]->is_called_.load(std::memory_order_acquire)); } for (unsigned i = 0; i < batch_count; ++i) @@ -445,8 +450,8 @@ TEST_F(BasicCurlHttpTests, SendGetRequestAsyncTimeout) sessions[i]->FinishSession(); ASSERT_FALSE(sessions[i]->IsSessionActive()); - ASSERT_TRUE(handlers[i]->is_called_); - ASSERT_FALSE(handlers[i]->got_response_); + ASSERT_TRUE(handlers[i]->is_called_.load(std::memory_order_acquire)); + ASSERT_FALSE(handlers[i]->got_response_.load(std::memory_order_acquire)); } } @@ -482,8 +487,8 @@ TEST_F(BasicCurlHttpTests, SendPostRequestAsync) ASSERT_FALSE(session->IsSessionActive()); } - ASSERT_TRUE(handler->is_called_); - ASSERT_TRUE(handler->got_response_); + ASSERT_TRUE(handler->is_called_.load(std::memory_order_acquire)); + ASSERT_TRUE(handler->got_response_.load(std::memory_order_acquire)); http_client.WaitBackgroundThreadExit(); } @@ -521,8 +526,8 @@ TEST_F(BasicCurlHttpTests, FinishInAsyncCallback) { ASSERT_FALSE(sessions[i]->IsSessionActive()); - ASSERT_TRUE(handlers[i]->is_called_); - ASSERT_TRUE(handlers[i]->got_response_); + ASSERT_TRUE(handlers[i]->is_called_.load(std::memory_order_acquire)); + ASSERT_TRUE(handlers[i]->got_response_.load(std::memory_order_acquire)); } } } From 6ed0651a42c88e347ff37b0f3171ab0f31d9edcb Mon Sep 17 00:00:00 2001 From: David Ashpole Date: Sat, 14 Dec 2024 05:59:28 -0500 Subject: [PATCH 02/12] [SEMANTIC CONVENTIONS] Update links to openmetrics to reference the v1.0.0 release (#3205) --- api/include/opentelemetry/semconv/incubating/hw_metrics.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/include/opentelemetry/semconv/incubating/hw_metrics.h b/api/include/opentelemetry/semconv/incubating/hw_metrics.h index 3a87fd2506..d950950f35 100644 --- a/api/include/opentelemetry/semconv/incubating/hw_metrics.h +++ b/api/include/opentelemetry/semconv/incubating/hw_metrics.h @@ -132,7 +132,7 @@ static inline nostd::shared_ptr CreateAsyncDouble * states

* @code hw.status @endcode is currently specified as an UpDownCounter but would ideally be * represented using a StateSet + * href="https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#stateset">StateSet * as defined in OpenMetrics. This semantic convention will be updated once StateSet is * specified in OpenTelemetry. This planned change is not expected to have any consequence on the * way users query their timeseries backend to retrieve the values of @code hw.status @endcode over From b7418152a08b00845cdcffeb557ee9e77f5f22a3 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Tue, 17 Dec 2024 17:24:48 +0100 Subject: [PATCH 03/12] [CI] Fix CI on ubuntu-latest (#3207) --- .github/workflows/ci.yml | 34 +++++++++++++-------------- .github/workflows/codeql-analysis.yml | 4 ++-- .github/workflows/iwyu.yml | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2cb354d5db..efc01e2a00 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,15 +49,15 @@ jobs: submodules: 'recursive' - name: setup env: - CC: /usr/bin/gcc-10 - CXX: /usr/bin/g++-10 + CC: /usr/bin/gcc-12 + CXX: /usr/bin/g++-12 run: | sudo -E ./ci/setup_googletest.sh sudo -E ./ci/setup_ci_environment.sh - name: run cmake tests (without otlp-exporter) env: - CC: /usr/bin/gcc-10 - CXX: /usr/bin/g++-10 + CC: /usr/bin/gcc-12 + CXX: /usr/bin/g++-12 run: | ./ci/do_ci.sh cmake.test @@ -263,15 +263,15 @@ jobs: submodules: 'recursive' - name: setup env: - CC: /usr/bin/gcc-10 - CXX: /usr/bin/g++-10 + CC: /usr/bin/gcc-12 + CXX: /usr/bin/g++-12 run: | sudo -E ./ci/setup_googletest.sh sudo -E ./ci/setup_ci_environment.sh - name: run cmake tests (without otlp-exporter) env: - CC: /usr/bin/gcc-10 - CXX: /usr/bin/g++-10 + CC: /usr/bin/gcc-12 + CXX: /usr/bin/g++-12 run: | ./ci/do_ci.sh cmake.with_async_export.test @@ -359,7 +359,7 @@ jobs: cmake_test_cxx20_clang: name: CMake C++20 test(Clang with libc++) - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 with: @@ -409,7 +409,7 @@ jobs: cmake_test_cxx23_clang: name: CMake C++23 test(Clang with libc++) - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 with: @@ -538,15 +538,15 @@ jobs: submodules: 'recursive' - name: setup env: - CC: /usr/bin/gcc-10 - CXX: /usr/bin/g++-10 + CC: /usr/bin/gcc-12 + CXX: /usr/bin/g++-12 run: | sudo -E ./ci/setup_googletest.sh sudo -E ./ci/setup_ci_environment.sh - name: run tests env: - CC: /usr/bin/gcc-10 - CXX: /usr/bin/g++-10 + CC: /usr/bin/gcc-12 + CXX: /usr/bin/g++-12 run: ./ci/do_ci.sh cmake.test_example_plugin bazel_test: @@ -858,7 +858,7 @@ jobs: code_coverage: name: Code coverage - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 with: @@ -936,8 +936,8 @@ jobs: submodules: 'recursive' - name: setup env: - CC: /usr/bin/gcc-10 - CXX: /usr/bin/g++-10 + CC: /usr/bin/gcc-12 + CXX: /usr/bin/g++-12 run: | sudo -E ./ci/setup_googletest.sh sudo -E ./ci/setup_ci_environment.sh diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 05acb56180..ebf367e4aa 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -20,8 +20,8 @@ jobs: rm -rf third_party - name: Setup env: - CC: /usr/bin/gcc-10 - CXX: /usr/bin/g++-10 + CC: /usr/bin/gcc-12 + CXX: /usr/bin/g++-12 GOOGLETEST_VERSION: 1.12.1 run: | sudo -E ./ci/setup_googletest.sh diff --git a/.github/workflows/iwyu.yml b/.github/workflows/iwyu.yml index 573af3a803..ae4c5fb96b 100644 --- a/.github/workflows/iwyu.yml +++ b/.github/workflows/iwyu.yml @@ -67,7 +67,7 @@ jobs: readonly WARNING_COUNT=`grep -c "include-what-you-use reported diagnostics:" iwyu.log` echo "include-what-you-use reported ${WARNING_COUNT} warning(s)" # Acceptable limit, to decrease over time down to 0 - readonly WARNING_LIMIT=10 + readonly WARNING_LIMIT=180 # FAIL the build if WARNING_COUNT > WARNING_LIMIT if [ $WARNING_COUNT -gt $WARNING_LIMIT ] ; then exit 1 From 1cbea09cb0c14c42a3d43a75ada8ae18afe39cc2 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Tue, 17 Dec 2024 18:07:01 +0100 Subject: [PATCH 04/12] [BUILD] Build break using protoc 3.14 (#3211) --- exporters/otlp/test/otlp_recordable_test.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exporters/otlp/test/otlp_recordable_test.cc b/exporters/otlp/test/otlp_recordable_test.cc index 0a58e52243..8309811ae0 100644 --- a/exporters/otlp/test/otlp_recordable_test.cc +++ b/exporters/otlp/test/otlp_recordable_test.cc @@ -136,7 +136,8 @@ TEST(OtlpRecordable, SetInstrumentationScopeWithAttributes) ASSERT_EQ(proto_instr_libr.attributes_size(), 1); const auto &proto_attributes = proto_instr_libr.attributes(0); - ASSERT_TRUE(proto_attributes.value().has_string_value()); + // Requires protoc 3.15.0 + // ASSERT_TRUE(proto_attributes.value().has_string_value()); EXPECT_EQ("test_key", proto_attributes.key()); EXPECT_EQ("test_value", proto_attributes.value().string_value()); } From 902ee88bef59dccb84ea0405657d26c77182f0e3 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Tue, 17 Dec 2024 19:49:16 +0100 Subject: [PATCH 05/12] [TEST] Build the singleton test on windows. (#3183) --- api/test/singleton/CMakeLists.txt | 106 +++++++++++++-------------- api/test/singleton/singleton_test.cc | 89 +++++++++++++++------- ci/do_ci.ps1 | 2 + 3 files changed, 116 insertions(+), 81 deletions(-) diff --git a/api/test/singleton/CMakeLists.txt b/api/test/singleton/CMakeLists.txt index 450308cd82..7c30d6e571 100644 --- a/api/test/singleton/CMakeLists.txt +++ b/api/test/singleton/CMakeLists.txt @@ -3,59 +3,53 @@ include(GoogleTest) -# Header only singletons are not available in windows yet. - -if(NOT WIN32) - - add_library(component_a STATIC component_a.cc) - target_link_libraries(component_a opentelemetry_api) - - add_library(component_b STATIC component_b.cc) - target_link_libraries(component_b opentelemetry_api) - - add_library(component_c SHARED component_c.cc) - set_target_properties(component_c PROPERTIES CXX_VISIBILITY_PRESET default) - target_link_libraries(component_c opentelemetry_api) - - add_library(component_d SHARED component_d.cc) - set_target_properties(component_d PROPERTIES CXX_VISIBILITY_PRESET hidden) - target_link_libraries(component_d opentelemetry_api) - - add_library(component_e SHARED component_e.cc) - set_target_properties(component_e PROPERTIES CXX_VISIBILITY_PRESET default) - target_link_libraries(component_e opentelemetry_api) - - add_library(component_f SHARED component_f.cc) - set_target_properties(component_f PROPERTIES CXX_VISIBILITY_PRESET hidden) - target_link_libraries(component_f opentelemetry_api) - - add_library(component_g SHARED component_g.cc) - set_target_properties(component_g PROPERTIES CXX_VISIBILITY_PRESET default) - target_link_libraries(component_g opentelemetry_api) - - add_library(component_h SHARED component_h.cc) - set_target_properties(component_h PROPERTIES CXX_VISIBILITY_PRESET hidden) - target_link_libraries(component_h opentelemetry_api) - - add_executable(singleton_test singleton_test.cc) - - # Not linking with component_g and component_h on purpose - target_link_libraries( - singleton_test - component_a - component_b - component_c - component_d - component_e - component_f - ${GTEST_BOTH_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} - ${CMAKE_DL_LIBS} - opentelemetry_api) - - gtest_add_tests( - TARGET singleton_test - TEST_PREFIX singleton. - TEST_LIST singleton_test) - -endif() +add_library(component_a STATIC component_a.cc) +target_link_libraries(component_a opentelemetry_api) + +add_library(component_b STATIC component_b.cc) +target_link_libraries(component_b opentelemetry_api) + +add_library(component_c SHARED component_c.cc) +set_target_properties(component_c PROPERTIES CXX_VISIBILITY_PRESET default) +target_link_libraries(component_c opentelemetry_api) + +add_library(component_d SHARED component_d.cc) +set_target_properties(component_d PROPERTIES CXX_VISIBILITY_PRESET hidden) +target_link_libraries(component_d opentelemetry_api) + +add_library(component_e SHARED component_e.cc) +set_target_properties(component_e PROPERTIES CXX_VISIBILITY_PRESET default) +target_link_libraries(component_e opentelemetry_api) + +add_library(component_f SHARED component_f.cc) +set_target_properties(component_f PROPERTIES CXX_VISIBILITY_PRESET hidden) +target_link_libraries(component_f opentelemetry_api) + +add_library(component_g SHARED component_g.cc) +set_target_properties(component_g PROPERTIES CXX_VISIBILITY_PRESET default) +target_link_libraries(component_g opentelemetry_api) + +add_library(component_h SHARED component_h.cc) +set_target_properties(component_h PROPERTIES CXX_VISIBILITY_PRESET hidden) +target_link_libraries(component_h opentelemetry_api) + +add_executable(singleton_test singleton_test.cc) + +# Not linking with component_g and component_h on purpose +target_link_libraries( + singleton_test + component_a + component_b + component_c + component_d + component_e + component_f + ${GTEST_BOTH_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ${CMAKE_DL_LIBS} + opentelemetry_api) + +gtest_add_tests( + TARGET singleton_test + TEST_PREFIX singleton. + TEST_LIST singleton_test) diff --git a/api/test/singleton/singleton_test.cc b/api/test/singleton/singleton_test.cc index d212221118..8b8cb1587d 100644 --- a/api/test/singleton/singleton_test.cc +++ b/api/test/singleton/singleton_test.cc @@ -4,12 +4,9 @@ #include #include -/* - TODO: - Once singleton are supported for windows, - expand this test to use ::LoadLibrary, ::GetProcAddress, ::FreeLibrary -*/ -#ifndef _WIN32 +#ifdef _WIN32 +# include +#else # include #endif @@ -58,28 +55,57 @@ void do_something() #ifndef BAZEL_BUILD /* Call do_something_in_g() */ +# ifdef _WIN32 + HMODULE component_g = LoadLibraryA("component_g.dll"); +# else void *component_g = dlopen("libcomponent_g.so", RTLD_NOW); +# endif + EXPECT_NE(component_g, nullptr); +# ifdef _WIN32 + auto *func_g = reinterpret_cast(GetProcAddress(component_g, "do_something_in_g")); +# else auto *func_g = reinterpret_cast(dlsym(component_g, "do_something_in_g")); +# endif + EXPECT_NE(func_g, nullptr); (*func_g)(); +# ifdef _WIN32 + FreeLibrary(component_g); +# else dlclose(component_g); +# endif /* Call do_something_in_h() */ +# ifdef _WIN32 + HMODULE component_h = LoadLibraryA("component_h.dll"); +# else void *component_h = dlopen("libcomponent_h.so", RTLD_NOW); +# endif + EXPECT_NE(component_h, nullptr); +# ifdef _WIN32 + auto *func_h = reinterpret_cast(GetProcAddress(component_h, "do_something_in_h")); +# else auto *func_h = reinterpret_cast(dlsym(component_h, "do_something_in_h")); +# endif + EXPECT_NE(func_h, nullptr); (*func_h)(); +# ifdef _WIN32 + FreeLibrary(component_h); +# else dlclose(component_h); -#endif +# endif + +#endif /* BAZEL_BUILD */ } int span_a_lib_count = 0; @@ -316,6 +342,14 @@ void cleanup_otel() trace_api::Provider::SetTracerProvider(provider); } +// TODO: Remove once windows api singletons are supported. +// See https://github.com/open-telemetry/opentelemetry-cpp/issues/2534 +#ifdef _WIN32 +# define RUN_FAILING_WINDOWS_TEST 0 +#else +# define RUN_FAILING_WINDOWS_TEST 1 +#endif + TEST(SingletonTest, Uniqueness) { do_something(); @@ -357,26 +391,31 @@ TEST(SingletonTest, Uniqueness) EXPECT_EQ(span_b_lib_count, 1); EXPECT_EQ(span_b_f1_count, 2); EXPECT_EQ(span_b_f2_count, 1); - EXPECT_EQ(span_c_lib_count, 1); - EXPECT_EQ(span_c_f1_count, 2); - EXPECT_EQ(span_c_f2_count, 1); - EXPECT_EQ(span_d_lib_count, 1); - EXPECT_EQ(span_d_f1_count, 2); - EXPECT_EQ(span_d_f2_count, 1); - EXPECT_EQ(span_e_lib_count, 1); - EXPECT_EQ(span_e_f1_count, 2); - EXPECT_EQ(span_e_f2_count, 1); - EXPECT_EQ(span_f_lib_count, 1); - EXPECT_EQ(span_f_f1_count, 2); - EXPECT_EQ(span_f_f2_count, 1); + +#if RUN_FAILING_WINDOWS_TEST + EXPECT_EQ(span_c_lib_count, 1); // Fails with shared libraries on Windows + EXPECT_EQ(span_c_f1_count, 2); // Fails with shared libraries on Windows + EXPECT_EQ(span_c_f2_count, 1); // Fails with shared libraries on Windows + EXPECT_EQ(span_d_lib_count, 1); // Fails with shared libraries on Windows + EXPECT_EQ(span_d_f1_count, 2); // Fails with shared libraries on Windows + EXPECT_EQ(span_d_f2_count, 1); // Fails with shared libraries on Windows + EXPECT_EQ(span_e_lib_count, 1); // Fails with shared libraries on Windows + EXPECT_EQ(span_e_f1_count, 2); // Fails with shared libraries on Windows + EXPECT_EQ(span_e_f2_count, 1); // Fails with shared libraries on Windows + EXPECT_EQ(span_f_lib_count, 1); // Fails with shared libraries on Windows + EXPECT_EQ(span_f_f1_count, 2); // Fails with shared libraries on Windows + EXPECT_EQ(span_f_f2_count, 1); // Fails with shared libraries on Windows +#endif #ifndef BAZEL_BUILD - EXPECT_EQ(span_g_lib_count, 1); - EXPECT_EQ(span_g_f1_count, 2); - EXPECT_EQ(span_g_f2_count, 1); - EXPECT_EQ(span_h_lib_count, 1); - EXPECT_EQ(span_h_f1_count, 2); - EXPECT_EQ(span_h_f2_count, 1); +# if RUN_FAILING_WINDOWS_TEST + EXPECT_EQ(span_g_lib_count, 1); // Fails with shared libraries on Windows + EXPECT_EQ(span_g_f1_count, 2); // Fails with shared libraries on Windows + EXPECT_EQ(span_g_f2_count, 1); // Fails with shared libraries on Windows + EXPECT_EQ(span_h_lib_count, 1); // Fails with shared libraries on Windows + EXPECT_EQ(span_h_f1_count, 2); // Fails with shared libraries on Windows + EXPECT_EQ(span_h_f2_count, 1); // Fails with shared libraries on Windows +# endif #endif EXPECT_EQ(unknown_span_count, 0); diff --git a/ci/do_ci.ps1 b/ci/do_ci.ps1 index e9c1f64646..a04ec938f5 100644 --- a/ci/do_ci.ps1 +++ b/ci/do_ci.ps1 @@ -27,6 +27,8 @@ $PLUGIN_DIR = Join-Path "$SRC_DIR" "plugin" $VCPKG_DIR = Join-Path "$SRC_DIR" "tools" "vcpkg" +$Env:CTEST_OUTPUT_ON_FAILURE = "1" + switch ($action) { "bazel.build" { bazel $BAZEL_STARTUP_OPTIONS build $BAZEL_OPTIONS --action_env=VCPKG_DIR=$VCPKG_DIR --deleted_packages=opentracing-shim -- //... From d9ad23ee86c95bc27a85df3052bc5552e6e984d5 Mon Sep 17 00:00:00 2001 From: WenTao Ou Date: Wed, 18 Dec 2024 15:37:47 +0800 Subject: [PATCH 06/12] [BUILD] Add cxx feature detections (#3203) --- CMakeLists.txt | 31 +++++++++++++++++++ .../opentelemetry/detail/preprocessor.h | 12 +++++++ .../elasticsearch/src/es_log_recordable.cc | 9 +++++- exporters/otlp/CMakeLists.txt | 23 -------------- exporters/zipkin/CMakeLists.txt | 11 ------- .../src/http/client/nosend/CMakeLists.txt | 19 ------------ 6 files changed, 51 insertions(+), 54 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bf093f2caf..408ee43046 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -645,6 +645,37 @@ if(BUILD_TESTING) endif() message(STATUS "GTEST_INCLUDE_DIRS = ${GTEST_INCLUDE_DIRS}") message(STATUS "GTEST_BOTH_LIBRARIES = ${GTEST_BOTH_LIBRARIES}") + + # Try to find gmock + if(NOT GMOCK_LIB AND TARGET GTest::gmock) + set(GMOCK_LIB GTest::gmock) + elseif(MSVC) + # Explicitly specify that we consume GTest from shared library. The rest of + # code logic below determines whether we link Release or Debug flavor of the + # library. These flavors have different prefix on Windows, gmock and gmockd + # respectively. + add_definitions(-DGTEST_LINKED_AS_SHARED_LIBRARY=1) + if(GMOCK_LIB) + # unset GMOCK_LIB to force find_library to redo the lookup, as the cached + # entry could cause linking to incorrect flavor of gmock and leading to + # runtime error. + unset(GMOCK_LIB CACHE) + endif() + endif() + if(NOT GMOCK_LIB) + if(MSVC AND CMAKE_BUILD_TYPE STREQUAL "Debug") + find_library(GMOCK_LIB gmockd PATH_SUFFIXES lib) + else() + find_library(GMOCK_LIB gmock PATH_SUFFIXES lib) + endif() + # Reset GMOCK_LIB if it was not found, or some target may link + # GMOCK_LIB-NOTFOUND + if(NOT GMOCK_LIB) + unset(GMOCK_LIB) + unset(GMOCK_LIB CACHE) + endif() + endif() + enable_testing() if(WITH_BENCHMARK) # Benchmark respects the CMAKE_PREFIX_PATH diff --git a/api/include/opentelemetry/detail/preprocessor.h b/api/include/opentelemetry/detail/preprocessor.h index dc8eb57824..acdf02eb08 100644 --- a/api/include/opentelemetry/detail/preprocessor.h +++ b/api/include/opentelemetry/detail/preprocessor.h @@ -11,3 +11,15 @@ #define OPENTELEMETRY_CONCAT(A, B) OPENTELEMETRY_CONCAT_(A, B) #define OPENTELEMETRY_CONCAT_(A, B) A##B + +// Import the C++20 feature-test macros +#ifdef __has_include +# if __has_include() +# include +# endif +#elif defined(_MSC_VER) && ((defined(__cplusplus) && __cplusplus >= 202002L) || \ + (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)) +# if _MSC_VER >= 1922 +# include +# endif +#endif diff --git a/exporters/elasticsearch/src/es_log_recordable.cc b/exporters/elasticsearch/src/es_log_recordable.cc index 0e7c3b0344..5c5f101282 100644 --- a/exporters/elasticsearch/src/es_log_recordable.cc +++ b/exporters/elasticsearch/src/es_log_recordable.cc @@ -1,11 +1,17 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +#include + #include #include #include #include +#if defined(__cpp_lib_format) +# include +#endif + #include "opentelemetry/exporters/elasticsearch/es_log_recordable.h" #include "opentelemetry/logs/severity.h" #include "opentelemetry/nostd/variant.h" @@ -71,7 +77,8 @@ void ElasticSearchRecordable::SetTimestamp( // If built with with at least cpp 20 then use std::format // Otherwise use the old style to format the timestamp in UTC -#if __cplusplus >= 202002L + // @see https://en.cppreference.com/w/cpp/feature_test#cpp_lib_format +#if defined(__cpp_lib_format) && __cpp_lib_format >= 201907 const std::string dateStr = std::format("{:%FT%T%Ez}", timePoint); #else std::time_t time = std::chrono::system_clock::to_time_t(timePoint); diff --git a/exporters/otlp/CMakeLists.txt b/exporters/otlp/CMakeLists.txt index 34da75b563..cd4e1b62fa 100644 --- a/exporters/otlp/CMakeLists.txt +++ b/exporters/otlp/CMakeLists.txt @@ -313,29 +313,6 @@ if(BUILD_TESTING) TEST_PREFIX exporter.otlp. TEST_LIST otlp_metrics_serialization_test) - if(NOT GMOCK_LIB AND TARGET GTest::gmock) - set(GMOCK_LIB GTest::gmock) - elseif(MSVC) - # Explicitly specify that we consume GTest from shared library. The rest of - # code logic below determines whether we link Release or Debug flavor of the - # library. These flavors have different prefix on Windows, gmock and gmockd - # respectively. - add_definitions(-DGTEST_LINKED_AS_SHARED_LIBRARY=1) - if(GMOCK_LIB) - # unset GMOCK_LIB to force find_library to redo the lookup, as the cached - # entry could cause linking to incorrect flavor of gmock and leading to - # runtime error. - unset(GMOCK_LIB CACHE) - endif() - endif() - if(NOT GMOCK_LIB) - if(MSVC AND CMAKE_BUILD_TYPE STREQUAL "Debug") - find_library(GMOCK_LIB gmockd PATH_SUFFIXES lib) - else() - find_library(GMOCK_LIB gmock PATH_SUFFIXES lib) - endif() - endif() - if(WITH_OTLP_GRPC) add_executable(otlp_grpc_exporter_test test/otlp_grpc_exporter_test.cc) target_link_libraries( diff --git a/exporters/zipkin/CMakeLists.txt b/exporters/zipkin/CMakeLists.txt index 60f8a80a2a..5944258ca3 100644 --- a/exporters/zipkin/CMakeLists.txt +++ b/exporters/zipkin/CMakeLists.txt @@ -49,17 +49,6 @@ if(BUILD_TESTING) TEST_PREFIX exporter. TEST_LIST zipkin_recordable_test) - if(MSVC) - if(GMOCK_LIB) - unset(GMOCK_LIB CACHE) - endif() - endif() - if(MSVC AND CMAKE_BUILD_TYPE STREQUAL "Debug") - find_library(GMOCK_LIB gmockd PATH_SUFFIXES lib) - else() - find_library(GMOCK_LIB gmock PATH_SUFFIXES lib) - endif() - add_executable(zipkin_exporter_test test/zipkin_exporter_test.cc) target_link_libraries( diff --git a/test_common/src/http/client/nosend/CMakeLists.txt b/test_common/src/http/client/nosend/CMakeLists.txt index 7394053a22..3f2b4c82bd 100644 --- a/test_common/src/http/client/nosend/CMakeLists.txt +++ b/test_common/src/http/client/nosend/CMakeLists.txt @@ -8,25 +8,6 @@ if(${BUILD_TESTING}) set_target_properties(opentelemetry_http_client_nosend PROPERTIES EXPORT_NAME opentelemetry_http_client_nosend) - if(MSVC) - # Explicitly specify that we consume GTest from shared library. The rest of - # code logic below determines whether we link Release or Debug flavor of the - # library. These flavors have different prefix on Windows, gmock and gmockd - # respectively. - add_definitions(-DGTEST_LINKED_AS_SHARED_LIBRARY=1) - if(GMOCK_LIB) - # unset GMOCK_LIB to force find_library to redo the lookup, as the cached - # entry could cause linking to incorrect flavor of gmock and leading to - # runtime error. - unset(GMOCK_LIB CACHE) - endif() - endif() - if(MSVC AND CMAKE_BUILD_TYPE STREQUAL "Debug") - find_library(GMOCK_LIB gmockd PATH_SUFFIXES lib) - else() - find_library(GMOCK_LIB gmock PATH_SUFFIXES lib) - endif() - target_link_libraries( opentelemetry_http_client_nosend opentelemetry_ext opentelemetry_test_common ${GMOCK_LIB} ${GTEST_BOTH_LIBRARIES}) From 2b9bff968831cfdaecfe970f76369475b0010a1f Mon Sep 17 00:00:00 2001 From: xiehuc Date: Wed, 18 Dec 2024 17:22:09 +0800 Subject: [PATCH 07/12] [SDK] Do not frequently create and destroy http client threads (#3198) --- CHANGELOG.md | 3 + .../ext/http/client/curl/http_client_curl.h | 20 +++--- ext/src/http/client/curl/http_client_curl.cc | 62 ++++++++++++++++++- ext/test/http/curl_http_test.cc | 50 +++++++++++++++ 4 files changed, 119 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22176df917..e1ee4af753 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ Increment the: ## [Unreleased] +* [SDK] Do not frequently create and destroy http client threads + [#3198](https://github.com/open-telemetry/opentelemetry-cpp/pull/3198) + ## [1.18 2024-11-25] * [EXPORTER] Fix crash in ElasticsearchLogRecordExporter diff --git a/ext/include/opentelemetry/ext/http/client/curl/http_client_curl.h b/ext/include/opentelemetry/ext/http/client/curl/http_client_curl.h index 97386890f2..bef15997fc 100644 --- a/ext/include/opentelemetry/ext/http/client/curl/http_client_curl.h +++ b/ext/include/opentelemetry/ext/http/client/curl/http_client_curl.h @@ -322,25 +322,16 @@ class HttpClient : public opentelemetry::ext::http::client::HttpClient inline CURLM *GetMultiHandle() noexcept { return multi_handle_; } - void MaybeSpawnBackgroundThread(); + // return true if create background thread, false is already exist background thread + bool MaybeSpawnBackgroundThread(); void ScheduleAddSession(uint64_t session_id); void ScheduleAbortSession(uint64_t session_id); void ScheduleRemoveSession(uint64_t session_id, HttpCurlEasyResource &&resource); - void WaitBackgroundThreadExit() - { - std::unique_ptr background_thread; - { - std::lock_guard lock_guard{background_thread_m_}; - background_thread.swap(background_thread_); - } + void SetBackgroundWaitFor(std::chrono::milliseconds ms); - if (background_thread && background_thread->joinable()) - { - background_thread->join(); - } - } + void WaitBackgroundThreadExit(); private: void wakeupBackgroundThread(); @@ -366,6 +357,9 @@ class HttpClient : public opentelemetry::ext::http::client::HttpClient std::unique_ptr background_thread_; std::chrono::milliseconds scheduled_delay_milliseconds_; + std::chrono::milliseconds background_thread_wait_for_; + std::atomic is_shutdown_{false}; + nostd::shared_ptr curl_global_initializer_; }; diff --git a/ext/src/http/client/curl/http_client_curl.cc b/ext/src/http/client/curl/http_client_curl.cc index 6827b9f9c7..e6292f54f2 100644 --- a/ext/src/http/client/curl/http_client_curl.cc +++ b/ext/src/http/client/curl/http_client_curl.cc @@ -189,11 +189,13 @@ HttpClient::HttpClient() next_session_id_{0}, max_sessions_per_connection_{8}, scheduled_delay_milliseconds_{std::chrono::milliseconds(256)}, + background_thread_wait_for_{std::chrono::minutes{1}}, curl_global_initializer_(HttpCurlGlobalInitializer::GetInstance()) {} HttpClient::~HttpClient() { + is_shutdown_.store(true, std::memory_order_release); while (true) { std::unique_ptr background_thread; @@ -211,6 +213,7 @@ HttpClient::~HttpClient() } if (background_thread->joinable()) { + wakeupBackgroundThread(); // if delay quit, wake up first background_thread->join(); } } @@ -335,29 +338,33 @@ void HttpClient::CleanupSession(uint64_t session_id) } } -void HttpClient::MaybeSpawnBackgroundThread() +bool HttpClient::MaybeSpawnBackgroundThread() { std::lock_guard lock_guard{background_thread_m_}; if (background_thread_) { - return; + return false; } background_thread_.reset(new std::thread( [](HttpClient *self) { int still_running = 1; + std::chrono::system_clock::time_point last_free_job_timepoint = + std::chrono::system_clock::now(); + bool need_wait_more = false; while (true) { CURLMsg *msg; int queued; CURLMcode mc = curl_multi_perform(self->multi_handle_, &still_running); + // According to https://curl.se/libcurl/c/curl_multi_perform.html, when mc is not OK, we // can not curl_multi_perform it again if (mc != CURLM_OK) { self->resetMultiHandle(); } - else if (still_running) + else if (still_running || need_wait_more) { // curl_multi_poll is added from libcurl 7.66.0, before 7.68.0, we can only wait util // timeout to do the rest jobs @@ -416,6 +423,32 @@ void HttpClient::MaybeSpawnBackgroundThread() still_running = 1; } + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + if (still_running > 0) + { + last_free_job_timepoint = now; + need_wait_more = false; + continue; + } + + std::chrono::milliseconds wait_for = std::chrono::milliseconds::zero(); + +#if LIBCURL_VERSION_NUM >= 0x074400 + // only available with curl_multi_poll+curl_multi_wakeup, because curl_multi_wait would + // cause CPU busy, curl_multi_wait+sleep could not wakeup quickly + wait_for = self->background_thread_wait_for_; +#endif + if (self->is_shutdown_.load(std::memory_order_acquire)) + { + wait_for = std::chrono::milliseconds::zero(); + } + + if (now - last_free_job_timepoint < wait_for) + { + need_wait_more = true; + continue; + } + if (still_running == 0) { std::lock_guard lock_guard{self->background_thread_m_}; @@ -454,6 +487,7 @@ void HttpClient::MaybeSpawnBackgroundThread() } }, this)); + return true; } void HttpClient::ScheduleAddSession(uint64_t session_id) @@ -502,6 +536,28 @@ void HttpClient::ScheduleRemoveSession(uint64_t session_id, HttpCurlEasyResource wakeupBackgroundThread(); } +void HttpClient::SetBackgroundWaitFor(std::chrono::milliseconds ms) +{ + background_thread_wait_for_ = ms; +} + +void HttpClient::WaitBackgroundThreadExit() +{ + is_shutdown_.store(true, std::memory_order_release); + std::unique_ptr background_thread; + { + std::lock_guard lock_guard{background_thread_m_}; + background_thread.swap(background_thread_); + } + + if (background_thread && background_thread->joinable()) + { + wakeupBackgroundThread(); + background_thread->join(); + } + is_shutdown_.store(false, std::memory_order_release); +} + void HttpClient::wakeupBackgroundThread() { // Before libcurl 7.68.0, we can only wait for timeout and do the rest jobs diff --git a/ext/test/http/curl_http_test.cc b/ext/test/http/curl_http_test.cc index 1b4289f400..497c5bb529 100644 --- a/ext/test/http/curl_http_test.cc +++ b/ext/test/http/curl_http_test.cc @@ -1,6 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +#include #include #include #include @@ -11,6 +12,7 @@ #include #include #include +#include #include #include @@ -531,3 +533,51 @@ TEST_F(BasicCurlHttpTests, FinishInAsyncCallback) } } } + +TEST_F(BasicCurlHttpTests, ElegantQuitQuick) +{ + auto http_client = http_client::HttpClientFactory::Create(); + std::static_pointer_cast(http_client)->MaybeSpawnBackgroundThread(); + // start background first, then test it could wakeup + auto session = http_client->CreateSession("http://127.0.0.1:19000/get/"); + auto request = session->CreateRequest(); + request->SetUri("get/"); + auto handler = std::make_shared(); + session->SendRequest(handler); + std::this_thread::sleep_for(std::chrono::milliseconds{10}); // let it enter poll state + auto beg = std::chrono::system_clock::now(); + http_client->FinishAllSessions(); + http_client.reset(); + // when background_thread_wait_for_ is used, it should have no side effect on elegant quit + // wait should be less than scheduled_delay_milliseconds_ + // Due to load on CI hosts (some take 10ms), we assert it is less than 20ms + auto cost = std::chrono::system_clock::now() - beg; + ASSERT_TRUE(cost < std::chrono::milliseconds{20}) + << "cost ms: " << std::chrono::duration_cast(cost).count() + << " libcurl version: 0x" << std::hex << LIBCURL_VERSION_NUM; + ASSERT_TRUE(handler->is_called_); + ASSERT_TRUE(handler->got_response_); +} + +TEST_F(BasicCurlHttpTests, BackgroundThreadWaitMore) +{ + { + curl::HttpClient http_client; + http_client.MaybeSpawnBackgroundThread(); + std::this_thread::sleep_for(std::chrono::milliseconds{10}); +#if LIBCURL_VERSION_NUM >= 0x074200 + ASSERT_FALSE(http_client.MaybeSpawnBackgroundThread()); +#else + // low version curl do not support delay quit, so old background would quit + ASSERT_TRUE(http_client.MaybeSpawnBackgroundThread()); +#endif + } + { + curl::HttpClient http_client; + http_client.SetBackgroundWaitFor(std::chrono::milliseconds::zero()); + http_client.MaybeSpawnBackgroundThread(); + std::this_thread::sleep_for(std::chrono::milliseconds{10}); + // we can disable delay quit by set wait for 0 + ASSERT_TRUE(http_client.MaybeSpawnBackgroundThread()); + } +} From 0b94d71258be109f16da573ad79a75027dcc6442 Mon Sep 17 00:00:00 2001 From: "Alex E." <36134278+chusitoo@users.noreply.github.com> Date: Wed, 18 Dec 2024 11:48:05 -0500 Subject: [PATCH 08/12] [EXPORTER] Optimize OTLP HTTP compression (#3178) --- exporters/otlp/src/otlp_http_client.cc | 2 +- ext/src/http/client/curl/http_client_curl.cc | 128 ++++++++++++++---- .../http/client/curl/http_operation_curl.cc | 4 +- ext/test/http/curl_http_test.cc | 127 ++++++++++++++++- 4 files changed, 232 insertions(+), 29 deletions(-) diff --git a/exporters/otlp/src/otlp_http_client.cc b/exporters/otlp/src/otlp_http_client.cc index 506295ad7f..a2620756cc 100644 --- a/exporters/otlp/src/otlp_http_client.cc +++ b/exporters/otlp/src/otlp_http_client.cc @@ -890,7 +890,7 @@ OtlpHttpClient::createSession( // Parse uri and store it to cache if (http_uri_.empty()) { - auto parse_url = opentelemetry::ext::http::common::UrlParser(std::string(options_.url)); + const auto parse_url = opentelemetry::ext::http::common::UrlParser(options_.url); if (!parse_url.success_) { std::string error_message = "[OTLP HTTP Client] Export failed, invalid url: " + options_.url; diff --git a/ext/src/http/client/curl/http_client_curl.cc b/ext/src/http/client/curl/http_client_curl.cc index e6292f54f2..a2b73ecb2b 100644 --- a/ext/src/http/client/curl/http_client_curl.cc +++ b/ext/src/http/client/curl/http_client_curl.cc @@ -3,14 +3,17 @@ #include #include +#include +#include #include #include -#include #include +#include #include #include #include #include +#include #include #include #include @@ -57,11 +60,85 @@ nostd::shared_ptr HttpCurlGlobalInitializer::GetInsta return shared_initializer; } +#ifdef ENABLE_OTLP_COMPRESSION_PREVIEW +// Original source: +// https://stackoverflow.com/questions/12398377/is-it-possible-to-have-zlib-read-from-and-write-to-the-same-memory-buffer/12412863#12412863 +int deflateInPlace(z_stream *strm, unsigned char *buf, uint32_t len, uint32_t *max_len) +{ + // must be large enough to hold zlib or gzip header (if any) and one more byte -- 11 works for the + // worst case here, but if gzip encoding is used and a deflateSetHeader() call is inserted in this + // code after the deflateReset(), then the 11 needs to be increased to accommodate the resulting + // gzip header size plus one + std::array temp{}; + + // kick start the process with a temporary output buffer -- this allows deflate to consume a large + // chunk of input data in order to make room for output data there + strm->next_in = buf; + strm->avail_in = len; + if (*max_len < len) + { + *max_len = len; + } + strm->next_out = temp.data(); + strm->avail_out = (std::min)(static_cast(temp.size()), *max_len); + auto ret = deflate(strm, Z_FINISH); + if (ret == Z_STREAM_ERROR) + { + return ret; + } + + // if we can, copy the temporary output data to the consumed portion of the input buffer, and then + // continue to write up to the start of the consumed input for as long as possible + auto have = strm->next_out - temp.data(); // number of bytes in temp[] + if (have <= static_cast(strm->avail_in ? len - strm->avail_in : *max_len)) + { + std::memcpy(buf, temp.data(), have); + strm->next_out = buf + have; + have = 0; + while (ret == Z_OK) + { + strm->avail_out = + strm->avail_in ? strm->next_in - strm->next_out : (buf + *max_len) - strm->next_out; + ret = deflate(strm, Z_FINISH); + } + if (ret != Z_BUF_ERROR || strm->avail_in == 0) + { + *max_len = strm->next_out - buf; + return ret == Z_STREAM_END ? Z_OK : ret; + } + } + + // the output caught up with the input due to insufficiently compressible data -- copy the + // remaining input data into an allocated buffer and complete the compression from there to the + // now empty input buffer (this will only occur for long incompressible streams, more than ~20 MB + // for the default deflate memLevel of 8, or when *max_len is too small and less than the length + // of the header plus one byte) + auto hold = static_cast>( + strm->zalloc(strm->opaque, strm->avail_in, 1)); // allocated buffer to hold input data + if (hold == Z_NULL) + { + return Z_MEM_ERROR; + } + std::memcpy(hold, strm->next_in, strm->avail_in); + strm->next_in = hold; + if (have) + { + std::memcpy(buf, temp.data(), have); + strm->next_out = buf + have; + } + strm->avail_out = (buf + *max_len) - strm->next_out; + ret = deflate(strm, Z_FINISH); + strm->zfree(strm->opaque, hold); + *max_len = strm->next_out - buf; + return ret == Z_OK ? Z_BUF_ERROR : (ret == Z_STREAM_END ? Z_OK : ret); +} +#endif // ENABLE_OTLP_COMPRESSION_PREVIEW + void Session::SendRequest( std::shared_ptr callback) noexcept { is_session_active_.store(true, std::memory_order_release); - std::string url = host_ + std::string(http_request_->uri_); + const auto &url = host_ + http_request_->uri_; auto callback_ptr = callback.get(); bool reuse_connection = false; @@ -76,44 +153,47 @@ void Session::SendRequest( if (http_request_->compression_ == opentelemetry::ext::http::client::Compression::kGzip) { #ifdef ENABLE_OTLP_COMPRESSION_PREVIEW - http_request_->AddHeader("Content-Encoding", "gzip"); - - opentelemetry::ext::http::client::Body compressed_body(http_request_->body_.size()); - z_stream zs; - zs.zalloc = Z_NULL; - zs.zfree = Z_NULL; - zs.opaque = Z_NULL; - zs.avail_in = static_cast(http_request_->body_.size()); - zs.next_in = http_request_->body_.data(); - zs.avail_out = static_cast(compressed_body.size()); - zs.next_out = compressed_body.data(); + z_stream zs{}; + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; // ZLIB: Have to maually specify 16 bits for the Gzip headers - const int window_bits = 15 + 16; + static constexpr int kWindowBits = MAX_WBITS + 16; + static constexpr int kMemLevel = MAX_MEM_LEVEL; - int stream = - deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, window_bits, 8, Z_DEFAULT_STRATEGY); + auto stream = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, kWindowBits, kMemLevel, + Z_DEFAULT_STRATEGY); if (stream == Z_OK) { - deflate(&zs, Z_FINISH); - deflateEnd(&zs); - compressed_body.resize(zs.total_out); - http_request_->SetBody(compressed_body); + auto size = static_cast(http_request_->body_.size()); + auto max_size = size; + stream = deflateInPlace(&zs, http_request_->body_.data(), size, &max_size); + + if (stream == Z_OK) + { + http_request_->AddHeader("Content-Encoding", "gzip"); + http_request_->body_.resize(max_size); + } } - else + + if (stream != Z_OK) { if (callback) { - callback->OnEvent(opentelemetry::ext::http::client::SessionState::CreateFailed, ""); + callback->OnEvent(opentelemetry::ext::http::client::SessionState::CreateFailed, + zs.msg ? zs.msg : ""); } is_session_active_.store(false, std::memory_order_release); } + + deflateEnd(&zs); #else OTEL_INTERNAL_LOG_ERROR( "[HTTP Client Curl] Set WITH_OTLP_HTTP_COMPRESSION=ON to use gzip compression with the " "OTLP HTTP Exporter"); -#endif +#endif // ENABLE_OTLP_COMPRESSION_PREVIEW } curl_operation_.reset(new HttpOperation( @@ -226,7 +306,7 @@ HttpClient::~HttpClient() std::shared_ptr HttpClient::CreateSession( nostd::string_view url) noexcept { - auto parsedUrl = common::UrlParser(std::string(url)); + const auto parsedUrl = common::UrlParser(std::string(url)); if (!parsedUrl.success_) { return std::make_shared(*this); diff --git a/ext/src/http/client/curl/http_operation_curl.cc b/ext/src/http/client/curl/http_operation_curl.cc index b80624d069..c27cff1b41 100644 --- a/ext/src/http/client/curl/http_operation_curl.cc +++ b/ext/src/http/client/curl/http_operation_curl.cc @@ -301,9 +301,7 @@ HttpOperation::HttpOperation(opentelemetry::ext::http::client::Method method, { for (auto &kv : this->request_headers_) { - std::string header = std::string(kv.first); - header += ": "; - header += std::string(kv.second); + const auto header = std::string(kv.first).append(": ").append(kv.second); curl_resource_.headers_chunk = curl_slist_append(curl_resource_.headers_chunk, header.c_str()); } diff --git a/ext/test/http/curl_http_test.cc b/ext/test/http/curl_http_test.cc index 497c5bb529..f1fbe495b7 100644 --- a/ext/test/http/curl_http_test.cc +++ b/ext/test/http/curl_http_test.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -558,7 +559,6 @@ TEST_F(BasicCurlHttpTests, ElegantQuitQuick) ASSERT_TRUE(handler->is_called_); ASSERT_TRUE(handler->got_response_); } - TEST_F(BasicCurlHttpTests, BackgroundThreadWaitMore) { { @@ -581,3 +581,128 @@ TEST_F(BasicCurlHttpTests, BackgroundThreadWaitMore) ASSERT_TRUE(http_client.MaybeSpawnBackgroundThread()); } } + +#ifdef ENABLE_OTLP_COMPRESSION_PREVIEW +struct GzipEventHandler : public CustomEventHandler +{ + ~GzipEventHandler() override = default; + + void OnResponse(http_client::Response & /* response */) noexcept override {} + + void OnEvent(http_client::SessionState state, nostd::string_view reason) noexcept override + { + is_called_ = true; + state_ = state; + reason_ = std::string{reason}; + } + + bool is_called_ = false; + http_client::SessionState state_ = static_cast(-1); + std::string reason_; +}; + +TEST_F(BasicCurlHttpTests, GzipCompressibleData) +{ + received_requests_.clear(); + auto session_manager = http_client::HttpClientFactory::Create(); + EXPECT_TRUE(session_manager != nullptr); + + auto session = session_manager->CreateSession("http://127.0.0.1:19000"); + auto request = session->CreateRequest(); + request->SetUri("post/"); + request->SetMethod(http_client::Method::Post); + + const auto original_size = 500UL; + http_client::Body body(original_size); + std::iota(body.begin(), body.end(), 0); + request->SetBody(body); + request->AddHeader("Content-Type", "text/plain"); + request->SetCompression(opentelemetry::ext::http::client::Compression::kGzip); + auto handler = std::make_shared(); + session->SendRequest(handler); + ASSERT_TRUE(waitForRequests(30, 1)); + session->FinishSession(); + ASSERT_TRUE(handler->is_called_); + ASSERT_EQ(handler->state_, http_client::SessionState::Response); + ASSERT_TRUE(handler->reason_.empty()); + + auto http_request = + dynamic_cast(request.get()); + ASSERT_TRUE(http_request != nullptr); + ASSERT_LT(http_request->body_.size(), original_size); + + session_manager->CancelAllSessions(); + session_manager->FinishAllSessions(); +} + +TEST_F(BasicCurlHttpTests, GzipIncompressibleData) +{ + received_requests_.clear(); + auto session_manager = http_client::HttpClientFactory::Create(); + EXPECT_TRUE(session_manager != nullptr); + + auto session = session_manager->CreateSession("http://127.0.0.1:19000"); + auto request = session->CreateRequest(); + request->SetUri("post/"); + request->SetMethod(http_client::Method::Post); + + // Random data generated using code snippet below. + // const auto original_size = 500UL; + // http_client::Body body(original_size); + // std::random_device rd; + // std::mt19937 gen(rd()); + // std::uniform_int_distribution<> uid(1, 255); + // std::generate(body.begin(), body.end(), [&]() { return uid(gen); }); + + // The input values are fixed to make the test repeatable in the event that some distributions + // might yield results that are, in fact, compressible. + http_client::Body body = { + 140, 198, 12, 56, 165, 185, 173, 20, 13, 83, 127, 223, 77, 38, 224, 43, 236, 10, 178, + 75, 169, 157, 136, 199, 74, 30, 148, 195, 51, 30, 225, 21, 121, 219, 7, 155, 198, 121, + 205, 102, 80, 38, 132, 202, 45, 229, 206, 90, 150, 202, 53, 221, 54, 37, 172, 90, 238, + 248, 191, 240, 109, 227, 248, 41, 251, 121, 35, 226, 107, 122, 15, 242, 203, 45, 64, 195, + 186, 23, 1, 158, 61, 196, 182, 26, 201, 47, 211, 241, 251, 209, 255, 170, 181, 192, 89, + 133, 176, 60, 178, 97, 168, 223, 152, 9, 118, 98, 169, 240, 170, 15, 13, 161, 24, 57, + 123, 117, 230, 30, 244, 117, 238, 255, 198, 232, 95, 148, 37, 61, 67, 103, 31, 240, 52, + 21, 145, 175, 201, 86, 19, 61, 228, 76, 131, 185, 111, 149, 203, 143, 16, 142, 95, 173, + 42, 106, 39, 203, 116, 235, 20, 162, 112, 173, 112, 70, 126, 191, 210, 219, 90, 145, 126, + 118, 43, 241, 101, 66, 175, 179, 5, 233, 208, 164, 180, 83, 214, 194, 173, 29, 179, 149, + 75, 202, 17, 152, 139, 130, 94, 247, 142, 249, 159, 224, 205, 131, 93, 82, 186, 226, 210, + 84, 17, 212, 155, 61, 226, 103, 152, 37, 3, 193, 216, 219, 203, 101, 99, 33, 59, 38, + 106, 62, 232, 127, 44, 125, 90, 169, 148, 238, 34, 106, 12, 221, 90, 173, 67, 122, 232, + 161, 89, 198, 43, 241, 195, 248, 219, 35, 47, 200, 11, 227, 168, 246, 243, 103, 38, 17, + 203, 237, 203, 158, 204, 89, 231, 19, 24, 25, 199, 160, 233, 43, 117, 144, 196, 117, 152, + 42, 121, 189, 217, 202, 221, 250, 157, 237, 47, 29, 64, 32, 10, 32, 243, 28, 114, 158, + 228, 102, 36, 191, 139, 217, 161, 162, 186, 19, 141, 212, 49, 1, 239, 153, 107, 249, 31, + 235, 138, 73, 80, 58, 152, 15, 149, 50, 42, 84, 75, 95, 82, 56, 86, 143, 45, 214, + 11, 184, 164, 181, 249, 74, 184, 26, 207, 165, 162, 240, 154, 90, 56, 175, 72, 4, 166, + 188, 78, 232, 87, 243, 50, 59, 62, 175, 213, 210, 182, 31, 123, 91, 118, 98, 249, 23, + 170, 240, 228, 236, 121, 87, 132, 129, 250, 41, 227, 204, 250, 147, 145, 109, 149, 210, 21, + 174, 165, 127, 234, 64, 211, 52, 93, 126, 117, 231, 216, 210, 15, 16, 2, 167, 215, 178, + 104, 245, 119, 211, 235, 120, 135, 202, 117, 150, 101, 94, 201, 136, 179, 205, 167, 212, 236, + 7, 178, 132, 228, 65, 230, 90, 171, 109, 31, 83, 31, 210, 123, 136, 76, 186, 81, 205, + 63, 35, 21, 121, 152, 22, 242, 199, 106, 217, 199, 211, 206, 165, 88, 77, 112, 108, 193, + 122, 8, 193, 74, 91, 50, 6, 156, 185, 165, 15, 92, 116, 3, 18, 244, 165, 191, 2, + 183, 9, 164, 116, 75, 127}; + const auto original_size = body.size(); + + request->SetBody(body); + request->AddHeader("Content-Type", "text/plain"); + request->SetCompression(opentelemetry::ext::http::client::Compression::kGzip); + auto handler = std::make_shared(); + session->SendRequest(handler); + ASSERT_TRUE(waitForRequests(30, 1)); + session->FinishSession(); + ASSERT_TRUE(handler->is_called_); + ASSERT_EQ(handler->state_, http_client::SessionState::Response); + ASSERT_TRUE(handler->reason_.empty()); + + auto http_request = + dynamic_cast(request.get()); + ASSERT_TRUE(http_request != nullptr); + ASSERT_EQ(http_request->body_.size(), original_size); + + session_manager->CancelAllSessions(); + session_manager->FinishAllSessions(); +} +#endif // ENABLE_OTLP_COMPRESSION_PREVIEW From 92bf8daad58a4122212c1a0302408473e41fde29 Mon Sep 17 00:00:00 2001 From: Doug Barker Date: Wed, 18 Dec 2024 13:13:44 -0700 Subject: [PATCH 09/12] [SDK] Fix include instrumentation scope attributes in equal method (#3214) --- CHANGELOG.md | 3 + .../sdk/common/attribute_utils.h | 83 +++++++++++ .../instrumentation_scope.h | 24 +++- sdk/src/logs/logger_provider.cc | 2 +- sdk/src/metrics/meter_provider.cc | 2 +- sdk/src/trace/tracer_provider.cc | 2 +- sdk/test/common/attribute_utils_test.cc | 132 ++++++++++++++++++ .../instrumentationscope_test.cc | 96 +++++++++++++ sdk/test/logs/logger_provider_sdk_test.cc | 44 +++++- sdk/test/metrics/meter_provider_sdk_test.cc | 72 ++++++++++ sdk/test/trace/tracer_provider_test.cc | 75 ++++++++++ 11 files changed, 528 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1ee4af753..8ac5e7012d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,9 @@ Increment the: * [SDK] Do not frequently create and destroy http client threads [#3198](https://github.com/open-telemetry/opentelemetry-cpp/pull/3198) +* [SDK] Fix instrumentation scope attributes evaluated in equal method + [#3214](https://github.com/open-telemetry/opentelemetry-cpp/pull/3214) + ## [1.18 2024-11-25] * [EXPORTER] Fix crash in ElasticsearchLogRecordExporter diff --git a/sdk/include/opentelemetry/sdk/common/attribute_utils.h b/sdk/include/opentelemetry/sdk/common/attribute_utils.h index 86b507a66b..c2d0209a7d 100644 --- a/sdk/include/opentelemetry/sdk/common/attribute_utils.h +++ b/sdk/include/opentelemetry/sdk/common/attribute_utils.h @@ -105,6 +105,60 @@ struct AttributeConverter } }; +/** + * Evaluates if an owned value (from an OwnedAttributeValue) is equal to another value (from a + * non-owning AttributeValue). This only supports the checking equality with + * nostd::visit(AttributeEqualToVisitor, OwnedAttributeValue, AttributeValue). + */ +struct AttributeEqualToVisitor +{ + // Different types are not equal including containers of different element types + template + bool operator()(const T &, const U &) const noexcept + { + return false; + } + + // Compare the same arithmetic types + template + bool operator()(const T &owned_value, const T &value) const noexcept + { + return owned_value == value; + } + + // Compare std::string and const char* + bool operator()(const std::string &owned_value, const char *value) const noexcept + { + return owned_value == value; + } + + // Compare std::string and nostd::string_view + bool operator()(const std::string &owned_value, nostd::string_view value) const noexcept + { + return owned_value == value; + } + + // Compare std::vector and nostd::span + bool operator()(const std::vector &owned_value, + const nostd::span &value) const noexcept + { + return owned_value.size() == value.size() && + std::equal(owned_value.begin(), owned_value.end(), value.begin(), + [](const std::string &owned_element, nostd::string_view element) { + return owned_element == element; + }); + } + + // Compare nostd::span and std::vector for arithmetic types + template + bool operator()(const std::vector &owned_value, + const nostd::span &value) const noexcept + { + return owned_value.size() == value.size() && + std::equal(owned_value.begin(), owned_value.end(), value.begin()); + } +}; + /** * Class for storing attributes. */ @@ -162,8 +216,37 @@ class AttributeMap : public std::unordered_map (*this)[std::string(key)] = nostd::visit(converter_, value); } + // Compare the attributes of this map with another KeyValueIterable + bool EqualTo(const opentelemetry::common::KeyValueIterable &attributes) const noexcept + { + if (attributes.size() != this->size()) + { + return false; + } + + const bool is_equal = attributes.ForEachKeyValue( + [this](nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept { + // Perform a linear search to find the key assuming the map is small + // This avoids temporary string creation from this->find(std::string(key)) + for (const auto &kv : *this) + { + if (kv.first == key) + { + // Order of arguments is important here. OwnedAttributeValue is first then + // AttributeValue AttributeEqualToVisitor does not support the reverse order + return nostd::visit(equal_to_visitor_, kv.second, value); + } + } + return false; + }); + + return is_equal; + } + private: AttributeConverter converter_; + AttributeEqualToVisitor equal_to_visitor_; }; /** diff --git a/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h b/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h index 1bf0facaa6..68e9d10d40 100644 --- a/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h +++ b/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h @@ -103,7 +103,8 @@ class InstrumentationScope */ bool operator==(const InstrumentationScope &other) const noexcept { - return equal(other.name_, other.version_, other.schema_url_); + return this->name_ == other.name_ && this->version_ == other.version_ && + this->schema_url_ == other.schema_url_ && this->attributes_ == other.attributes_; } /** @@ -112,14 +113,31 @@ class InstrumentationScope * @param name name of the instrumentation scope to compare. * @param version version of the instrumentation scope to compare. * @param schema_url schema url of the telemetry emitted by the scope. + * @param attributes attributes of the instrumentation scope to compare. * @returns true if name and version in this instrumentation scope are equal with the given name * and version. */ bool equal(const nostd::string_view name, const nostd::string_view version, - const nostd::string_view schema_url = "") const noexcept + const nostd::string_view schema_url = "", + const opentelemetry::common::KeyValueIterable *attributes = nullptr) const noexcept { - return this->name_ == name && this->version_ == version && this->schema_url_ == schema_url; + + if (this->name_ != name || this->version_ != version || this->schema_url_ != schema_url) + { + return false; + } + + if (attributes == nullptr) + { + if (attributes_.empty()) + { + return true; + } + return false; + } + + return attributes_.EqualTo(*attributes); } const std::string &GetName() const noexcept { return name_; } diff --git a/sdk/src/logs/logger_provider.cc b/sdk/src/logs/logger_provider.cc index 14febdf721..da282ab655 100644 --- a/sdk/src/logs/logger_provider.cc +++ b/sdk/src/logs/logger_provider.cc @@ -80,7 +80,7 @@ opentelemetry::nostd::shared_ptr LoggerProvider::Ge { auto &logger_lib = logger->GetInstrumentationScope(); if (logger->GetName() == logger_name && - logger_lib.equal(library_name, library_version, schema_url)) + logger_lib.equal(library_name, library_version, schema_url, &attributes)) { return opentelemetry::nostd::shared_ptr{logger}; } diff --git a/sdk/src/metrics/meter_provider.cc b/sdk/src/metrics/meter_provider.cc index 1c70fc2ed3..6856dac3a1 100644 --- a/sdk/src/metrics/meter_provider.cc +++ b/sdk/src/metrics/meter_provider.cc @@ -71,7 +71,7 @@ nostd::shared_ptr MeterProvider::GetMeter( for (auto &meter : context_->GetMeters()) { auto meter_lib = meter->GetInstrumentationScope(); - if (meter_lib->equal(name, version, schema_url)) + if (meter_lib->equal(name, version, schema_url, attributes)) { return nostd::shared_ptr{meter}; } diff --git a/sdk/src/trace/tracer_provider.cc b/sdk/src/trace/tracer_provider.cc index 6a26e13914..81bd7e6f11 100644 --- a/sdk/src/trace/tracer_provider.cc +++ b/sdk/src/trace/tracer_provider.cc @@ -101,7 +101,7 @@ nostd::shared_ptr TracerProvider::GetTracer( for (auto &tracer : tracers_) { auto &tracer_scope = tracer->GetInstrumentationScope(); - if (tracer_scope.equal(name, version, schema_url)) + if (tracer_scope.equal(name, version, schema_url, attributes)) { return nostd::shared_ptr{tracer}; } diff --git a/sdk/test/common/attribute_utils_test.cc b/sdk/test/common/attribute_utils_test.cc index 9b1f6bd56e..da303643d0 100644 --- a/sdk/test/common/attribute_utils_test.cc +++ b/sdk/test/common/attribute_utils_test.cc @@ -2,11 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 #include +#include #include #include #include #include "opentelemetry/common/key_value_iterable_view.h" +#include "opentelemetry/nostd/span.h" +#include "opentelemetry/nostd/string_view.h" #include "opentelemetry/nostd/variant.h" #include "opentelemetry/sdk/common/attribute_utils.h" @@ -55,3 +58,132 @@ TEST(OrderedAttributeMapTest, AttributesConstruction) EXPECT_EQ(opentelemetry::nostd::get(attribute_map.GetAttributes().at(keys[i])), values[i]); } } + +TEST(AttributeEqualToVisitorTest, AttributeValueEqualTo) +{ + namespace sdk = opentelemetry::sdk::common; + namespace api = opentelemetry::common; + namespace nostd = opentelemetry::nostd; + + using AV = api::AttributeValue; + using OV = sdk::OwnedAttributeValue; + + sdk::AttributeEqualToVisitor equal_to_visitor; + + // arithmetic types + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{bool(true)}, AV{bool(true)})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{int32_t(22)}, AV{int32_t(22)})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{int64_t(22)}, AV{int64_t(22)})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{uint32_t(22)}, AV{uint32_t(22)})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{uint64_t(22)}, AV{uint64_t(22)})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{double(22.0)}, AV{double(22.0)})); + + // string types + EXPECT_TRUE(opentelemetry::nostd::visit( + equal_to_visitor, OV{std::string("string to const char*")}, AV{"string to const char*"})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, + OV{std::string("string to string_view")}, + AV{nostd::string_view("string to string_view")})); + + // container types + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{true, false}}, + AV{std::array{true, false}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, + AV{std::array{33, 44}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, + AV{std::array{33, 44}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, + AV{std::array{33, 44}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, + AV{std::array{33, 44}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, + AV{std::array{33, 44}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33.0, 44.0}}, + AV{std::array{33.0, 44.0}})); + EXPECT_TRUE(opentelemetry::nostd::visit( + equal_to_visitor, OV{std::vector{"a string", "another string"}}, + AV{std::array{"a string", "another string"}})); +} + +TEST(AttributeEqualToVisitorTest, AttributeValueNotEqualTo) +{ + namespace sdk = opentelemetry::sdk::common; + namespace api = opentelemetry::common; + namespace nostd = opentelemetry::nostd; + + using AV = api::AttributeValue; + using OV = sdk::OwnedAttributeValue; + + sdk::AttributeEqualToVisitor equal_to_visitor; + + // check different values of the same type + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{bool(true)}, AV{bool(false)})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{int32_t(22)}, AV{int32_t(33)})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{int64_t(22)}, AV{int64_t(33)})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{uint32_t(22)}, AV{uint32_t(33)})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{double(22.2)}, AV{double(33.3)})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::string("string one")}, + AV{"another string"})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::string("string one")}, + AV{nostd::string_view("another string")})); + + // check different value types + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{bool(true)}, AV{uint32_t(1)})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{int32_t(22)}, AV{uint32_t(22)})); + + // check containers of different element values + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{true, false}}, + AV{std::array{false, true}})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{22, 33}}, + AV{std::array{33, 44}})); + EXPECT_FALSE(opentelemetry::nostd::visit( + equal_to_visitor, OV{std::vector{"a string", "another string"}}, + AV{std::array{"a string", "a really different string"}})); + + // check containers of different element types + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{22, 33}}, + AV{std::array{22, 33}})); +} + +TEST(AttributeMapTest, EqualTo) +{ + using Attributes = std::initializer_list< + std::pair>; + + // check for case where both are empty + Attributes attributes_empty = {}; + auto kv_iterable_empty = + opentelemetry::common::MakeKeyValueIterableView(attributes_empty); + opentelemetry::sdk::common::AttributeMap attribute_map_empty(kv_iterable_empty); + EXPECT_TRUE(attribute_map_empty.EqualTo(kv_iterable_empty)); + + // check for equality with a range of attributes and types + Attributes attributes = {{"key0", "some value"}, {"key1", 1}, {"key2", 2.0}, {"key3", true}}; + auto kv_iterable_match = opentelemetry::common::MakeKeyValueIterableView(attributes); + opentelemetry::sdk::common::AttributeMap attribute_map(attributes); + EXPECT_TRUE(attribute_map.EqualTo(kv_iterable_match)); + + // check for several cases where the attributes are different + Attributes attributes_different_value = { + {"key0", "some value"}, {"key1", 1}, {"key2", 2.0}, {"key3", false}}; + Attributes attributes_different_type = { + {"key0", "some value"}, {"key1", 1.0}, {"key2", 2.0}, {"key3", true}}; + Attributes attributes_different_size = {{"key0", "some value"}}; + + // check for the case where the number of attributes is the same but all keys are different + Attributes attributes_different_all = {{"a", "b"}, {"c", "d"}, {"e", 4.0}, {"f", uint8_t(5)}}; + + auto kv_iterable_different_value = + opentelemetry::common::MakeKeyValueIterableView(attributes_different_value); + auto kv_iterable_different_type = + opentelemetry::common::MakeKeyValueIterableView(attributes_different_type); + auto kv_iterable_different_size = + opentelemetry::common::MakeKeyValueIterableView(attributes_different_size); + auto kv_iterable_different_all = + opentelemetry::common::MakeKeyValueIterableView(attributes_different_all); + + EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_value)); + EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_type)); + EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_size)); + EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_all)); +} diff --git a/sdk/test/instrumentationscope/instrumentationscope_test.cc b/sdk/test/instrumentationscope/instrumentationscope_test.cc index da00ec8e93..347e107aca 100644 --- a/sdk/test/instrumentationscope/instrumentationscope_test.cc +++ b/sdk/test/instrumentationscope/instrumentationscope_test.cc @@ -208,3 +208,99 @@ TEST(InstrumentationScope, LegacyInstrumentationLibrary) EXPECT_EQ(instrumentation_library->GetVersion(), library_version); EXPECT_EQ(instrumentation_library->GetSchemaURL(), schema_url); } + +TEST(InstrumentationScope, Equal) +{ + using Attributes = std::initializer_list< + std::pair>; + Attributes attributes_empty = {}; + Attributes attributes_match = { + {"key0", "some value"}, {"key1", 1}, {"key2", 2.0}, {"key3", true}}; + Attributes attributes_different = {{"key42", "some other"}}; + + auto kv_iterable_empty = + opentelemetry::common::MakeKeyValueIterableView(attributes_empty); + auto kv_iterable_match = + opentelemetry::common::MakeKeyValueIterableView(attributes_match); + auto kv_iterable_different = + opentelemetry::common::MakeKeyValueIterableView(attributes_different); + + // try with no attributes added to the instrumentation scope + auto instrumentation_scope = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name", "library_version", "schema_url"); + + // the instrumentation scope is equal if all parameters are equal (must handle nullptr attributes + // or empty attributes) + EXPECT_TRUE(instrumentation_scope->equal("library_name", "library_version", "schema_url")); + EXPECT_TRUE( + instrumentation_scope->equal("library_name", "library_version", "schema_url", nullptr)); + EXPECT_TRUE(instrumentation_scope->equal("library_name", "library_version", "schema_url", + &kv_iterable_empty)); + + // the instrumentation scope is not equal if any parameter is different + EXPECT_FALSE(instrumentation_scope->equal("library_name", "")); + EXPECT_FALSE(instrumentation_scope->equal("library_name", "library_version", "")); + EXPECT_FALSE(instrumentation_scope->equal("library_name", "library_version", "schema_url", + &kv_iterable_different)); + + // try with attributes added to the instrumentation scope + auto instrumentation_scope_w_attributes = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name", "library_version", "schema_url", attributes_match); + + // the instrumentation scope is equal if all parameters including all attribute keys, types, and + // values are equal + EXPECT_TRUE(instrumentation_scope_w_attributes->equal("library_name", "library_version", + "schema_url", &kv_iterable_match)); + EXPECT_FALSE(instrumentation_scope_w_attributes->equal("library_name", "library_version", + "schema_url", nullptr)); + EXPECT_FALSE(instrumentation_scope_w_attributes->equal("library_name", "library_version", + "schema_url", &kv_iterable_empty)); + EXPECT_FALSE(instrumentation_scope_w_attributes->equal("library_name", "library_version", + "schema_url", &kv_iterable_different)); +} + +TEST(InstrumentationScope, OperatorEqual) +{ + using Attributes = std::initializer_list< + std::pair>; + Attributes attributes_empty = {}; + Attributes attributes_match = { + {"key0", "some value"}, {"key1", 1}, {"key2", 2.0}, {"key3", true}}; + Attributes attributes_different = {{"key42", "some other"}}; + + auto instrumentation_scope_1a = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name", "library_version", "schema_url"); + + auto instrumentation_scope_1b = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name", "library_version", "schema_url"); + + auto instrumentation_scope_2a = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name_2", "library_version", "schema_url"); + + auto instrumentation_scope_2b = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name_2", "library_version", "schema_url", attributes_empty); + + auto instrumentation_scope_3a = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name_2", "library_version", "schema_url", attributes_match); + + auto instrumentation_scope_3b = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name_2", "library_version", "schema_url", attributes_match); + + auto instrumentation_scope_4 = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name_2", "library_version", "schema_url", attributes_different); + + EXPECT_EQ(*instrumentation_scope_1a, *instrumentation_scope_1b); + EXPECT_FALSE(*instrumentation_scope_1a == *instrumentation_scope_2a); + EXPECT_EQ(*instrumentation_scope_2a, *instrumentation_scope_2b); + EXPECT_EQ(*instrumentation_scope_3a, *instrumentation_scope_3b); + EXPECT_FALSE(*instrumentation_scope_3a == *instrumentation_scope_4); +} diff --git a/sdk/test/logs/logger_provider_sdk_test.cc b/sdk/test/logs/logger_provider_sdk_test.cc index a5a3d3a68a..edddf2ef96 100644 --- a/sdk/test/logs/logger_provider_sdk_test.cc +++ b/sdk/test/logs/logger_provider_sdk_test.cc @@ -129,7 +129,7 @@ TEST(LoggerProviderSDK, EventLoggerProviderFactory) auto event_logger = elp->CreateEventLogger(logger1, "otel-cpp.test"); } -TEST(LoggerPviderSDK, LoggerEquityCheck) +TEST(LoggerProviderSDK, LoggerEqualityCheck) { auto lp = std::shared_ptr(new LoggerProvider()); nostd::string_view schema_url{"https://opentelemetry.io/schemas/1.11.0"}; @@ -141,6 +141,48 @@ TEST(LoggerPviderSDK, LoggerEquityCheck) auto logger3 = lp->GetLogger("logger3"); auto another_logger3 = lp->GetLogger("logger3"); EXPECT_EQ(logger3, another_logger3); + + auto logger4 = lp->GetLogger("logger4", "opentelelemtry_library", "1.0.0", schema_url); + auto another_logger4 = lp->GetLogger("logger4", "opentelelemtry_library", "1.0.0", schema_url); + EXPECT_EQ(logger4, another_logger4); + + auto logger5 = + lp->GetLogger("logger5", "opentelelemtry_library", "1.0.0", schema_url, {{"key", "value"}}); + auto another_logger5 = + lp->GetLogger("logger5", "opentelelemtry_library", "1.0.0", schema_url, {{"key", "value"}}); + EXPECT_EQ(logger5, another_logger5); +} + +TEST(LoggerProviderSDK, GetLoggerInequalityCheck) +{ + auto lp = std::shared_ptr(new LoggerProvider()); + auto logger_library_1 = lp->GetLogger("logger1", "library_1"); + auto logger_library_2 = lp->GetLogger("logger1", "library_2"); + auto logger_version_1 = lp->GetLogger("logger1", "library_1", "1.0.0"); + auto logger_version_2 = lp->GetLogger("logger1", "library_1", "2.0.0"); + auto logger_url_1 = lp->GetLogger("logger1", "library_1", "1.0.0", "url_1"); + auto logger_url_2 = lp->GetLogger("logger1", "library_1", "1.0.0", "url_2"); + auto logger_attribute_1 = + lp->GetLogger("logger1", "library_1", "1.0.0", "url_1", {{"key", "one"}}); + auto logger_attribute_2 = + lp->GetLogger("logger1", "library_1", "1.0.0", "url_1", {{"key", "two"}}); + + // different scope names should return distinct loggers + EXPECT_NE(logger_library_1, logger_library_2); + + // different scope versions should return distinct loggers + EXPECT_NE(logger_version_1, logger_library_1); + EXPECT_NE(logger_version_1, logger_version_2); + + // different scope schema urls should return distinct loggers + EXPECT_NE(logger_url_1, logger_library_1); + EXPECT_NE(logger_url_1, logger_version_1); + EXPECT_NE(logger_url_1, logger_url_2); + + // different scope attributes should return distinct loggers + EXPECT_NE(logger_attribute_1, logger_library_1); + EXPECT_NE(logger_attribute_1, logger_url_1); + EXPECT_NE(logger_attribute_1, logger_attribute_2); } class DummyLogRecordable final : public opentelemetry::sdk::logs::Recordable diff --git a/sdk/test/metrics/meter_provider_sdk_test.cc b/sdk/test/metrics/meter_provider_sdk_test.cc index 36cb28c228..ee8a8a88c6 100644 --- a/sdk/test/metrics/meter_provider_sdk_test.cc +++ b/sdk/test/metrics/meter_provider_sdk_test.cc @@ -12,6 +12,7 @@ #include "opentelemetry/sdk/metrics/instruments.h" #include "opentelemetry/sdk/metrics/meter.h" #include "opentelemetry/sdk/metrics/meter_provider.h" +#include "opentelemetry/sdk/metrics/meter_provider_factory.h" #include "opentelemetry/sdk/metrics/metric_reader.h" #include "opentelemetry/sdk/metrics/push_metric_exporter.h" #include "opentelemetry/sdk/metrics/view/instrument_selector.h" @@ -239,3 +240,74 @@ TEST(MeterProvider, RemoveMeter) mp.Shutdown(); } #endif /* OPENTELEMETRY_ABI_VERSION_NO >= 2 */ + +TEST(MeterProvider, GetMeterEqualityCheck) +{ + auto provider = MeterProviderFactory::Create(); + + // providing the same scope names should return the same Meter + auto meter_library_1a = provider->GetMeter("library_name"); + auto meter_library_1b = provider->GetMeter("library_name"); + EXPECT_EQ(meter_library_1a, meter_library_1b); + + // providing the same scope name and version should return the same meter + auto meter_version_1a = provider->GetMeter("library_name", "v1.0"); + auto meter_version_1b = provider->GetMeter("library_name", "v1.0"); + EXPECT_EQ(meter_version_1a, meter_version_1b); + + // providing the same name, version, and schema urls should return the same meter + auto meter_urla = provider->GetMeter("library_name", "v1.0", "url"); + auto meter_urlb = provider->GetMeter("library_name", "v1.0", "url"); + EXPECT_EQ(meter_urla, meter_urlb); +} + +TEST(MeterProvider, GetMeterInequalityCheck) +{ + auto provider = MeterProviderFactory::Create(); + + auto meter_library_1 = provider->GetMeter("library_1"); + auto meter_library_2 = provider->GetMeter("library_2"); + auto meter_version_1 = provider->GetMeter("library_1", "v1.0"); + auto meter_version_2 = provider->GetMeter("library_1", "v2.0"); + auto meter_url_1 = provider->GetMeter("library_1", "v1.0", "url_1"); + auto meter_url_2 = provider->GetMeter("library_1", "v1.0", "url_2"); + + // different scope names should return distinct meters + EXPECT_NE(meter_library_1, meter_library_2); + + // different scope versions should return distinct meters + EXPECT_NE(meter_version_1, meter_library_1); + EXPECT_NE(meter_version_1, meter_version_2); + + // different scope schema urls should return distinct meters + EXPECT_NE(meter_url_1, meter_library_1); + EXPECT_NE(meter_url_1, meter_version_1); + EXPECT_NE(meter_url_1, meter_url_2); +} + +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 + +TEST(MeterProvider, GetMeterEqualityCheckAbiv2) +{ + auto provider = MeterProviderFactory::Create(); + + // providing the same name, version, schema url and attributes should return the same meter + auto meter_attribute1a = provider->GetMeter("library_name", "v1.0", "url", {{"key", "one"}}); + auto meter_attribute1b = provider->GetMeter("library_name", "v1.0", "url", {{"key", "one"}}); + EXPECT_EQ(meter_attribute1a, meter_attribute1b); +} + +TEST(MeterProvider, GetMeterInequalityCheckAbiv2) +{ + auto provider = MeterProviderFactory::Create(); + + auto meter_1 = provider->GetMeter("library_name", "v1.0", "url"); + auto meter_attribute_1 = provider->GetMeter("library_name", "v1.0", "url", {{"key", "one"}}); + auto meter_attribute_2 = provider->GetMeter("library_name", "v1.0", "url", {{"key", "two"}}); + + // different scope attributes should return distinct meters + EXPECT_NE(meter_attribute_1, meter_1); + EXPECT_NE(meter_attribute_1, meter_attribute_2); +} + +#endif /* OPENTELEMETRY_ABI_VERSION_NO >= 2 */ diff --git a/sdk/test/trace/tracer_provider_test.cc b/sdk/test/trace/tracer_provider_test.cc index fa3afa2690..8bdad908ad 100644 --- a/sdk/test/trace/tracer_provider_test.cc +++ b/sdk/test/trace/tracer_provider_test.cc @@ -19,9 +19,11 @@ #include "opentelemetry/sdk/trace/sampler.h" #include "opentelemetry/sdk/trace/samplers/always_off.h" #include "opentelemetry/sdk/trace/simple_processor.h" +#include "opentelemetry/sdk/trace/simple_processor_factory.h" #include "opentelemetry/sdk/trace/tracer.h" #include "opentelemetry/sdk/trace/tracer_context.h" #include "opentelemetry/sdk/trace/tracer_provider.h" +#include "opentelemetry/sdk/trace/tracer_provider_factory.h" using namespace opentelemetry::sdk::trace; using namespace opentelemetry::sdk::resource; @@ -89,7 +91,80 @@ TEST(TracerProvider, GetTracer) ASSERT_EQ(instrumentation_scope3.GetVersion(), "1.0.0"); } +TEST(TracerProvider, GetTracerEqualityCheck) +{ + auto processor = SimpleSpanProcessorFactory::Create(nullptr); + auto provider = TracerProviderFactory::Create(std::move(processor)); + + // providing the same scope names should return the same tracer + auto tracer_1a = provider->GetTracer("library_name"); + auto tracer_1b = provider->GetTracer("library_name"); + EXPECT_EQ(tracer_1a, tracer_1b); + + // providing the same scope name and version should return the same tracer + auto tracer_version1a = provider->GetTracer("library_name", "v1.0"); + auto tracer_version1b = provider->GetTracer("library_name", "v1.0"); + EXPECT_EQ(tracer_version1a, tracer_version1b); + + // providing the same name, version, and schema urls should return the same tracer + auto tracer_urla = provider->GetTracer("library_name", "v1.0", "url"); + auto tracer_urlb = provider->GetTracer("library_name", "v1.0", "url"); + EXPECT_EQ(tracer_urla, tracer_urlb); +} + +TEST(TracerProvider, GetTracerInequalityCheck) +{ + auto processor = SimpleSpanProcessorFactory::Create(nullptr); + auto provider = TracerProviderFactory::Create(std::move(processor)); + + auto tracer_library_1 = provider->GetTracer("library_1"); + auto tracer_library_2 = provider->GetTracer("library_2"); + auto tracer_version_1 = provider->GetTracer("library_1", "v1.0"); + auto tracer_version_2 = provider->GetTracer("library_1", "v2.0"); + auto tracer_url_1 = provider->GetTracer("library_1", "v1.0", "url_1"); + auto tracer_url_2 = provider->GetTracer("library_1", "v1.0", "url_2"); + + // different scope names should return distinct tracers + EXPECT_NE(tracer_library_1, tracer_library_2); + + // different scope versions should return distinct tracers + EXPECT_NE(tracer_version_1, tracer_library_1); + EXPECT_NE(tracer_version_1, tracer_version_2); + + // different scope schema urls should return distinct tracers + EXPECT_NE(tracer_url_1, tracer_library_1); + EXPECT_NE(tracer_url_1, tracer_version_1); + EXPECT_NE(tracer_url_1, tracer_url_2); +} + #if OPENTELEMETRY_ABI_VERSION_NO >= 2 + +TEST(TracerProvider, GetTracerEqualityCheckAbiv2) +{ + auto processor = SimpleSpanProcessorFactory::Create(nullptr); + auto provider = TracerProviderFactory::Create(std::move(processor)); + + auto tracer_attribute1a = provider->GetTracer("library_name", "v1.0", "url", {{"key", "one"}}); + auto tracer_attribute1b = provider->GetTracer("library_name", "v1.0", "url", {{"key", "one"}}); + + // providing the same name, version, schema url and attributes should return the same tracer + EXPECT_EQ(tracer_attribute1a, tracer_attribute1b); +} + +TEST(TracerProvider, GetTracerInequalityCheckAbiv2) +{ + auto processor = SimpleSpanProcessorFactory::Create(nullptr); + auto provider = TracerProviderFactory::Create(std::move(processor)); + + auto tracer_1 = provider->GetTracer("library_name", "v1.0", "url"); + auto tracer_attribute1 = provider->GetTracer("library_name", "v1.0", "url", {{"key", "one"}}); + auto tracer_attribute2 = provider->GetTracer("library_name", "v1.0", "url", {{"key", "two"}}); + + // different scope attributes should return distinct tracers + EXPECT_NE(tracer_attribute1, tracer_1); + EXPECT_NE(tracer_attribute1, tracer_attribute2); +} + TEST(TracerProvider, GetTracerAbiv2) { std::unique_ptr processor(new SimpleSpanProcessor(nullptr)); From 40d7b76a916baf32c5557eeb042c4078aa7ad65a Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Thu, 19 Dec 2024 01:25:17 +0100 Subject: [PATCH 10/12] Upgrade to opentelemetry-proto 1.5.0 (#3210) --- MODULE.bazel | 2 +- bazel/repository.bzl | 6 +++--- third_party/opentelemetry-proto | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index b3c7077108..4cc1a41bee 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -13,7 +13,7 @@ bazel_dep(name = "bazel_skylib", version = "1.5.0") bazel_dep(name = "curl", version = "8.8.0") bazel_dep(name = "grpc", version = "1.63.1.bcr.1", repo_name = "com_github_grpc_grpc") bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "github_nlohmann_json") -bazel_dep(name = "opentelemetry-proto", version = "1.4.0", repo_name = "com_github_opentelemetry_proto") +bazel_dep(name = "opentelemetry-proto", version = "1.5.0", repo_name = "com_github_opentelemetry_proto") bazel_dep(name = "opentracing-cpp", version = "1.6.0", repo_name = "com_github_opentracing") bazel_dep(name = "platforms", version = "0.0.8") bazel_dep(name = "prometheus-cpp", version = "1.3.0", repo_name = "com_github_jupp0r_prometheus_cpp") diff --git a/bazel/repository.bzl b/bazel/repository.bzl index b4f6b5fb1f..423db01fd1 100644 --- a/bazel/repository.bzl +++ b/bazel/repository.bzl @@ -88,10 +88,10 @@ def opentelemetry_cpp_deps(): http_archive, name = "com_github_opentelemetry_proto", build_file = "@io_opentelemetry_cpp//bazel:opentelemetry_proto.BUILD", - sha256 = "53cd32cedb27762ea2060a9c8d83e4b822de13d73b5d5d37a2db3cf55018d694", - strip_prefix = "opentelemetry-proto-1.4.0", + sha256 = "08f40636adbc5f33d2084bd8e7b64e491dd0239d1a95021dbffbdf1ca8cea454", + strip_prefix = "opentelemetry-proto-1.5.0", urls = [ - "https://github.com/open-telemetry/opentelemetry-proto/archive/v1.4.0.tar.gz", + "https://github.com/open-telemetry/opentelemetry-proto/archive/v1.5.0.tar.gz", ], ) diff --git a/third_party/opentelemetry-proto b/third_party/opentelemetry-proto index 0adf6aac00..2bd940b2b7 160000 --- a/third_party/opentelemetry-proto +++ b/third_party/opentelemetry-proto @@ -1 +1 @@ -Subproject commit 0adf6aac004578b28267394514b2e55ee9cc012f +Subproject commit 2bd940b2b77c1ab57c27166af21384906da7bb2b From 807d61022533293472c8be695ae2081fcc0fd760 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Thu, 19 Dec 2024 16:41:23 +0100 Subject: [PATCH 11/12] [TEST] Added support for SELINUX in functional tests (#3212) --- functional/otlp/run_test.sh | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/functional/otlp/run_test.sh b/functional/otlp/run_test.sh index 0be5a2f9e6..db51325987 100755 --- a/functional/otlp/run_test.sh +++ b/functional/otlp/run_test.sh @@ -15,6 +15,19 @@ export CERT_DIR=../cert export TEST_BIN_DIR=${BUILD_DIR}/functional/otlp/ +# SELINUX +# https://docs.docker.com/storage/bind-mounts/#configure-the-selinux-label + +USE_MOUNT_OPTION="" + +if [ -x "$(command -v getenforce)" ]; then + SELINUXSTATUS=$(getenforce); + if [ "${SELINUXSTATUS}" == "Enforcing" ]; then + echo "Detected SELINUX" + USE_MOUNT_OPTION=":z" + fi; +fi + ${TEST_BIN_DIR}/func_otlp_http --list > test_list.txt # @@ -44,7 +57,7 @@ echo "" docker run -d \ - -v `pwd`/otel-docker-config-http.yaml:/otel-cpp/otel-config.yaml \ + -v `pwd`/otel-docker-config-http.yaml:/otel-cpp/otel-config.yaml${USE_MOUNT_OPTION} \ -p 4318:4318 \ --name otelcpp-test-http \ otelcpp-func-test @@ -74,10 +87,10 @@ echo "###############################################################" echo "" docker run -d \ - -v `pwd`/otel-docker-config-https.yaml:/otel-cpp/otel-config.yaml \ - -v `pwd`/../cert/ca.pem:/otel-cpp/ca.pem \ - -v `pwd`/../cert/server_cert.pem:/otel-cpp/server_cert.pem \ - -v `pwd`/../cert/server_cert-key.pem:/otel-cpp/server_cert-key.pem \ + -v `pwd`/otel-docker-config-https.yaml:/otel-cpp/otel-config.yaml${USE_MOUNT_OPTION} \ + -v `pwd`/../cert/ca.pem:/otel-cpp/ca.pem${USE_MOUNT_OPTION} \ + -v `pwd`/../cert/server_cert.pem:/otel-cpp/server_cert.pem${USE_MOUNT_OPTION} \ + -v `pwd`/../cert/server_cert-key.pem:/otel-cpp/server_cert-key.pem${USE_MOUNT_OPTION} \ -p 4318:4318 \ --name otelcpp-test-https \ otelcpp-func-test From 4998eb178601f69481e1629e5464d0272532ec9e Mon Sep 17 00:00:00 2001 From: Doug Barker Date: Thu, 19 Dec 2024 10:24:29 -0700 Subject: [PATCH 12/12] [EDITORIAL] fix changelog entry for PR 3185 (#3217) --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ac5e7012d..52f280eb22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,9 @@ Increment the: * [SDK] Fix instrumentation scope attributes evaluated in equal method [#3214](https://github.com/open-telemetry/opentelemetry-cpp/pull/3214) +* [EXPORTER] Fix scope attributes missing from otlp traces metrics + [#3185](https://github.com/open-telemetry/opentelemetry-cpp/pull/3185) + ## [1.18 2024-11-25] * [EXPORTER] Fix crash in ElasticsearchLogRecordExporter @@ -155,9 +158,6 @@ Increment the: * [bazel] Update opentelemetry-proto in MODULE.bazel [#3163](https://github.com/open-telemetry/opentelemetry-cpp/pull/3163) -* [EXPORTER] Fix scope attributes missing from otlp traces metrics - [#3185](https://github.com/open-telemetry/opentelemetry-cpp/pull/3185) - Important changes: * [API] Jaeger Propagator should not be deprecated