diff --git a/api/include/opentelemetry/metrics/TBD b/api/include/opentelemetry/metrics/TBD deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/api/include/opentelemetry/metrics/meter.h b/api/include/opentelemetry/metrics/meter.h new file mode 100644 index 00000000000..42c189a6dda --- /dev/null +++ b/api/include/opentelemetry/metrics/meter.h @@ -0,0 +1,18 @@ +#pragma once +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE + +namespace metrics +{ + +class Meter +{ +public: + Meter() = default; + +}; + +} // namespace metrics + +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/metrics/meter_provider.h b/api/include/opentelemetry/metrics/meter_provider.h new file mode 100644 index 00000000000..aa577156321 --- /dev/null +++ b/api/include/opentelemetry/metrics/meter_provider.h @@ -0,0 +1,27 @@ +#pragma once + +#include "opentelemetry/metrics/meter.h" +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/nostd/string_view.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace metrics +{ +/** + * Creates new Meter instances. + */ +class MeterProvider +{ +public: + virtual ~MeterProvider() = default; + /** + * Gets or creates a named Meter instance. + * + * Optionally a version can be passed to create a named and versioned Meter + * instance. + */ + virtual nostd::shared_ptr GetMeter(nostd::string_view library_name, + nostd::string_view library_version = "") = 0; +}; +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/metrics/noop.h b/api/include/opentelemetry/metrics/noop.h new file mode 100644 index 00000000000..a53a591232a --- /dev/null +++ b/api/include/opentelemetry/metrics/noop.h @@ -0,0 +1,42 @@ +#pragma once +// Please refer to provider.h for documentation on how to obtain a Meter object. +// +// This file is part of the internal implementation of OpenTelemetry. Nothing in this file should be +// used directly. Please refer to meter.h for documentation on these interfaces. + +#include "opentelemetry/metrics/meter.h" +#include "opentelemetry/metrics/meter_provider.h" +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/nostd/unique_ptr.h" +#include "opentelemetry/version.h" + +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace metrics +{ +/** + * No-op implementation of a MeterProvider. + */ +class NoopMeter final : public Meter, public std::enable_shared_from_this {}; + +class NoopMeterProvider final : public opentelemetry::metrics::MeterProvider +{ +public: + NoopMeterProvider() + : meter_{nostd::shared_ptr( + new opentelemetry::metrics::NoopMeter)} + {} + + nostd::shared_ptr GetMeter( + nostd::string_view library_name, + nostd::string_view library_version) override + { + return meter_; + } + +private: + nostd::shared_ptr meter_; +}; +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/metrics/provider.h b/api/include/opentelemetry/metrics/provider.h new file mode 100644 index 00000000000..be79611e1ef --- /dev/null +++ b/api/include/opentelemetry/metrics/provider.h @@ -0,0 +1,60 @@ +#pragma once + +#include + +#include "opentelemetry/metrics/meter_provider.h" +#include "opentelemetry/metrics/noop.h" +#include "opentelemetry/nostd/shared_ptr.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace metrics +{ +/** + * Stores the singleton global MeterProvider. + */ +class Provider +{ +public: + /** + * Returns the singleton MeterProvider. + * + * By default, a no-op MeterProvider is returned. This will never return a + * nullptr MeterProvider. + */ + static nostd::shared_ptr GetMeterProvider() noexcept + { + while (GetLock().test_and_set(std::memory_order_acquire)) + ; + auto provider = nostd::shared_ptr(GetProvider()); + GetLock().clear(std::memory_order_release); + + return provider; + } + + /** + * Changes the singleton MeterProvider. + */ + static void SetMeterProvider(nostd::shared_ptr tp) noexcept + { + while (GetLock().test_and_set(std::memory_order_acquire)) + ; + GetProvider() = tp; + GetLock().clear(std::memory_order_release); + } + +private: + static nostd::shared_ptr &GetProvider() noexcept + { + static nostd::shared_ptr provider(new NoopMeterProvider); + return provider; + } + + static std::atomic_flag &GetLock() noexcept + { + static std::atomic_flag lock = ATOMIC_FLAG_INIT; + return lock; + } +}; + +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE diff --git a/api/test/CMakeLists.txt b/api/test/CMakeLists.txt index 21b3e9a3509..8c0833a51ee 100644 --- a/api/test/CMakeLists.txt +++ b/api/test/CMakeLists.txt @@ -2,3 +2,4 @@ add_subdirectory(core) add_subdirectory(plugin) add_subdirectory(nostd) add_subdirectory(trace) +add_subdirectory(metrics) diff --git a/api/test/metrics/BUILD b/api/test/metrics/BUILD new file mode 100644 index 00000000000..54feb0c75b8 --- /dev/null +++ b/api/test/metrics/BUILD @@ -0,0 +1,12 @@ +load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark") + +cc_test( + name = "meter_provider_test", + srcs = [ + "meter_provider_test.cc", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/api/test/metrics/CMakeLists.txt b/api/test/metrics/CMakeLists.txt new file mode 100644 index 00000000000..1f2aca70a84 --- /dev/null +++ b/api/test/metrics/CMakeLists.txt @@ -0,0 +1,6 @@ +foreach(testname meter_provider_test) + add_executable(${testname} "${testname}.cc") + target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api) + gtest_add_tests(TARGET ${testname} TEST_PREFIX metrics. TEST_LIST ${testname}) +endforeach() diff --git a/api/test/metrics/meter_provider_test.cc b/api/test/metrics/meter_provider_test.cc new file mode 100644 index 00000000000..252cead5167 --- /dev/null +++ b/api/test/metrics/meter_provider_test.cc @@ -0,0 +1,41 @@ +#include "opentelemetry/metrics/provider.h" +#include "opentelemetry/nostd/shared_ptr.h" + +#include + +using opentelemetry::metrics::Meter; +using opentelemetry::metrics::MeterProvider; +using opentelemetry::metrics::Provider; + +class TestProvider : public MeterProvider +{ + opentelemetry::nostd::shared_ptr GetMeter( + opentelemetry::nostd::string_view library_name, + opentelemetry::nostd::string_view library_version) override + { + return opentelemetry::nostd::shared_ptr(nullptr); + } +}; + +TEST(Provider, GetMeterProviderDefault) +{ + auto tf = Provider::GetMeterProvider(); + EXPECT_NE(nullptr, tf); +} + +TEST(Provider, SetMeterProvider) +{ + auto tf = opentelemetry::nostd::shared_ptr(new TestProvider()); + Provider::SetMeterProvider(tf); + ASSERT_EQ(tf, Provider::GetMeterProvider()); +} + +TEST(Provider, MultipleMeterProviders) +{ + auto tf = opentelemetry::nostd::shared_ptr(new TestProvider()); + Provider::SetMeterProvider(tf); + auto tf2 = opentelemetry::nostd::shared_ptr(new TestProvider()); + Provider::SetMeterProvider(tf2); + + ASSERT_NE(Provider::GetMeterProvider(), tf); +}