diff --git a/src/core/telemetry/metrics.h b/src/core/telemetry/metrics.h index 0a02cf9acfc..2fb92d4597e 100644 --- a/src/core/telemetry/metrics.h +++ b/src/core/telemetry/metrics.h @@ -329,6 +329,9 @@ class StatsPlugin { // Removes a callback previously added via AddCallback(). The stats // plugin may not use the callback after this method returns. virtual void RemoveCallback(RegisteredMetricCallback* callback) = 0; + // Returns true if instrument \a handle is enabled. + virtual bool IsInstrumentEnabled( + GlobalInstrumentsRegistry::GlobalInstrumentHandle handle) = 0; // Gets a ClientCallTracer associated with this stats plugin which can be used // in a call. @@ -424,6 +427,17 @@ class GlobalStatsPluginRegistry { optional_values); } } + // Returns true if any of the stats plugins in the group have enabled \a + // handle. + bool IsInstrumentEnabled( + GlobalInstrumentsRegistry::GlobalInstrumentHandle handle) { + for (auto& state : plugins_state_) { + if (state.plugin->IsInstrumentEnabled(handle)) { + return true; + } + } + return false; + } // Registers a callback to be used to populate callback metrics. // The callback will update the specified metrics. The callback diff --git a/src/cpp/ext/otel/otel_plugin.cc b/src/cpp/ext/otel/otel_plugin.cc index 588404f75df..18cee7af41f 100644 --- a/src/cpp/ext/otel/otel_plugin.cc +++ b/src/cpp/ext/otel/otel_plugin.cc @@ -913,6 +913,12 @@ grpc_core::ServerCallTracer* OpenTelemetryPlugin::GetServerCallTracer( scope_config)); } +bool OpenTelemetryPlugin::IsInstrumentEnabled( + grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle handle) { + return !absl::holds_alternative( + instruments_data_.at(handle.index).instrument); +} + } // namespace internal constexpr absl::string_view diff --git a/src/cpp/ext/otel/otel_plugin.h b/src/cpp/ext/otel/otel_plugin.h index 5bce0cc39ac..9928390222a 100644 --- a/src/cpp/ext/otel/otel_plugin.h +++ b/src/cpp/ext/otel/otel_plugin.h @@ -404,6 +404,9 @@ class OpenTelemetryPlugin : public grpc_core::StatsPlugin { grpc_core::ServerCallTracer* GetServerCallTracer( std::shared_ptr scope_config) override; + bool IsInstrumentEnabled( + grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle handle) + override; const absl::AnyInvocable& server_selector() const { diff --git a/test/core/test_util/fake_stats_plugin.h b/test/core/test_util/fake_stats_plugin.h index 1c26425fe01..045fffa443e 100644 --- a/test/core/test_util/fake_stats_plugin.h +++ b/test/core/test_util/fake_stats_plugin.h @@ -210,7 +210,8 @@ class FakeStatsPlugin : public StatsPlugin { bool(const experimental::StatsPluginChannelScope& /*scope*/) const> channel_filter = nullptr, bool use_disabled_by_default_metrics = false) - : channel_filter_(std::move(channel_filter)) { + : channel_filter_(std::move(channel_filter)), + use_disabled_by_default_metrics_(use_disabled_by_default_metrics) { GlobalInstrumentsRegistry::ForEach( [&](const GlobalInstrumentsRegistry::GlobalInstrumentDescriptor& descriptor) { @@ -359,6 +360,12 @@ class FakeStatsPlugin : public StatsPlugin { std::shared_ptr /*scope_config*/) override { return nullptr; } + bool IsInstrumentEnabled( + GlobalInstrumentsRegistry::GlobalInstrumentHandle handle) override { + const auto& descriptor = + GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle); + return use_disabled_by_default_metrics_ || descriptor.enable_by_default; + } absl::optional GetUInt64CounterValue( GlobalInstrumentsRegistry::GlobalInstrumentHandle handle, @@ -600,6 +607,7 @@ class FakeStatsPlugin : public StatsPlugin { absl::AnyInvocable channel_filter_; + bool use_disabled_by_default_metrics_; // Instruments. Mutex mu_; absl::flat_hash_map> uint64_counters_ diff --git a/test/cpp/ext/otel/otel_plugin_test.cc b/test/cpp/ext/otel/otel_plugin_test.cc index a71dff599af..258f44fb315 100644 --- a/test/cpp/ext/otel/otel_plugin_test.cc +++ b/test/cpp/ext/otel/otel_plugin_test.cc @@ -39,6 +39,7 @@ #include "src/core/lib/config/core_configuration.h" #include "src/core/telemetry/call_tracer.h" +#include "test/core/test_util/fake_stats_plugin.h" #include "test/core/test_util/test_config.h" #include "test/cpp/end2end/test_service_impl.h" #include "test/cpp/ext/otel/otel_test_library.h" @@ -1281,7 +1282,17 @@ TEST_F(OpenTelemetryPluginOptionEnd2EndTest, EXPECT_EQ(absl::get(server_attributes.at("key5")), "value5"); } -using OpenTelemetryPluginNPCMetricsTest = OpenTelemetryPluginEnd2EndTest; +class OpenTelemetryPluginNPCMetricsTest + : public OpenTelemetryPluginEnd2EndTest { + protected: + void TearDown() override { + // We are tearing down OpenTelemetryPluginEnd2EndTest first to ensure that + // gRPC has shutdown before we reset the instruments registry. + OpenTelemetryPluginEnd2EndTest::TearDown(); + grpc_core::GlobalInstrumentsRegistryTestPeer:: + ResetGlobalInstrumentsRegistry(); + } +}; TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordUInt64Counter) { constexpr absl::string_view kMetricName = "uint64_counter"; @@ -1677,6 +1688,28 @@ TEST_F(OpenTelemetryPluginNPCMetricsTest, ::testing::DoubleEq(kMax), kCount)))))); } +TEST_F(OpenTelemetryPluginNPCMetricsTest, InstrumentsEnabledTest) { + constexpr absl::string_view kDoubleHistogramMetricName = + "yet_another_yet_another_double_histogram"; + constexpr absl::string_view kUnit64CounterMetricName = "uint64_counter"; + auto histogram_handle = + grpc_core::GlobalInstrumentsRegistry::RegisterDoubleHistogram( + kDoubleHistogramMetricName, "A simple double histogram.", "unit", + /*enable_by_default=*/false) + .Build(); + auto counter_handle = + grpc_core::GlobalInstrumentsRegistry::RegisterUInt64Counter( + kUnit64CounterMetricName, "A simple unit64 counter.", "unit", + /*enable_by_default=*/false) + .Build(); + Init(std::move(Options().set_metric_names({kDoubleHistogramMetricName}))); + auto stats_plugins = + grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForServer( + grpc_core::ChannelArgs()); + EXPECT_TRUE(stats_plugins.IsInstrumentEnabled(histogram_handle)); + EXPECT_FALSE(stats_plugins.IsInstrumentEnabled(counter_handle)); +} + using OpenTelemetryPluginCallbackMetricsTest = OpenTelemetryPluginEnd2EndTest; // The callback minimal interval is longer than the OT reporting interval, so we