[OTel C++] Add API to set channel scope filter (#36189)

Also addressing a TODO from previous PRs where `authority` is not being populated in the `ChannelScope`.

Closes #36189

COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36189 from yashykt:OTelChannelScope e76f9ce0ca
PiperOrigin-RevId: 621231764
pull/36228/head
Yash Tibrewal 11 months ago committed by Copybara-Service
parent d9badb171a
commit 952a2421f9
  1. 1
      BUILD
  2. 4
      CMakeLists.txt
  3. 1
      Makefile
  4. 1
      Package.swift
  5. 4
      build_autogenerated.yaml
  6. 1
      gRPC-Core.podspec
  7. 1
      grpc.gemspec
  8. 1
      include/grpc/module.modulemap
  9. 51
      include/grpc/support/metrics.h
  10. 12
      include/grpcpp/ext/otel_plugin.h
  11. 1
      package.xml
  12. 2
      src/core/ext/xds/xds_client_grpc.cc
  13. 2
      src/core/lib/channel/metrics.cc
  14. 18
      src/core/lib/channel/metrics.h
  15. 9
      src/core/lib/surface/legacy_channel.cc
  16. 45
      src/cpp/ext/otel/otel_plugin.cc
  17. 31
      src/cpp/ext/otel/otel_plugin.h
  18. 52
      test/core/channel/metrics_test.cc
  19. 2
      test/core/util/fake_stats_plugin.cc
  20. 16
      test/core/util/fake_stats_plugin.h
  21. 5
      test/cpp/ext/csm/metadata_exchange_test.cc
  22. 63
      test/cpp/ext/otel/otel_plugin_test.cc
  23. 2
      test/cpp/ext/otel/otel_test_library.cc
  24. 13
      test/cpp/ext/otel/otel_test_library.h
  25. 1
      tools/doxygen/Doxyfile.c++
  26. 1
      tools/doxygen/Doxyfile.c++.internal
  27. 1
      tools/doxygen/Doxyfile.core
  28. 1
      tools/doxygen/Doxyfile.core.internal

@ -252,6 +252,7 @@ GPR_PUBLIC_HDRS = [
"include/grpc/support/json.h",
"include/grpc/support/log.h",
"include/grpc/support/log_windows.h",
"include/grpc/support/metrics.h",
"include/grpc/support/port_platform.h",
"include/grpc/support/string_util.h",
"include/grpc/support/sync.h",

4
CMakeLists.txt generated

@ -1783,6 +1783,7 @@ foreach(_hdr
include/grpc/support/json.h
include/grpc/support/log.h
include/grpc/support/log_windows.h
include/grpc/support/metrics.h
include/grpc/support/port_platform.h
include/grpc/support/string_util.h
include/grpc/support/sync.h
@ -2746,6 +2747,7 @@ foreach(_hdr
include/grpc/support/json.h
include/grpc/support/log.h
include/grpc/support/log_windows.h
include/grpc/support/metrics.h
include/grpc/support/port_platform.h
include/grpc/support/string_util.h
include/grpc/support/sync.h
@ -3446,6 +3448,7 @@ foreach(_hdr
include/grpc/support/json.h
include/grpc/support/log.h
include/grpc/support/log_windows.h
include/grpc/support/metrics.h
include/grpc/support/port_platform.h
include/grpc/support/string_util.h
include/grpc/support/sync.h
@ -5495,6 +5498,7 @@ foreach(_hdr
include/grpc/support/json.h
include/grpc/support/log.h
include/grpc/support/log_windows.h
include/grpc/support/metrics.h
include/grpc/support/port_platform.h
include/grpc/support/string_util.h
include/grpc/support/sync.h

1
Makefile generated

@ -1786,6 +1786,7 @@ PUBLIC_HEADERS_C += \
include/grpc/support/json.h \
include/grpc/support/log.h \
include/grpc/support/log_windows.h \
include/grpc/support/metrics.h \
include/grpc/support/port_platform.h \
include/grpc/support/string_util.h \
include/grpc/support/sync.h \

1
Package.swift generated

@ -104,6 +104,7 @@ let package = Package(
"include/grpc/support/json.h",
"include/grpc/support/log.h",
"include/grpc/support/log_windows.h",
"include/grpc/support/metrics.h",
"include/grpc/support/port_platform.h",
"include/grpc/support/string_util.h",
"include/grpc/support/sync.h",

@ -40,6 +40,7 @@ libs:
- include/grpc/support/json.h
- include/grpc/support/log.h
- include/grpc/support/log_windows.h
- include/grpc/support/metrics.h
- include/grpc/support/port_platform.h
- include/grpc/support/string_util.h
- include/grpc/support/sync.h
@ -206,6 +207,7 @@ libs:
- include/grpc/support/json.h
- include/grpc/support/log.h
- include/grpc/support/log_windows.h
- include/grpc/support/metrics.h
- include/grpc/support/port_platform.h
- include/grpc/support/string_util.h
- include/grpc/support/sync.h
@ -2192,6 +2194,7 @@ libs:
- include/grpc/support/json.h
- include/grpc/support/log.h
- include/grpc/support/log_windows.h
- include/grpc/support/metrics.h
- include/grpc/support/port_platform.h
- include/grpc/support/string_util.h
- include/grpc/support/sync.h
@ -4369,6 +4372,7 @@ libs:
- include/grpc/support/json.h
- include/grpc/support/log.h
- include/grpc/support/log_windows.h
- include/grpc/support/metrics.h
- include/grpc/support/port_platform.h
- include/grpc/support/string_util.h
- include/grpc/support/sync.h

1
gRPC-Core.podspec generated

@ -178,6 +178,7 @@ Pod::Spec.new do |s|
'include/grpc/support/json.h',
'include/grpc/support/log.h',
'include/grpc/support/log_windows.h',
'include/grpc/support/metrics.h',
'include/grpc/support/port_platform.h',
'include/grpc/support/string_util.h',
'include/grpc/support/sync.h',

1
grpc.gemspec generated

@ -110,6 +110,7 @@ Gem::Specification.new do |s|
s.files += %w( include/grpc/support/json.h )
s.files += %w( include/grpc/support/log.h )
s.files += %w( include/grpc/support/log_windows.h )
s.files += %w( include/grpc/support/metrics.h )
s.files += %w( include/grpc/support/port_platform.h )
s.files += %w( include/grpc/support/string_util.h )
s.files += %w( include/grpc/support/sync.h )

@ -46,6 +46,7 @@ header "byte_buffer.h"
header "support/json.h"
header "support/log.h"
header "support/log_windows.h"
header "support/metrics.h"
header "support/port_platform.h"
header "support/string_util.h"
header "support/sync.h"

@ -0,0 +1,51 @@
// Copyright 2024 The gRPC Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef GRPC_SUPPORT_METRICS_H
#define GRPC_SUPPORT_METRICS_H
#include <grpc/support/port_platform.h>
#include "absl/strings/string_view.h"
namespace grpc_core {
namespace experimental {
// Configuration (scope) for a specific client channel to be used for stats
// plugins.
class StatsPluginChannelScope {
public:
StatsPluginChannelScope(absl::string_view target,
absl::string_view default_authority)
: target_(target), default_authority_(default_authority) {}
/// Returns the target used for creating the channel in the canonical form.
/// (Canonicalized target definition -
/// https://github.com/grpc/proposal/blob/master/A66-otel-stats.md)
absl::string_view target() const { return target_; }
/// Returns the default authority for the channel.
absl::string_view default_authority() const { return default_authority_; }
private:
// Disable copy constructor and copy-assignment operator.
StatsPluginChannelScope(const StatsPluginChannelScope&) = delete;
StatsPluginChannelScope& operator=(const StatsPluginChannelScope&) = delete;
absl::string_view target_;
absl::string_view default_authority_;
};
} // namespace experimental
} // namespace grpc_core
#endif /* GRPC_SUPPORT_METRICS_H */

@ -31,10 +31,13 @@
#include "absl/strings/string_view.h"
#include "opentelemetry/metrics/meter_provider.h"
#include <grpc/support/metrics.h>
namespace grpc {
namespace internal {
class OpenTelemetryPluginBuilderImpl;
class OpenTelemetryPlugin;
} // namespace internal
class OpenTelemetryPluginOption {
@ -57,6 +60,8 @@ class OpenTelemetryPluginOption {
/// grpc.server.call.rcvd_total_compressed_message_size
class OpenTelemetryPluginBuilder {
public:
using ChannelScope = grpc_core::experimental::StatsPluginChannelScope;
/// Metrics
static constexpr absl::string_view kClientAttemptStartedInstrumentName =
"grpc.client.attempt.started";
@ -113,9 +118,14 @@ class OpenTelemetryPluginBuilder {
/// options can be added.
OpenTelemetryPluginBuilder& AddPluginOption(
std::unique_ptr<OpenTelemetryPluginOption> option);
// Records \a optional_label_key on all metrics that provide it.
/// Records \a optional_label_key on all metrics that provide it.
OpenTelemetryPluginBuilder& AddOptionalLabel(
absl::string_view optional_label_key);
/// Set scope filter to choose which channels are recorded by this plugin.
/// Server-side recording remains unaffected.
OpenTelemetryPluginBuilder& SetChannelScopeFilter(
absl::AnyInvocable<bool(const ChannelScope& /*scope*/) const>
channel_scope_filter);
/// Registers a global plugin that acts on all channels and servers running on
/// the process.
absl::Status BuildAndRegisterGlobal();

1
package.xml generated

@ -92,6 +92,7 @@
<file baseinstalldir="/" name="include/grpc/support/json.h" role="src" />
<file baseinstalldir="/" name="include/grpc/support/log.h" role="src" />
<file baseinstalldir="/" name="include/grpc/support/log_windows.h" role="src" />
<file baseinstalldir="/" name="include/grpc/support/metrics.h" role="src" />
<file baseinstalldir="/" name="include/grpc/support/port_platform.h" role="src" />
<file baseinstalldir="/" name="include/grpc/support/string_util.h" role="src" />
<file baseinstalldir="/" name="include/grpc/support/sync.h" role="src" />

@ -271,7 +271,7 @@ GlobalStatsPluginRegistry::StatsPluginGroup GetStatsPluginGroupForKey(
return GlobalStatsPluginRegistry::GetStatsPluginsForServer(ChannelArgs{});
}
// TODO(roth): How do we set the authority here?
StatsPlugin::ChannelScope scope(key, "");
experimental::StatsPluginChannelScope scope(key, "");
return GlobalStatsPluginRegistry::GetStatsPluginsForChannel(scope);
}

@ -364,7 +364,7 @@ void GlobalStatsPluginRegistry::RegisterStatsPlugin(
GlobalStatsPluginRegistry::StatsPluginGroup
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
const StatsPlugin::ChannelScope& scope) {
const experimental::StatsPluginChannelScope& scope) {
MutexLock lock(&*mutex_);
StatsPluginGroup group;
for (const auto& plugin : *plugins_) {

@ -28,6 +28,7 @@
#include "absl/types/span.h"
#include <grpc/support/log.h>
#include <grpc/support/metrics.h>
#include "src/core/lib/channel/call_tracer.h"
#include "src/core/lib/channel/channel_args.h"
@ -167,19 +168,6 @@ class RegisteredMetricCallback;
// The StatsPlugin interface.
class StatsPlugin {
public:
// Configuration (scope) for a specific client channel.
class ChannelScope {
public:
ChannelScope(absl::string_view target, absl::string_view authority)
: target_(target), authority_(authority) {}
absl::string_view target() const { return target_; }
absl::string_view authority() const { return authority_; }
private:
absl::string_view target_;
absl::string_view authority_;
};
// A general-purpose way for stats plugin to store per-channel or per-server
// state.
class ScopeConfig {
@ -193,7 +181,7 @@ class StatsPlugin {
// Returns true and a channel-specific ScopeConfig which may then be used to
// configure the ClientCallTracer in GetClientCallTracer().
virtual std::pair<bool, std::shared_ptr<ScopeConfig>> IsEnabledForChannel(
const ChannelScope& scope) const = 0;
const experimental::StatsPluginChannelScope& scope) const = 0;
// Whether this stats plugin is enabled for the server specified by \a args.
// Returns true and a server-specific ScopeConfig which may then be used to
// configure the ServerCallTracer in GetServerCallTracer().
@ -365,7 +353,7 @@ class GlobalStatsPluginRegistry {
// The following functions can be invoked to get a StatsPluginGroup for
// a specified scope.
static StatsPluginGroup GetStatsPluginsForChannel(
const StatsPlugin::ChannelScope& scope);
const experimental::StatsPluginChannelScope& scope);
static StatsPluginGroup GetStatsPluginsForServer(const ChannelArgs& args);
private:

@ -93,10 +93,11 @@ absl::StatusOr<OrphanablePtr<Channel>> LegacyChannel::Create(
*(*r)->stats_plugin_group =
GlobalStatsPluginRegistry::GetStatsPluginsForServer(args);
} else {
// TODO(roth): Figure out how to populate authority here.
// Or maybe just don't worry about this if no one needs it until after
// the call v3 stack lands.
StatsPlugin::ChannelScope scope(target, "");
experimental::StatsPluginChannelScope scope(
target, args.GetOwnedString(GRPC_ARG_DEFAULT_AUTHORITY)
.value_or(CoreConfiguration::Get()
.resolver_registry()
.GetDefaultAuthority(target)));
*(*r)->stats_plugin_group =
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(scope);
}

@ -172,14 +172,6 @@ OpenTelemetryPluginBuilderImpl::DisableAllMetrics() {
return *this;
}
OpenTelemetryPluginBuilderImpl&
OpenTelemetryPluginBuilderImpl::SetTargetSelector(
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
target_selector) {
target_selector_ = std::move(target_selector);
return *this;
}
OpenTelemetryPluginBuilderImpl&
OpenTelemetryPluginBuilderImpl::SetTargetAttributeFilter(
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
@ -222,17 +214,25 @@ OpenTelemetryPluginBuilderImpl::AddOptionalLabel(
return *this;
}
OpenTelemetryPluginBuilderImpl&
OpenTelemetryPluginBuilderImpl::SetChannelScopeFilter(
absl::AnyInvocable<
bool(const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) const>
channel_scope_filter) {
channel_scope_filter_ = std::move(channel_scope_filter);
return *this;
}
absl::Status OpenTelemetryPluginBuilderImpl::BuildAndRegisterGlobal() {
if (meter_provider_ == nullptr) {
return absl::OkStatus();
}
grpc_core::GlobalStatsPluginRegistry::RegisterStatsPlugin(
std::make_shared<OpenTelemetryPlugin>(
metrics_, meter_provider_, std::move(target_selector_),
std::move(target_attribute_filter_),
metrics_, meter_provider_, std::move(target_attribute_filter_),
std::move(generic_method_attribute_filter_),
std::move(server_selector_), std::move(plugin_options_),
std::move(optional_label_keys_)));
std::move(optional_label_keys_), std::move(channel_scope_filter_)));
return absl::OkStatus();
}
@ -240,8 +240,6 @@ OpenTelemetryPlugin::OpenTelemetryPlugin(
const absl::flat_hash_set<std::string>& metrics,
opentelemetry::nostd::shared_ptr<opentelemetry::metrics::MeterProvider>
meter_provider,
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
target_selector,
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
target_attribute_filter,
absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>
@ -250,14 +248,17 @@ OpenTelemetryPlugin::OpenTelemetryPlugin(
server_selector,
std::vector<std::unique_ptr<InternalOpenTelemetryPluginOption>>
plugin_options,
std::shared_ptr<std::set<absl::string_view>> optional_label_keys)
std::shared_ptr<std::set<absl::string_view>> optional_label_keys,
absl::AnyInvocable<
bool(const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) const>
channel_scope_filter)
: meter_provider_(std::move(meter_provider)),
target_selector_(std::move(target_selector)),
server_selector_(std::move(server_selector)),
target_attribute_filter_(std::move(target_attribute_filter)),
generic_method_attribute_filter_(
std::move(generic_method_attribute_filter)),
plugin_options_(std::move(plugin_options)) {
plugin_options_(std::move(plugin_options)),
channel_scope_filter_(std::move(channel_scope_filter)) {
auto meter = meter_provider_->GetMeter("grpc-c++", GRPC_CPP_VERSION_STRING);
// Per-call metrics.
if (metrics.contains(grpc::OpenTelemetryPluginBuilder::
@ -427,8 +428,9 @@ OpenTelemetryPlugin::OpenTelemetryPlugin(
}
std::pair<bool, std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig>>
OpenTelemetryPlugin::IsEnabledForChannel(const ChannelScope& scope) const {
if (target_selector_ == nullptr || target_selector_(scope.target())) {
OpenTelemetryPlugin::IsEnabledForChannel(
const OpenTelemetryPluginBuilder::ChannelScope& scope) const {
if (channel_scope_filter_ == nullptr || channel_scope_filter_(scope)) {
return {true, std::make_shared<ClientScopeConfig>(this, scope)};
}
return {false, nullptr};
@ -643,6 +645,13 @@ OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::AddOptionalLabel(
return *this;
}
OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::SetChannelScopeFilter(
absl::AnyInvocable<bool(const ChannelScope& /*scope*/) const>
channel_scope_filter) {
impl_->SetChannelScopeFilter(std::move(channel_scope_filter));
return *this;
}
absl::Status OpenTelemetryPluginBuilder::BuildAndRegisterGlobal() {
return impl_->BuildAndRegisterGlobal();
}

@ -140,11 +140,6 @@ class OpenTelemetryPluginBuilderImpl {
OpenTelemetryPluginBuilderImpl& DisableMetrics(
absl::Span<const absl::string_view> metric_names);
OpenTelemetryPluginBuilderImpl& DisableAllMetrics();
// If set, \a target_selector is called per channel to decide whether to
// collect metrics on that target or not.
OpenTelemetryPluginBuilderImpl& SetTargetSelector(
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
target_selector);
// If set, \a server_selector is called per incoming call on the server
// to decide whether to collect metrics on that call or not.
// TODO(yashkt): We should only need to do this per server connection or even
@ -173,6 +168,12 @@ class OpenTelemetryPluginBuilderImpl {
// Records \a optional_label_key on all metrics that provide it.
OpenTelemetryPluginBuilderImpl& AddOptionalLabel(
absl::string_view optional_label_key);
// Set scope filter to choose which channels are recorded by this plugin.
// Server-side recording remains unaffected.
OpenTelemetryPluginBuilderImpl& SetChannelScopeFilter(
absl::AnyInvocable<
bool(const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) const>
channel_scope_filter);
absl::Status BuildAndRegisterGlobal();
const absl::flat_hash_set<std::string>& TestOnlyEnabledMetrics() {
@ -185,7 +186,6 @@ class OpenTelemetryPluginBuilderImpl {
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
target_attribute_filter_;
absl::flat_hash_set<std::string> metrics_;
absl::AnyInvocable<bool(absl::string_view /*target*/) const> target_selector_;
absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>
generic_method_attribute_filter_;
absl::AnyInvocable<bool(const grpc_core::ChannelArgs& /*args*/) const>
@ -193,6 +193,9 @@ class OpenTelemetryPluginBuilderImpl {
std::vector<std::unique_ptr<InternalOpenTelemetryPluginOption>>
plugin_options_;
std::shared_ptr<std::set<absl::string_view>> optional_label_keys_;
absl::AnyInvocable<bool(
const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) const>
channel_scope_filter_;
};
class OpenTelemetryPlugin : public grpc_core::StatsPlugin {
@ -201,8 +204,6 @@ class OpenTelemetryPlugin : public grpc_core::StatsPlugin {
const absl::flat_hash_set<std::string>& metrics,
opentelemetry::nostd::shared_ptr<opentelemetry::metrics::MeterProvider>
meter_provider,
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
target_selector,
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
target_attribute_filter,
absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>
@ -211,7 +212,10 @@ class OpenTelemetryPlugin : public grpc_core::StatsPlugin {
server_selector,
std::vector<std::unique_ptr<InternalOpenTelemetryPluginOption>>
plugin_options,
std::shared_ptr<std::set<absl::string_view>> optional_label_keys);
std::shared_ptr<std::set<absl::string_view>> optional_label_keys,
absl::AnyInvocable<
bool(const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) const>
channel_scope_filter);
private:
class ClientCallTracer;
@ -273,7 +277,7 @@ class OpenTelemetryPlugin : public grpc_core::StatsPlugin {
class ClientScopeConfig : public grpc_core::StatsPlugin::ScopeConfig {
public:
ClientScopeConfig(const OpenTelemetryPlugin* otel_plugin,
const ChannelScope& scope)
const OpenTelemetryPluginBuilder::ChannelScope& scope)
: active_plugin_options_view_(ActivePluginOptionsView::MakeForClient(
scope.target(), otel_plugin)),
filtered_target_(
@ -333,7 +337,8 @@ class OpenTelemetryPlugin : public grpc_core::StatsPlugin {
// StatsPlugin:
std::pair<bool, std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig>>
IsEnabledForChannel(const ChannelScope& scope) const override;
IsEnabledForChannel(
const OpenTelemetryPluginBuilder::ChannelScope& scope) const override;
std::pair<bool, std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig>>
IsEnabledForServer(const grpc_core::ChannelArgs& args) const override;
void AddCounter(
@ -409,7 +414,6 @@ class OpenTelemetryPlugin : public grpc_core::StatsPlugin {
std::vector<InstrumentData> instruments_data_;
opentelemetry::nostd::shared_ptr<opentelemetry::metrics::MeterProvider>
meter_provider_;
absl::AnyInvocable<bool(absl::string_view /*target*/) const> target_selector_;
absl::AnyInvocable<bool(const grpc_core::ChannelArgs& /*args*/) const>
server_selector_;
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
@ -418,6 +422,9 @@ class OpenTelemetryPlugin : public grpc_core::StatsPlugin {
generic_method_attribute_filter_;
std::vector<std::unique_ptr<InternalOpenTelemetryPluginOption>>
plugin_options_;
absl::AnyInvocable<bool(
const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) const>
channel_scope_filter_;
};
} // namespace internal

@ -29,6 +29,8 @@
namespace grpc_core {
namespace {
using experimental::StatsPluginChannelScope;
class MetricsTest : public ::testing::Test {
public:
void TearDown() override {
@ -55,13 +57,13 @@ TEST_F(MetricsTest, UInt64Counter) {
auto plugin2 = MakeStatsPluginForTarget(kDomain2To4);
auto plugin3 = MakeStatsPluginForTarget(kDomain3To4);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain1To4, ""))
StatsPluginChannelScope(kDomain1To4, ""))
.AddCounter(uint64_counter_handle, 1, kLabelValues, kOptionalLabelValues);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain2To4, ""))
StatsPluginChannelScope(kDomain2To4, ""))
.AddCounter(uint64_counter_handle, 2, kLabelValues, kOptionalLabelValues);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain3To4, ""))
StatsPluginChannelScope(kDomain3To4, ""))
.AddCounter(uint64_counter_handle, 3, kLabelValues, kOptionalLabelValues);
EXPECT_THAT(plugin1->GetCounterValue(uint64_counter_handle, kLabelValues,
kOptionalLabelValues),
@ -92,15 +94,15 @@ TEST_F(MetricsTest, DoubleCounter) {
auto plugin2 = MakeStatsPluginForTarget(kDomain2To4);
auto plugin3 = MakeStatsPluginForTarget(kDomain3To4);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain1To4, ""))
StatsPluginChannelScope(kDomain1To4, ""))
.AddCounter(double_counter_handle, 1.23, kLabelValues,
kOptionalLabelValues);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain2To4, ""))
StatsPluginChannelScope(kDomain2To4, ""))
.AddCounter(double_counter_handle, 2.34, kLabelValues,
kOptionalLabelValues);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain3To4, ""))
StatsPluginChannelScope(kDomain3To4, ""))
.AddCounter(double_counter_handle, 3.45, kLabelValues,
kOptionalLabelValues);
EXPECT_THAT(plugin1->GetCounterValue(double_counter_handle, kLabelValues,
@ -133,15 +135,15 @@ TEST_F(MetricsTest, UInt64Histogram) {
auto plugin2 = MakeStatsPluginForTarget(kDomain2To4);
auto plugin3 = MakeStatsPluginForTarget(kDomain3To4);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain1To4, ""))
StatsPluginChannelScope(kDomain1To4, ""))
.RecordHistogram(uint64_histogram_handle, 1, kLabelValues,
kOptionalLabelValues);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain2To4, ""))
StatsPluginChannelScope(kDomain2To4, ""))
.RecordHistogram(uint64_histogram_handle, 2, kLabelValues,
kOptionalLabelValues);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain3To4, ""))
StatsPluginChannelScope(kDomain3To4, ""))
.RecordHistogram(uint64_histogram_handle, 3, kLabelValues,
kOptionalLabelValues);
EXPECT_THAT(plugin1->GetHistogramValue(uint64_histogram_handle, kLabelValues,
@ -174,15 +176,15 @@ TEST_F(MetricsTest, DoubleHistogram) {
auto plugin2 = MakeStatsPluginForTarget(kDomain2To4);
auto plugin3 = MakeStatsPluginForTarget(kDomain3To4);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain1To4, ""))
StatsPluginChannelScope(kDomain1To4, ""))
.RecordHistogram(double_histogram_handle, 1.23, kLabelValues,
kOptionalLabelValues);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain2To4, ""))
StatsPluginChannelScope(kDomain2To4, ""))
.RecordHistogram(double_histogram_handle, 2.34, kLabelValues,
kOptionalLabelValues);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain3To4, ""))
StatsPluginChannelScope(kDomain3To4, ""))
.RecordHistogram(double_histogram_handle, 3.45, kLabelValues,
kOptionalLabelValues);
EXPECT_THAT(plugin1->GetHistogramValue(double_histogram_handle, kLabelValues,
@ -215,13 +217,13 @@ TEST_F(MetricsTest, Int64Gauge) {
auto plugin2 = MakeStatsPluginForTarget(kDomain2To4);
auto plugin3 = MakeStatsPluginForTarget(kDomain3To4);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain1To4, ""))
StatsPluginChannelScope(kDomain1To4, ""))
.SetGauge(int64_gauge_handle, 1, kLabelValues, kOptionalLabelValues);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain2To4, ""))
StatsPluginChannelScope(kDomain2To4, ""))
.SetGauge(int64_gauge_handle, 2, kLabelValues, kOptionalLabelValues);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain3To4, ""))
StatsPluginChannelScope(kDomain3To4, ""))
.SetGauge(int64_gauge_handle, 3, kLabelValues, kOptionalLabelValues);
EXPECT_THAT(plugin1->GetGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
@ -252,13 +254,13 @@ TEST_F(MetricsTest, DoubleGauge) {
auto plugin2 = MakeStatsPluginForTarget(kDomain2To4);
auto plugin3 = MakeStatsPluginForTarget(kDomain3To4);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain1To4, ""))
StatsPluginChannelScope(kDomain1To4, ""))
.SetGauge(double_gauge_handle, 1.23, kLabelValues, kOptionalLabelValues);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain2To4, ""))
StatsPluginChannelScope(kDomain2To4, ""))
.SetGauge(double_gauge_handle, 2.34, kLabelValues, kOptionalLabelValues);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain3To4, ""))
StatsPluginChannelScope(kDomain3To4, ""))
.SetGauge(double_gauge_handle, 3.45, kLabelValues, kOptionalLabelValues);
EXPECT_THAT(plugin1->GetGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
@ -295,7 +297,7 @@ TEST_F(MetricsTest, Int64CallbackGauge) {
// label values. The callbacks get used only by plugin1.
gpr_log(GPR_INFO, "testing callbacks for: plugin1");
auto group1 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain3To4, ""));
StatsPluginChannelScope(kDomain3To4, ""));
auto callback1 = group1.RegisterCallback(
[&](CallbackMetricReporter& reporter) {
reporter.Report(int64_gauge_handle, 1, kLabelValues,
@ -356,7 +358,7 @@ TEST_F(MetricsTest, Int64CallbackGauge) {
// Now register callbacks that hit both plugin1 and plugin2.
gpr_log(GPR_INFO, "testing callbacks for: plugin1, plugin2");
auto group2 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain2To4, ""));
StatsPluginChannelScope(kDomain2To4, ""));
callback1 = group2.RegisterCallback(
[&](CallbackMetricReporter& reporter) {
reporter.Report(int64_gauge_handle, 3, kLabelValues,
@ -417,7 +419,7 @@ TEST_F(MetricsTest, Int64CallbackGauge) {
// Now register callbacks that hit all three plugins.
gpr_log(GPR_INFO, "testing callbacks for: plugin1, plugin2, plugin3");
auto group3 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain1To4, ""));
StatsPluginChannelScope(kDomain1To4, ""));
callback1 = group3.RegisterCallback(
[&](CallbackMetricReporter& reporter) {
reporter.Report(int64_gauge_handle, 5, kLabelValues,
@ -501,7 +503,7 @@ TEST_F(MetricsTest, DoubleCallbackGauge) {
// label values. The callbacks get used only by plugin1.
gpr_log(GPR_INFO, "testing callbacks for: plugin1");
auto group1 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain3To4, ""));
StatsPluginChannelScope(kDomain3To4, ""));
auto callback1 = group1.RegisterCallback(
[&](CallbackMetricReporter& reporter) {
reporter.Report(double_gauge_handle, 1.23, kLabelValues,
@ -562,7 +564,7 @@ TEST_F(MetricsTest, DoubleCallbackGauge) {
// Now register callbacks that hit both plugin1 and plugin2.
gpr_log(GPR_INFO, "testing callbacks for: plugin1, plugin2");
auto group2 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain2To4, ""));
StatsPluginChannelScope(kDomain2To4, ""));
callback1 = group2.RegisterCallback(
[&](CallbackMetricReporter& reporter) {
reporter.Report(double_gauge_handle, 3.45, kLabelValues,
@ -623,7 +625,7 @@ TEST_F(MetricsTest, DoubleCallbackGauge) {
// Now register callbacks that hit all three plugins.
gpr_log(GPR_INFO, "testing callbacks for: plugin1, plugin2, plugin3");
auto group3 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain1To4, ""));
StatsPluginChannelScope(kDomain1To4, ""));
callback1 = group3.RegisterCallback(
[&](CallbackMetricReporter& reporter) {
reporter.Report(double_gauge_handle, 5.67, kLabelValues,
@ -698,7 +700,7 @@ TEST_F(MetricsTest, DisableByDefaultMetricIsNotRecordedByFakeStatsPlugin) {
constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
auto plugin = MakeStatsPluginForTarget(kDomain1To4);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPlugin::ChannelScope(kDomain1To4, ""))
StatsPluginChannelScope(kDomain1To4, ""))
.RecordHistogram(double_histogram_handle, 1.23, kLabelValues,
kOptionalLabelValues);
EXPECT_EQ(plugin->GetHistogramValue(double_histogram_handle, kLabelValues,

@ -107,7 +107,7 @@ std::shared_ptr<FakeStatsPlugin> MakeStatsPluginForTarget(
absl::string_view target_suffix) {
return FakeStatsPluginBuilder()
.SetChannelFilter(
[target_suffix](const StatsPlugin::ChannelScope& scope) {
[target_suffix](const experimental::StatsPluginChannelScope& scope) {
return absl::EndsWith(scope.target(), target_suffix);
})
.BuildAndRegister();

@ -207,7 +207,8 @@ class FakeStatsPlugin : public StatsPlugin {
class ScopeConfig : public StatsPlugin::ScopeConfig {};
explicit FakeStatsPlugin(
absl::AnyInvocable<bool(const ChannelScope& /*scope*/) const>
absl::AnyInvocable<
bool(const experimental::StatsPluginChannelScope& /*scope*/) const>
channel_filter = nullptr,
bool use_disabled_by_default_metrics = false)
: channel_filter_(std::move(channel_filter)) {
@ -269,7 +270,8 @@ class FakeStatsPlugin : public StatsPlugin {
}
std::pair<bool, std::shared_ptr<StatsPlugin::ScopeConfig>>
IsEnabledForChannel(const ChannelScope& scope) const override {
IsEnabledForChannel(
const experimental::StatsPluginChannelScope& scope) const override {
if (channel_filter_ == nullptr || channel_filter_(scope)) {
return {true, nullptr};
}
@ -658,7 +660,9 @@ class FakeStatsPlugin : public StatsPlugin {
absl::flat_hash_map<std::string, T> storage_;
};
absl::AnyInvocable<bool(const ChannelScope& /*scope*/) const> channel_filter_;
absl::AnyInvocable<bool(
const experimental::StatsPluginChannelScope& /*scope*/) const>
channel_filter_;
// Instruments.
Mutex mu_;
absl::flat_hash_map<uint32_t, Counter<uint64_t>> uint64_counters_
@ -684,7 +688,8 @@ class FakeStatsPlugin : public StatsPlugin {
class FakeStatsPluginBuilder {
public:
FakeStatsPluginBuilder& SetChannelFilter(
absl::AnyInvocable<bool(const StatsPlugin::ChannelScope& /*scope*/) const>
absl::AnyInvocable<
bool(const experimental::StatsPluginChannelScope& /*scope*/) const>
channel_filter) {
channel_filter_ = std::move(channel_filter);
return *this;
@ -703,7 +708,8 @@ class FakeStatsPluginBuilder {
}
private:
absl::AnyInvocable<bool(const StatsPlugin::ChannelScope& /*scope*/) const>
absl::AnyInvocable<bool(
const experimental::StatsPluginChannelScope& /*scope*/) const>
channel_filter_;
bool use_disabled_by_default_metrics_ = false;
};

@ -182,8 +182,9 @@ class MetadataExchangeTest
.add_plugin_option(std::make_unique<MeshLabelsPluginOption>(
GetParam().GetTestResource().GetAttributes()))
.set_labels_to_inject(std::move(labels_to_inject))
.set_target_selector(
[enable_client_side_injector](absl::string_view /*target*/) {
.set_channel_scope_filter(
[enable_client_side_injector](
const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) {
return enable_client_side_injector;
})));
}

@ -384,14 +384,17 @@ TEST_F(OpenTelemetryPluginEnd2EndTest, NoMeterProviderRegistered) {
SendRPC();
}
// Test that a channel selector returning true records metrics on the channel.
TEST_F(OpenTelemetryPluginEnd2EndTest, TargetSelectorReturnsTrue) {
Init(
std::move(Options()
.set_metric_names({grpc::OpenTelemetryPluginBuilder::
kClientAttemptStartedInstrumentName})
.set_target_selector(
[](absl::string_view /*target*/) { return true; })));
// Test that a channel scope filter returning true records metrics on the
// channel.
TEST_F(OpenTelemetryPluginEnd2EndTest, ChannelScopeFilterReturnsTrue) {
Init(std::move(
Options()
.set_metric_names({grpc::OpenTelemetryPluginBuilder::
kClientAttemptStartedInstrumentName})
.set_channel_scope_filter(
[](const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) {
return true;
})));
SendRPC();
const char* kMetricName = "grpc.client.attempt.started";
auto data = ReadCurrentMetricsData(
@ -418,15 +421,17 @@ TEST_F(OpenTelemetryPluginEnd2EndTest, TargetSelectorReturnsTrue) {
EXPECT_EQ(*target_value, canonical_server_address_);
}
// Test that a target selector returning false does not record metrics on the
// channel.
TEST_F(OpenTelemetryPluginEnd2EndTest, TargetSelectorReturnsFalse) {
Init(
std::move(Options()
.set_metric_names({grpc::OpenTelemetryPluginBuilder::
kClientAttemptStartedInstrumentName})
.set_target_selector(
[](absl::string_view /*target*/) { return false; })));
// Test that a channel scope filter returning false does not record metrics on
// the channel.
TEST_F(OpenTelemetryPluginEnd2EndTest, ChannelScopeFilterReturnsFalse) {
Init(std::move(
Options()
.set_metric_names({grpc::OpenTelemetryPluginBuilder::
kClientAttemptStartedInstrumentName})
.set_channel_scope_filter(
[](const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) {
return false;
})));
SendRPC();
auto data = ReadCurrentMetricsData(
[&](const absl::flat_hash_map<
@ -1024,14 +1029,18 @@ TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordUInt64Counter) {
kOptionalLabelKeys, /*enable_by_default=*/true);
Init(std::move(Options()
.set_metric_names({kMetricName})
.set_target_selector([](absl::string_view target) {
return absl::StartsWith(target, "dns:///");
})
.set_channel_scope_filter(
[](const OpenTelemetryPluginBuilder::ChannelScope&
channel_scope) {
return absl::StartsWith(channel_scope.target(),
"dns:///");
})
.add_optional_label(kOptionalLabelKeys[0])
.add_optional_label(kOptionalLabelKeys[1])));
auto stats_plugins =
grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
grpc_core::StatsPlugin::ChannelScope("dns:///localhost:8080", ""));
grpc_core::experimental::StatsPluginChannelScope(
"dns:///localhost:8080", ""));
for (auto v : kCounterValues) {
stats_plugins.AddCounter(handle, v, kLabelValues, kOptionalLabelValues);
}
@ -1065,14 +1074,18 @@ TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordDoubleCounter) {
kOptionalLabelKeys, /*enable_by_default=*/false);
Init(std::move(Options()
.set_metric_names({kMetricName})
.set_target_selector([](absl::string_view target) {
return absl::StartsWith(target, "dns:///");
})
.set_channel_scope_filter(
[](const OpenTelemetryPluginBuilder::ChannelScope&
channel_scope) {
return absl::StartsWith(channel_scope.target(),
"dns:///");
})
.add_optional_label(kOptionalLabelKeys[0])
.add_optional_label(kOptionalLabelKeys[1])));
auto stats_plugins =
grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
grpc_core::StatsPlugin::ChannelScope("dns:///localhost:8080", ""));
grpc_core::experimental::StatsPluginChannelScope(
"dns:///localhost:8080", ""));
for (auto v : kCounterValues) {
stats_plugins.AddCounter(handle, v, kLabelValues, kOptionalLabelValues);
}

@ -207,7 +207,7 @@ OpenTelemetryPluginEnd2EndTest::BuildAndRegisterOpenTelemetryPlugin(
meter_provider->AddMetricReader(reader);
ot_builder.SetMeterProvider(std::move(meter_provider));
}
ot_builder.SetTargetSelector(std::move(options.target_selector));
ot_builder.SetChannelScopeFilter(std::move(options.channel_scope_filter));
ot_builder.SetServerSelector(std::move(options.server_selector));
ot_builder.SetTargetAttributeFilter(
std::move(options.target_attribute_filter));

@ -80,9 +80,11 @@ class OpenTelemetryPluginEnd2EndTest : public ::testing::Test {
return *this;
}
Options& set_target_selector(
absl::AnyInvocable<bool(absl::string_view /*target*/) const> func) {
target_selector = std::move(func);
Options& set_channel_scope_filter(
absl::AnyInvocable<bool(
const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) const>
func) {
channel_scope_filter = std::move(func);
return *this;
}
@ -128,8 +130,9 @@ class OpenTelemetryPluginEnd2EndTest : public ::testing::Test {
std::unique_ptr<grpc::internal::LabelsInjector> labels_injector;
bool use_meter_provider = true;
std::map<std::string, std::string> labels_to_inject;
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
target_selector;
absl::AnyInvocable<bool(
const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) const>
channel_scope_filter;
absl::AnyInvocable<bool(const grpc_core::ChannelArgs& /*channel_args*/)
const>
server_selector;

@ -939,6 +939,7 @@ include/grpc/support/cpu.h \
include/grpc/support/json.h \
include/grpc/support/log.h \
include/grpc/support/log_windows.h \
include/grpc/support/metrics.h \
include/grpc/support/port_platform.h \
include/grpc/support/string_util.h \
include/grpc/support/sync.h \

@ -939,6 +939,7 @@ include/grpc/support/cpu.h \
include/grpc/support/json.h \
include/grpc/support/log.h \
include/grpc/support/log_windows.h \
include/grpc/support/metrics.h \
include/grpc/support/port_platform.h \
include/grpc/support/string_util.h \
include/grpc/support/sync.h \

@ -872,6 +872,7 @@ include/grpc/support/cpu.h \
include/grpc/support/json.h \
include/grpc/support/log.h \
include/grpc/support/log_windows.h \
include/grpc/support/metrics.h \
include/grpc/support/port_platform.h \
include/grpc/support/string_util.h \
include/grpc/support/sync.h \

@ -872,6 +872,7 @@ include/grpc/support/cpu.h \
include/grpc/support/json.h \
include/grpc/support/log.h \
include/grpc/support/log_windows.h \
include/grpc/support/metrics.h \
include/grpc/support/port_platform.h \
include/grpc/support/string_util.h \
include/grpc/support/sync.h \

Loading…
Cancel
Save