From e2c22df4347992fb6c248819e2c5602eceb63375 Mon Sep 17 00:00:00 2001 From: Pranav Sharma Date: Tue, 11 Feb 2025 20:13:21 +0000 Subject: [PATCH 01/10] Add meter scope configurator --- sdk/include/opentelemetry/sdk/metrics/meter.h | 4 ++ .../opentelemetry/sdk/metrics/meter_config.h | 34 +++++++++++++++ .../opentelemetry/sdk/metrics/meter_context.h | 11 ++++- .../sdk/metrics/meter_context_factory.h | 5 +++ .../sdk/metrics/meter_provider.h | 9 +++- .../sdk/metrics/meter_provider_factory.h | 5 +++ sdk/src/metrics/CMakeLists.txt | 1 + sdk/src/metrics/meter_config.cc | 41 +++++++++++++++++++ sdk/src/metrics/meter_context.cc | 15 ++++++- sdk/src/metrics/meter_context_factory.cc | 14 ++++++- sdk/src/metrics/meter_provider.cc | 7 +++- sdk/src/metrics/meter_provider_factory.cc | 14 ++++++- 12 files changed, 152 insertions(+), 8 deletions(-) create mode 100644 sdk/include/opentelemetry/sdk/metrics/meter_config.h create mode 100644 sdk/src/metrics/meter_config.cc diff --git a/sdk/include/opentelemetry/sdk/metrics/meter.h b/sdk/include/opentelemetry/sdk/metrics/meter.h index 2e9153e151..fda9953302 100644 --- a/sdk/include/opentelemetry/sdk/metrics/meter.h +++ b/sdk/include/opentelemetry/sdk/metrics/meter.h @@ -19,6 +19,7 @@ #include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h" #include "opentelemetry/sdk/metrics/instrument_metadata_validator.h" #include "opentelemetry/sdk/metrics/instruments.h" +#include "opentelemetry/sdk/metrics/meter_config.h" #include "opentelemetry/sdk/metrics/meter_context.h" #include "opentelemetry/sdk/metrics/state/async_metric_storage.h" #include "opentelemetry/sdk/resource/resource.h" @@ -135,6 +136,7 @@ class Meter final : public opentelemetry::metrics::Meter // meter-context. std::unique_ptr scope_; std::weak_ptr meter_context_; + // MeterConfig meter_config_; // Mapping between instrument-name and Aggregation Storage. std::unordered_map> storage_registry_; std::shared_ptr observable_registry_; @@ -144,6 +146,8 @@ class Meter final : public opentelemetry::metrics::Meter InstrumentDescriptor &instrument_descriptor); opentelemetry::common::SpinLockMutex storage_lock_; + // static const opentelemetry::metrics::NoopMeter kNoopMeter; + static nostd::shared_ptr GetNoopObservableInsrument() { diff --git a/sdk/include/opentelemetry/sdk/metrics/meter_config.h b/sdk/include/opentelemetry/sdk/metrics/meter_config.h new file mode 100644 index 0000000000..64b68e5b24 --- /dev/null +++ b/sdk/include/opentelemetry/sdk/metrics/meter_config.h @@ -0,0 +1,34 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +class MeterConfig +{ +public: + bool operator==(const MeterConfig &other) const noexcept; + + bool IsEnabled() const noexcept; + + static MeterConfig Disabled(); + + static MeterConfig Enabled(); + + static MeterConfig Default(); + +private: + explicit MeterConfig(const bool disabled = false) : disabled_(disabled) {} + bool disabled_; + static const MeterConfig kDefaultConfig; + static const MeterConfig kDisabledConfig; +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/sdk/include/opentelemetry/sdk/metrics/meter_context.h b/sdk/include/opentelemetry/sdk/metrics/meter_context.h index 8a19cd7466..91c0be2158 100644 --- a/sdk/include/opentelemetry/sdk/metrics/meter_context.h +++ b/sdk/include/opentelemetry/sdk/metrics/meter_context.h @@ -13,6 +13,8 @@ #include "opentelemetry/nostd/function_ref.h" #include "opentelemetry/nostd/span.h" #include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/sdk/instrumentationscope/scope_configurator.h" +#include "opentelemetry/sdk/metrics/meter_config.h" #include "opentelemetry/sdk/metrics/metric_reader.h" #include "opentelemetry/sdk/metrics/state/metric_collector.h" #include "opentelemetry/sdk/metrics/view/instrument_selector.h" @@ -55,7 +57,11 @@ class MeterContext : public std::enable_shared_from_this MeterContext( std::unique_ptr views = std::unique_ptr(new ViewRegistry()), const opentelemetry::sdk::resource::Resource &resource = - opentelemetry::sdk::resource::Resource::Create({})) noexcept; + opentelemetry::sdk::resource::Resource::Create({}), + std::unique_ptr> meter_configurator = + std::make_unique>( + instrumentationscope::ScopeConfigurator::Builder(MeterConfig::Default()) + .Build())) noexcept; /** * Obtain the resource associated with this meter context. @@ -69,6 +75,8 @@ class MeterContext : public std::enable_shared_from_this */ ViewRegistry *GetViewRegistry() const noexcept; + const instrumentationscope::ScopeConfigurator &GetMeterConfigurator() const noexcept; + /** * NOTE - INTERNAL method, can change in future. * Process callback for each meter in thread-safe manner @@ -154,6 +162,7 @@ class MeterContext : public std::enable_shared_from_this std::vector> collectors_; std::unique_ptr views_; opentelemetry::common::SystemTimestamp sdk_start_ts_; + std::unique_ptr> meter_configurator_; std::vector> meters_; #ifdef ENABLE_METRICS_EXEMPLAR_PREVIEW diff --git a/sdk/include/opentelemetry/sdk/metrics/meter_context_factory.h b/sdk/include/opentelemetry/sdk/metrics/meter_context_factory.h index 1185a6075a..763a07fd9c 100644 --- a/sdk/include/opentelemetry/sdk/metrics/meter_context_factory.h +++ b/sdk/include/opentelemetry/sdk/metrics/meter_context_factory.h @@ -32,6 +32,11 @@ class OPENTELEMETRY_EXPORT MeterContextFactory static std::unique_ptr Create( std::unique_ptr views, const opentelemetry::sdk::resource::Resource &resource); + + static std::unique_ptr Create( + std::unique_ptr views, + const opentelemetry::sdk::resource::Resource &resource, + std::unique_ptr> meter_configurator); }; } // namespace metrics diff --git a/sdk/include/opentelemetry/sdk/metrics/meter_provider.h b/sdk/include/opentelemetry/sdk/metrics/meter_provider.h index 46b4efc93c..9feb1a18fa 100644 --- a/sdk/include/opentelemetry/sdk/metrics/meter_provider.h +++ b/sdk/include/opentelemetry/sdk/metrics/meter_provider.h @@ -20,6 +20,9 @@ #include "opentelemetry/sdk/resource/resource.h" #include "opentelemetry/version.h" +#include "opentelemetry/sdk/instrumentationscope/scope_configurator.h" +#include "opentelemetry/sdk/metrics/meter.h" + #ifdef ENABLE_METRICS_EXEMPLAR_PREVIEW # include "opentelemetry/sdk/metrics/exemplar/filter_type.h" #endif @@ -40,7 +43,11 @@ class OPENTELEMETRY_EXPORT MeterProvider final : public opentelemetry::metrics:: */ MeterProvider( std::unique_ptr views = std::unique_ptr(new ViewRegistry()), - const sdk::resource::Resource &resource = sdk::resource::Resource::Create({})) noexcept; + const sdk::resource::Resource &resource = sdk::resource::Resource::Create({}), + std::unique_ptr> meter_configurator = + std::make_unique>( + instrumentationscope::ScopeConfigurator::Builder(MeterConfig::Default()) + .Build())) noexcept; /** * Initialize a new meter provider with a specified context diff --git a/sdk/include/opentelemetry/sdk/metrics/meter_provider_factory.h b/sdk/include/opentelemetry/sdk/metrics/meter_provider_factory.h index 499c87ae6a..f31b06ae10 100644 --- a/sdk/include/opentelemetry/sdk/metrics/meter_provider_factory.h +++ b/sdk/include/opentelemetry/sdk/metrics/meter_provider_factory.h @@ -30,6 +30,11 @@ class OPENTELEMETRY_EXPORT MeterProviderFactory std::unique_ptr views, const opentelemetry::sdk::resource::Resource &resource); + static std::unique_ptr Create( + std::unique_ptr views, + const opentelemetry::sdk::resource::Resource &resource, + std::unique_ptr> meter_configurator); + static std::unique_ptr Create( std::unique_ptr context); }; diff --git a/sdk/src/metrics/CMakeLists.txt b/sdk/src/metrics/CMakeLists.txt index 5a726b4eee..f1ba16a116 100644 --- a/sdk/src/metrics/CMakeLists.txt +++ b/sdk/src/metrics/CMakeLists.txt @@ -8,6 +8,7 @@ add_library( meter_provider.cc meter_provider_factory.cc meter.cc + meter_config.cc meter_context.cc meter_context_factory.cc metric_reader.cc diff --git a/sdk/src/metrics/meter_config.cc b/sdk/src/metrics/meter_config.cc new file mode 100644 index 0000000000..088ec786c3 --- /dev/null +++ b/sdk/src/metrics/meter_config.cc @@ -0,0 +1,41 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/sdk/metrics/meter_config.h" +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +const MeterConfig MeterConfig::kDefaultConfig = MeterConfig(); +const MeterConfig MeterConfig::kDisabledConfig = MeterConfig(true); + +bool MeterConfig::operator==(const MeterConfig &other) const noexcept +{ + return disabled_ == other.disabled_; +} + +bool MeterConfig::IsEnabled() const noexcept +{ + return !disabled_; +} + +MeterConfig MeterConfig::Disabled() +{ + return kDisabledConfig; +} + +MeterConfig MeterConfig::Enabled() +{ + return kDefaultConfig; +} + +MeterConfig MeterConfig::Default() +{ + return kDefaultConfig; +} + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/sdk/src/metrics/meter_context.cc b/sdk/src/metrics/meter_context.cc index 31dd1af8b1..df808aff20 100644 --- a/sdk/src/metrics/meter_context.cc +++ b/sdk/src/metrics/meter_context.cc @@ -35,8 +35,13 @@ namespace metrics { MeterContext::MeterContext(std::unique_ptr views, - const opentelemetry::sdk::resource::Resource &resource) noexcept - : resource_{resource}, views_(std::move(views)), sdk_start_ts_{std::chrono::system_clock::now()} + const opentelemetry::sdk::resource::Resource &resource, + std::unique_ptr> + meter_configurator) noexcept + : resource_{resource}, + views_(std::move(views)), + sdk_start_ts_{std::chrono::system_clock::now()}, + meter_configurator_(std::move(meter_configurator)) {} const resource::Resource &MeterContext::GetResource() const noexcept @@ -49,6 +54,12 @@ ViewRegistry *MeterContext::GetViewRegistry() const noexcept return views_.get(); } +const instrumentationscope::ScopeConfigurator &MeterContext::GetMeterConfigurator() + const noexcept +{ + return *meter_configurator_; +} + bool MeterContext::ForEachMeter( nostd::function_ref &meter)> callback) noexcept { diff --git a/sdk/src/metrics/meter_context_factory.cc b/sdk/src/metrics/meter_context_factory.cc index 59e97ce264..a7f7d74269 100644 --- a/sdk/src/metrics/meter_context_factory.cc +++ b/sdk/src/metrics/meter_context_factory.cc @@ -33,7 +33,19 @@ std::unique_ptr MeterContextFactory::Create( std::unique_ptr views, const opentelemetry::sdk::resource::Resource &resource) { - std::unique_ptr context(new MeterContext(std::move(views), resource)); + auto meter_configurator = std::make_unique>( + instrumentationscope::ScopeConfigurator::Builder(MeterConfig::Default()) + .Build()); + return Create(std::move(views), resource, std::move(meter_configurator)); +} + +std::unique_ptr MeterContextFactory::Create( + std::unique_ptr views, + const opentelemetry::sdk::resource::Resource &resource, + std::unique_ptr> meter_configurator) +{ + std::unique_ptr context( + new MeterContext(std::move(views), resource, std::move(meter_configurator))); return context; } diff --git a/sdk/src/metrics/meter_provider.cc b/sdk/src/metrics/meter_provider.cc index 1e0df0f6f3..e6c25caf07 100644 --- a/sdk/src/metrics/meter_provider.cc +++ b/sdk/src/metrics/meter_provider.cc @@ -36,8 +36,11 @@ MeterProvider::MeterProvider(std::unique_ptr context) noexcept {} MeterProvider::MeterProvider(std::unique_ptr views, - const sdk::resource::Resource &resource) noexcept - : context_(std::make_shared(std::move(views), resource)) + const sdk::resource::Resource &resource, + std::unique_ptr> + meter_configurator) noexcept + : context_( + std::make_shared(std::move(views), resource, std::move(meter_configurator))) { OTEL_INTERNAL_LOG_DEBUG("[MeterProvider] MeterProvider created."); } diff --git a/sdk/src/metrics/meter_provider_factory.cc b/sdk/src/metrics/meter_provider_factory.cc index c5e368aca6..eb82b8ed33 100644 --- a/sdk/src/metrics/meter_provider_factory.cc +++ b/sdk/src/metrics/meter_provider_factory.cc @@ -34,9 +34,21 @@ std::unique_ptr MeterProviderFactory std::unique_ptr MeterProviderFactory::Create( std::unique_ptr views, const opentelemetry::sdk::resource::Resource &resource) +{ + auto meter_configurator = std::make_unique>( + instrumentationscope::ScopeConfigurator::Builder(MeterConfig::Default()) + .Build()); + return Create(std::move(views), resource, std::move(meter_configurator)); +} + +std::unique_ptr MeterProviderFactory::Create( + std::unique_ptr views, + const opentelemetry::sdk::resource::Resource &resource, + std::unique_ptr> meter_configurator) { std::unique_ptr provider( - new opentelemetry::sdk::metrics::MeterProvider(std::move(views), resource)); + new opentelemetry::sdk::metrics::MeterProvider(std::move(views), resource, + std::move(meter_configurator))); return provider; } From 74c9e34470e0d55ff4669cd260628930eab8cf47 Mon Sep 17 00:00:00 2001 From: Pranav Sharma Date: Tue, 11 Feb 2025 21:51:58 +0000 Subject: [PATCH 02/10] Add documentation for updated code --- .../opentelemetry/sdk/metrics/meter_config.h | 27 ++++++++++++++++++- .../opentelemetry/sdk/metrics/meter_context.h | 8 ++++-- .../sdk/metrics/meter_context_factory.h | 21 ++++++++++++++- .../sdk/metrics/meter_provider.h | 4 ++- sdk/src/metrics/meter_config.cc | 2 +- 5 files changed, 56 insertions(+), 6 deletions(-) diff --git a/sdk/include/opentelemetry/sdk/metrics/meter_config.h b/sdk/include/opentelemetry/sdk/metrics/meter_config.h index 64b68e5b24..abb22154d2 100644 --- a/sdk/include/opentelemetry/sdk/metrics/meter_config.h +++ b/sdk/include/opentelemetry/sdk/metrics/meter_config.h @@ -10,17 +10,42 @@ namespace sdk { namespace metrics { +/** + * MeterConfig defines various configurable aspects of a Meter's behavior. + * This class should not be used directly to configure a Meter's behavior, instead a + * ScopeConfigurator should be used to compute the desired MeterConfig which can then be used to + * configure a Meter. + */ class MeterConfig { public: bool operator==(const MeterConfig &other) const noexcept; + /** + * Returns if the Meter is enabled or disabled. Meters are enabled by default. + * @return a boolean indicating if the Meter is enabled. Defaults to true. + */ bool IsEnabled() const noexcept; + /** + * Returns a MeterConfig that represents a disabled Meter. A disabled meter behaves like a + * no-op meter. + * @return a static constant MeterConfig that represents a disabled meter. + */ static MeterConfig Disabled(); + /** + * Returns a MeterConfig that represents an enabled Meter. + * @return a static constant MeterConfig that represents an enabled meter. + */ static MeterConfig Enabled(); + /** + * Returns a MeterConfig that represents a Meter configured with the default behavior. + * The default behavior is guided by the OpenTelemetry specification. + * @return a static constant MeterConfig that represents a meter configured with default + * behavior. + */ static MeterConfig Default(); private: @@ -31,4 +56,4 @@ class MeterConfig }; } // namespace metrics } // namespace sdk -OPENTELEMETRY_END_NAMESPACE \ No newline at end of file +OPENTELEMETRY_END_NAMESPACE diff --git a/sdk/include/opentelemetry/sdk/metrics/meter_context.h b/sdk/include/opentelemetry/sdk/metrics/meter_context.h index 91c0be2158..ca0a489c19 100644 --- a/sdk/include/opentelemetry/sdk/metrics/meter_context.h +++ b/sdk/include/opentelemetry/sdk/metrics/meter_context.h @@ -75,16 +75,20 @@ class MeterContext : public std::enable_shared_from_this */ ViewRegistry *GetViewRegistry() const noexcept; + /** + * Obtain the ScopeConfigurator with this meter context. + * @return The ScopeConfigurator for this meter context. + */ const instrumentationscope::ScopeConfigurator &GetMeterConfigurator() const noexcept; /** - * NOTE - INTERNAL method, can change in future. + * NOTE - INTERNAL method, can change in the future. * Process callback for each meter in thread-safe manner */ bool ForEachMeter(nostd::function_ref &meter)> callback) noexcept; /** - * NOTE - INTERNAL method, can change in future. + * NOTE - INTERNAL method, can change in the future. * Get the configured meters. * This method is NOT thread safe, and only called through MeterProvider * diff --git a/sdk/include/opentelemetry/sdk/metrics/meter_context_factory.h b/sdk/include/opentelemetry/sdk/metrics/meter_context_factory.h index 763a07fd9c..3b6544b984 100644 --- a/sdk/include/opentelemetry/sdk/metrics/meter_context_factory.h +++ b/sdk/include/opentelemetry/sdk/metrics/meter_context_factory.h @@ -23,16 +23,35 @@ class OPENTELEMETRY_EXPORT MeterContextFactory { public: /** - * Create a MeterContext. + * Create a MeterContext with valid defaults. + * @return A unique pointer to the created MeterContext object. */ static std::unique_ptr Create(); + /** + * Create a MeterContext with specified views. + * @param views ViewRegistry containing OpenTelemetry views registered with this meter context. + */ static std::unique_ptr Create(std::unique_ptr views); + /** + * Create a MeterContext with specified views and resource. + * @param views ViewRegistry containing OpenTelemetry views registered with this meter context. + * @param resource The OpenTelemetry resource associated with this meter context. + * @return A unique pointer to the created MeterContext object. + */ static std::unique_ptr Create( std::unique_ptr views, const opentelemetry::sdk::resource::Resource &resource); + /** + * Create a MeterContext with specified views, resource and meter scope configurator. + * @param views ViewRegistry containing OpenTelemetry views registered with this meter context. + * @param resource The OpenTelemetry resource associated with this meter context. + * @param meter_configurator A scope configurator defining the behavior of a meter associated with + * this meter context. + * @return A unique pointer to the created MeterContext object. + */ static std::unique_ptr Create( std::unique_ptr views, const opentelemetry::sdk::resource::Resource &resource, diff --git a/sdk/include/opentelemetry/sdk/metrics/meter_provider.h b/sdk/include/opentelemetry/sdk/metrics/meter_provider.h index 9feb1a18fa..5b794fa809 100644 --- a/sdk/include/opentelemetry/sdk/metrics/meter_provider.h +++ b/sdk/include/opentelemetry/sdk/metrics/meter_provider.h @@ -37,9 +37,11 @@ class OPENTELEMETRY_EXPORT MeterProvider final : public opentelemetry::metrics:: { public: /** - * Initialize a new meter provider + * Initialize a new meter provider. * @param views The views for this meter provider * @param resource The resources for this meter provider. + * @param meter_configurator Provides access to a function that computes the MeterConfig for + * Meters provided by this MeterProvider. */ MeterProvider( std::unique_ptr views = std::unique_ptr(new ViewRegistry()), diff --git a/sdk/src/metrics/meter_config.cc b/sdk/src/metrics/meter_config.cc index 088ec786c3..cef0d60da1 100644 --- a/sdk/src/metrics/meter_config.cc +++ b/sdk/src/metrics/meter_config.cc @@ -38,4 +38,4 @@ MeterConfig MeterConfig::Default() } // namespace metrics } // namespace sdk -OPENTELEMETRY_END_NAMESPACE \ No newline at end of file +OPENTELEMETRY_END_NAMESPACE From 91e63e603bc84a803094075420fa8e28765e8617 Mon Sep 17 00:00:00 2001 From: Pranav Sharma Date: Wed, 12 Feb 2025 17:41:08 +0000 Subject: [PATCH 03/10] Update meter's behavior based on MeterConfig --- sdk/include/opentelemetry/sdk/metrics/meter.h | 4 +- sdk/src/metrics/meter.cc | 91 ++++++++++++++++++- 2 files changed, 91 insertions(+), 4 deletions(-) diff --git a/sdk/include/opentelemetry/sdk/metrics/meter.h b/sdk/include/opentelemetry/sdk/metrics/meter.h index fda9953302..bf1b0e6c37 100644 --- a/sdk/include/opentelemetry/sdk/metrics/meter.h +++ b/sdk/include/opentelemetry/sdk/metrics/meter.h @@ -136,17 +136,17 @@ class Meter final : public opentelemetry::metrics::Meter // meter-context. std::unique_ptr scope_; std::weak_ptr meter_context_; - // MeterConfig meter_config_; // Mapping between instrument-name and Aggregation Storage. std::unordered_map> storage_registry_; std::shared_ptr observable_registry_; + MeterConfig meter_config_; std::unique_ptr RegisterSyncMetricStorage( InstrumentDescriptor &instrument_descriptor); std::unique_ptr RegisterAsyncMetricStorage( InstrumentDescriptor &instrument_descriptor); opentelemetry::common::SpinLockMutex storage_lock_; - // static const opentelemetry::metrics::NoopMeter kNoopMeter; + static opentelemetry::metrics::NoopMeter kNoopMeter; static nostd::shared_ptr GetNoopObservableInsrument() diff --git a/sdk/src/metrics/meter.cc b/sdk/src/metrics/meter.cc index 2b95802fe0..c77e26b168 100644 --- a/sdk/src/metrics/meter.cc +++ b/sdk/src/metrics/meter.cc @@ -49,19 +49,37 @@ namespace metrics namespace metrics = opentelemetry::metrics; +metrics::NoopMeter Meter::kNoopMeter = metrics::NoopMeter(); + Meter::Meter( std::weak_ptr meter_context, std::unique_ptr instrumentation_scope) noexcept : scope_{std::move(instrumentation_scope)}, meter_context_{std::move(meter_context)}, - observable_registry_(new ObservableRegistry()) -{} + observable_registry_(new ObservableRegistry()), + meter_config_(MeterConfig::Default()) +{ + if (auto meter_context_locked_ptr = meter_context_.lock()) + { + meter_config_ = meter_context_locked_ptr->GetMeterConfigurator().ComputeConfig(*scope_); + } + else + { + OTEL_INTERNAL_LOG_ERROR("[Meter::Meter()] - Error during initialization." + << "The metric context is invalid") + } +} opentelemetry::nostd::unique_ptr> Meter::CreateUInt64Counter( opentelemetry::nostd::string_view name, opentelemetry::nostd::string_view description, opentelemetry::nostd::string_view unit) noexcept { + if (!meter_config_.IsEnabled()) + { + return kNoopMeter.CreateUInt64Counter(name, description, unit); + } + if (!ValidateInstrument(name, description, unit)) { OTEL_INTERNAL_LOG_ERROR("Meter::CreateUInt64Counter - failed. Invalid parameters." @@ -83,6 +101,11 @@ opentelemetry::nostd::unique_ptr> Meter::CreateDoubleCo opentelemetry::nostd::string_view description, opentelemetry::nostd::string_view unit) noexcept { + if (!meter_config_.IsEnabled()) + { + return kNoopMeter.CreateDoubleCounter(name, description, unit); + } + if (!ValidateInstrument(name, description, unit)) { OTEL_INTERNAL_LOG_ERROR("Meter::CreateDoubleCounter - failed. Invalid parameters." @@ -105,6 +128,11 @@ Meter::CreateInt64ObservableCounter(opentelemetry::nostd::string_view name, opentelemetry::nostd::string_view description, opentelemetry::nostd::string_view unit) noexcept { + if (!meter_config_.IsEnabled()) + { + return kNoopMeter.CreateInt64ObservableCounter(name, description, unit); + } + if (!ValidateInstrument(name, description, unit)) { OTEL_INTERNAL_LOG_ERROR("Meter::CreateInt64ObservableCounter - failed. Invalid parameters." @@ -126,6 +154,11 @@ Meter::CreateDoubleObservableCounter(opentelemetry::nostd::string_view name, opentelemetry::nostd::string_view description, opentelemetry::nostd::string_view unit) noexcept { + if (!meter_config_.IsEnabled()) + { + return kNoopMeter.CreateDoubleObservableCounter(name, description, unit); + } + if (!ValidateInstrument(name, description, unit)) { OTEL_INTERNAL_LOG_ERROR("Meter::CreateDoubleObservableCounter - failed. Invalid parameters." @@ -147,6 +180,11 @@ opentelemetry::nostd::unique_ptr> Meter::CreateUInt opentelemetry::nostd::string_view description, opentelemetry::nostd::string_view unit) noexcept { + if (!meter_config_.IsEnabled()) + { + return kNoopMeter.CreateUInt64Histogram(name, description, unit); + } + if (!ValidateInstrument(name, description, unit)) { OTEL_INTERNAL_LOG_ERROR("Meter::CreateUInt64Histogram - failed. Invalid parameters." @@ -169,6 +207,11 @@ opentelemetry::nostd::unique_ptr> Meter::CreateDouble opentelemetry::nostd::string_view description, opentelemetry::nostd::string_view unit) noexcept { + if (!meter_config_.IsEnabled()) + { + return kNoopMeter.CreateDoubleHistogram(name, description, unit); + } + if (!ValidateInstrument(name, description, unit)) { OTEL_INTERNAL_LOG_ERROR("Meter::CreateDoubleHistogram - failed. Invalid parameters." @@ -192,6 +235,11 @@ opentelemetry::nostd::unique_ptr> Meter::CreateInt64Gaug opentelemetry::nostd::string_view description, opentelemetry::nostd::string_view unit) noexcept { + if (!meter_config_.IsEnabled()) + { + return kNoopMeter.CreateInt64Gauge(name, description, unit); + } + if (!ValidateInstrument(name, description, unit)) { OTEL_INTERNAL_LOG_ERROR("Meter::CreateInt64Gauge - failed. Invalid parameters." @@ -213,6 +261,11 @@ opentelemetry::nostd::unique_ptr> Meter::CreateDoubleGaug opentelemetry::nostd::string_view description, opentelemetry::nostd::string_view unit) noexcept { + if (!meter_config_.IsEnabled()) + { + return kNoopMeter.CreateDoubleGauge(name, description, unit); + } + if (!ValidateInstrument(name, description, unit)) { OTEL_INTERNAL_LOG_ERROR("Meter::CreateDoubleGauge - failed. Invalid parameters." @@ -235,6 +288,11 @@ Meter::CreateInt64ObservableGauge(opentelemetry::nostd::string_view name, opentelemetry::nostd::string_view description, opentelemetry::nostd::string_view unit) noexcept { + if (!meter_config_.IsEnabled()) + { + return kNoopMeter.CreateInt64ObservableGauge(name, description, unit); + } + if (!ValidateInstrument(name, description, unit)) { OTEL_INTERNAL_LOG_ERROR("Meter::CreateInt64ObservableGauge - failed. Invalid parameters." @@ -256,6 +314,11 @@ Meter::CreateDoubleObservableGauge(opentelemetry::nostd::string_view name, opentelemetry::nostd::string_view description, opentelemetry::nostd::string_view unit) noexcept { + if (!meter_config_.IsEnabled()) + { + return kNoopMeter.CreateDoubleObservableGauge(name, description, unit); + } + if (!ValidateInstrument(name, description, unit)) { OTEL_INTERNAL_LOG_ERROR("Meter::CreateDoubleObservableGauge - failed. Invalid parameters." @@ -277,6 +340,11 @@ opentelemetry::nostd::unique_ptr> Meter::CreateI opentelemetry::nostd::string_view description, opentelemetry::nostd::string_view unit) noexcept { + if (!meter_config_.IsEnabled()) + { + return kNoopMeter.CreateInt64UpDownCounter(name, description, unit); + } + if (!ValidateInstrument(name, description, unit)) { OTEL_INTERNAL_LOG_ERROR("Meter::CreateInt64UpDownCounter - failed. Invalid parameters." @@ -299,6 +367,11 @@ opentelemetry::nostd::unique_ptr> Meter::CreateDo opentelemetry::nostd::string_view description, opentelemetry::nostd::string_view unit) noexcept { + if (!meter_config_.IsEnabled()) + { + return kNoopMeter.CreateDoubleUpDownCounter(name, description, unit); + } + if (!ValidateInstrument(name, description, unit)) { OTEL_INTERNAL_LOG_ERROR("Meter::CreateDoubleUpDownCounter - failed. Invalid parameters." @@ -321,6 +394,11 @@ Meter::CreateInt64ObservableUpDownCounter(opentelemetry::nostd::string_view name opentelemetry::nostd::string_view description, opentelemetry::nostd::string_view unit) noexcept { + if (!meter_config_.IsEnabled()) + { + return kNoopMeter.CreateInt64ObservableUpDownCounter(name, description, unit); + } + if (!ValidateInstrument(name, description, unit)) { OTEL_INTERNAL_LOG_ERROR( @@ -342,6 +420,11 @@ Meter::CreateDoubleObservableUpDownCounter(opentelemetry::nostd::string_view nam opentelemetry::nostd::string_view description, opentelemetry::nostd::string_view unit) noexcept { + if (!meter_config_.IsEnabled()) + { + return kNoopMeter.CreateDoubleObservableUpDownCounter(name, description, unit); + } + if (!ValidateInstrument(name, description, unit)) { OTEL_INTERNAL_LOG_ERROR( @@ -486,6 +569,10 @@ std::unique_ptr Meter::RegisterAsyncMetricStorage( std::vector Meter::Collect(CollectorHandle *collector, opentelemetry::common::SystemTimestamp collect_ts) noexcept { + if (!meter_config_.IsEnabled()) + { + return std::vector(); + } observable_registry_->Observe(collect_ts); std::vector metric_data_list; auto ctx = meter_context_.lock(); From a674d49f0e26ddf6e1e38e4738c142215dc1fb1c Mon Sep 17 00:00:00 2001 From: Pranav Sharma Date: Wed, 12 Feb 2025 17:45:40 +0000 Subject: [PATCH 04/10] Fix iwyu warnings --- sdk/src/metrics/meter.cc | 2 ++ sdk/src/metrics/meter_context.cc | 2 ++ sdk/src/metrics/meter_context_factory.cc | 3 +++ sdk/src/metrics/meter_provider.cc | 2 ++ sdk/src/metrics/meter_provider_factory.cc | 3 +++ 5 files changed, 12 insertions(+) diff --git a/sdk/src/metrics/meter.cc b/sdk/src/metrics/meter.cc index c77e26b168..f89de3b6b0 100644 --- a/sdk/src/metrics/meter.cc +++ b/sdk/src/metrics/meter.cc @@ -21,10 +21,12 @@ #include "opentelemetry/nostd/unique_ptr.h" #include "opentelemetry/sdk/common/global_log_handler.h" #include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h" +#include "opentelemetry/sdk/instrumentationscope/scope_configurator.h" #include "opentelemetry/sdk/metrics/async_instruments.h" #include "opentelemetry/sdk/metrics/data/metric_data.h" #include "opentelemetry/sdk/metrics/instruments.h" #include "opentelemetry/sdk/metrics/meter.h" +#include "opentelemetry/sdk/metrics/meter_config.h" #include "opentelemetry/sdk/metrics/meter_context.h" #include "opentelemetry/sdk/metrics/state/async_metric_storage.h" #include "opentelemetry/sdk/metrics/state/metric_collector.h" diff --git a/sdk/src/metrics/meter_context.cc b/sdk/src/metrics/meter_context.cc index df808aff20..1aa4782c34 100644 --- a/sdk/src/metrics/meter_context.cc +++ b/sdk/src/metrics/meter_context.cc @@ -17,7 +17,9 @@ #include "opentelemetry/nostd/string_view.h" #include "opentelemetry/sdk/common/global_log_handler.h" #include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h" +#include "opentelemetry/sdk/instrumentationscope/scope_configurator.h" #include "opentelemetry/sdk/metrics/meter.h" +#include "opentelemetry/sdk/metrics/meter_config.h" #include "opentelemetry/sdk/metrics/meter_context.h" #include "opentelemetry/sdk/metrics/metric_reader.h" #include "opentelemetry/sdk/metrics/state/metric_collector.h" diff --git a/sdk/src/metrics/meter_context_factory.cc b/sdk/src/metrics/meter_context_factory.cc index a7f7d74269..27efbc965f 100644 --- a/sdk/src/metrics/meter_context_factory.cc +++ b/sdk/src/metrics/meter_context_factory.cc @@ -4,6 +4,9 @@ #include #include +#include +#include "opentelemetry/sdk/instrumentationscope/scope_configurator.h" +#include "opentelemetry/sdk/metrics/meter_config.h" #include "opentelemetry/sdk/metrics/meter_context.h" #include "opentelemetry/sdk/metrics/meter_context_factory.h" #include "opentelemetry/sdk/metrics/view/view_registry.h" diff --git a/sdk/src/metrics/meter_provider.cc b/sdk/src/metrics/meter_provider.cc index e6c25caf07..82af065f30 100644 --- a/sdk/src/metrics/meter_provider.cc +++ b/sdk/src/metrics/meter_provider.cc @@ -12,7 +12,9 @@ #include "opentelemetry/nostd/string_view.h" #include "opentelemetry/sdk/common/global_log_handler.h" #include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h" +#include "opentelemetry/sdk/instrumentationscope/scope_configurator.h" #include "opentelemetry/sdk/metrics/meter.h" +#include "opentelemetry/sdk/metrics/meter_config.h" #include "opentelemetry/sdk/metrics/meter_context.h" #include "opentelemetry/sdk/metrics/meter_provider.h" #include "opentelemetry/sdk/metrics/metric_reader.h" diff --git a/sdk/src/metrics/meter_provider_factory.cc b/sdk/src/metrics/meter_provider_factory.cc index eb82b8ed33..052639e341 100644 --- a/sdk/src/metrics/meter_provider_factory.cc +++ b/sdk/src/metrics/meter_provider_factory.cc @@ -4,6 +4,9 @@ #include #include +#include +#include "opentelemetry/sdk/instrumentationscope/scope_configurator.h" +#include "opentelemetry/sdk/metrics/meter_config.h" #include "opentelemetry/sdk/metrics/meter_context.h" #include "opentelemetry/sdk/metrics/meter_provider.h" #include "opentelemetry/sdk/metrics/meter_provider_factory.h" From 98a4e3054f2a0b90f4e8a16e69c6089f36cd50a6 Mon Sep 17 00:00:00 2001 From: Pranav Sharma Date: Wed, 12 Feb 2025 19:38:04 +0000 Subject: [PATCH 05/10] Add unit tests for MeterConfig --- sdk/test/metrics/BUILD | 15 +++++ sdk/test/metrics/CMakeLists.txt | 1 + sdk/test/metrics/meter_config_test.cc | 89 +++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 sdk/test/metrics/meter_config_test.cc diff --git a/sdk/test/metrics/BUILD b/sdk/test/metrics/BUILD index 70d0cc063a..5a16cbcc28 100644 --- a/sdk/test/metrics/BUILD +++ b/sdk/test/metrics/BUILD @@ -18,6 +18,21 @@ cc_library( ], ) +cc_test( + name = "meter_config_test", + srcs = [ + "meter_config_test.cc", + ], + tags = [ + "test", + "metrics", + ], + deps = [ + "metrics_common_test_utils", + "@com_google_googletest//:gtest_main", + ], +) + cc_test( name = "all_tests", srcs = glob(["*_test.cc"]), diff --git a/sdk/test/metrics/CMakeLists.txt b/sdk/test/metrics/CMakeLists.txt index 186c6cbbbd..f82a386816 100644 --- a/sdk/test/metrics/CMakeLists.txt +++ b/sdk/test/metrics/CMakeLists.txt @@ -6,6 +6,7 @@ target_link_libraries(metrics_common_test_utils opentelemetry_metrics) foreach( testname + meter_config_test meter_provider_set_test meter_provider_sdk_test meter_test diff --git a/sdk/test/metrics/meter_config_test.cc b/sdk/test/metrics/meter_config_test.cc new file mode 100644 index 0000000000..31518936ef --- /dev/null +++ b/sdk/test/metrics/meter_config_test.cc @@ -0,0 +1,89 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/sdk/metrics/meter_config.h" +#include +#include +#include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h" +#include "opentelemetry/sdk/instrumentationscope/scope_configurator.h" + +namespace metrics_sdk = opentelemetry::sdk::metrics; +namespace instrumentation_scope = opentelemetry::sdk::instrumentationscope; + +/** Test to verify the basic behavior of metrics_sdk::MeterConfig */ + +TEST(MeterConfig, CheckDisabledWorksAsExpected) +{ + metrics_sdk::MeterConfig disabled_config = metrics_sdk::MeterConfig::Disabled(); + ASSERT_FALSE(disabled_config.IsEnabled()); +} + +TEST(MeterConfig, CheckEnabledWorksAsExpected) +{ + metrics_sdk::MeterConfig enabled_config = metrics_sdk::MeterConfig::Enabled(); + ASSERT_TRUE(enabled_config.IsEnabled()); +} + +TEST(MeterConfig, CheckDefaultConfigWorksAccToSpec) +{ + metrics_sdk::MeterConfig enabled_config = metrics_sdk::MeterConfig::Default(); + ASSERT_TRUE(enabled_config.IsEnabled()); +} + +/** Tests to verify the behavior of metrics_sdk::MeterConfig::Default */ + +static std::pair attr1 = { + "accept_single_attr", true}; +static std::pair attr2 = { + "accept_second_attr", "some other attr"}; +static std::pair attr3 = { + "accept_third_attr", 3}; + +static instrumentation_scope::InstrumentationScope test_scope_1 = + *instrumentation_scope::InstrumentationScope::Create("test_scope_1"); +static instrumentation_scope::InstrumentationScope test_scope_2 = + *instrumentation_scope::InstrumentationScope::Create("test_scope_2", "1.0"); +static instrumentation_scope::InstrumentationScope test_scope_3 = + *instrumentation_scope::InstrumentationScope::Create( + "test_scope_3", + "0", + "https://opentelemetry.io/schemas/v1.18.0"); +static instrumentation_scope::InstrumentationScope test_scope_4 = + *instrumentation_scope::InstrumentationScope::Create("test_scope_4", + "0", + "https://opentelemetry.io/schemas/v1.18.0", + {attr1}); +static instrumentation_scope::InstrumentationScope test_scope_5 = + *instrumentation_scope::InstrumentationScope::Create("test_scope_5", + "0", + "https://opentelemetry.io/schemas/v1.18.0", + {attr1, attr2, attr3}); + +// This array could also directly contain the reference types, but that leads to 'uninitialized +// value was created by heap allocation' errors in Valgrind memcheck. This is a bug in Googletest +// library, see https://github.com/google/googletest/issues/3805#issuecomment-1397301790 for more +// details. Using pointers is a workaround to prevent the Valgrind warnings. +const std::array instrumentation_scopes = { + &test_scope_1, &test_scope_2, &test_scope_3, &test_scope_4, &test_scope_5, +}; + +// Test fixture for VerifyDefaultConfiguratorBehavior +class DefaultMeterConfiguratorTestFixture + : public ::testing::TestWithParam +{}; + +// verifies that the default configurator always returns the default meter config +TEST_P(DefaultMeterConfiguratorTestFixture, VerifyDefaultConfiguratorBehavior) +{ + instrumentation_scope::InstrumentationScope *scope = GetParam(); + instrumentation_scope::ScopeConfigurator default_configurator = + instrumentation_scope::ScopeConfigurator::Builder( + metrics_sdk::MeterConfig::Default()) + .Build(); + + ASSERT_EQ(default_configurator.ComputeConfig(*scope), metrics_sdk::MeterConfig::Default()); +} + +INSTANTIATE_TEST_SUITE_P(InstrumentationScopes, + DefaultMeterConfiguratorTestFixture, + ::testing::ValuesIn(instrumentation_scopes)); \ No newline at end of file From 7180288f5fd933368bb65cca8d22b11a67de1c87 Mon Sep 17 00:00:00 2001 From: Pranav Sharma Date: Thu, 13 Feb 2025 06:18:35 +0000 Subject: [PATCH 06/10] Fix documentation string --- sdk/include/opentelemetry/sdk/metrics/meter_context.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/include/opentelemetry/sdk/metrics/meter_context.h b/sdk/include/opentelemetry/sdk/metrics/meter_context.h index ca0a489c19..8925059a96 100644 --- a/sdk/include/opentelemetry/sdk/metrics/meter_context.h +++ b/sdk/include/opentelemetry/sdk/metrics/meter_context.h @@ -50,7 +50,6 @@ class MeterContext : public std::enable_shared_from_this public: /** * Initialize a new meter provider - * @param readers The readers to be configured with meter context. * @param views The views to be configured with meter context. * @param resource The resource for this meter context. */ From e75db696fa1df71f8f3e9ef663d6351188795dd5 Mon Sep 17 00:00:00 2001 From: Pranav Sharma Date: Thu, 13 Feb 2025 06:20:01 +0000 Subject: [PATCH 07/10] Add meter tests for scope configurator --- sdk/test/metrics/meter_config_test.cc | 8 +- sdk/test/metrics/meter_test.cc | 216 ++++++++++++++++++++++++++ 2 files changed, 220 insertions(+), 4 deletions(-) diff --git a/sdk/test/metrics/meter_config_test.cc b/sdk/test/metrics/meter_config_test.cc index 31518936ef..b560976c27 100644 --- a/sdk/test/metrics/meter_config_test.cc +++ b/sdk/test/metrics/meter_config_test.cc @@ -33,11 +33,11 @@ TEST(MeterConfig, CheckDefaultConfigWorksAccToSpec) /** Tests to verify the behavior of metrics_sdk::MeterConfig::Default */ static std::pair attr1 = { - "accept_single_attr", true}; + "accept_single_attr", true}; static std::pair attr2 = { - "accept_second_attr", "some other attr"}; + "accept_second_attr", "some other attr"}; static std::pair attr3 = { - "accept_third_attr", 3}; + "accept_third_attr", 3}; static instrumentation_scope::InstrumentationScope test_scope_1 = *instrumentation_scope::InstrumentationScope::Create("test_scope_1"); @@ -64,7 +64,7 @@ static instrumentation_scope::InstrumentationScope test_scope_5 = // library, see https://github.com/google/googletest/issues/3805#issuecomment-1397301790 for more // details. Using pointers is a workaround to prevent the Valgrind warnings. const std::array instrumentation_scopes = { - &test_scope_1, &test_scope_2, &test_scope_3, &test_scope_4, &test_scope_5, + &test_scope_1, &test_scope_2, &test_scope_3, &test_scope_4, &test_scope_5, }; // Test fixture for VerifyDefaultConfiguratorBehavior diff --git a/sdk/test/metrics/meter_test.cc b/sdk/test/metrics/meter_test.cc index 078ef809cd..8502218301 100644 --- a/sdk/test/metrics/meter_test.cc +++ b/sdk/test/metrics/meter_test.cc @@ -15,6 +15,10 @@ #include "opentelemetry/metrics/async_instruments.h" #include "opentelemetry/metrics/meter.h" + +#include +#include + #include "opentelemetry/metrics/meter_provider.h" #include "opentelemetry/metrics/observer_result.h" #include "opentelemetry/metrics/sync_instruments.h" // IWYU pragma: keep @@ -50,6 +54,22 @@ void asyc_generate_measurements(opentelemetry::metrics::ObserverResult observer, nostd::get>>(observer); observer_long->Observe(10); } + +std::shared_ptr GetMeterProviderWithScopeConfigurator( + const ScopeConfigurator &meter_configurator, + MetricReader **metric_reader_ptr) +{ + auto views = ViewRegistryFactory::Create(); + auto resource = sdk::resource::Resource::Create({}); + std::unique_ptr metric_reader(new MockMetricReader()); + *metric_reader_ptr = metric_reader.get(); + std::shared_ptr provider( + new MeterProvider(std::move(views), resource, + std::make_unique>(meter_configurator))); + auto p = std::static_pointer_cast(provider); + p->AddMetricReader(std::move(metric_reader)); + return p; +} } // namespace TEST(MeterTest, BasicAsyncTests) @@ -133,3 +153,199 @@ TEST(MeterTest, StressMultiThread) } } } + +TEST(MeterTest, MeterWithDisabledConfig) +{ + ScopeConfigurator disable_all_scopes = + ScopeConfigurator::Builder(MeterConfig::Disabled()).Build(); + MetricReader *metric_reader_ptr = nullptr; + std::shared_ptr meter_provider = + GetMeterProviderWithScopeConfigurator(disable_all_scopes, &metric_reader_ptr); + + auto meter = meter_provider->GetMeter("foo", "0.1.0", "https://opentelemetry.io/schemas/1.24.0"); + + // Test all supported instruments from this meter + // Test DoubleCounter + auto double_counter = meter->CreateDoubleCounter("double_counter"); + double_counter->Add(1.0f); + metric_reader_ptr->Collect([&](ResourceMetrics &metric_data) { + EXPECT_EQ(metric_data.scope_metric_data_.size(), 0); + return true; + }); + + // Test DoubleHistogram + auto double_histogram = meter->CreateDoubleHistogram("double_histogram"); + double_histogram->Record(23.2f, {}); + metric_reader_ptr->Collect([&](ResourceMetrics &metric_data) { + EXPECT_EQ(metric_data.scope_metric_data_.size(), 0); + return true; + }); + + // Test DoubleUpDownCounter + auto double_up_down_counter = meter->CreateDoubleUpDownCounter("double_up_down_counter"); + double_up_down_counter->Add(-2.4f); + metric_reader_ptr->Collect([&](ResourceMetrics &metric_data) { + EXPECT_EQ(metric_data.scope_metric_data_.size(), 0); + return true; + }); +} + +TEST(MeterTest, MeterWithEnabledConfig) +{ + ScopeConfigurator disable_all_scopes = + ScopeConfigurator::Builder(MeterConfig::Enabled()).Build(); + MetricReader *metric_reader_ptr = nullptr; + std::shared_ptr meter_provider = + GetMeterProviderWithScopeConfigurator(disable_all_scopes, &metric_reader_ptr); + + auto meter = meter_provider->GetMeter("foo", "0.1.0", "https://opentelemetry.io/schemas/1.24.0"); + + // Test supported instruments from this meter + // Test DoubleCounter + auto double_counter = meter->CreateDoubleCounter("double_counter"); + double_counter->Add(1.0f); + metric_reader_ptr->Collect([&](const ResourceMetrics &metric_data) { + EXPECT_EQ(metric_data.scope_metric_data_.size(), 1); + EXPECT_EQ(metric_data.scope_metric_data_.at(0).scope_->GetName(), "foo"); + bool instrument_found = false; + for (const MetricData &md : metric_data.scope_metric_data_.at(0).metric_data_) + { + if (md.instrument_descriptor.name_ == "double_counter") + { + instrument_found = true; + break; + } + } + EXPECT_TRUE(instrument_found); + return true; + }); + + // Test DoubleHistogram + auto double_histogram = meter->CreateDoubleHistogram("double_histogram"); + double_histogram->Record(23.2f, {}); + metric_reader_ptr->Collect([&](ResourceMetrics &metric_data) { + EXPECT_EQ(metric_data.scope_metric_data_.size(), 1); + EXPECT_EQ(metric_data.scope_metric_data_.at(0).scope_->GetName(), "foo"); + bool instrument_found = false; + for (const MetricData &md : metric_data.scope_metric_data_.at(0).metric_data_) + { + if (md.instrument_descriptor.name_ == "double_histogram") + { + instrument_found = true; + break; + } + } + EXPECT_TRUE(instrument_found); + return true; + }); + + // Test DoubleUpDownCounter + auto double_up_down_counter = meter->CreateDoubleUpDownCounter("double_up_down_counter"); + double_up_down_counter->Add(-2.4f); + metric_reader_ptr->Collect([&](ResourceMetrics &metric_data) { + EXPECT_EQ(metric_data.scope_metric_data_.size(), 1); + EXPECT_EQ(metric_data.scope_metric_data_.at(0).scope_->GetName(), "foo"); + bool instrument_found = false; + for (const MetricData &md : metric_data.scope_metric_data_.at(0).metric_data_) + { + if (md.instrument_descriptor.name_ == "double_up_down_counter") + { + instrument_found = true; + break; + } + } + EXPECT_TRUE(instrument_found); + return true; + }); +} + +TEST(MeterTest, MeterWithCustomConfig) +{ + auto check_if_version_present = [](const InstrumentationScope &scope_info) { + return !scope_info.GetVersion().empty(); + }; + + // custom scope configurator that only disables meters with name "foo_library" or do not have + // version information + ScopeConfigurator custom_scope_configurator = + ScopeConfigurator::Builder(MeterConfig::Disabled()) + .AddConditionNameEquals("foo_library", MeterConfig::Disabled()) + .AddCondition(check_if_version_present, MeterConfig::Enabled()) + .Build(); + MetricReader *metric_reader_ptr = nullptr; + std::shared_ptr meter_provider = + GetMeterProviderWithScopeConfigurator(custom_scope_configurator, &metric_reader_ptr); + + // The meter has version information and name is not "foo_library" + // All instruments from this meter should be active and recording metrics + auto meter_enabled_expected_bar = + meter_provider->GetMeter("bar_library", "0.1.0", "https://opentelemetry.io/schemas/1.24.0"); + + // Test supported instruments from this meter + auto double_counter_bar = meter_enabled_expected_bar->CreateDoubleCounter("double_counter"); + double_counter_bar->Add(1.0f); + metric_reader_ptr->Collect([&](const ResourceMetrics &metric_data) { + bool instrument_found = false; + for (const ScopeMetrics &sm : metric_data.scope_metric_data_) + { + std::string curr_scope = sm.scope_->GetName(); + for (const MetricData &md : sm.metric_data_) + { + if (md.instrument_descriptor.name_ == "double_counter" && curr_scope == "bar_library") + { + instrument_found = true; + } + } + } + EXPECT_TRUE(instrument_found); + return true; + }); + + // The meter has version information and name is "foo_library" + // All instruments from this meter should be noop + auto meter_disabled_expected_foo = + meter_provider->GetMeter("foo_library", "0.1.0", "https://opentelemetry.io/schemas/1.24.0"); + + // Test supported instruments from this meter + auto double_counter_foo = meter_disabled_expected_foo->CreateDoubleCounter("double_counter"); + double_counter_foo->Add(1.0f); + metric_reader_ptr->Collect([&](const ResourceMetrics &metric_data) { + bool unexpected_instrument_found = false; + for (const ScopeMetrics &sm : metric_data.scope_metric_data_) + { + std::string curr_scope = sm.scope_->GetName(); + for (const MetricData &md : sm.metric_data_) + { + if (md.instrument_descriptor.name_ == "double_counter" && curr_scope == "foo_library") + { + unexpected_instrument_found = true; + } + } + } + EXPECT_FALSE(unexpected_instrument_found); + return true; + }); + + auto meter_disabled_expected_baz = + meter_provider->GetMeter("baz_library", "", "https://opentelemetry.io/schemas/1.24.0"); + + // Test supported instruments from this meter + auto double_counter_baz = meter_disabled_expected_baz->CreateDoubleCounter("double_counter"); + double_counter_baz->Add(1.0f); + metric_reader_ptr->Collect([&](const ResourceMetrics &metric_data) { + bool unexpected_instrument_found = false; + for (const ScopeMetrics &sm : metric_data.scope_metric_data_) + { + std::string curr_scope = sm.scope_->GetName(); + for (const MetricData &md : sm.metric_data_) + { + if (md.instrument_descriptor.name_ == "double_counter" && curr_scope == "baz_library") + { + unexpected_instrument_found = true; + } + } + } + EXPECT_FALSE(unexpected_instrument_found); + return true; + }); +} From 9abfe65856ad3d256398fef7ba88026c58f56ed5 Mon Sep 17 00:00:00 2001 From: Pranav Sharma Date: Thu, 13 Feb 2025 16:42:47 +0000 Subject: [PATCH 08/10] Fix CI check failures --- sdk/test/metrics/BUILD | 2 +- sdk/test/metrics/meter_config_test.cc | 10 ++++++++-- sdk/test/metrics/meter_test.cc | 11 ++++++++++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/sdk/test/metrics/BUILD b/sdk/test/metrics/BUILD index 5a16cbcc28..929511a89b 100644 --- a/sdk/test/metrics/BUILD +++ b/sdk/test/metrics/BUILD @@ -24,8 +24,8 @@ cc_test( "meter_config_test.cc", ], tags = [ - "test", "metrics", + "test", ], deps = [ "metrics_common_test_utils", diff --git a/sdk/test/metrics/meter_config_test.cc b/sdk/test/metrics/meter_config_test.cc index b560976c27..c16b1d93f0 100644 --- a/sdk/test/metrics/meter_config_test.cc +++ b/sdk/test/metrics/meter_config_test.cc @@ -3,7 +3,13 @@ #include "opentelemetry/sdk/metrics/meter_config.h" #include -#include +#include +#include +#include +#include +#include +#include "opentelemetry/common/attribute_value.h" +#include "opentelemetry/nostd/string_view.h" #include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h" #include "opentelemetry/sdk/instrumentationscope/scope_configurator.h" @@ -86,4 +92,4 @@ TEST_P(DefaultMeterConfiguratorTestFixture, VerifyDefaultConfiguratorBehavior) INSTANTIATE_TEST_SUITE_P(InstrumentationScopes, DefaultMeterConfiguratorTestFixture, - ::testing::ValuesIn(instrumentation_scopes)); \ No newline at end of file + ::testing::ValuesIn(instrumentation_scopes)); diff --git a/sdk/test/metrics/meter_test.cc b/sdk/test/metrics/meter_test.cc index 8502218301..fc1b6eca6f 100644 --- a/sdk/test/metrics/meter_test.cc +++ b/sdk/test/metrics/meter_test.cc @@ -13,10 +13,17 @@ #include #include "common.h" +#include +#include "opentelemetry/context/context.h" #include "opentelemetry/metrics/async_instruments.h" #include "opentelemetry/metrics/meter.h" +#include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h" +#include "opentelemetry/sdk/instrumentationscope/scope_configurator.h" +#include "opentelemetry/sdk/metrics/instruments.h" +#include "opentelemetry/sdk/metrics/meter_config.h" +#include "opentelemetry/sdk/metrics/view/view_registry.h" +#include "opentelemetry/sdk/resource/resource.h" -#include #include #include "opentelemetry/metrics/meter_provider.h" @@ -261,6 +268,8 @@ TEST(MeterTest, MeterWithEnabledConfig) TEST(MeterTest, MeterWithCustomConfig) { + // TODO: Replace with a single collect call and check for all expected and unexpected instruments + // within the same call auto check_if_version_present = [](const InstrumentationScope &scope_info) { return !scope_info.GetVersion().empty(); }; From 11b4ee5f8c3a1b2ae5af737d68d4881205967757 Mon Sep 17 00:00:00 2001 From: Pranav Sharma Date: Thu, 13 Feb 2025 18:23:48 +0000 Subject: [PATCH 09/10] Improve unit tests --- sdk/test/metrics/meter_test.cc | 242 +++++++++++++++++---------------- 1 file changed, 128 insertions(+), 114 deletions(-) diff --git a/sdk/test/metrics/meter_test.cc b/sdk/test/metrics/meter_test.cc index fc1b6eca6f..e3335b9a0b 100644 --- a/sdk/test/metrics/meter_test.cc +++ b/sdk/test/metrics/meter_test.cc @@ -55,13 +55,22 @@ nostd::shared_ptr InitMeter(MetricReader **metricReaderPtr, return meter; } -void asyc_generate_measurements(opentelemetry::metrics::ObserverResult observer, void * /* state */) +void asyc_generate_measurements_long(opentelemetry::metrics::ObserverResult observer, + void * /* state */) { auto observer_long = nostd::get>>(observer); observer_long->Observe(10); } +void asyc_generate_measurements_double(opentelemetry::metrics::ObserverResult observer, + void * /* state */) +{ + auto observer_double = + nostd::get>>(observer); + observer_double->Observe(10.2f); +} + std::shared_ptr GetMeterProviderWithScopeConfigurator( const ScopeConfigurator &meter_configurator, MetricReader **metric_reader_ptr) @@ -84,7 +93,7 @@ TEST(MeterTest, BasicAsyncTests) MetricReader *metric_reader_ptr = nullptr; auto meter = InitMeter(&metric_reader_ptr); auto observable_counter = meter->CreateInt64ObservableCounter("observable_counter"); - observable_counter->AddCallback(asyc_generate_measurements, nullptr); + observable_counter->AddCallback(asyc_generate_measurements_long, nullptr); size_t count = 0; metric_reader_ptr->Collect([&count](ResourceMetrics &metric_data) { @@ -100,7 +109,7 @@ TEST(MeterTest, BasicAsyncTests) } return true; }); - observable_counter->RemoveCallback(asyc_generate_measurements, nullptr); + observable_counter->RemoveCallback(asyc_generate_measurements_long, nullptr); } constexpr static unsigned MAX_THREADS = 25; @@ -137,7 +146,7 @@ TEST(MeterTest, StressMultiThread) std::cout << "\n creating async thread " << std::to_string(numIterations); auto observable_instrument = meter->CreateInt64ObservableUpDownCounter( "test_gauge_" + std::to_string(instrument_id)); - observable_instrument->AddCallback(asyc_generate_measurements, nullptr); + observable_instrument->AddCallback(asyc_generate_measurements_long, nullptr); observable_instruments.push_back(std::move(observable_instrument)); do_collect.store(true); instrument_id++; @@ -171,26 +180,39 @@ TEST(MeterTest, MeterWithDisabledConfig) auto meter = meter_provider->GetMeter("foo", "0.1.0", "https://opentelemetry.io/schemas/1.24.0"); - // Test all supported instruments from this meter - // Test DoubleCounter - auto double_counter = meter->CreateDoubleCounter("double_counter"); - double_counter->Add(1.0f); - metric_reader_ptr->Collect([&](ResourceMetrics &metric_data) { - EXPECT_EQ(metric_data.scope_metric_data_.size(), 0); - return true; - }); + // Test all supported instruments from this meter - create instruments + auto double_counter = meter->CreateDoubleCounter("double_counter"); + auto double_histogram = meter->CreateDoubleHistogram("double_histogram"); + auto double_up_down_counter = meter->CreateDoubleUpDownCounter("double_up_down_counter"); + auto double_obs_counter = meter->CreateDoubleObservableCounter("double_obs_counter"); + auto double_obs_gauge = meter->CreateDoubleObservableGauge("double_obs_gauge"); + auto double_obs_up_down_counter = + meter->CreateDoubleObservableUpDownCounter("double_obs_up_down_counter"); - // Test DoubleHistogram - auto double_histogram = meter->CreateDoubleHistogram("double_histogram"); - double_histogram->Record(23.2f, {}); - metric_reader_ptr->Collect([&](ResourceMetrics &metric_data) { - EXPECT_EQ(metric_data.scope_metric_data_.size(), 0); - return true; - }); + auto uint64_counter = meter->CreateUInt64Counter("uint64_counter"); + auto uint64_histogram = meter->CreateUInt64Histogram("uint64_histogram"); + auto int64_up_down_counter = meter->CreateInt64UpDownCounter("int64_up_down_counter"); + auto int64_obs_counter = meter->CreateInt64ObservableCounter("int64_obs_counter"); + auto int64_obs_gauge = meter->CreateInt64ObservableGauge("int64_obs_gauge"); + auto int64_obs_up_down_counter = + meter->CreateInt64ObservableUpDownCounter("int64_obs_up_down_counter"); - // Test DoubleUpDownCounter - auto double_up_down_counter = meter->CreateDoubleUpDownCounter("double_up_down_counter"); + // Invoke the created instruments + double_counter->Add(1.0f); + double_histogram->Record(23.2f, {}); double_up_down_counter->Add(-2.4f); + double_obs_counter->AddCallback(asyc_generate_measurements_double, nullptr); + double_obs_gauge->AddCallback(asyc_generate_measurements_double, nullptr); + double_obs_up_down_counter->AddCallback(asyc_generate_measurements_double, nullptr); + + uint64_counter->Add(1); + uint64_histogram->Record(23, {}); + int64_up_down_counter->Add(-2); + int64_obs_counter->AddCallback(asyc_generate_measurements_long, nullptr); + int64_obs_gauge->AddCallback(asyc_generate_measurements_long, nullptr); + int64_obs_up_down_counter->AddCallback(asyc_generate_measurements_long, nullptr); + + // No active instruments are expected - since all scopes are disabled. metric_reader_ptr->Collect([&](ResourceMetrics &metric_data) { EXPECT_EQ(metric_data.scope_metric_data_.size(), 0); return true; @@ -199,76 +221,87 @@ TEST(MeterTest, MeterWithDisabledConfig) TEST(MeterTest, MeterWithEnabledConfig) { - ScopeConfigurator disable_all_scopes = + ScopeConfigurator enable_all_scopes = ScopeConfigurator::Builder(MeterConfig::Enabled()).Build(); MetricReader *metric_reader_ptr = nullptr; std::shared_ptr meter_provider = - GetMeterProviderWithScopeConfigurator(disable_all_scopes, &metric_reader_ptr); + GetMeterProviderWithScopeConfigurator(enable_all_scopes, &metric_reader_ptr); auto meter = meter_provider->GetMeter("foo", "0.1.0", "https://opentelemetry.io/schemas/1.24.0"); - // Test supported instruments from this meter - // Test DoubleCounter - auto double_counter = meter->CreateDoubleCounter("double_counter"); - double_counter->Add(1.0f); - metric_reader_ptr->Collect([&](const ResourceMetrics &metric_data) { - EXPECT_EQ(metric_data.scope_metric_data_.size(), 1); - EXPECT_EQ(metric_data.scope_metric_data_.at(0).scope_->GetName(), "foo"); - bool instrument_found = false; - for (const MetricData &md : metric_data.scope_metric_data_.at(0).metric_data_) - { - if (md.instrument_descriptor.name_ == "double_counter") - { - instrument_found = true; - break; - } - } - EXPECT_TRUE(instrument_found); - return true; - }); + // Test all supported instruments from this meter - create instruments + auto double_counter = meter->CreateDoubleCounter("double_counter"); + auto double_histogram = meter->CreateDoubleHistogram("double_histogram"); + auto double_up_down_counter = meter->CreateDoubleUpDownCounter("double_up_down_counter"); + auto double_obs_counter = meter->CreateDoubleObservableCounter("double_obs_counter"); + auto double_obs_gauge = meter->CreateDoubleObservableGauge("double_obs_gauge"); + auto double_obs_up_down_counter = + meter->CreateDoubleObservableUpDownCounter("double_obs_up_down_counter"); - // Test DoubleHistogram - auto double_histogram = meter->CreateDoubleHistogram("double_histogram"); - double_histogram->Record(23.2f, {}); - metric_reader_ptr->Collect([&](ResourceMetrics &metric_data) { - EXPECT_EQ(metric_data.scope_metric_data_.size(), 1); - EXPECT_EQ(metric_data.scope_metric_data_.at(0).scope_->GetName(), "foo"); - bool instrument_found = false; - for (const MetricData &md : metric_data.scope_metric_data_.at(0).metric_data_) - { - if (md.instrument_descriptor.name_ == "double_histogram") - { - instrument_found = true; - break; - } - } - EXPECT_TRUE(instrument_found); - return true; - }); + auto uint64_counter = meter->CreateUInt64Counter("uint64_counter"); + auto uint64_histogram = meter->CreateUInt64Histogram("uint64_histogram"); + auto int64_up_down_counter = meter->CreateInt64UpDownCounter("int64_up_down_counter"); + auto int64_obs_counter = meter->CreateInt64ObservableCounter("int64_obs_counter"); + auto int64_obs_gauge = meter->CreateInt64ObservableGauge("int64_obs_gauge"); + auto int64_obs_up_down_counter = + meter->CreateInt64ObservableUpDownCounter("int64_obs_up_down_counter"); - // Test DoubleUpDownCounter - auto double_up_down_counter = meter->CreateDoubleUpDownCounter("double_up_down_counter"); + // Invoke the created instruments + double_counter->Add(1.0f); + double_histogram->Record(23.2f, {}); double_up_down_counter->Add(-2.4f); - metric_reader_ptr->Collect([&](ResourceMetrics &metric_data) { + double_obs_counter->AddCallback(asyc_generate_measurements_double, nullptr); + double_obs_gauge->AddCallback(asyc_generate_measurements_double, nullptr); + double_obs_up_down_counter->AddCallback(asyc_generate_measurements_double, nullptr); + + uint64_counter->Add(1); + uint64_histogram->Record(23, {}); + int64_up_down_counter->Add(-2); + int64_obs_counter->AddCallback(asyc_generate_measurements_long, nullptr); + int64_obs_gauge->AddCallback(asyc_generate_measurements_long, nullptr); + int64_obs_up_down_counter->AddCallback(asyc_generate_measurements_long, nullptr); + + // Expected active instruments + std::vector> active_scope_instrument_pairs; + active_scope_instrument_pairs.emplace_back("foo", "double_counter"); + active_scope_instrument_pairs.emplace_back("foo", "double_histogram"); + active_scope_instrument_pairs.emplace_back("foo", "double_up_down_counter"); + active_scope_instrument_pairs.emplace_back("foo", "double_obs_up_down_counter"); + active_scope_instrument_pairs.emplace_back("foo", "double_obs_counter"); + active_scope_instrument_pairs.emplace_back("foo", "double_obs_gauge"); + active_scope_instrument_pairs.emplace_back("foo", "uint64_counter"); + active_scope_instrument_pairs.emplace_back("foo", "uint64_histogram"); + active_scope_instrument_pairs.emplace_back("foo", "int64_up_down_counter"); + active_scope_instrument_pairs.emplace_back("foo", "int64_obs_up_down_counter"); + active_scope_instrument_pairs.emplace_back("foo", "int64_obs_counter"); + active_scope_instrument_pairs.emplace_back("foo", "int64_obs_gauge"); + + metric_reader_ptr->Collect([&](const ResourceMetrics &metric_data) { + bool unexpected_instrument_found = false; + std::string curr_scope_name = metric_data.scope_metric_data_.at(0).scope_->GetName(); EXPECT_EQ(metric_data.scope_metric_data_.size(), 1); EXPECT_EQ(metric_data.scope_metric_data_.at(0).scope_->GetName(), "foo"); - bool instrument_found = false; + EXPECT_EQ(metric_data.scope_metric_data_.at(0).metric_data_.size(), 12); for (const MetricData &md : metric_data.scope_metric_data_.at(0).metric_data_) { - if (md.instrument_descriptor.name_ == "double_up_down_counter") + auto found_instrument = std::make_pair(curr_scope_name, md.instrument_descriptor.name_); + // confirm if the found instrument is expected + auto it = std::find(active_scope_instrument_pairs.begin(), + active_scope_instrument_pairs.end(), found_instrument); + if (it == active_scope_instrument_pairs.end()) { - instrument_found = true; + // found instrument is not expected + unexpected_instrument_found = true; break; } } - EXPECT_TRUE(instrument_found); + EXPECT_FALSE(unexpected_instrument_found); return true; }); } TEST(MeterTest, MeterWithCustomConfig) { - // TODO: Replace with a single collect call and check for all expected and unexpected instruments // within the same call auto check_if_version_present = [](const InstrumentationScope &scope_info) { return !scope_info.GetVersion().empty(); @@ -285,75 +318,56 @@ TEST(MeterTest, MeterWithCustomConfig) std::shared_ptr meter_provider = GetMeterProviderWithScopeConfigurator(custom_scope_configurator, &metric_reader_ptr); - // The meter has version information and name is not "foo_library" - // All instruments from this meter should be active and recording metrics + // The meter has version information and name is not "foo_library". + // All instruments from this meter should be active and recording metrics. auto meter_enabled_expected_bar = meter_provider->GetMeter("bar_library", "0.1.0", "https://opentelemetry.io/schemas/1.24.0"); - // Test supported instruments from this meter - auto double_counter_bar = meter_enabled_expected_bar->CreateDoubleCounter("double_counter"); - double_counter_bar->Add(1.0f); - metric_reader_ptr->Collect([&](const ResourceMetrics &metric_data) { - bool instrument_found = false; - for (const ScopeMetrics &sm : metric_data.scope_metric_data_) - { - std::string curr_scope = sm.scope_->GetName(); - for (const MetricData &md : sm.metric_data_) - { - if (md.instrument_descriptor.name_ == "double_counter" && curr_scope == "bar_library") - { - instrument_found = true; - } - } - } - EXPECT_TRUE(instrument_found); - return true; - }); - - // The meter has version information and name is "foo_library" - // All instruments from this meter should be noop + // The meter has version information and name is "foo_library". + // All instruments from this meter should be noop. auto meter_disabled_expected_foo = meter_provider->GetMeter("foo_library", "0.1.0", "https://opentelemetry.io/schemas/1.24.0"); - // Test supported instruments from this meter - auto double_counter_foo = meter_disabled_expected_foo->CreateDoubleCounter("double_counter"); - double_counter_foo->Add(1.0f); - metric_reader_ptr->Collect([&](const ResourceMetrics &metric_data) { - bool unexpected_instrument_found = false; - for (const ScopeMetrics &sm : metric_data.scope_metric_data_) - { - std::string curr_scope = sm.scope_->GetName(); - for (const MetricData &md : sm.metric_data_) - { - if (md.instrument_descriptor.name_ == "double_counter" && curr_scope == "foo_library") - { - unexpected_instrument_found = true; - } - } - } - EXPECT_FALSE(unexpected_instrument_found); - return true; - }); - + // This meter has no version information. + // All instruments from this meter should be noop. auto meter_disabled_expected_baz = meter_provider->GetMeter("baz_library", "", "https://opentelemetry.io/schemas/1.24.0"); - // Test supported instruments from this meter + // Create instruments from all meters + auto double_counter_bar = meter_enabled_expected_bar->CreateDoubleCounter("double_counter"); + auto double_counter_foo = meter_disabled_expected_foo->CreateDoubleCounter("double_counter"); auto double_counter_baz = meter_disabled_expected_baz->CreateDoubleCounter("double_counter"); + + // Invoke created instruments at least once + double_counter_bar->Add(1.0f); + double_counter_foo->Add(1.0f); double_counter_baz->Add(1.0f); + + std::vector> active_scope_instrument_pairs; + active_scope_instrument_pairs.emplace_back("bar_library", "double_counter"); + metric_reader_ptr->Collect([&](const ResourceMetrics &metric_data) { + int found_instruments = 0; bool unexpected_instrument_found = false; for (const ScopeMetrics &sm : metric_data.scope_metric_data_) { std::string curr_scope = sm.scope_->GetName(); for (const MetricData &md : sm.metric_data_) { - if (md.instrument_descriptor.name_ == "double_counter" && curr_scope == "baz_library") + found_instruments++; + auto found_instrument = std::make_pair(curr_scope, md.instrument_descriptor.name_); + // confirm if the found instrument is expected + auto it = std::find(active_scope_instrument_pairs.begin(), + active_scope_instrument_pairs.end(), found_instrument); + if (it == active_scope_instrument_pairs.end()) { + // found instrument is not expected unexpected_instrument_found = true; + break; } } } + EXPECT_EQ(found_instruments, active_scope_instrument_pairs.size()); EXPECT_FALSE(unexpected_instrument_found); return true; }); From 92207b5229e29f27d27c063e364f83fffc9754bc Mon Sep 17 00:00:00 2001 From: Pranav Sharma Date: Thu, 13 Feb 2025 19:21:02 +0000 Subject: [PATCH 10/10] Update Changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90ea49e17c..0a4fc9b228 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,9 @@ Increment the: * [SDK] Support OTEL_SDK_DISABLED environment variable [#3245](https://github.com/open-telemetry/opentelemetry-cpp/pull/3245) +* [SDK] Add meter scope configurator + [#3268](https://github.com/open-telemetry/opentelemetry-cpp/pull/3268) + Important changes: * [SDK] Support OTEL_SDK_DISABLED environment variable