From 368ee792107961c6ad7c140864af276955f5dc58 Mon Sep 17 00:00:00 2001 From: WenTao Ou Date: Thu, 28 Sep 2023 15:02:55 +0800 Subject: [PATCH 1/3] Fix deadlock when shuting down http client. (#2337) --- ext/src/http/client/curl/http_client_curl.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ext/src/http/client/curl/http_client_curl.cc b/ext/src/http/client/curl/http_client_curl.cc index 94bbf9fa7b..287059a1c6 100644 --- a/ext/src/http/client/curl/http_client_curl.cc +++ b/ext/src/http/client/curl/http_client_curl.cc @@ -244,6 +244,7 @@ void HttpClient::CleanupSession(uint64_t session_id) } } + bool need_wakeup_background_thread = false; { std::lock_guard lock_guard{session_ids_m_}; pending_to_add_session_ids_.erase(session_id); @@ -259,10 +260,15 @@ void HttpClient::CleanupSession(uint64_t session_id) { // If this session is already running, give it to the background thread for cleanup. pending_to_abort_sessions_[session_id] = std::move(session); - wakeupBackgroundThread(); + need_wakeup_background_thread = true; } } } + + if (need_wakeup_background_thread) + { + wakeupBackgroundThread(); + } } void HttpClient::MaybeSpawnBackgroundThread() @@ -519,7 +525,8 @@ bool HttpClient::doRemoveSessions() std::lock_guard session_id_lock_guard{session_ids_m_}; pending_to_remove_session_handles_.swap(pending_to_remove_session_handles); pending_to_remove_sessions_.swap(pending_to_remove_sessions); - + } + { // If user callback do not call CancelSession or FinishSession, We still need to remove it // from sessions_ std::lock_guard session_lock_guard{sessions_m_}; From 5e96b80bc964eeb61ddfd62a61d7b746fe75a97a Mon Sep 17 00:00:00 2001 From: Matthijs Brobbel Date: Thu, 28 Sep 2023 09:46:17 +0200 Subject: [PATCH 2/3] [Exporter] Group spans by resource and instrumentation scope in OTLP export requests (#2335) --- .../exporters/otlp/otlp_recordable.h | 3 + exporters/otlp/src/otlp_recordable.cc | 11 +++ exporters/otlp/src/otlp_recordable_utils.cc | 49 +++++++++-- exporters/otlp/test/otlp_recordable_test.cc | 88 +++++++++++++++++++ 4 files changed, 144 insertions(+), 7 deletions(-) diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h index 29bc6011f9..bc505a959b 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h @@ -27,7 +27,10 @@ class OtlpRecordable final : public opentelemetry::sdk::trace::Recordable /** Dynamically converts the resource of this span into a proto. */ proto::resource::v1::Resource ProtoResource() const noexcept; + const opentelemetry::sdk::resource::Resource *GetResource() const noexcept; const std::string GetResourceSchemaURL() const noexcept; + const opentelemetry::sdk::instrumentationscope::InstrumentationScope *GetInstrumentationScope() + const noexcept; const std::string GetInstrumentationLibrarySchemaURL() const noexcept; proto::common::v1::InstrumentationScope GetProtoInstrumentationScope() const noexcept; diff --git a/exporters/otlp/src/otlp_recordable.cc b/exporters/otlp/src/otlp_recordable.cc index e0b181a452..a3ab4327f2 100644 --- a/exporters/otlp/src/otlp_recordable.cc +++ b/exporters/otlp/src/otlp_recordable.cc @@ -40,6 +40,11 @@ proto::resource::v1::Resource OtlpRecordable::ProtoResource() const noexcept return proto; } +const opentelemetry::sdk::resource::Resource *OtlpRecordable::GetResource() const noexcept +{ + return resource_; +} + const std::string OtlpRecordable::GetResourceSchemaURL() const noexcept { std::string schema_url; @@ -51,6 +56,12 @@ const std::string OtlpRecordable::GetResourceSchemaURL() const noexcept return schema_url; } +const opentelemetry::sdk::instrumentationscope::InstrumentationScope * +OtlpRecordable::GetInstrumentationScope() const noexcept +{ + return instrumentation_scope_; +} + const std::string OtlpRecordable::GetInstrumentationLibrarySchemaURL() const noexcept { std::string schema_url; diff --git a/exporters/otlp/src/otlp_recordable_utils.cc b/exporters/otlp/src/otlp_recordable_utils.cc index 1b1da94e08..59e4aadf4e 100644 --- a/exporters/otlp/src/otlp_recordable_utils.cc +++ b/exporters/otlp/src/otlp_recordable_utils.cc @@ -56,19 +56,54 @@ void OtlpRecordableUtils::PopulateRequest( return; } + using spans_by_scope = + std::unordered_map>>; + std::unordered_map spans_index; + + // Collect spans per resource and instrumentation scope for (auto &recordable : spans) { auto rec = std::unique_ptr(static_cast(recordable.release())); - auto resource_span = request->add_resource_spans(); - auto scope_spans = resource_span->add_scope_spans(); + auto resource = rec->GetResource(); + auto instrumentation = rec->GetInstrumentationScope(); - *scope_spans->add_spans() = std::move(rec->span()); - *scope_spans->mutable_scope() = rec->GetProtoInstrumentationScope(); + spans_index[resource][instrumentation].emplace_back(std::move(rec)); + } - scope_spans->set_schema_url(rec->GetInstrumentationLibrarySchemaURL()); + // Add all resource spans + for (auto &input_resource_spans : spans_index) + { + // Add the resource + auto resource_spans = request->add_resource_spans(); + if (input_resource_spans.first) + { + proto::resource::v1::Resource resource_proto; + OtlpPopulateAttributeUtils::PopulateAttribute(&resource_proto, *input_resource_spans.first); + *resource_spans->mutable_resource() = resource_proto; + resource_spans->set_schema_url(input_resource_spans.first->GetSchemaURL()); + } - *resource_span->mutable_resource() = rec->ProtoResource(); - resource_span->set_schema_url(rec->GetResourceSchemaURL()); + // Add all scope spans + for (auto &input_scope_spans : input_resource_spans.second) + { + // Add the instrumentation scope + auto scope_spans = resource_spans->add_scope_spans(); + if (input_scope_spans.first) + { + proto::common::v1::InstrumentationScope instrumentation_scope_proto; + instrumentation_scope_proto.set_name(input_scope_spans.first->GetName()); + instrumentation_scope_proto.set_version(input_scope_spans.first->GetVersion()); + *scope_spans->mutable_scope() = instrumentation_scope_proto; + scope_spans->set_schema_url(input_scope_spans.first->GetSchemaURL()); + } + + // Add all spans to this scope spans + for (auto &input_span : input_scope_spans.second) + { + *scope_spans->add_spans() = std::move(input_span->span()); + } + } } } diff --git a/exporters/otlp/test/otlp_recordable_test.cc b/exporters/otlp/test/otlp_recordable_test.cc index 4db58844f7..9f3ba62b16 100644 --- a/exporters/otlp/test/otlp_recordable_test.cc +++ b/exporters/otlp/test/otlp_recordable_test.cc @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 #include "opentelemetry/exporters/otlp/otlp_recordable.h" +#include "opentelemetry/exporters/otlp/otlp_recordable_utils.h" #include "opentelemetry/sdk/resource/resource.h" #if defined(__GNUC__) @@ -285,6 +286,93 @@ TEST(OtlpRecordable, SetArrayAttribute) } } +// Test otlp resource populate request util +TEST(OtlpRecordable, PopulateRequest) +{ + auto rec1 = std::unique_ptr(new OtlpRecordable); + auto resource1 = resource::Resource::Create({{"service.name", "one"}}); + rec1->SetResource(resource1); + auto inst_lib1 = trace_sdk::InstrumentationScope::Create("one", "1"); + rec1->SetInstrumentationScope(*inst_lib1); + + auto rec2 = std::unique_ptr(new OtlpRecordable); + auto resource2 = resource::Resource::Create({{"service.name", "two"}}); + rec2->SetResource(resource2); + auto inst_lib2 = trace_sdk::InstrumentationScope::Create("two", "2"); + rec2->SetInstrumentationScope(*inst_lib2); + + // This has the same resource as rec2, but a different scope + auto rec3 = std::unique_ptr(new OtlpRecordable); + rec3->SetResource(resource2); + auto inst_lib3 = trace_sdk::InstrumentationScope::Create("three", "3"); + rec3->SetInstrumentationScope(*inst_lib3); + + proto::collector::trace::v1::ExportTraceServiceRequest req; + std::vector> spans; + spans.push_back(std::move(rec1)); + spans.push_back(std::move(rec2)); + spans.push_back(std::move(rec3)); + const nostd::span, 3> spans_span(spans.data(), 3); + OtlpRecordableUtils::PopulateRequest(spans_span, &req); + + EXPECT_EQ(req.resource_spans().size(), 2); + for (auto resource_spans : req.resource_spans()) + { + auto service_name = resource_spans.resource().attributes(0).value().string_value(); + auto scope_spans_size = resource_spans.scope_spans().size(); + if (service_name == "one") + { + EXPECT_EQ(scope_spans_size, 1); + EXPECT_EQ(resource_spans.scope_spans(0).scope().name(), "one"); + } + if (service_name == "two") + { + EXPECT_EQ(scope_spans_size, 2); + } + } +} + +// Test otlp resource populate request util with missing data +TEST(OtlpRecordable, PopulateRequestMissing) +{ + // Missing scope + auto rec1 = std::unique_ptr(new OtlpRecordable); + auto resource1 = resource::Resource::Create({{"service.name", "one"}}); + rec1->SetResource(resource1); + + // Missing resource + auto rec2 = std::unique_ptr(new OtlpRecordable); + auto inst_lib2 = trace_sdk::InstrumentationScope::Create("two", "2"); + rec2->SetInstrumentationScope(*inst_lib2); + + proto::collector::trace::v1::ExportTraceServiceRequest req; + std::vector> spans; + spans.push_back(std::move(rec1)); + spans.push_back(std::move(rec2)); + const nostd::span, 2> spans_span(spans.data(), 2); + OtlpRecordableUtils::PopulateRequest(spans_span, &req); + + EXPECT_EQ(req.resource_spans().size(), 2); + for (auto resource_spans : req.resource_spans()) + { + // Both should have scope spans + EXPECT_EQ(resource_spans.scope_spans().size(), 1); + auto scope = resource_spans.scope_spans(0).scope(); + // Select the one with missing scope + if (scope.name() == "") + { + // Version is also empty + EXPECT_EQ(scope.version(), ""); + } + else + { + // The other has a name and version + EXPECT_EQ(scope.name(), "two"); + EXPECT_EQ(scope.version(), "2"); + } + } +} + template struct EmptyArrayAttributeTest : public testing::Test { From ad626cec4598165e0d297b0bdb3880968c5dfe88 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Thu, 28 Sep 2023 10:25:51 +0200 Subject: [PATCH 3/3] [BUILD] Need fine-grained HAVE_CPP_STDLIB (#2304) --- .github/workflows/ci.yml | 36 +++++++++++++++++++ CHANGELOG.md | 23 ++++++++++++ CMakeLists.txt | 22 +++--------- api/CMakeLists.txt | 33 ++++++++++++++--- api/include/opentelemetry/nostd/shared_ptr.h | 14 +++++--- api/include/opentelemetry/nostd/span.h | 36 ++++++++++--------- api/include/opentelemetry/nostd/string_view.h | 13 ++++--- api/include/opentelemetry/nostd/type_traits.h | 13 ++++--- api/include/opentelemetry/nostd/unique_ptr.h | 13 ++++--- api/include/opentelemetry/nostd/utility.h | 12 ++++--- api/include/opentelemetry/nostd/variant.h | 13 ++++--- api/include/opentelemetry/std/span.h | 16 ++++----- api/test/nostd/span_test.cc | 15 -------- api/test/nostd/string_view_test.cc | 2 +- ci/do_ci.sh | 26 ++++++++++++++ docs/building-with-stdlib.md | 14 ++++++-- docs/dependencies.md | 5 +-- exporters/etw/README.md | 2 +- .../otlp/test/otlp_grpc_exporter_test.cc | 4 +-- .../otlp/test/otlp_http_exporter_test.cc | 4 +-- .../otlp_http_log_record_exporter_test.cc | 4 +-- exporters/zipkin/test/zipkin_exporter_test.cc | 4 +-- ext/test/http/CMakeLists.txt | 2 +- 23 files changed, 225 insertions(+), 101 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d8db91364..01ea48fb86 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -316,6 +316,42 @@ jobs: CXX: /usr/bin/g++-4.8 run: ./ci/do_ci.sh cmake.legacy.exporter.otprotocol.test + cmake_test_cxx14_gcc: + name: CMake C++14 test(GCC) + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v4 + with: + submodules: 'recursive' + - name: setup + env: + CMAKE_VERSION: 3.20.6 + run: | + sudo -E ./ci/setup_ci_environment.sh + sudo -E ./ci/setup_cmake.sh + - name: run tests (enable stl) + env: + CXX_STANDARD: '14' + run: ./ci/do_ci.sh cmake.c++14.stl.test + + cmake_test_cxx17_gcc: + name: CMake C++17 test(GCC) + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v4 + with: + submodules: 'recursive' + - name: setup + env: + CMAKE_VERSION: 3.20.6 + run: | + sudo -E ./ci/setup_ci_environment.sh + sudo -E ./ci/setup_cmake.sh + - name: run tests (enable stl) + env: + CXX_STANDARD: '17' + run: ./ci/do_ci.sh cmake.c++17.stl.test + cmake_test_cxx20_gcc: name: CMake C++20 test(GCC) runs-on: ubuntu-20.04 diff --git a/CHANGELOG.md b/CHANGELOG.md index 7901a35732..b349ba8ec7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,29 @@ Increment the: * [EXPORTER] Replace colons with underscores when converting to Prometheus label [#2324](https://github.com/open-telemetry/opentelemetry-cpp/pull/2330) +Breaking changes: + +* [BUILD] Need fine-grained HAVE_CPP_STDLIB + [#2304](https://github.com/open-telemetry/opentelemetry-cpp/pull/2304) + * In `CMAKE`, the boolean option `WITH_STL` as changed to an option + that accepts the values `OFF`, `ON`, `CXX11`, `CXX14`, `CXX17`, + `CXX20` and `CXX23`. + * Applications makefiles that did not set WITH_STL need to use + `WITH_STL=OFF` instead (this is the default). + * Applications makefiles that did set WITH_STL need to use + `WITH_STL=ON` instead, or may choose to pick a specific value. + * In the `API` header files, the preprocessor symbol `HAVE_CPP_STDLIB` + is no longer used. + * Applications that did set `HAVE_CPP_STDLIB` before, need to set + `OPENTELEMETRY_STL_VERSION=` instead, to build with a + specific STL version (2011, 2014, 2017, 2020, 2023). + * The opentelemetry-cpp makefile no longer sets + CMAKE_CXX_STANDARD by itself. + Instead, the CMAKE_CXX_STANDARD and/or compiler options -stdc++ used + by the caller are honored. + * Applications that set neither CMAKE_CXX_STANDARD nor -stdc++ + options may need to provide a C++ standard in their makefiles. + ## [1.11.0] 2023-08-21 * [BUILD] Fix more cases for symbol name for 32-bit win32 DLL build diff --git a/CMakeLists.txt b/CMakeLists.txt index f579efe431..10c1a0ab6f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,7 +154,10 @@ message(STATUS "OPENTELEMETRY_VERSION=${OPENTELEMETRY_VERSION}") option(WITH_NO_DEPRECATED_CODE "Do not include deprecated code" OFF) -option(WITH_STL "Whether to use Standard Library for C++ latest features" OFF) +set(WITH_STL + "OFF" + CACHE STRING "Which version of the Standard Library for C++ to use") + option(WITH_GSL "Whether to use Guidelines Support Library for C++ latest features" OFF) @@ -169,22 +172,7 @@ option(OPENTELEMETRY_INSTALL "Whether to install opentelemetry targets" include("${PROJECT_SOURCE_DIR}/cmake/tools.cmake") -if(NOT DEFINED CMAKE_CXX_STANDARD) - if(WITH_STL) - # Require at least C++17. C++20 is needed to avoid gsl::span - if(CMAKE_VERSION VERSION_GREATER 3.11.999) - # Ask for 20, may get anything below - set(CMAKE_CXX_STANDARD 20) - else() - # Ask for 17, may get anything below - set(CMAKE_CXX_STANDARD 17) - endif() - else() - set(CMAKE_CXX_STANDARD 11) - endif() -endif() - -if(WITH_STL) +if(NOT WITH_STL STREQUAL "OFF") # These definitions are needed for test projects that do not link against # opentelemetry-api library directly. We ensure that variant implementation # (absl::variant or std::variant) in variant unit test code is consistent with diff --git a/api/CMakeLists.txt b/api/CMakeLists.txt index f5f1fbf897..dd1eda3c78 100644 --- a/api/CMakeLists.txt +++ b/api/CMakeLists.txt @@ -51,11 +51,36 @@ if(WITH_ABSEIL) "absl_bits" "absl_city") endif() -if(WITH_STL) - message("Building with standard library types...") - target_compile_definitions(opentelemetry_api INTERFACE HAVE_CPP_STDLIB) +if(WITH_STL STREQUAL "OFF") + message(STATUS "Building WITH_STL=OFF") +elseif(WITH_STL STREQUAL "CXX11") + message(STATUS "Building WITH_STL=CXX11") + target_compile_definitions(opentelemetry_api + INTERFACE OPENTELEMETRY_STL_VERSION=2011) +elseif(WITH_STL STREQUAL "CXX14") + message(STATUS "Building WITH_STL=CXX14") + target_compile_definitions(opentelemetry_api + INTERFACE OPENTELEMETRY_STL_VERSION=2014) +elseif(WITH_STL STREQUAL "CXX17") + message(STATUS "Building WITH_STL=CXX17") + target_compile_definitions(opentelemetry_api + INTERFACE OPENTELEMETRY_STL_VERSION=2017) +elseif(WITH_STL STREQUAL "CXX20") + message(STATUS "Building WITH_STL=CXX20") + target_compile_definitions(opentelemetry_api + INTERFACE OPENTELEMETRY_STL_VERSION=2020) +elseif(WITH_STL STREQUAL "CXX23") + message(STATUS "Building WITH_STL=CXX23") + target_compile_definitions(opentelemetry_api + INTERFACE OPENTELEMETRY_STL_VERSION=2023) +elseif(WITH_STL STREQUAL "ON") + message(STATUS "Building WITH_STL=ON") + # "ON" corresponds to "CXX23" at this time. + target_compile_definitions(opentelemetry_api + INTERFACE OPENTELEMETRY_STL_VERSION=2023) else() - message("Building with nostd types...") + message( + FATAL_ERROR "WITH_STL must be ON, OFF, CXX11, CXX14, CXX17, CXX20 or CXX23") endif() if(WITH_GSL) diff --git a/api/include/opentelemetry/nostd/shared_ptr.h b/api/include/opentelemetry/nostd/shared_ptr.h index 4f7dd86bb4..0222352030 100644 --- a/api/include/opentelemetry/nostd/shared_ptr.h +++ b/api/include/opentelemetry/nostd/shared_ptr.h @@ -2,9 +2,15 @@ // SPDX-License-Identifier: Apache-2.0 #pragma once -#ifdef HAVE_CPP_STDLIB -# include "opentelemetry/std/shared_ptr.h" -#else + +#if defined(OPENTELEMETRY_STL_VERSION) +# if OPENTELEMETRY_STL_VERSION >= 2011 +# include "opentelemetry/std/shared_ptr.h" +# define OPENTELEMETRY_HAVE_STD_SHARED_PTR +# endif +#endif + +#if !defined(OPENTELEMETRY_HAVE_STD_SHARED_PTR) # include # include # include @@ -201,4 +207,4 @@ inline bool operator!=(std::nullptr_t, const shared_ptr &rhs) noexcept } } // namespace nostd OPENTELEMETRY_END_NAMESPACE -#endif +#endif /* OPENTELEMETRY_HAVE_STD_SHARED_PTR */ diff --git a/api/include/opentelemetry/nostd/span.h b/api/include/opentelemetry/nostd/span.h index 3022a913d9..da0f385cf0 100644 --- a/api/include/opentelemetry/nostd/span.h +++ b/api/include/opentelemetry/nostd/span.h @@ -4,32 +4,34 @@ #pragma once // Try to use either `std::span` or `gsl::span` -#ifdef HAVE_CPP_STDLIB -# include -# include -# include -# include +#if defined(OPENTELEMETRY_STL_VERSION) +# if OPENTELEMETRY_STL_VERSION >= 2020 +# include +# include +# include +# include /** * @brief Clang 14.0.0 with libc++ do not support implicitly construct a span * for a range. We just use our fallback version. * */ -# if !defined(OPENTELEMETRY_OPTION_USE_STD_SPAN) && defined(_LIBCPP_VERSION) -# if _LIBCPP_VERSION <= 14000 -# define OPENTELEMETRY_OPTION_USE_STD_SPAN 0 +# if !defined(OPENTELEMETRY_OPTION_USE_STD_SPAN) && defined(_LIBCPP_VERSION) +# if _LIBCPP_VERSION <= 14000 +# define OPENTELEMETRY_OPTION_USE_STD_SPAN 0 +# endif # endif -# endif -# ifndef OPENTELEMETRY_OPTION_USE_STD_SPAN -# define OPENTELEMETRY_OPTION_USE_STD_SPAN 1 -# endif -# if OPENTELEMETRY_OPTION_USE_STD_SPAN -# include "opentelemetry/std/span.h" -# endif -#endif +# ifndef OPENTELEMETRY_OPTION_USE_STD_SPAN +# define OPENTELEMETRY_OPTION_USE_STD_SPAN 1 +# endif +# if OPENTELEMETRY_OPTION_USE_STD_SPAN +# include "opentelemetry/std/span.h" +# endif +# endif /* OPENTELEMETRY_STL_VERSION >= 2020 */ +#endif /* OPENTELEMETRY_STL_VERSION */ // Fallback to `nostd::span` if necessary -#if !defined(HAVE_SPAN) +#if !defined(OPENTELEMETRY_HAVE_SPAN) # include # include # include diff --git a/api/include/opentelemetry/nostd/string_view.h b/api/include/opentelemetry/nostd/string_view.h index 4f065effa0..9f9fb42180 100644 --- a/api/include/opentelemetry/nostd/string_view.h +++ b/api/include/opentelemetry/nostd/string_view.h @@ -3,9 +3,14 @@ #pragma once -#ifdef HAVE_CPP_STDLIB -# include "opentelemetry/std/string_view.h" -#else +#if defined(OPENTELEMETRY_STL_VERSION) +# if OPENTELEMETRY_STL_VERSION >= 2017 +# include "opentelemetry/std/string_view.h" +# define OPENTELEMETRY_HAVE_STD_STRING_VIEW +# endif +#endif + +#if !defined(OPENTELEMETRY_HAVE_STD_STRING_VIEW) # include # include # include @@ -216,4 +221,4 @@ struct hash } }; } // namespace std -#endif +#endif /* OPENTELEMETRY_HAVE_STD_STRING_VIEW */ diff --git a/api/include/opentelemetry/nostd/type_traits.h b/api/include/opentelemetry/nostd/type_traits.h index 3d212ea3e2..46d11c89cb 100644 --- a/api/include/opentelemetry/nostd/type_traits.h +++ b/api/include/opentelemetry/nostd/type_traits.h @@ -3,9 +3,14 @@ #pragma once -#ifdef HAVE_CPP_STDLIB -# include "opentelemetry/std/type_traits.h" -#else +#if defined(OPENTELEMETRY_STL_VERSION) +# if OPENTELEMETRY_STL_VERSION >= 2011 +# include "opentelemetry/std/type_traits.h" +# define OPENTELEMETRY_HAVE_STD_TYPE_TRAITS +# endif +#endif + +#if !defined(OPENTELEMETRY_HAVE_STD_TYPE_TRAITS) # include # include @@ -154,4 +159,4 @@ struct is_trivially_move_assignable # endif } // namespace nostd OPENTELEMETRY_END_NAMESPACE -#endif +#endif /* OPENTELEMETRY_HAVE_STD_TYPE_TRAITS */ diff --git a/api/include/opentelemetry/nostd/unique_ptr.h b/api/include/opentelemetry/nostd/unique_ptr.h index a97111b9d0..f864eb4f04 100644 --- a/api/include/opentelemetry/nostd/unique_ptr.h +++ b/api/include/opentelemetry/nostd/unique_ptr.h @@ -3,9 +3,14 @@ #pragma once -#ifdef HAVE_CPP_STDLIB -# include "opentelemetry/std/unique_ptr.h" -#else +#if defined(OPENTELEMETRY_STL_VERSION) +# if OPENTELEMETRY_STL_VERSION >= 2011 +# include "opentelemetry/std/unique_ptr.h" +# define OPENTELEMETRY_HAVE_STD_UNIQUE_PTR +# endif +#endif + +#if !defined(OPENTELEMETRY_HAVE_STD_UNIQUE_PTR) # include # include # include @@ -172,4 +177,4 @@ bool operator!=(std::nullptr_t, const unique_ptr &rhs) noexcept } } // namespace nostd OPENTELEMETRY_END_NAMESPACE -#endif +#endif /* OPENTELEMETRY_HAVE_STD_UNIQUE_PTR */ diff --git a/api/include/opentelemetry/nostd/utility.h b/api/include/opentelemetry/nostd/utility.h index bb350594ad..e7ad2d77f0 100644 --- a/api/include/opentelemetry/nostd/utility.h +++ b/api/include/opentelemetry/nostd/utility.h @@ -3,10 +3,14 @@ #pragma once -#ifdef HAVE_CPP_STDLIB -# include "opentelemetry/std/utility.h" -#else +#if defined(OPENTELEMETRY_STL_VERSION) +# if OPENTELEMETRY_STL_VERSION >= 2014 +# include "opentelemetry/std/utility.h" +# define OPENTELEMETRY_HAVE_STD_UTILITY +# endif +#endif +#if !defined(OPENTELEMETRY_HAVE_STD_UTILITY) # include # include # include @@ -153,4 +157,4 @@ struct in_place_type_t }; } // namespace nostd OPENTELEMETRY_END_NAMESPACE -#endif +#endif /* OPENTELEMETRY_HAVE_STD_UTILITY */ diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index b6b2326998..d0b2d96001 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -5,9 +5,14 @@ #include "opentelemetry/version.h" -#ifdef HAVE_CPP_STDLIB -# include "opentelemetry/std/variant.h" -#else +#if defined(OPENTELEMETRY_STL_VERSION) +# if OPENTELEMETRY_STL_VERSION >= 2017 +# include "opentelemetry/std/variant.h" +# define OPENTELEMETRY_HAVE_STD_VARIANT +# endif +#endif + +#if !defined(OPENTELEMETRY_HAVE_STD_VARIANT) # ifndef HAVE_ABSEIL // We use a LOCAL snapshot of Abseil that is known to compile with Visual Studio 2015. @@ -73,4 +78,4 @@ using absl::visit; } // namespace nostd OPENTELEMETRY_END_NAMESPACE -#endif +#endif /* OPENTELEMETRY_HAVE_STD_VARIANT */ diff --git a/api/include/opentelemetry/std/span.h b/api/include/opentelemetry/std/span.h index 5fdff57fd5..2a3dc12a84 100644 --- a/api/include/opentelemetry/std/span.h +++ b/api/include/opentelemetry/std/span.h @@ -12,18 +12,18 @@ # if __has_include() // Check for __cpp_{feature} # include # if defined(__cpp_lib_span) && __cplusplus > 201703L -# define HAVE_SPAN +# define OPENTELEMETRY_HAVE_SPAN # endif # endif -# if !defined(HAVE_SPAN) +# if !defined(OPENTELEMETRY_HAVE_SPAN) # // Check for Visual Studio span # if defined(_MSVC_LANG) && _HAS_CXX20 -# define HAVE_SPAN +# define OPENTELEMETRY_HAVE_SPAN # endif # // Check for other compiler span implementation # if !defined(_MSVC_LANG) && __has_include() && __cplusplus > 201703L // This works as long as compiler standard is set to C++20 -# define HAVE_SPAN +# define OPENTELEMETRY_HAVE_SPAN # endif # endif # if !__has_include() @@ -31,7 +31,7 @@ # endif #endif -#if !defined(HAVE_SPAN) +#if !defined(OPENTELEMETRY_HAVE_SPAN) # if defined(HAVE_GSL) # include // Guidelines Support Library provides an implementation of std::span @@ -44,12 +44,12 @@ template using span = gsl::span; } // namespace nostd OPENTELEMETRY_END_NAMESPACE -# define HAVE_SPAN +# define OPENTELEMETRY_HAVE_SPAN # else // No `gsl::span`, no `std::span`, fallback to `nostd::span` # endif -#else // HAVE_SPAN +#else // OPENTELEMETRY_HAVE_SPAN // Using std::span (https://wg21.link/P0122R7) from Standard Library available in C++20 : // - GCC libstdc++ 10+ // - Clang libc++ 7 @@ -66,4 +66,4 @@ template using span = std::span; } // namespace nostd OPENTELEMETRY_END_NAMESPACE -#endif // of HAVE_SPAN +#endif // if OPENTELEMETRY_HAVE_SPAN diff --git a/api/test/nostd/span_test.cc b/api/test/nostd/span_test.cc index 98e825142d..5c13ee590e 100644 --- a/api/test/nostd/span_test.cc +++ b/api/test/nostd/span_test.cc @@ -60,11 +60,6 @@ TEST(SpanTest, PointerCountConstruction) span s2{array.data(), array.size()}; EXPECT_EQ(s2.data(), array.data()); EXPECT_EQ(s2.size(), array.size()); - -#ifndef HAVE_CPP_STDLIB - /* This test is not supposed to fail with STL. Why is this invalid construct? */ - EXPECT_DEATH((span{array.data(), array.size()}), ".*"); -#endif } TEST(SpanTest, RangeConstruction) @@ -78,11 +73,6 @@ TEST(SpanTest, RangeConstruction) span s2{std::begin(array), std::end(array)}; EXPECT_EQ(s2.data(), array); EXPECT_EQ(s2.size(), 3); - -#ifndef HAVE_CPP_STDLIB - /* This test is not supposed to fail with STL. Why is this invalid construct? */ - EXPECT_DEATH((span{std::begin(array), std::end(array)}), ".*"); -#endif } TEST(SpanTest, ArrayConstruction) @@ -122,11 +112,6 @@ TEST(SpanTest, ContainerConstruction) EXPECT_EQ(s2.data(), v.data()); EXPECT_EQ(s2.size(), v.size()); -#ifndef HAVE_CPP_STDLIB - /* This test is not supposed to fail with STL. Why is this invalid construct? */ - EXPECT_DEATH((span{v.data(), 3}), ".*"); -#endif - EXPECT_FALSE((std::is_constructible, std::vector>::value)); EXPECT_FALSE((std::is_constructible, std::list>::value)); } diff --git a/api/test/nostd/string_view_test.cc b/api/test/nostd/string_view_test.cc index fc580debc1..52c72ea4d8 100644 --- a/api/test/nostd/string_view_test.cc +++ b/api/test/nostd/string_view_test.cc @@ -71,7 +71,7 @@ TEST(StringViewTest, SubstrPortion) TEST(StringViewTest, SubstrOutOfRange) { string_view s = "abc123"; -#if __EXCEPTIONS || defined(HAVE_CPP_STDLIB) +#if __EXCEPTIONS || ((defined(OPENTELEMETRY_STL_VERSION) && (OPENTELEMETRY_STL_VERSION >= 2020))) EXPECT_THROW(s.substr(10), std::out_of_range); #else EXPECT_DEATH({ s.substr(10); }, ""); diff --git a/ci/do_ci.sh b/ci/do_ci.sh index 6452faa451..04063eb6ba 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -221,6 +221,32 @@ elif [[ "$1" == "cmake.c++20.test" ]]; then eval "$MAKE_COMMAND" make test exit 0 +elif [[ "$1" == "cmake.c++14.stl.test" ]]; then + cd "${BUILD_DIR}" + rm -rf * + cmake ${CMAKE_OPTIONS[@]} \ + -DWITH_METRICS_EXEMPLAR_PREVIEW=ON \ + -DCMAKE_CXX_FLAGS="-Werror $CXXFLAGS" \ + -DWITH_ASYNC_EXPORT_PREVIEW=ON \ + -DWITH_STL=CXX14 \ + ${IWYU} \ + "${SRC_DIR}" + eval "$MAKE_COMMAND" + make test + exit 0 +elif [[ "$1" == "cmake.c++17.stl.test" ]]; then + cd "${BUILD_DIR}" + rm -rf * + cmake ${CMAKE_OPTIONS[@]} \ + -DWITH_METRICS_EXEMPLAR_PREVIEW=ON \ + -DCMAKE_CXX_FLAGS="-Werror $CXXFLAGS" \ + -DWITH_ASYNC_EXPORT_PREVIEW=ON \ + -DWITH_STL=CXX17 \ + ${IWYU} \ + "${SRC_DIR}" + eval "$MAKE_COMMAND" + make test + exit 0 elif [[ "$1" == "cmake.c++20.stl.test" ]]; then cd "${BUILD_DIR}" rm -rf * diff --git a/docs/building-with-stdlib.md b/docs/building-with-stdlib.md index a90a14a6ed..d9c73073da 100644 --- a/docs/building-with-stdlib.md +++ b/docs/building-with-stdlib.md @@ -138,14 +138,22 @@ Visual Studio provides 1st class debug experience for the standard library. Supported build flavors: * `nostd` - OpenTelemetry backport of classes for C++11. Not using standard lib. -* `stdlib` - Standard Library. Full native experience with C++20 compiler. - C++17 works but with additional dependencies, e.g. either MS-GSL or Abseil for +* `stdlib` - Standard Library. + Native experience with C++11/C++14/C++17/C++20/C++23 compiler. + Depending on the stdlib level in effect, + C++ features are used from the standard library, + completed with `nostd` replacement implementations. + C++17 and below works but with additional dependencies, + e.g. either MS-GSL or Abseil for `std::span` implementation (`gsl::span` or `absl::Span`). * `absl` - TODO: this should allow using Abseil C++ library only (no MS-GSL). Currently only `nostd` and `stdlib` configurations are implemented in CMake build. `absl` is reserved for future use. Build systems other than CMake need to -`#define HAVE_CPP_STDLIB` to enable the Standard Library classes. +`#define OPENTELEMETRY_STL_VERSION=` to enable the Standard Library classes. + +Valid values for `OPENTELEMETRY_STL_VERSION` are `2011`, `2014`, `2017`, `2020` and +`2023`. ### Build matrix diff --git a/docs/dependencies.md b/docs/dependencies.md index 62fbefc297..d0dc09c54f 100644 --- a/docs/dependencies.md +++ b/docs/dependencies.md @@ -24,8 +24,9 @@ Both these dependencies are listed here: [SDK](/sdk): - Uses Standard C++ library for latest features (std::string_view, std::variant, std::span, std::shared_ptr, std::unique_ptr) with C++14/17/20 - compiler if `WITH_STL` cmake option is enabled or `HAVE_CPP_STDLIB` macro is - defined. License: `GNU General Public License` + compiler if cmake option `WITH_STL` is enabled + or macro `OPENTELEMETRY_STL_VERSION` is defined. + License: `GNU General Public License` - For C++11/14/17 compilers, fallback to gsl::span if [GSL C++ library](https://github.com/microsoft/GSL) is installed. License: `MIT License` diff --git a/exporters/etw/README.md b/exporters/etw/README.md index 29dc3de430..3339223fa6 100644 --- a/exporters/etw/README.md +++ b/exporters/etw/README.md @@ -121,7 +121,7 @@ compiled: | Name | Description | |---------------------|------------------------------------------------------------------------------------------------------------------------| -| HAVE_CPP_STDLIB | Use STL classes for API surface. This option requires at least C++17. C++20 is recommended. Some customers may benefit from STL library provided with the compiler instead of using custom OpenTelemetry `nostd::` implementation due to security and performance considerations. | +| OPENTELEMETRY_STL_VERSION | Use STL classes for API surface. C++20 is recommended. Some customers may benefit from STL library provided with the compiler instead of using custom OpenTelemetry `nostd::` implementation due to security and performance considerations. | | HAVE_GSL | Use [Microsoft GSL](https://github.com/microsoft/GSL) for `gsl::span` implementation. Library must be in include path. Microsoft GSL claims to be the most feature-complete implementation of `std::span`. It may be used instead of `nostd::span` implementation in projects that statically link OpenTelemetry SDK. | | HAVE_TLD | Use ETW/TraceLogging Dynamic protocol. This is the default implementation compatible with existing C# "listeners" / "decoders" of ETW events. This option requires an additional optional Microsoft MIT-licensed `TraceLoggingDynamic.h` header. | diff --git a/exporters/otlp/test/otlp_grpc_exporter_test.cc b/exporters/otlp/test/otlp_grpc_exporter_test.cc index 3298e5390d..3be2bcc653 100644 --- a/exporters/otlp/test/otlp_grpc_exporter_test.cc +++ b/exporters/otlp/test/otlp_grpc_exporter_test.cc @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -#ifndef HAVE_CPP_STDLIB +#ifndef OPENTELEMETRY_STL_VERSION // Unfortunately as of 04/27/2021 the fix is NOT in the vcpkg snapshot of Google Test. // Remove above `#ifdef` once the GMock fix for C++20 is in the mainline. // @@ -284,4 +284,4 @@ TEST_F(OtlpGrpcExporterTestPeer, ConfigUnknownInsecureFromEnv) } // namespace otlp } // namespace exporter OPENTELEMETRY_END_NAMESPACE -#endif +#endif /* OPENTELEMETRY_STL_VERSION */ diff --git a/exporters/otlp/test/otlp_http_exporter_test.cc b/exporters/otlp/test/otlp_http_exporter_test.cc index 2ac698b0de..42258d2b45 100644 --- a/exporters/otlp/test/otlp_http_exporter_test.cc +++ b/exporters/otlp/test/otlp_http_exporter_test.cc @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -#ifndef HAVE_CPP_STDLIB +#ifndef OPENTELEMETRY_STL_VERSION # include # include @@ -612,4 +612,4 @@ TEST_F(OtlpHttpExporterTestPeer, ConfigFromTracesEnv) } // namespace otlp } // namespace exporter OPENTELEMETRY_END_NAMESPACE -#endif +#endif /* OPENTELEMETRY_STL_VERSION */ diff --git a/exporters/otlp/test/otlp_http_log_record_exporter_test.cc b/exporters/otlp/test/otlp_http_log_record_exporter_test.cc index 4dc3b5829d..df89ca17fa 100644 --- a/exporters/otlp/test/otlp_http_log_record_exporter_test.cc +++ b/exporters/otlp/test/otlp_http_log_record_exporter_test.cc @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -#ifndef HAVE_CPP_STDLIB +#ifndef OPENTELEMETRY_STL_VERSION # include # include @@ -740,4 +740,4 @@ TEST_F(OtlpHttpLogRecordExporterTestPeer, DefaultEndpoint) } // namespace otlp } // namespace exporter OPENTELEMETRY_END_NAMESPACE -#endif +#endif /* OPENTELEMETRY_STL_VERSION */ diff --git a/exporters/zipkin/test/zipkin_exporter_test.cc b/exporters/zipkin/test/zipkin_exporter_test.cc index fab19efb65..870ff427e9 100644 --- a/exporters/zipkin/test/zipkin_exporter_test.cc +++ b/exporters/zipkin/test/zipkin_exporter_test.cc @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -#ifndef HAVE_CPP_STDLIB +#ifndef OPENTELEMETRY_STL_VERSION # include "opentelemetry/exporters/zipkin/zipkin_exporter.h" # include "opentelemetry/ext/http/client/curl/http_client_curl.h" @@ -246,4 +246,4 @@ TEST_F(ZipkinExporterTestPeer, ConfigFromEnv) } // namespace zipkin } // namespace exporter OPENTELEMETRY_END_NAMESPACE -#endif // HAVE_CPP_STDLIB +#endif /* OPENTELEMETRY_STL_VERSION */ diff --git a/ext/test/http/CMakeLists.txt b/ext/test/http/CMakeLists.txt index 3ce72b3b83..328f78638b 100644 --- a/ext/test/http/CMakeLists.txt +++ b/ext/test/http/CMakeLists.txt @@ -25,7 +25,7 @@ endif() set(URL_PARSER_FILENAME url_parser_test) add_executable(${URL_PARSER_FILENAME} ${URL_PARSER_FILENAME}.cc) target_link_libraries(${URL_PARSER_FILENAME} ${GTEST_BOTH_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT}) + ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api) gtest_add_tests( TARGET ${URL_PARSER_FILENAME} TEST_PREFIX ext.http.urlparser.