From ef23861f24d597b2493078661b5ea31e1316250c Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Tue, 6 Sep 2022 22:43:33 +0200 Subject: [PATCH 01/12] WIP Add singleton_test unit test alone. --- api/test/CMakeLists.txt | 1 + api/test/singleton/BUILD | 142 +++++++++++++ api/test/singleton/CMakeLists.txt | 39 ++++ api/test/singleton/component_a.cc | 37 ++++ api/test/singleton/component_a.h | 4 + api/test/singleton/component_b.cc | 37 ++++ api/test/singleton/component_b.h | 4 + api/test/singleton/component_c.cc | 39 ++++ api/test/singleton/component_c.h | 15 ++ api/test/singleton/component_d.cc | 39 ++++ api/test/singleton/component_d.h | 21 ++ api/test/singleton/component_e.cc | 39 ++++ api/test/singleton/component_e.h | 15 ++ api/test/singleton/component_f.cc | 39 ++++ api/test/singleton/component_f.h | 21 ++ api/test/singleton/singleton_test.cc | 289 +++++++++++++++++++++++++++ 16 files changed, 781 insertions(+) create mode 100644 api/test/singleton/BUILD create mode 100644 api/test/singleton/CMakeLists.txt create mode 100644 api/test/singleton/component_a.cc create mode 100644 api/test/singleton/component_a.h create mode 100644 api/test/singleton/component_b.cc create mode 100644 api/test/singleton/component_b.h create mode 100644 api/test/singleton/component_c.cc create mode 100644 api/test/singleton/component_c.h create mode 100644 api/test/singleton/component_d.cc create mode 100644 api/test/singleton/component_d.h create mode 100644 api/test/singleton/component_e.cc create mode 100644 api/test/singleton/component_e.h create mode 100644 api/test/singleton/component_f.cc create mode 100644 api/test/singleton/component_f.h create mode 100644 api/test/singleton/singleton_test.cc diff --git a/api/test/CMakeLists.txt b/api/test/CMakeLists.txt index 41125005ee..06f29d7365 100644 --- a/api/test/CMakeLists.txt +++ b/api/test/CMakeLists.txt @@ -13,3 +13,4 @@ if(WITH_LOGS_PREVIEW) endif() add_subdirectory(common) add_subdirectory(baggage) +add_subdirectory(singleton) diff --git a/api/test/singleton/BUILD b/api/test/singleton/BUILD new file mode 100644 index 0000000000..a8f5450532 --- /dev/null +++ b/api/test/singleton/BUILD @@ -0,0 +1,142 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +# FIXME: visibility("hidden") / visibility("default") compiling options. + +DEFAULT_WIN_COPTS = [ +] + +# gcc and clang, assumed to be used on this platform +DEFAULT_NOWIN_COPTS = [ + "-fvisibility=default", +] + +HIDDEN_WIN_COPTS = [ +] + +# gcc and clang, assumed to be used on this platform +HIDDEN_NOWIN_COPTS = [ + "-fvisibility=hidden", +] + +cc_library( + name = "component_a", + srcs = [ + "component_a.cc", + ], + hdrs = [ + "component_a.h", + ], + linkstatic = True, + deps = [ + "//api", + ], +) + +cc_library( + name = "component_b", + srcs = [ + "component_b.cc", + ], + hdrs = [ + "component_b.h", + ], + linkstatic = True, + deps = [ + "//api", + ], +) + +cc_library( + name = "component_c", + srcs = [ + "component_c.cc", + ], + hdrs = [ + "component_c.h", + ], + copts = select({ + "//bazel:windows": DEFAULT_WIN_COPTS, + "//conditions:default": DEFAULT_NOWIN_COPTS, + }), + linkstatic = False, + deps = [ + "//api", + ], +) + +cc_library( + name = "component_d", + srcs = [ + "component_d.cc", + ], + hdrs = [ + "component_d.h", + ], + copts = select({ + "//bazel:windows": HIDDEN_WIN_COPTS, + "//conditions:default": HIDDEN_NOWIN_COPTS, + }), + linkstatic = False, + deps = [ + "//api", + ], +) + +cc_library( + name = "component_e", + srcs = [ + "component_e.cc", + ], + hdrs = [ + "component_e.h", + ], + copts = select({ + "//bazel:windows": DEFAULT_WIN_COPTS, + "//conditions:default": DEFAULT_NOWIN_COPTS, + }), + linkstatic = False, + deps = [ + "//api", + ], +) + +cc_library( + name = "component_f", + srcs = [ + "component_f.cc", + ], + hdrs = [ + "component_f.h", + ], + copts = select({ + "//bazel:windows": HIDDEN_WIN_COPTS, + "//conditions:default": HIDDEN_NOWIN_COPTS, + }), + linkstatic = False, + deps = [ + "//api", + ], +) + +cc_test( + name = "singleton_test", + srcs = [ + "singleton_test.cc", + ], + linkstatic = False, + tags = [ + "api", + "test", + ], + deps = [ + "component_a", + "component_b", + "component_c", + "component_d", + "component_e", + "component_f", + "//api", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/api/test/singleton/CMakeLists.txt b/api/test/singleton/CMakeLists.txt new file mode 100644 index 0000000000..ef475bb34d --- /dev/null +++ b/api/test/singleton/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +include(GoogleTest) + +add_library(component_a STATIC component_a.cc) + +add_library(component_b STATIC component_b.cc) + +add_library(component_c SHARED component_c.cc) +set_target_properties(component_c PROPERTIES CXX_VISIBILITY_PRESET default) + +add_library(component_d SHARED component_d.cc) +set_target_properties(component_d PROPERTIES CXX_VISIBILITY_PRESET hidden) + +add_library(component_e SHARED component_e.cc) +set_target_properties(component_e PROPERTIES CXX_VISIBILITY_PRESET default) + +add_library(component_f SHARED component_f.cc) +set_target_properties(component_f PROPERTIES CXX_VISIBILITY_PRESET hidden) + +add_executable(singleton_test singleton_test.cc) + +target_link_libraries( + singleton_test + component_a + component_b + component_c + component_d + component_e + component_f + ${GTEST_BOTH_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + opentelemetry_api) + +gtest_add_tests( + TARGET singleton_test + TEST_PREFIX singleton. + TEST_LIST singleton_test) diff --git a/api/test/singleton/component_a.cc b/api/test/singleton/component_a.cc new file mode 100644 index 0000000000..bdf03cb699 --- /dev/null +++ b/api/test/singleton/component_a.cc @@ -0,0 +1,37 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/trace/provider.h" +#include "opentelemetry/version.h" + +#include "component_a.h" + +namespace trace = opentelemetry::trace; +namespace nostd = opentelemetry::nostd; + +static nostd::shared_ptr get_tracer() +{ + auto provider = trace::Provider::GetTracerProvider(); + return provider->GetTracer("A", "10.1"); +} + +static void f1() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("A::f1")); +} + +static void f2() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("A::f2")); + + f1(); + f1(); +} + +void do_something_in_a() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("A::library")); + + f2(); +} diff --git a/api/test/singleton/component_a.h b/api/test/singleton/component_a.h new file mode 100644 index 0000000000..2e06edf9ca --- /dev/null +++ b/api/test/singleton/component_a.h @@ -0,0 +1,4 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +void do_something_in_a(); diff --git a/api/test/singleton/component_b.cc b/api/test/singleton/component_b.cc new file mode 100644 index 0000000000..966d9c461a --- /dev/null +++ b/api/test/singleton/component_b.cc @@ -0,0 +1,37 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/trace/provider.h" +#include "opentelemetry/version.h" + +#include "component_b.h" + +namespace trace = opentelemetry::trace; +namespace nostd = opentelemetry::nostd; + +static nostd::shared_ptr get_tracer() +{ + auto provider = trace::Provider::GetTracerProvider(); + return provider->GetTracer("B", "20.2"); +} + +static void f1() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("B::f1")); +} + +static void f2() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("B::f2")); + + f1(); + f1(); +} + +void do_something_in_b() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("B::library")); + + f2(); +} diff --git a/api/test/singleton/component_b.h b/api/test/singleton/component_b.h new file mode 100644 index 0000000000..2e526e21d5 --- /dev/null +++ b/api/test/singleton/component_b.h @@ -0,0 +1,4 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +void do_something_in_b(); diff --git a/api/test/singleton/component_c.cc b/api/test/singleton/component_c.cc new file mode 100644 index 0000000000..cd87ceb727 --- /dev/null +++ b/api/test/singleton/component_c.cc @@ -0,0 +1,39 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/trace/provider.h" +#include "opentelemetry/version.h" + +#define BUILD_COMPONENT_C + +#include "component_c.h" + +namespace trace = opentelemetry::trace; +namespace nostd = opentelemetry::nostd; + +static nostd::shared_ptr get_tracer() +{ + auto provider = trace::Provider::GetTracerProvider(); + return provider->GetTracer("C", "30.3"); +} + +static void f1() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("C::f1")); +} + +static void f2() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("C::f2")); + + f1(); + f1(); +} + +void do_something_in_c() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("C::library")); + + f2(); +} diff --git a/api/test/singleton/component_c.h b/api/test/singleton/component_c.h new file mode 100644 index 0000000000..31193da2df --- /dev/null +++ b/api/test/singleton/component_c.h @@ -0,0 +1,15 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#if defined(_MSC_VER) +// component_c is a DDL + +# ifdef BUILD_COMPONENT_C +__declspec(dllexport) +# else +__declspec(dllimport) +# endif + +#endif + + void do_something_in_c(); diff --git a/api/test/singleton/component_d.cc b/api/test/singleton/component_d.cc new file mode 100644 index 0000000000..313fd1d23a --- /dev/null +++ b/api/test/singleton/component_d.cc @@ -0,0 +1,39 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/trace/provider.h" +#include "opentelemetry/version.h" + +#define BUILD_COMPONENT_D + +#include "component_d.h" + +namespace trace = opentelemetry::trace; +namespace nostd = opentelemetry::nostd; + +static nostd::shared_ptr get_tracer() +{ + auto provider = trace::Provider::GetTracerProvider(); + return provider->GetTracer("D", "40.4"); +} + +static void f1() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("D::f1")); +} + +static void f2() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("D::f2")); + + f1(); + f1(); +} + +void do_something_in_d() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("D::library")); + + f2(); +} diff --git a/api/test/singleton/component_d.h b/api/test/singleton/component_d.h new file mode 100644 index 0000000000..be65f4b5ac --- /dev/null +++ b/api/test/singleton/component_d.h @@ -0,0 +1,21 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Make the entry point visible, loaded dynamically + +#if defined(_MSC_VER) +// component_d is a DDL + +# ifdef BUILD_COMPONENT_D +__declspec(dllexport) +# else +__declspec(dllimport) +# endif + +#else +// component_d is a shared library (*.so) +// component_d is compiled with visibility("hidden"), +__attribute__((visibility("default"))) +#endif + + void do_something_in_d(); diff --git a/api/test/singleton/component_e.cc b/api/test/singleton/component_e.cc new file mode 100644 index 0000000000..9c88d27732 --- /dev/null +++ b/api/test/singleton/component_e.cc @@ -0,0 +1,39 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/trace/provider.h" +#include "opentelemetry/version.h" + +#define BUILD_COMPONENT_E + +#include "component_e.h" + +namespace trace = opentelemetry::trace; +namespace nostd = opentelemetry::nostd; + +static nostd::shared_ptr get_tracer() +{ + auto provider = trace::Provider::GetTracerProvider(); + return provider->GetTracer("E", "50.5"); +} + +static void f1() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("E::f1")); +} + +static void f2() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("E::f2")); + + f1(); + f1(); +} + +void do_something_in_e() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("E::library")); + + f2(); +} diff --git a/api/test/singleton/component_e.h b/api/test/singleton/component_e.h new file mode 100644 index 0000000000..53782d76f7 --- /dev/null +++ b/api/test/singleton/component_e.h @@ -0,0 +1,15 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#if defined(_MSC_VER) +// component_e is a DDL + +# ifdef BUILD_COMPONENT_E +__declspec(dllexport) +# else +__declspec(dllimport) +# endif + +#endif + + void do_something_in_e(); diff --git a/api/test/singleton/component_f.cc b/api/test/singleton/component_f.cc new file mode 100644 index 0000000000..33b0af2fbd --- /dev/null +++ b/api/test/singleton/component_f.cc @@ -0,0 +1,39 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/trace/provider.h" +#include "opentelemetry/version.h" + +#define BUILD_COMPONENT_F + +#include "component_f.h" + +namespace trace = opentelemetry::trace; +namespace nostd = opentelemetry::nostd; + +static nostd::shared_ptr get_tracer() +{ + auto provider = trace::Provider::GetTracerProvider(); + return provider->GetTracer("F", "60.6"); +} + +static void f1() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("F::f1")); +} + +static void f2() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("F::f2")); + + f1(); + f1(); +} + +void do_something_in_f() +{ + auto scoped_span = trace::Scope(get_tracer()->StartSpan("F::library")); + + f2(); +} diff --git a/api/test/singleton/component_f.h b/api/test/singleton/component_f.h new file mode 100644 index 0000000000..775a6cf758 --- /dev/null +++ b/api/test/singleton/component_f.h @@ -0,0 +1,21 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Make the entry point visible, loaded dynamically + +#if defined(_MSC_VER) +// component_d is a DDL + +# ifdef BUILD_COMPONENT_F +__declspec(dllexport) +# else +__declspec(dllimport) +# endif + +#else +// component_d is a shared library (*.so) +// component_d is compiled with visibility("hidden"), +__attribute__((visibility("default"))) +#endif + + void do_something_in_f(); diff --git a/api/test/singleton/singleton_test.cc b/api/test/singleton/singleton_test.cc new file mode 100644 index 0000000000..f9942c2f65 --- /dev/null +++ b/api/test/singleton/singleton_test.cc @@ -0,0 +1,289 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include + +#include +#include + +#include "component_a.h" +#include "component_b.h" +#include "component_c.h" +#include "component_d.h" +#include "component_e.h" +#include "component_f.h" + +#include "opentelemetry/trace/default_span.h" +#include "opentelemetry/trace/provider.h" +#include "opentelemetry/trace/span.h" +#include "opentelemetry/trace/span_context_kv_iterable.h" +#include "opentelemetry/trace/span_startoptions.h" +#include "opentelemetry/trace/tracer_provider.h" + +using namespace opentelemetry; + +void do_something() +{ + do_something_in_a(); + do_something_in_b(); + do_something_in_c(); + do_something_in_d(); + do_something_in_e(); + do_something_in_f(); +} + +int span_a_lib_count = 0; +int span_a_f1_count = 0; +int span_a_f2_count = 0; +int span_b_lib_count = 0; +int span_b_f1_count = 0; +int span_b_f2_count = 0; +int span_c_lib_count = 0; +int span_c_f1_count = 0; +int span_c_f2_count = 0; +int span_d_lib_count = 0; +int span_d_f1_count = 0; +int span_d_f2_count = 0; +int span_e_lib_count = 0; +int span_e_f1_count = 0; +int span_e_f2_count = 0; +int span_f_lib_count = 0; +int span_f_f1_count = 0; +int span_f_f2_count = 0; +int unknown_span_count = 0; + +void reset_counts() +{ + span_a_lib_count = 0; + span_a_f1_count = 0; + span_a_f2_count = 0; + span_b_lib_count = 0; + span_b_f1_count = 0; + span_b_f2_count = 0; + span_c_lib_count = 0; + span_c_f1_count = 0; + span_c_f2_count = 0; + span_d_lib_count = 0; + span_d_f1_count = 0; + span_d_f2_count = 0; + span_e_lib_count = 0; + span_e_f1_count = 0; + span_e_f2_count = 0; + span_f_lib_count = 0; + span_f_f1_count = 0; + span_f_f2_count = 0; + unknown_span_count = 0; +} + +class MyTracer : public trace::Tracer +{ +public: + nostd::shared_ptr StartSpan(nostd::string_view name, + const common::KeyValueIterable &attributes, + const trace::SpanContextKeyValueIterable &links, + const trace::StartSpanOptions &options) noexcept override + { + nostd::shared_ptr result(new trace::DefaultSpan(trace::SpanContext::GetInvalid())); + + /* + Unit test code, no need to be fancy. + */ + + if (name == "A::library") + { + span_a_lib_count++; + } + else if (name == "A::f1") + { + span_a_f1_count++; + } + else if (name == "A::f2") + { + span_a_f2_count++; + } + else if (name == "B::library") + { + span_b_lib_count++; + } + else if (name == "B::f1") + { + span_b_f1_count++; + } + else if (name == "B::f2") + { + span_b_f2_count++; + } + else if (name == "C::library") + { + span_c_lib_count++; + } + else if (name == "C::f1") + { + span_c_f1_count++; + } + else if (name == "C::f2") + { + span_c_f2_count++; + } + else if (name == "D::library") + { + span_d_lib_count++; + } + else if (name == "D::f1") + { + span_d_f1_count++; + } + else if (name == "D::f2") + { + span_d_f2_count++; + } + else if (name == "E::library") + { + span_e_lib_count++; + } + else if (name == "E::f1") + { + span_e_f1_count++; + } + else if (name == "E::f2") + { + span_e_f2_count++; + } + else if (name == "F::library") + { + span_f_lib_count++; + } + else if (name == "F::f1") + { + span_f_f1_count++; + } + else if (name == "F::f2") + { + span_f_f2_count++; + } + else + { + unknown_span_count++; + } + + return result; + } + + void ForceFlushWithMicroseconds(uint64_t timeout) noexcept override {} + + void CloseWithMicroseconds(uint64_t timeout) noexcept override {} +}; + +class MyTracerProvider : public trace::TracerProvider +{ +public: + static std::shared_ptr Create() + { + std::shared_ptr result(new MyTracerProvider()); + return result; + } + + nostd::shared_ptr GetTracer(nostd::string_view library_name, + nostd::string_view library_version, + nostd::string_view schema_url) noexcept override + { + nostd::shared_ptr result(new MyTracer()); + return result; + } +}; + +void setup_otel() +{ + std::shared_ptr provider = MyTracerProvider::Create(); + + // The whole point of this test is to make sure + // that the API singleton behind SetTracerProvider() + // works for all components, static and dynamic. + + // Set the global tracer provider + trace_api::Provider::SetTracerProvider(provider); +} + +void cleanup_otel() +{ + std::shared_ptr provider( + new opentelemetry::trace::NoopTracerProvider()); + + // Set the global tracer provider + trace_api::Provider::SetTracerProvider(provider); +} + +TEST(SingletonTest, Uniqueness) +{ + do_something(); + + EXPECT_EQ(span_a_lib_count, 0); + EXPECT_EQ(span_a_f1_count, 0); + EXPECT_EQ(span_a_f2_count, 0); + EXPECT_EQ(span_b_lib_count, 0); + EXPECT_EQ(span_b_f1_count, 0); + EXPECT_EQ(span_b_f2_count, 0); + EXPECT_EQ(span_c_lib_count, 0); + EXPECT_EQ(span_c_f1_count, 0); + EXPECT_EQ(span_c_f2_count, 0); + EXPECT_EQ(span_d_lib_count, 0); + EXPECT_EQ(span_d_f1_count, 0); + EXPECT_EQ(span_d_f2_count, 0); + EXPECT_EQ(span_e_lib_count, 0); + EXPECT_EQ(span_e_f1_count, 0); + EXPECT_EQ(span_e_f2_count, 0); + EXPECT_EQ(span_f_lib_count, 0); + EXPECT_EQ(span_f_f1_count, 0); + EXPECT_EQ(span_f_f2_count, 0); + EXPECT_EQ(unknown_span_count, 0); + + reset_counts(); + setup_otel(); + + do_something(); + + EXPECT_EQ(span_a_lib_count, 1); + EXPECT_EQ(span_a_f1_count, 2); + EXPECT_EQ(span_a_f2_count, 1); + 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); + EXPECT_EQ(unknown_span_count, 0); + + reset_counts(); + cleanup_otel(); + + do_something(); + + EXPECT_EQ(span_a_lib_count, 0); + EXPECT_EQ(span_a_f1_count, 0); + EXPECT_EQ(span_a_f2_count, 0); + EXPECT_EQ(span_b_lib_count, 0); + EXPECT_EQ(span_b_f1_count, 0); + EXPECT_EQ(span_b_f2_count, 0); + EXPECT_EQ(span_c_lib_count, 0); + EXPECT_EQ(span_c_f1_count, 0); + EXPECT_EQ(span_c_f2_count, 0); + EXPECT_EQ(span_d_lib_count, 0); + EXPECT_EQ(span_d_f1_count, 0); + EXPECT_EQ(span_d_f2_count, 0); + EXPECT_EQ(span_e_lib_count, 0); + EXPECT_EQ(span_e_f1_count, 0); + EXPECT_EQ(span_e_f2_count, 0); + EXPECT_EQ(span_f_lib_count, 0); + EXPECT_EQ(span_f_f1_count, 0); + EXPECT_EQ(span_f_f2_count, 0); + EXPECT_EQ(unknown_span_count, 0); +} From d2311979d73fc4f15c1805955bd6111368132ea7 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Tue, 6 Sep 2022 23:42:30 +0200 Subject: [PATCH 02/12] WIP Testing alternate fix, with annotation on methods. Windows not covered. --- api/include/opentelemetry/_metrics/provider.h | 5 +++-- api/include/opentelemetry/baggage/baggage.h | 3 ++- api/include/opentelemetry/common/macros.h | 14 ++++++++++++++ .../context/propagation/global_propagator.h | 7 ++++--- .../opentelemetry/context/runtime_context.h | 5 +++-- api/include/opentelemetry/logs/provider.h | 5 +++-- api/include/opentelemetry/metrics/provider.h | 7 ++++--- api/include/opentelemetry/trace/provider.h | 5 +++-- api/include/opentelemetry/trace/trace_state.h | 3 ++- 9 files changed, 38 insertions(+), 16 deletions(-) diff --git a/api/include/opentelemetry/_metrics/provider.h b/api/include/opentelemetry/_metrics/provider.h index e079b34d5f..397aa64c16 100644 --- a/api/include/opentelemetry/_metrics/provider.h +++ b/api/include/opentelemetry/_metrics/provider.h @@ -7,6 +7,7 @@ # include "opentelemetry/_metrics/meter_provider.h" # include "opentelemetry/_metrics/noop.h" +# include "opentelemetry/common/macros.h" # include "opentelemetry/common/spin_lock_mutex.h" # include "opentelemetry/nostd/shared_ptr.h" @@ -41,13 +42,13 @@ class Provider } private: - static nostd::shared_ptr &GetProvider() noexcept + OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetProvider() noexcept { static nostd::shared_ptr provider(new NoopMeterProvider); return provider; } - static common::SpinLockMutex &GetLock() noexcept + OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept { static common::SpinLockMutex lock; return lock; diff --git a/api/include/opentelemetry/baggage/baggage.h b/api/include/opentelemetry/baggage/baggage.h index eb5e4dcc7c..2bf0fda0d4 100644 --- a/api/include/opentelemetry/baggage/baggage.h +++ b/api/include/opentelemetry/baggage/baggage.h @@ -6,6 +6,7 @@ #include #include "opentelemetry/common/kv_properties.h" +#include "opentelemetry/common/macros.h" #include "opentelemetry/nostd/shared_ptr.h" #include "opentelemetry/nostd/string_view.h" #include "opentelemetry/version.h" @@ -34,7 +35,7 @@ class Baggage : kv_properties_(new opentelemetry::common::KeyValueProperties(keys_and_values)) {} - static nostd::shared_ptr GetDefault() + OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr GetDefault() { static nostd::shared_ptr baggage{new Baggage()}; return baggage; diff --git a/api/include/opentelemetry/common/macros.h b/api/include/opentelemetry/common/macros.h index 204c1ed04e..15e877a55f 100644 --- a/api/include/opentelemetry/common/macros.h +++ b/api/include/opentelemetry/common/macros.h @@ -89,3 +89,17 @@ #else # define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) #endif + +/** + @def OPENTELEMETRY_API_SINGLETON + Declare a symbol with visibility default. +*/ +#if defined(__clang__) +# define OPENTELEMETRY_API_SINGLETON __attribute__((visibility("default"))) +#elif defined(__GNUC__) +# define OPENTELEMETRY_API_SINGLETON __attribute__((visibility("default"))) +#elif defined(_MSC_VER) +# define OPENTELEMETRY_API_SINGLETON +#else +# define OPENTELEMETRY_API_SINGLETON +#endif diff --git a/api/include/opentelemetry/context/propagation/global_propagator.h b/api/include/opentelemetry/context/propagation/global_propagator.h index b4e49325cd..6d26b84019 100644 --- a/api/include/opentelemetry/context/propagation/global_propagator.h +++ b/api/include/opentelemetry/context/propagation/global_propagator.h @@ -8,6 +8,7 @@ #include "opentelemetry/context/propagation/noop_propagator.h" #include "opentelemetry/context/propagation/text_map_propagator.h" +#include "opentelemetry/common/macros.h" #include "opentelemetry/common/spin_lock_mutex.h" #include "opentelemetry/nostd/shared_ptr.h" @@ -37,13 +38,13 @@ class GlobalTextMapPropagator } private: - static nostd::shared_ptr &GetPropagator() noexcept + OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetPropagator() noexcept { static nostd::shared_ptr propagator(new NoOpPropagator()); return propagator; } - static common::SpinLockMutex &GetLock() noexcept + OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept { static common::SpinLockMutex lock; return lock; @@ -52,4 +53,4 @@ class GlobalTextMapPropagator } // namespace propagation } // namespace context -OPENTELEMETRY_END_NAMESPACE \ No newline at end of file +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/context/runtime_context.h b/api/include/opentelemetry/context/runtime_context.h index 167a928f10..a92dcdf05f 100644 --- a/api/include/opentelemetry/context/runtime_context.h +++ b/api/include/opentelemetry/context/runtime_context.h @@ -3,6 +3,7 @@ #pragma once +#include "opentelemetry/common/macros.h" #include "opentelemetry/context/context.h" OPENTELEMETRY_BEGIN_NAMESPACE @@ -166,7 +167,7 @@ class RuntimeContext return GetStorage(); } - static nostd::shared_ptr &GetStorage() noexcept + OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetStorage() noexcept { static nostd::shared_ptr context(GetDefaultStorage()); return context; @@ -315,7 +316,7 @@ class ThreadLocalContextStorage : public RuntimeContextStorage Context *base_; }; - Stack &GetStack() + OPENTELEMETRY_API_SINGLETON Stack &GetStack() { static thread_local Stack stack_ = Stack(); return stack_; diff --git a/api/include/opentelemetry/logs/provider.h b/api/include/opentelemetry/logs/provider.h index 38186bbe75..6f4b76fbd7 100644 --- a/api/include/opentelemetry/logs/provider.h +++ b/api/include/opentelemetry/logs/provider.h @@ -6,6 +6,7 @@ # include +# include "opentelemetry/common/macros.h" # include "opentelemetry/common/spin_lock_mutex.h" # include "opentelemetry/logs/logger_provider.h" # include "opentelemetry/logs/noop.h" @@ -42,13 +43,13 @@ class Provider } private: - static nostd::shared_ptr &GetProvider() noexcept + OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetProvider() noexcept { static nostd::shared_ptr provider(new NoopLoggerProvider); return provider; } - static common::SpinLockMutex &GetLock() noexcept + OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept { static common::SpinLockMutex lock; return lock; diff --git a/api/include/opentelemetry/metrics/provider.h b/api/include/opentelemetry/metrics/provider.h index 3bacac9760..0eddc61142 100644 --- a/api/include/opentelemetry/metrics/provider.h +++ b/api/include/opentelemetry/metrics/provider.h @@ -6,6 +6,7 @@ # include +# include "opentelemetry/common/macros.h" # include "opentelemetry/common/spin_lock_mutex.h" # include "opentelemetry/metrics/meter_provider.h" # include "opentelemetry/metrics/noop.h" @@ -42,13 +43,13 @@ class Provider } private: - static nostd::shared_ptr &GetProvider() noexcept + OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetProvider() noexcept { static nostd::shared_ptr provider(new NoopMeterProvider); return provider; } - static common::SpinLockMutex &GetLock() noexcept + OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept { static common::SpinLockMutex lock; return lock; @@ -57,4 +58,4 @@ class Provider } // namespace metrics OPENTELEMETRY_END_NAMESPACE -#endif \ No newline at end of file +#endif diff --git a/api/include/opentelemetry/trace/provider.h b/api/include/opentelemetry/trace/provider.h index 6267cbd4d2..e59c5f9512 100644 --- a/api/include/opentelemetry/trace/provider.h +++ b/api/include/opentelemetry/trace/provider.h @@ -5,6 +5,7 @@ #include +#include "opentelemetry/common/macros.h" #include "opentelemetry/common/spin_lock_mutex.h" #include "opentelemetry/nostd/shared_ptr.h" #include "opentelemetry/trace/noop.h" @@ -41,13 +42,13 @@ class Provider } private: - static nostd::shared_ptr &GetProvider() noexcept + OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetProvider() noexcept { static nostd::shared_ptr provider(new NoopTracerProvider); return provider; } - static common::SpinLockMutex &GetLock() noexcept + OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept { static common::SpinLockMutex lock; return lock; diff --git a/api/include/opentelemetry/trace/trace_state.h b/api/include/opentelemetry/trace/trace_state.h index 0343637cfa..750cdefe11 100644 --- a/api/include/opentelemetry/trace/trace_state.h +++ b/api/include/opentelemetry/trace/trace_state.h @@ -15,6 +15,7 @@ #endif #include "opentelemetry/common/kv_properties.h" +#include "opentelemetry/common/macros.h" #include "opentelemetry/nostd/shared_ptr.h" #include "opentelemetry/nostd/span.h" #include "opentelemetry/nostd/string_view.h" @@ -41,7 +42,7 @@ class TraceState static constexpr auto kKeyValueSeparator = '='; static constexpr auto kMembersSeparator = ','; - static nostd::shared_ptr GetDefault() + OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr GetDefault() { static nostd::shared_ptr ts{new TraceState()}; return ts; From 7c52d4bc9eb06c08909655401a19e273663dffdb Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Wed, 7 Sep 2022 00:35:59 +0200 Subject: [PATCH 03/12] Testing tentative fix for windows --- api/include/opentelemetry/common/macros.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/include/opentelemetry/common/macros.h b/api/include/opentelemetry/common/macros.h index 15e877a55f..58e54f8568 100644 --- a/api/include/opentelemetry/common/macros.h +++ b/api/include/opentelemetry/common/macros.h @@ -99,7 +99,8 @@ #elif defined(__GNUC__) # define OPENTELEMETRY_API_SINGLETON __attribute__((visibility("default"))) #elif defined(_MSC_VER) -# define OPENTELEMETRY_API_SINGLETON +/* Tentative fix */ +# define OPENTELEMETRY_API_SINGLETON __declspec(selectany) #else # define OPENTELEMETRY_API_SINGLETON #endif From 6a8f2ff88f182accacd4c276efe243429dccd50c Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Wed, 7 Sep 2022 01:49:39 +0200 Subject: [PATCH 04/12] Disable unit test for windows --- api/include/opentelemetry/common/macros.h | 4 ++-- api/test/singleton/CMakeLists.txt | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/api/include/opentelemetry/common/macros.h b/api/include/opentelemetry/common/macros.h index 58e54f8568..be8f8b0e33 100644 --- a/api/include/opentelemetry/common/macros.h +++ b/api/include/opentelemetry/common/macros.h @@ -99,8 +99,8 @@ #elif defined(__GNUC__) # define OPENTELEMETRY_API_SINGLETON __attribute__((visibility("default"))) #elif defined(_MSC_VER) -/* Tentative fix */ -# define OPENTELEMETRY_API_SINGLETON __declspec(selectany) +/* TODO: fix windows as well. */ +# define OPENTELEMETRY_API_SINGLETON #else # define OPENTELEMETRY_API_SINGLETON #endif diff --git a/api/test/singleton/CMakeLists.txt b/api/test/singleton/CMakeLists.txt index ef475bb34d..71f151078e 100644 --- a/api/test/singleton/CMakeLists.txt +++ b/api/test/singleton/CMakeLists.txt @@ -33,7 +33,12 @@ target_link_libraries( ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api) +if(NOT WIN32) + gtest_add_tests( TARGET singleton_test TEST_PREFIX singleton. TEST_LIST singleton_test) + +endif() + From c81cc34d72b823e2fc527169da8299dd25899c11 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Wed, 7 Sep 2022 11:06:50 +0200 Subject: [PATCH 05/12] Partial revert of: commit 74ec691e4a73c3160f2bb2aaf0a9626fb282beec Author: WenTao Ou Date: Thu Apr 7 14:06:59 2022 +0800 Move public definitions into `opentelemetry_api`. (#1314) Signed-off-by: owent When using WITH_STL in cmake, HAVE_CPP_STDLIB must be defined for unit tests. --- CMakeLists.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a1b6934003..a94bf14a2a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,9 +127,12 @@ endif() if(WITH_STL) # 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 - # the global project build definitions. Optimize for speed to reduce the hops + # opentelemetry-api library directly. We ensure that STL implementation + # (nostd:: or std::) in unit test code is consistent with + # the global project build definitions. + add_definitions(-DHAVE_CPP_STDLIB) + + # Optimize for speed to reduce the hops if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") if(CMAKE_BUILD_TYPE MATCHES Debug) # Turn off optimizations for DEBUG From 84d6bab1eea106a5b171fb8f802f9a453a7105be Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Wed, 7 Sep 2022 12:04:34 +0200 Subject: [PATCH 06/12] format --- api/test/singleton/CMakeLists.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/api/test/singleton/CMakeLists.txt b/api/test/singleton/CMakeLists.txt index 71f151078e..942973a11c 100644 --- a/api/test/singleton/CMakeLists.txt +++ b/api/test/singleton/CMakeLists.txt @@ -35,10 +35,9 @@ target_link_libraries( if(NOT WIN32) -gtest_add_tests( - TARGET singleton_test - TEST_PREFIX singleton. - TEST_LIST singleton_test) + gtest_add_tests( + TARGET singleton_test + TEST_PREFIX singleton. + TEST_LIST singleton_test) endif() - From 5de5b6a6b724a6ade44ad89140774771e6a2b5ab Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Wed, 7 Sep 2022 13:37:12 +0200 Subject: [PATCH 07/12] format --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a94bf14a2a..b2c4f44974 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,8 +128,8 @@ endif() if(WITH_STL) # These definitions are needed for test projects that do not link against # opentelemetry-api library directly. We ensure that STL implementation - # (nostd:: or std::) in unit test code is consistent with - # the global project build definitions. + # (nostd:: or std::) in unit test code is consistent with the global project + # build definitions. add_definitions(-DHAVE_CPP_STDLIB) # Optimize for speed to reduce the hops From cbf70a70c70d67e423b5703d6a6d61774e6ce85f Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Wed, 7 Sep 2022 14:47:57 +0200 Subject: [PATCH 08/12] Alternate implementation for windows. --- api/include/opentelemetry/_metrics/provider.h | 14 ++ api/include/opentelemetry/baggage/baggage.h | 10 ++ api/include/opentelemetry/common/macros.h | 130 +++++++++++++++++- .../context/propagation/global_propagator.h | 15 ++ .../opentelemetry/context/runtime_context.h | 14 ++ api/include/opentelemetry/logs/provider.h | 15 ++ api/include/opentelemetry/metrics/provider.h | 15 ++ api/include/opentelemetry/trace/provider.h | 15 ++ api/include/opentelemetry/trace/trace_state.h | 11 ++ api/test/singleton/CMakeLists.txt | 12 +- 10 files changed, 240 insertions(+), 11 deletions(-) diff --git a/api/include/opentelemetry/_metrics/provider.h b/api/include/opentelemetry/_metrics/provider.h index 397aa64c16..425544be6b 100644 --- a/api/include/opentelemetry/_metrics/provider.h +++ b/api/include/opentelemetry/_metrics/provider.h @@ -44,17 +44,31 @@ class Provider private: OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetProvider() noexcept { +# ifdef OPENTELEMETRY_SINGLETON_IN_METHOD static nostd::shared_ptr provider(new NoopMeterProvider); +# endif return provider; } OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept { +# ifdef OPENTELEMETRY_SINGLETON_IN_METHOD static common::SpinLockMutex lock; +# endif return lock; } + +# ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER + static nostd::shared_ptr provider; + static common::SpinLockMutex lock; +# endif }; +# ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER +static nostd::shared_ptr Provider::provider(new NoopMeterProvider); +static common::SpinLockMutex Provider::lock; +# endif + } // namespace metrics OPENTELEMETRY_END_NAMESPACE #endif diff --git a/api/include/opentelemetry/baggage/baggage.h b/api/include/opentelemetry/baggage/baggage.h index 2bf0fda0d4..c059a5e952 100644 --- a/api/include/opentelemetry/baggage/baggage.h +++ b/api/include/opentelemetry/baggage/baggage.h @@ -37,7 +37,9 @@ class Baggage OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr GetDefault() { +#ifdef OPENTELEMETRY_SINGLETON_IN_METHOD static nostd::shared_ptr baggage{new Baggage()}; +#endif return baggage; } @@ -293,8 +295,16 @@ class Baggage private: // Store entries in a C-style array to avoid using std::array or std::vector. nostd::unique_ptr kv_properties_; + +#ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER + static nostd::shared_ptr baggage; +#endif }; +#ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER +OPENTELEMETRY_MEMBER_SINGLETON nostd::shared_ptr Baggage::baggage{new Baggage()}; +#endif + } // namespace baggage OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/common/macros.h b/api/include/opentelemetry/common/macros.h index be8f8b0e33..e97e3d13e2 100644 --- a/api/include/opentelemetry/common/macros.h +++ b/api/include/opentelemetry/common/macros.h @@ -90,17 +90,141 @@ # define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) #endif +/* clang-format off */ + /** - @def OPENTELEMETRY_API_SINGLETON - Declare a symbol with visibility default. + @page HEADER_ONLY_SINGLETON Header only singleton. + + @section ELF_SINGLETON + + For clang and gcc, the desired coding pattern is as follows. + + @verbatim + class Foo + { + // (a) + __attribute__((visibility("default"))) + // (b) + T& get_singleton() + { + // (c) + static T singleton; + return singleton; + } + }; + @endverbatim + + (a) is needed when the code is build with + @code -fvisibility="hidden" @endcode + to ensure that all instances of (b) are visible to the linker. + + What is duplicated in the binary is @em code, in (b). + + The linker will make sure only one instance + of all the (b) methods is used. + + (c) is a singleton implemented inside a method. + + This is very desirable, because: + + - the C++ compiler guarantees the variable (c) is thread safe, + starting with C++ XX (TODO: link needed) + + - constructors for (c) singletons are executed in code path order, + or not at all if the singleton is never used. + + @section WINDOWS_SINGLETON + + For Visual Studio, the desired coding pattern is as follows. + + @verbatim + class Foo + { + // (d) + T& get_singleton() + { + return singleton; + } + + // (e) + static T singleton; + }; + + // (f) + __declspec(selectany) T Foo::singleton; + @endverbatim + + (d) is just used to expose the singleton, + so that other methods do not see implementation details. + + (e) is a declaration + + (f) is a definition, that breaks ODR (One Definition Rule), + corrected with the + @code __declspec(selectany) @endcode + annotation. + + (f) has to be done separately from (e), in an "out of class definition", + because combining (e) and (f) in an "in class definition" is not a valid + syntax with @c selectany. + + What is duplicated in the binary is @em data, in (f). + + In this pattern, initialization of (f) does not happen in code path order, + initialization depends on global C++ constructors. + + @section CODING_PATTERN + + As a result, to support all platforms, + the coding pattern to use is as follows + + @verbatim + class Foo + { + OPENTELEMETRY_API_SINGLETON + T& get_singleton() + { + #ifdef OPENTELEMETRY_SINGLETON_IN_METHOD + static T singleton; + #endif + return singleton; + } + +#ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER + static T singleton; +#endif + }; + + +#ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER + OPENTELEMETRY_MEMBER_SINGLETON T Foo::singleton; +#endif + @endverbatim */ + +/* clang-format on */ + #if defined(__clang__) + +# define OPENTELEMETRY_SINGLETON_IN_METHOD # define OPENTELEMETRY_API_SINGLETON __attribute__((visibility("default"))) + #elif defined(__GNUC__) + +# define OPENTELEMETRY_SINGLETON_IN_METHOD # define OPENTELEMETRY_API_SINGLETON __attribute__((visibility("default"))) + #elif defined(_MSC_VER) -/* TODO: fix windows as well. */ + +# define OPENTELEMETRY_SINGLETON_IN_MEMBER # define OPENTELEMETRY_API_SINGLETON +# define OPENTELEMETRY_MEMBER_SINGLETON __declspec(selectany) + #else + +/* Add support for another compiler here. */ + +# define OPENTELEMETRY_SINGLETON_IN_METHOD # define OPENTELEMETRY_API_SINGLETON + #endif diff --git a/api/include/opentelemetry/context/propagation/global_propagator.h b/api/include/opentelemetry/context/propagation/global_propagator.h index 6d26b84019..9ee2c12b40 100644 --- a/api/include/opentelemetry/context/propagation/global_propagator.h +++ b/api/include/opentelemetry/context/propagation/global_propagator.h @@ -40,17 +40,32 @@ class GlobalTextMapPropagator private: OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetPropagator() noexcept { +#ifdef OPENTELEMETRY_SINGLETON_IN_METHOD static nostd::shared_ptr propagator(new NoOpPropagator()); +#endif return propagator; } OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept { +#ifdef OPENTELEMETRY_SINGLETON_IN_METHOD static common::SpinLockMutex lock; +#endif return lock; } + +#ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER + static nostd::shared_ptr propagator(new NoOpPropagator()); + static common::SpinLockMutex lock; +#endif }; +#ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER +OPENTELEMETRY_MEMBER_SINGLETON nostd::shared_ptr + GlobalTextMapPropagator::propagator(new NoOpPropagator()); +OPENTELEMETRY_MEMBER_SINGLETON common::SpinLockMutex GlobalTextMapPropagator::lock; +#endif + } // namespace propagation } // namespace context OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/context/runtime_context.h b/api/include/opentelemetry/context/runtime_context.h index a92dcdf05f..89c89627cd 100644 --- a/api/include/opentelemetry/context/runtime_context.h +++ b/api/include/opentelemetry/context/runtime_context.h @@ -169,11 +169,22 @@ class RuntimeContext OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetStorage() noexcept { +#ifdef OPENTELEMETRY_SINGLETON_IN_METHOD static nostd::shared_ptr context(GetDefaultStorage()); +#endif return context; } + +#ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER + static nostd::shared_ptr context; +#endif }; +#ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER +OPENTELEMETRY_MEMBER_SINGLETON nostd::shared_ptr RuntimeContext::context( + GetDefaultStorage()); +#endif + inline Token::~Token() noexcept { context::RuntimeContext::Detach(*this); @@ -318,6 +329,9 @@ class ThreadLocalContextStorage : public RuntimeContextStorage OPENTELEMETRY_API_SINGLETON Stack &GetStack() { + // Safe with OPENTELEMETRY_SINGLETON_IN_METHOD. + + // TODO: Investigate if this is safe with windows static thread_local Stack stack_ = Stack(); return stack_; } diff --git a/api/include/opentelemetry/logs/provider.h b/api/include/opentelemetry/logs/provider.h index 6f4b76fbd7..9584187765 100644 --- a/api/include/opentelemetry/logs/provider.h +++ b/api/include/opentelemetry/logs/provider.h @@ -45,17 +45,32 @@ class Provider private: OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetProvider() noexcept { +# ifdef OPENTELEMETRY_SINGLETON_IN_METHOD static nostd::shared_ptr provider(new NoopLoggerProvider); +# endif return provider; } OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept { +# ifdef OPENTELEMETRY_SINGLETON_IN_METHOD static common::SpinLockMutex lock; +# endif return lock; } + +# ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER + static nostd::shared_ptr provider; + static common::SpinLockMutex lock; +# endif }; +# ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER +OPENTELEMETRY_MEMBER_SINGLETON nostd::shared_ptr Provider::provider( + new NoopLoggerProvider); +OPENTELEMETRY_MEMBER_SINGLETON common::SpinLockMutex Provider::lock; +# endif + } // namespace logs OPENTELEMETRY_END_NAMESPACE #endif diff --git a/api/include/opentelemetry/metrics/provider.h b/api/include/opentelemetry/metrics/provider.h index 0eddc61142..d3e62959c3 100644 --- a/api/include/opentelemetry/metrics/provider.h +++ b/api/include/opentelemetry/metrics/provider.h @@ -45,17 +45,32 @@ class Provider private: OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetProvider() noexcept { +# ifdef OPENTELEMETRY_SINGLETON_IN_METHOD static nostd::shared_ptr provider(new NoopMeterProvider); +# endif return provider; } OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept { +# ifdef OPENTELEMETRY_SINGLETON_IN_METHOD static common::SpinLockMutex lock; +# endif return lock; } + +# ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER + static nostd::shared_ptr provider; + static common::SpinLockMutex lock; +# endif }; +# ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER +OPENTELEMETRY_MEMBER_SINGLETON nostd::shared_ptr Provider::provider( + new NoopMeterProvider); +OPENTELEMETRY_MEMBER_SINGLETON common::SpinLockMutex Provider::lock; +# endif + } // namespace metrics OPENTELEMETRY_END_NAMESPACE #endif diff --git a/api/include/opentelemetry/trace/provider.h b/api/include/opentelemetry/trace/provider.h index e59c5f9512..bf916b3830 100644 --- a/api/include/opentelemetry/trace/provider.h +++ b/api/include/opentelemetry/trace/provider.h @@ -44,16 +44,31 @@ class Provider private: OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetProvider() noexcept { +#ifdef OPENTELEMETRY_SINGLETON_IN_METHOD static nostd::shared_ptr provider(new NoopTracerProvider); +#endif return provider; } OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept { +#ifdef OPENTELEMETRY_SINGLETON_IN_METHOD static common::SpinLockMutex lock; +#endif return lock; } + +#ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER + static nostd::shared_ptr provider; + static common::SpinLockMutex lock; +#endif }; +#ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER +OPENTELEMETRY_MEMBER_SINGLETON nostd::shared_ptr Provider::provider( + new NoopTracerProvider); +OPENTELEMETRY_MEMBER_SINGLETON common::SpinLockMutex Provider::lock; +#endif + } // namespace trace OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/trace/trace_state.h b/api/include/opentelemetry/trace/trace_state.h index 750cdefe11..c0460a39bb 100644 --- a/api/include/opentelemetry/trace/trace_state.h +++ b/api/include/opentelemetry/trace/trace_state.h @@ -44,7 +44,9 @@ class TraceState OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr GetDefault() { +#ifdef OPENTELEMETRY_SINGLETON_IN_METHOD static nostd::shared_ptr ts{new TraceState()}; +#endif return ts; } @@ -316,6 +318,15 @@ class TraceState private: // Store entries in a C-style array to avoid using std::array or std::vector. nostd::unique_ptr kv_properties_; + +#ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER + static nostd::shared_ptr ts; +#endif }; + +#ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER +OPENTELEMETRY_MEMBER_SINGLETON nostd::shared_ptr TraceState::ts{new TraceState()}; +#endif + } // namespace trace OPENTELEMETRY_END_NAMESPACE diff --git a/api/test/singleton/CMakeLists.txt b/api/test/singleton/CMakeLists.txt index 942973a11c..ef475bb34d 100644 --- a/api/test/singleton/CMakeLists.txt +++ b/api/test/singleton/CMakeLists.txt @@ -33,11 +33,7 @@ target_link_libraries( ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api) -if(NOT WIN32) - - gtest_add_tests( - TARGET singleton_test - TEST_PREFIX singleton. - TEST_LIST singleton_test) - -endif() +gtest_add_tests( + TARGET singleton_test + TEST_PREFIX singleton. + TEST_LIST singleton_test) From 5aeeb7481a71a46d77e09d4e0e46383390c87104 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Wed, 7 Sep 2022 15:32:13 +0200 Subject: [PATCH 09/12] Fixed windows build break. --- .../opentelemetry/context/propagation/global_propagator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/include/opentelemetry/context/propagation/global_propagator.h b/api/include/opentelemetry/context/propagation/global_propagator.h index 9ee2c12b40..9c8a03e47f 100644 --- a/api/include/opentelemetry/context/propagation/global_propagator.h +++ b/api/include/opentelemetry/context/propagation/global_propagator.h @@ -55,7 +55,7 @@ class GlobalTextMapPropagator } #ifdef OPENTELEMETRY_SINGLETON_IN_MEMBER - static nostd::shared_ptr propagator(new NoOpPropagator()); + static nostd::shared_ptr propagator; static common::SpinLockMutex lock; #endif }; From 556b5925615442829f712c9e8e437c08aa5350d7 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Thu, 8 Sep 2022 21:49:50 +0200 Subject: [PATCH 10/12] Fix code review comments, proper cmake dependency in opentelemetry-api --- CMakeLists.txt | 9 +++------ api/test/singleton/CMakeLists.txt | 6 ++++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b2c4f44974..a1b6934003 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,12 +127,9 @@ endif() if(WITH_STL) # These definitions are needed for test projects that do not link against - # opentelemetry-api library directly. We ensure that STL implementation - # (nostd:: or std::) in unit test code is consistent with the global project - # build definitions. - add_definitions(-DHAVE_CPP_STDLIB) - - # Optimize for speed to reduce the hops + # opentelemetry-api library directly. We ensure that variant implementation + # (absl::variant or std::variant) in variant unit test code is consistent with + # the global project build definitions. Optimize for speed to reduce the hops if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") if(CMAKE_BUILD_TYPE MATCHES Debug) # Turn off optimizations for DEBUG diff --git a/api/test/singleton/CMakeLists.txt b/api/test/singleton/CMakeLists.txt index ef475bb34d..71b759af8f 100644 --- a/api/test/singleton/CMakeLists.txt +++ b/api/test/singleton/CMakeLists.txt @@ -4,20 +4,26 @@ include(GoogleTest) 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_executable(singleton_test singleton_test.cc) From b5b65529e49799bc32724faff8395b737bd5a391 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Thu, 8 Sep 2022 22:57:07 +0200 Subject: [PATCH 11/12] Tentative, to test on CI: only test static libraries for windows. --- api/test/singleton/component_f.h | 6 +++--- api/test/singleton/singleton_test.cc | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/api/test/singleton/component_f.h b/api/test/singleton/component_f.h index 775a6cf758..e042ba5bb3 100644 --- a/api/test/singleton/component_f.h +++ b/api/test/singleton/component_f.h @@ -4,7 +4,7 @@ // Make the entry point visible, loaded dynamically #if defined(_MSC_VER) -// component_d is a DDL +// component_f is a DDL # ifdef BUILD_COMPONENT_F __declspec(dllexport) @@ -13,8 +13,8 @@ __declspec(dllimport) # endif #else -// component_d is a shared library (*.so) -// component_d is compiled with visibility("hidden"), +// component_f is a shared library (*.so) +// component_f is compiled with visibility("hidden"), __attribute__((visibility("default"))) #endif diff --git a/api/test/singleton/singleton_test.cc b/api/test/singleton/singleton_test.cc index f9942c2f65..468cadc70d 100644 --- a/api/test/singleton/singleton_test.cc +++ b/api/test/singleton/singleton_test.cc @@ -6,6 +6,12 @@ #include #include +#if defined(_MSC_VER) +/* Singleton in windows DDL not supported yet. */ +#else +# define WITH_DYNAMIC_TEST +#endif + #include "component_a.h" #include "component_b.h" #include "component_c.h" @@ -26,10 +32,12 @@ void do_something() { do_something_in_a(); do_something_in_b(); +#ifdef WITH_DYNAMIC_TEST do_something_in_c(); do_something_in_d(); do_something_in_e(); do_something_in_f(); +#endif } int span_a_lib_count = 0; @@ -223,6 +231,7 @@ TEST(SingletonTest, Uniqueness) EXPECT_EQ(span_b_lib_count, 0); EXPECT_EQ(span_b_f1_count, 0); EXPECT_EQ(span_b_f2_count, 0); +#ifdef WITH_DYNAMIC_TEST EXPECT_EQ(span_c_lib_count, 0); EXPECT_EQ(span_c_f1_count, 0); EXPECT_EQ(span_c_f2_count, 0); @@ -235,6 +244,7 @@ TEST(SingletonTest, Uniqueness) EXPECT_EQ(span_f_lib_count, 0); EXPECT_EQ(span_f_f1_count, 0); EXPECT_EQ(span_f_f2_count, 0); +#endif EXPECT_EQ(unknown_span_count, 0); reset_counts(); @@ -249,6 +259,7 @@ TEST(SingletonTest, Uniqueness) EXPECT_EQ(span_b_f1_count, 2); EXPECT_EQ(span_b_f2_count, 1); EXPECT_EQ(span_c_lib_count, 1); +#ifdef WITH_DYNAMIC_TEST EXPECT_EQ(span_c_f1_count, 2); EXPECT_EQ(span_c_f2_count, 1); EXPECT_EQ(span_d_lib_count, 1); @@ -260,6 +271,7 @@ TEST(SingletonTest, Uniqueness) EXPECT_EQ(span_f_lib_count, 1); EXPECT_EQ(span_f_f1_count, 2); EXPECT_EQ(span_f_f2_count, 1); +#endif EXPECT_EQ(unknown_span_count, 0); reset_counts(); @@ -273,6 +285,7 @@ TEST(SingletonTest, Uniqueness) EXPECT_EQ(span_b_lib_count, 0); EXPECT_EQ(span_b_f1_count, 0); EXPECT_EQ(span_b_f2_count, 0); +#ifdef WITH_DYNAMIC_TEST EXPECT_EQ(span_c_lib_count, 0); EXPECT_EQ(span_c_f1_count, 0); EXPECT_EQ(span_c_f2_count, 0); @@ -285,5 +298,6 @@ TEST(SingletonTest, Uniqueness) EXPECT_EQ(span_f_lib_count, 0); EXPECT_EQ(span_f_f1_count, 0); EXPECT_EQ(span_f_f2_count, 0); +#endif EXPECT_EQ(unknown_span_count, 0); } From 868b6b0744aaf54b6316b976396364aa8cb5d789 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Fri, 9 Sep 2022 11:46:40 +0200 Subject: [PATCH 12/12] Tentative, testing CI with windows static lib, no annotation --- api/include/opentelemetry/common/macros.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/include/opentelemetry/common/macros.h b/api/include/opentelemetry/common/macros.h index e97e3d13e2..11ba26aa87 100644 --- a/api/include/opentelemetry/common/macros.h +++ b/api/include/opentelemetry/common/macros.h @@ -214,11 +214,11 @@ # define OPENTELEMETRY_SINGLETON_IN_METHOD # define OPENTELEMETRY_API_SINGLETON __attribute__((visibility("default"))) -#elif defined(_MSC_VER) +// #elif defined(_MSC_VER) -# define OPENTELEMETRY_SINGLETON_IN_MEMBER -# define OPENTELEMETRY_API_SINGLETON -# define OPENTELEMETRY_MEMBER_SINGLETON __declspec(selectany) +// # define OPENTELEMETRY_SINGLETON_IN_MEMBER +// # define OPENTELEMETRY_API_SINGLETON +// # define OPENTELEMETRY_MEMBER_SINGLETON __declspec(selectany) #else