xref: /aosp_15_r20/external/grpc-grpc/src/cpp/ext/otel/otel_plugin.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 //
3 // Copyright 2023 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 #include <grpc/support/port_platform.h>
20 
21 #include "src/cpp/ext/otel/otel_plugin.h"
22 
23 #include <memory>
24 #include <type_traits>
25 #include <utility>
26 
27 #include "opentelemetry/metrics/meter.h"
28 #include "opentelemetry/metrics/meter_provider.h"
29 #include "opentelemetry/metrics/sync_instruments.h"
30 #include "opentelemetry/nostd/shared_ptr.h"
31 #include "opentelemetry/nostd/unique_ptr.h"
32 #include "opentelemetry/nostd/variant.h"
33 
34 #include <grpc/support/log.h>
35 #include <grpcpp/ext/otel_plugin.h>
36 #include <grpcpp/version_info.h>
37 
38 #include "src/core/client_channel/client_channel_filter.h"
39 #include "src/core/lib/channel/call_tracer.h"
40 #include "src/core/lib/channel/channel_args.h"
41 #include "src/core/lib/config/core_configuration.h"
42 #include "src/core/lib/gprpp/match.h"
43 #include "src/core/lib/surface/channel_stack_type.h"
44 #include "src/cpp/ext/otel/key_value_iterable.h"
45 #include "src/cpp/ext/otel/otel_client_call_tracer.h"
46 #include "src/cpp/ext/otel/otel_server_call_tracer.h"
47 
48 namespace grpc {
49 namespace internal {
50 
OpenTelemetryMethodKey()51 absl::string_view OpenTelemetryMethodKey() { return "grpc.method"; }
52 
OpenTelemetryStatusKey()53 absl::string_view OpenTelemetryStatusKey() { return "grpc.status"; }
54 
OpenTelemetryTargetKey()55 absl::string_view OpenTelemetryTargetKey() { return "grpc.target"; }
56 
57 namespace {
BaseMetrics()58 absl::flat_hash_set<std::string> BaseMetrics() {
59   absl::flat_hash_set<std::string> base_metrics{
60       std::string(grpc::OpenTelemetryPluginBuilder::
61                       kClientAttemptStartedInstrumentName),
62       std::string(grpc::OpenTelemetryPluginBuilder::
63                       kClientAttemptDurationInstrumentName),
64       std::string(
65           grpc::OpenTelemetryPluginBuilder::
66               kClientAttemptSentTotalCompressedMessageSizeInstrumentName),
67       std::string(
68           grpc::OpenTelemetryPluginBuilder::
69               kClientAttemptRcvdTotalCompressedMessageSizeInstrumentName),
70       std::string(
71           grpc::OpenTelemetryPluginBuilder::kServerCallStartedInstrumentName),
72       std::string(
73           grpc::OpenTelemetryPluginBuilder::kServerCallDurationInstrumentName),
74       std::string(grpc::OpenTelemetryPluginBuilder::
75                       kServerCallSentTotalCompressedMessageSizeInstrumentName),
76       std::string(grpc::OpenTelemetryPluginBuilder::
77                       kServerCallRcvdTotalCompressedMessageSizeInstrumentName)};
78   grpc_core::GlobalInstrumentsRegistry::ForEach(
79       [&](const grpc_core::GlobalInstrumentsRegistry::
80               GlobalInstrumentDescriptor& descriptor) {
81         if (descriptor.enable_by_default) {
82           base_metrics.emplace(descriptor.name);
83         }
84       });
85   return base_metrics;
86 }
87 }  // namespace
88 
89 class OpenTelemetryPlugin::NPCMetricsKeyValueIterable
90     : public opentelemetry::common::KeyValueIterable {
91  public:
NPCMetricsKeyValueIterable(absl::Span<const absl::string_view> label_keys,absl::Span<const absl::string_view> label_values,absl::Span<const absl::string_view> optional_label_keys,absl::Span<const absl::string_view> optional_label_values,const OptionalLabelsBitSet & optional_labels_bits)92   NPCMetricsKeyValueIterable(
93       absl::Span<const absl::string_view> label_keys,
94       absl::Span<const absl::string_view> label_values,
95       absl::Span<const absl::string_view> optional_label_keys,
96       absl::Span<const absl::string_view> optional_label_values,
97       const OptionalLabelsBitSet& optional_labels_bits)
98       : label_keys_(label_keys),
99         label_values_(label_values),
100         optional_label_keys_(optional_label_keys),
101         optional_label_values_(optional_label_values),
102         optional_labels_bits_(optional_labels_bits) {}
103 
ForEachKeyValue(opentelemetry::nostd::function_ref<bool (opentelemetry::nostd::string_view,opentelemetry::common::AttributeValue)> callback) const104   bool ForEachKeyValue(opentelemetry::nostd::function_ref<
105                        bool(opentelemetry::nostd::string_view,
106                             opentelemetry::common::AttributeValue)>
107                            callback) const noexcept override {
108     for (size_t i = 0; i < label_keys_.size(); i++) {
109       if (!callback(AbslStrViewToOpenTelemetryStrView(label_keys_[i]),
110                     AbslStrViewToOpenTelemetryStrView(label_values_[i]))) {
111         return false;
112       }
113     }
114     // Since we are saving the optional label values as std::string for callback
115     // gauges, we want to minimize memory usage by filtering out the disabled
116     // optional label values.
117     bool filtered = optional_label_values_.size() < optional_label_keys_.size();
118     for (size_t i = 0, j = 0; i < optional_label_keys_.size(); ++i) {
119       if (!optional_labels_bits_.test(i)) {
120         if (!filtered) ++j;
121         continue;
122       }
123       if (!callback(
124               AbslStrViewToOpenTelemetryStrView(optional_label_keys_[i]),
125               AbslStrViewToOpenTelemetryStrView(optional_label_values_[j++]))) {
126         return false;
127       }
128     }
129     return true;
130   }
131 
size() const132   size_t size() const noexcept override {
133     return label_keys_.size() + optional_labels_bits_.count();
134   }
135 
136  private:
137   absl::Span<const absl::string_view> label_keys_;
138   absl::Span<const absl::string_view> label_values_;
139   absl::Span<const absl::string_view> optional_label_keys_;
140   absl::Span<const absl::string_view> optional_label_values_;
141   const OptionalLabelsBitSet& optional_labels_bits_;
142 };
143 
144 //
145 // OpenTelemetryPluginBuilderImpl
146 //
147 
OpenTelemetryPluginBuilderImpl()148 OpenTelemetryPluginBuilderImpl::OpenTelemetryPluginBuilderImpl()
149     : metrics_(BaseMetrics()) {}
150 
151 OpenTelemetryPluginBuilderImpl::~OpenTelemetryPluginBuilderImpl() = default;
152 
153 OpenTelemetryPluginBuilderImpl&
SetMeterProvider(std::shared_ptr<opentelemetry::metrics::MeterProvider> meter_provider)154 OpenTelemetryPluginBuilderImpl::SetMeterProvider(
155     std::shared_ptr<opentelemetry::metrics::MeterProvider> meter_provider) {
156   meter_provider_ = std::move(meter_provider);
157   return *this;
158 }
159 
EnableMetrics(absl::Span<const absl::string_view> metric_names)160 OpenTelemetryPluginBuilderImpl& OpenTelemetryPluginBuilderImpl::EnableMetrics(
161     absl::Span<const absl::string_view> metric_names) {
162   for (const auto& metric_name : metric_names) {
163     metrics_.emplace(metric_name);
164   }
165   return *this;
166 }
167 
DisableMetrics(absl::Span<const absl::string_view> metric_names)168 OpenTelemetryPluginBuilderImpl& OpenTelemetryPluginBuilderImpl::DisableMetrics(
169     absl::Span<const absl::string_view> metric_names) {
170   for (const auto& metric_name : metric_names) {
171     metrics_.erase(metric_name);
172   }
173   return *this;
174 }
175 
176 OpenTelemetryPluginBuilderImpl&
DisableAllMetrics()177 OpenTelemetryPluginBuilderImpl::DisableAllMetrics() {
178   metrics_.clear();
179   return *this;
180 }
181 
182 OpenTelemetryPluginBuilderImpl&
SetTargetAttributeFilter(absl::AnyInvocable<bool (absl::string_view)const> target_attribute_filter)183 OpenTelemetryPluginBuilderImpl::SetTargetAttributeFilter(
184     absl::AnyInvocable<bool(absl::string_view /*target*/) const>
185         target_attribute_filter) {
186   target_attribute_filter_ = std::move(target_attribute_filter);
187   return *this;
188 }
189 
190 OpenTelemetryPluginBuilderImpl&
SetGenericMethodAttributeFilter(absl::AnyInvocable<bool (absl::string_view)const> generic_method_attribute_filter)191 OpenTelemetryPluginBuilderImpl::SetGenericMethodAttributeFilter(
192     absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>
193         generic_method_attribute_filter) {
194   generic_method_attribute_filter_ = std::move(generic_method_attribute_filter);
195   return *this;
196 }
197 
198 OpenTelemetryPluginBuilderImpl&
SetServerSelector(absl::AnyInvocable<bool (const grpc_core::ChannelArgs &)const> server_selector)199 OpenTelemetryPluginBuilderImpl::SetServerSelector(
200     absl::AnyInvocable<bool(const grpc_core::ChannelArgs& /*args*/) const>
201         server_selector) {
202   server_selector_ = std::move(server_selector);
203   return *this;
204 }
205 
AddPluginOption(std::unique_ptr<InternalOpenTelemetryPluginOption> option)206 OpenTelemetryPluginBuilderImpl& OpenTelemetryPluginBuilderImpl::AddPluginOption(
207     std::unique_ptr<InternalOpenTelemetryPluginOption> option) {
208   // We allow a limit of 64 plugin options to be registered at this time.
209   GPR_ASSERT(plugin_options_.size() < 64);
210   plugin_options_.push_back(std::move(option));
211   return *this;
212 }
213 
214 OpenTelemetryPluginBuilderImpl&
AddOptionalLabel(absl::string_view optional_label_key)215 OpenTelemetryPluginBuilderImpl::AddOptionalLabel(
216     absl::string_view optional_label_key) {
217   optional_label_keys_.emplace(optional_label_key);
218   return *this;
219 }
220 
221 OpenTelemetryPluginBuilderImpl&
SetChannelScopeFilter(absl::AnyInvocable<bool (const OpenTelemetryPluginBuilder::ChannelScope &)const> channel_scope_filter)222 OpenTelemetryPluginBuilderImpl::SetChannelScopeFilter(
223     absl::AnyInvocable<
224         bool(const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) const>
225         channel_scope_filter) {
226   channel_scope_filter_ = std::move(channel_scope_filter);
227   return *this;
228 }
229 
BuildAndRegisterGlobal()230 absl::Status OpenTelemetryPluginBuilderImpl::BuildAndRegisterGlobal() {
231   if (meter_provider_ == nullptr) {
232     return absl::OkStatus();
233   }
234   grpc_core::GlobalStatsPluginRegistry::RegisterStatsPlugin(
235       std::make_shared<OpenTelemetryPlugin>(
236           metrics_, meter_provider_, std::move(target_attribute_filter_),
237           std::move(generic_method_attribute_filter_),
238           std::move(server_selector_), std::move(plugin_options_),
239           std::move(optional_label_keys_), std::move(channel_scope_filter_)));
240   return absl::OkStatus();
241 }
242 
CallbackMetricReporter(OpenTelemetryPlugin * ot_plugin,grpc_core::RegisteredMetricCallback * key)243 OpenTelemetryPlugin::CallbackMetricReporter::CallbackMetricReporter(
244     OpenTelemetryPlugin* ot_plugin, grpc_core::RegisteredMetricCallback* key)
245     : ot_plugin_(ot_plugin), key_(key) {
246   // Since we are updating the timestamp and updating the cache for all
247   // registered instruments in a RegisteredMetricCallback, we will need to
248   // clear all the cache cells for this RegisteredMetricCallback first, so
249   // that if a particular combination of labels was previously present but
250   // is no longer present, we won't continue to report it.
251   for (const auto& handle : key->metrics()) {
252     grpc_core::Match(
253         handle,
254         [&](const grpc_core::GlobalInstrumentsRegistry::
255                 GlobalCallbackInt64GaugeHandle& handle) {
256           auto& callback_gauge_state =
257               absl::get<std::unique_ptr<CallbackGaugeState<int64_t>>>(
258                   ot_plugin_->instruments_data_.at(handle.index).instrument);
259           callback_gauge_state->caches[key].clear();
260         },
261         [&](const grpc_core::GlobalInstrumentsRegistry::
262                 GlobalCallbackDoubleGaugeHandle& handle) {
263           auto& callback_gauge_state =
264               absl::get<std::unique_ptr<CallbackGaugeState<double>>>(
265                   ot_plugin_->instruments_data_.at(handle.index).instrument);
266           callback_gauge_state->caches[key].clear();
267         });
268   }
269 }
270 
Report(grpc_core::GlobalInstrumentsRegistry::GlobalCallbackInt64GaugeHandle handle,int64_t value,absl::Span<const absl::string_view> label_values,absl::Span<const absl::string_view> optional_values)271 void OpenTelemetryPlugin::CallbackMetricReporter::Report(
272     grpc_core::GlobalInstrumentsRegistry::GlobalCallbackInt64GaugeHandle handle,
273     int64_t value, absl::Span<const absl::string_view> label_values,
274     absl::Span<const absl::string_view> optional_values) {
275   const auto& instrument_data = ot_plugin_->instruments_data_.at(handle.index);
276   auto* callback_gauge_state =
277       absl::get_if<std::unique_ptr<CallbackGaugeState<int64_t>>>(
278           &instrument_data.instrument);
279   GPR_ASSERT(callback_gauge_state != nullptr);
280   const auto& descriptor =
281       grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle);
282   GPR_ASSERT(descriptor.label_keys.size() == label_values.size());
283   GPR_ASSERT(descriptor.optional_label_keys.size() == optional_values.size());
284   auto& cell = (*callback_gauge_state)->caches.at(key_);
285   std::vector<std::string> key;
286   key.reserve(label_values.size() +
287               instrument_data.optional_labels_bits.count());
288   for (const absl::string_view value : label_values) {
289     key.emplace_back(value);
290   }
291   for (size_t i = 0; i < optional_values.size(); ++i) {
292     if (instrument_data.optional_labels_bits.test(i)) {
293       key.emplace_back(optional_values[i]);
294     }
295   }
296   cell.insert_or_assign(std::move(key), value);
297 }
298 
Report(grpc_core::GlobalInstrumentsRegistry::GlobalCallbackDoubleGaugeHandle handle,double value,absl::Span<const absl::string_view> label_values,absl::Span<const absl::string_view> optional_values)299 void OpenTelemetryPlugin::CallbackMetricReporter::Report(
300     grpc_core::GlobalInstrumentsRegistry::GlobalCallbackDoubleGaugeHandle
301         handle,
302     double value, absl::Span<const absl::string_view> label_values,
303     absl::Span<const absl::string_view> optional_values) {
304   const auto& instrument_data = ot_plugin_->instruments_data_.at(handle.index);
305   auto* callback_gauge_state =
306       absl::get_if<std::unique_ptr<CallbackGaugeState<double>>>(
307           &instrument_data.instrument);
308   GPR_ASSERT(callback_gauge_state != nullptr);
309   const auto& descriptor =
310       grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle);
311   GPR_ASSERT(descriptor.label_keys.size() == label_values.size());
312   GPR_ASSERT(descriptor.optional_label_keys.size() == optional_values.size());
313   auto& cell = (*callback_gauge_state)->caches.at(key_);
314   std::vector<std::string> key;
315   key.reserve(label_values.size() +
316               instrument_data.optional_labels_bits.count());
317   for (const absl::string_view value : label_values) {
318     key.emplace_back(value);
319   }
320   for (size_t i = 0; i < optional_values.size(); ++i) {
321     if (instrument_data.optional_labels_bits.test(i)) {
322       key.emplace_back(optional_values[i]);
323     }
324   }
325   cell.insert_or_assign(std::move(key), value);
326 }
327 
OpenTelemetryPlugin(const absl::flat_hash_set<std::string> & metrics,opentelemetry::nostd::shared_ptr<opentelemetry::metrics::MeterProvider> meter_provider,absl::AnyInvocable<bool (absl::string_view)const> target_attribute_filter,absl::AnyInvocable<bool (absl::string_view)const> generic_method_attribute_filter,absl::AnyInvocable<bool (const grpc_core::ChannelArgs &)const> server_selector,std::vector<std::unique_ptr<InternalOpenTelemetryPluginOption>> plugin_options,const std::set<absl::string_view> & optional_label_keys,absl::AnyInvocable<bool (const OpenTelemetryPluginBuilder::ChannelScope &)const> channel_scope_filter)328 OpenTelemetryPlugin::OpenTelemetryPlugin(
329     const absl::flat_hash_set<std::string>& metrics,
330     opentelemetry::nostd::shared_ptr<opentelemetry::metrics::MeterProvider>
331         meter_provider,
332     absl::AnyInvocable<bool(absl::string_view /*target*/) const>
333         target_attribute_filter,
334     absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>
335         generic_method_attribute_filter,
336     absl::AnyInvocable<bool(const grpc_core::ChannelArgs& /*args*/) const>
337         server_selector,
338     std::vector<std::unique_ptr<InternalOpenTelemetryPluginOption>>
339         plugin_options,
340     const std::set<absl::string_view>& optional_label_keys,
341     absl::AnyInvocable<
342         bool(const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) const>
343         channel_scope_filter)
344     : meter_provider_(std::move(meter_provider)),
345       server_selector_(std::move(server_selector)),
346       target_attribute_filter_(std::move(target_attribute_filter)),
347       generic_method_attribute_filter_(
348           std::move(generic_method_attribute_filter)),
349       plugin_options_(std::move(plugin_options)),
350       channel_scope_filter_(std::move(channel_scope_filter)) {
351   auto meter = meter_provider_->GetMeter("grpc-c++", GRPC_CPP_VERSION_STRING);
352   // Per-call metrics.
353   if (metrics.contains(grpc::OpenTelemetryPluginBuilder::
354                            kClientAttemptStartedInstrumentName)) {
355     client_.attempt.started = meter->CreateUInt64Counter(
356         std::string(grpc::OpenTelemetryPluginBuilder::
357                         kClientAttemptStartedInstrumentName),
358         "Number of client call attempts started", "{attempt}");
359   }
360   if (metrics.contains(grpc::OpenTelemetryPluginBuilder::
361                            kClientAttemptDurationInstrumentName)) {
362     client_.attempt.duration = meter->CreateDoubleHistogram(
363         std::string(grpc::OpenTelemetryPluginBuilder::
364                         kClientAttemptDurationInstrumentName),
365         "End-to-end time taken to complete a client call attempt", "s");
366   }
367   if (metrics.contains(
368           grpc::OpenTelemetryPluginBuilder::
369               kClientAttemptSentTotalCompressedMessageSizeInstrumentName)) {
370     client_.attempt.sent_total_compressed_message_size =
371         meter->CreateUInt64Histogram(
372             std::string(
373                 grpc::OpenTelemetryPluginBuilder::
374                     kClientAttemptSentTotalCompressedMessageSizeInstrumentName),
375             "Compressed message bytes sent per client call attempt", "By");
376   }
377   if (metrics.contains(
378           grpc::OpenTelemetryPluginBuilder::
379               kClientAttemptRcvdTotalCompressedMessageSizeInstrumentName)) {
380     client_.attempt.rcvd_total_compressed_message_size =
381         meter->CreateUInt64Histogram(
382             std::string(
383                 grpc::OpenTelemetryPluginBuilder::
384                     kClientAttemptRcvdTotalCompressedMessageSizeInstrumentName),
385             "Compressed message bytes received per call attempt", "By");
386   }
387   if (metrics.contains(
388           grpc::OpenTelemetryPluginBuilder::kServerCallStartedInstrumentName)) {
389     server_.call.started = meter->CreateUInt64Counter(
390         std::string(
391             grpc::OpenTelemetryPluginBuilder::kServerCallStartedInstrumentName),
392         "Number of server calls started", "{call}");
393   }
394   if (metrics.contains(grpc::OpenTelemetryPluginBuilder::
395                            kServerCallDurationInstrumentName)) {
396     server_.call.duration = meter->CreateDoubleHistogram(
397         std::string(grpc::OpenTelemetryPluginBuilder::
398                         kServerCallDurationInstrumentName),
399         "End-to-end time taken to complete a call from server transport's "
400         "perspective",
401         "s");
402   }
403   if (metrics.contains(
404           grpc::OpenTelemetryPluginBuilder::
405               kServerCallSentTotalCompressedMessageSizeInstrumentName)) {
406     server_.call.sent_total_compressed_message_size =
407         meter->CreateUInt64Histogram(
408             std::string(
409                 grpc::OpenTelemetryPluginBuilder::
410                     kServerCallSentTotalCompressedMessageSizeInstrumentName),
411             "Compressed message bytes sent per server call", "By");
412   }
413   if (metrics.contains(
414           grpc::OpenTelemetryPluginBuilder::
415               kServerCallRcvdTotalCompressedMessageSizeInstrumentName)) {
416     server_.call.rcvd_total_compressed_message_size =
417         meter->CreateUInt64Histogram(
418             std::string(
419                 grpc::OpenTelemetryPluginBuilder::
420                     kServerCallRcvdTotalCompressedMessageSizeInstrumentName),
421             "Compressed message bytes received per server call", "By");
422   }
423   // Store optional label keys for per call metrics
424   GPR_ASSERT(static_cast<size_t>(
425                  grpc_core::ClientCallTracer::CallAttemptTracer::
426                      OptionalLabelKey::kSize) <= kOptionalLabelsSizeLimit);
427   for (const auto& key : optional_label_keys) {
428     auto optional_key = OptionalLabelStringToKey(key);
429     if (optional_key.has_value()) {
430       per_call_optional_label_bits_.set(
431           static_cast<size_t>(optional_key.value()));
432     }
433   }
434   // Non-per-call metrics.
435   grpc_core::GlobalInstrumentsRegistry::ForEach(
436       [&, this](const grpc_core::GlobalInstrumentsRegistry::
437                     GlobalInstrumentDescriptor& descriptor) {
438         GPR_ASSERT(descriptor.optional_label_keys.size() <=
439                    kOptionalLabelsSizeLimit);
440         if (instruments_data_.size() < descriptor.index + 1) {
441           instruments_data_.resize(descriptor.index + 1);
442         }
443         if (!metrics.contains(descriptor.name)) {
444           return;
445         }
446         switch (descriptor.instrument_type) {
447           case grpc_core::GlobalInstrumentsRegistry::InstrumentType::kCounter:
448             switch (descriptor.value_type) {
449               case grpc_core::GlobalInstrumentsRegistry::ValueType::kUInt64:
450                 instruments_data_[descriptor.index].instrument =
451                     meter->CreateUInt64Counter(
452                         std::string(descriptor.name),
453                         std::string(descriptor.description),
454                         std::string(descriptor.unit));
455                 break;
456               case grpc_core::GlobalInstrumentsRegistry::ValueType::kDouble:
457                 instruments_data_[descriptor.index].instrument =
458                     meter->CreateDoubleCounter(
459                         std::string(descriptor.name),
460                         std::string(descriptor.description),
461                         std::string(descriptor.unit));
462                 break;
463               default:
464                 grpc_core::Crash(
465                     absl::StrFormat("Unknown or unsupported value type: %d",
466                                     descriptor.value_type));
467             }
468             break;
469           case grpc_core::GlobalInstrumentsRegistry::InstrumentType::kHistogram:
470             switch (descriptor.value_type) {
471               case grpc_core::GlobalInstrumentsRegistry::ValueType::kUInt64:
472                 instruments_data_[descriptor.index].instrument =
473                     meter->CreateUInt64Histogram(
474                         std::string(descriptor.name),
475                         std::string(descriptor.description),
476                         std::string(descriptor.unit));
477                 break;
478               case grpc_core::GlobalInstrumentsRegistry::ValueType::kDouble:
479                 instruments_data_[descriptor.index].instrument =
480                     meter->CreateDoubleHistogram(
481                         std::string(descriptor.name),
482                         std::string(descriptor.description),
483                         std::string(descriptor.unit));
484                 break;
485               default:
486                 grpc_core::Crash(
487                     absl::StrFormat("Unknown or unsupported value type: %d",
488                                     descriptor.value_type));
489             }
490             break;
491           case grpc_core::GlobalInstrumentsRegistry::InstrumentType::kGauge:
492             grpc_core::Crash(
493                 "Non-callback gauge is not supported and will be deleted in "
494                 "the future.");
495             break;
496           case grpc_core::GlobalInstrumentsRegistry::InstrumentType::
497               kCallbackGauge:
498             switch (descriptor.value_type) {
499               case grpc_core::GlobalInstrumentsRegistry::ValueType::kInt64: {
500                 auto observable_state =
501                     std::make_unique<CallbackGaugeState<int64_t>>();
502                 observable_state->id = descriptor.index;
503                 observable_state->ot_plugin = this;
504                 observable_state->instrument =
505                     meter->CreateInt64ObservableGauge(
506                         std::string(descriptor.name),
507                         std::string(descriptor.description),
508                         std::string(descriptor.unit));
509                 instruments_data_[descriptor.index].instrument =
510                     std::move(observable_state);
511                 break;
512               }
513               case grpc_core::GlobalInstrumentsRegistry::ValueType::kDouble: {
514                 auto observable_state =
515                     std::make_unique<CallbackGaugeState<double>>();
516                 observable_state->id = descriptor.index;
517                 observable_state->ot_plugin = this;
518                 observable_state->instrument =
519                     meter->CreateDoubleObservableGauge(
520                         std::string(descriptor.name),
521                         std::string(descriptor.description),
522                         std::string(descriptor.unit));
523                 instruments_data_[descriptor.index].instrument =
524                     std::move(observable_state);
525                 break;
526               }
527               default:
528                 grpc_core::Crash(
529                     absl::StrFormat("Unknown or unsupported value type: %d",
530                                     descriptor.value_type));
531             }
532             break;
533           default:
534             grpc_core::Crash(absl::StrFormat("Unknown instrument_type: %d",
535                                              descriptor.instrument_type));
536         }
537         for (size_t i = 0; i < descriptor.optional_label_keys.size(); ++i) {
538           if (optional_label_keys.find(descriptor.optional_label_keys[i]) !=
539               optional_label_keys.end()) {
540             instruments_data_[descriptor.index].optional_labels_bits.set(i);
541           }
542         }
543       });
544 }
545 
546 namespace {
547 constexpr absl::string_view kLocality = "grpc.lb.locality";
548 }
549 
OptionalLabelKeyToString(grpc_core::ClientCallTracer::CallAttemptTracer::OptionalLabelKey key)550 absl::string_view OpenTelemetryPlugin::OptionalLabelKeyToString(
551     grpc_core::ClientCallTracer::CallAttemptTracer::OptionalLabelKey key) {
552   switch (key) {
553     case grpc_core::ClientCallTracer::CallAttemptTracer::OptionalLabelKey::
554         kLocality:
555       return kLocality;
556     default:
557       grpc_core::Crash("Illegal OptionalLabelKey index");
558   }
559 }
560 
561 absl::optional<grpc_core::ClientCallTracer::CallAttemptTracer::OptionalLabelKey>
OptionalLabelStringToKey(absl::string_view key)562 OpenTelemetryPlugin::OptionalLabelStringToKey(absl::string_view key) {
563   if (key == kLocality) {
564     return grpc_core::ClientCallTracer::CallAttemptTracer::OptionalLabelKey::
565         kLocality;
566   }
567   return absl::nullopt;
568 }
569 
570 std::pair<bool, std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig>>
IsEnabledForChannel(const OpenTelemetryPluginBuilder::ChannelScope & scope) const571 OpenTelemetryPlugin::IsEnabledForChannel(
572     const OpenTelemetryPluginBuilder::ChannelScope& scope) const {
573   if (channel_scope_filter_ == nullptr || channel_scope_filter_(scope)) {
574     return {true, std::make_shared<ClientScopeConfig>(this, scope)};
575   }
576   return {false, nullptr};
577 }
578 
579 std::pair<bool, std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig>>
IsEnabledForServer(const grpc_core::ChannelArgs & args) const580 OpenTelemetryPlugin::IsEnabledForServer(
581     const grpc_core::ChannelArgs& args) const {
582   // Return true only if there is no server selector registered or if the server
583   // selector returns true.
584   if (server_selector_ == nullptr || server_selector_(args)) {
585     return {true, std::make_shared<ServerScopeConfig>(this, args)};
586   }
587   return {false, nullptr};
588 }
589 
AddCounter(grpc_core::GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle,uint64_t value,absl::Span<const absl::string_view> label_values,absl::Span<const absl::string_view> optional_values)590 void OpenTelemetryPlugin::AddCounter(
591     grpc_core::GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle,
592     uint64_t value, absl::Span<const absl::string_view> label_values,
593     absl::Span<const absl::string_view> optional_values) {
594   const auto& instrument_data = instruments_data_.at(handle.index);
595   if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
596     // This instrument is disabled.
597     return;
598   }
599   GPR_ASSERT(absl::holds_alternative<
600              std::unique_ptr<opentelemetry::metrics::Counter<uint64_t>>>(
601       instrument_data.instrument));
602   const auto& descriptor =
603       grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle);
604   GPR_ASSERT(descriptor.label_keys.size() == label_values.size());
605   GPR_ASSERT(descriptor.optional_label_keys.size() == optional_values.size());
606   absl::get<std::unique_ptr<opentelemetry::metrics::Counter<uint64_t>>>(
607       instrument_data.instrument)
608       ->Add(value, NPCMetricsKeyValueIterable(
609                        descriptor.label_keys, label_values,
610                        descriptor.optional_label_keys, optional_values,
611                        instrument_data.optional_labels_bits));
612 }
613 
AddCounter(grpc_core::GlobalInstrumentsRegistry::GlobalDoubleCounterHandle handle,double value,absl::Span<const absl::string_view> label_values,absl::Span<const absl::string_view> optional_values)614 void OpenTelemetryPlugin::AddCounter(
615     grpc_core::GlobalInstrumentsRegistry::GlobalDoubleCounterHandle handle,
616     double value, absl::Span<const absl::string_view> label_values,
617     absl::Span<const absl::string_view> optional_values) {
618   const auto& instrument_data = instruments_data_.at(handle.index);
619   if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
620     // This instrument is disabled.
621     return;
622   }
623   GPR_ASSERT(absl::holds_alternative<
624              std::unique_ptr<opentelemetry::metrics::Counter<double>>>(
625       instrument_data.instrument));
626   const auto& descriptor =
627       grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle);
628   GPR_ASSERT(descriptor.label_keys.size() == label_values.size());
629   GPR_ASSERT(descriptor.optional_label_keys.size() == optional_values.size());
630   absl::get<std::unique_ptr<opentelemetry::metrics::Counter<double>>>(
631       instrument_data.instrument)
632       ->Add(value, NPCMetricsKeyValueIterable(
633                        descriptor.label_keys, label_values,
634                        descriptor.optional_label_keys, optional_values,
635                        instrument_data.optional_labels_bits));
636 }
637 
RecordHistogram(grpc_core::GlobalInstrumentsRegistry::GlobalUInt64HistogramHandle handle,uint64_t value,absl::Span<const absl::string_view> label_values,absl::Span<const absl::string_view> optional_values)638 void OpenTelemetryPlugin::RecordHistogram(
639     grpc_core::GlobalInstrumentsRegistry::GlobalUInt64HistogramHandle handle,
640     uint64_t value, absl::Span<const absl::string_view> label_values,
641     absl::Span<const absl::string_view> optional_values) {
642   const auto& instrument_data = instruments_data_.at(handle.index);
643   if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
644     // This instrument is disabled.
645     return;
646   }
647   GPR_ASSERT(absl::holds_alternative<
648              std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>>(
649       instrument_data.instrument));
650   const auto& descriptor =
651       grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle);
652   GPR_ASSERT(descriptor.label_keys.size() == label_values.size());
653   GPR_ASSERT(descriptor.optional_label_keys.size() == optional_values.size());
654   absl::get<std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>>(
655       instrument_data.instrument)
656       ->Record(value,
657                NPCMetricsKeyValueIterable(descriptor.label_keys, label_values,
658                                           descriptor.optional_label_keys,
659                                           optional_values,
660                                           instrument_data.optional_labels_bits),
661                opentelemetry::context::Context{});
662 }
663 
RecordHistogram(grpc_core::GlobalInstrumentsRegistry::GlobalDoubleHistogramHandle handle,double value,absl::Span<const absl::string_view> label_values,absl::Span<const absl::string_view> optional_values)664 void OpenTelemetryPlugin::RecordHistogram(
665     grpc_core::GlobalInstrumentsRegistry::GlobalDoubleHistogramHandle handle,
666     double value, absl::Span<const absl::string_view> label_values,
667     absl::Span<const absl::string_view> optional_values) {
668   const auto& instrument_data = instruments_data_.at(handle.index);
669   if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
670     // This instrument is disabled.
671     return;
672   }
673   GPR_ASSERT(absl::holds_alternative<
674              std::unique_ptr<opentelemetry::metrics::Histogram<double>>>(
675       instrument_data.instrument));
676   const auto& descriptor =
677       grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle);
678   GPR_ASSERT(descriptor.label_keys.size() == label_values.size());
679   GPR_ASSERT(descriptor.optional_label_keys.size() == optional_values.size());
680   absl::get<std::unique_ptr<opentelemetry::metrics::Histogram<double>>>(
681       instrument_data.instrument)
682       ->Record(value,
683                NPCMetricsKeyValueIterable(descriptor.label_keys, label_values,
684                                           descriptor.optional_label_keys,
685                                           optional_values,
686                                           instrument_data.optional_labels_bits),
687                opentelemetry::context::Context{});
688 }
689 
AddCallback(grpc_core::RegisteredMetricCallback * callback)690 void OpenTelemetryPlugin::AddCallback(
691     grpc_core::RegisteredMetricCallback* callback) {
692   std::vector<
693       absl::variant<CallbackGaugeState<int64_t>*, CallbackGaugeState<double>*>>
694       gauges_that_need_to_add_callback;
695   {
696     grpc_core::MutexLock lock(&mu_);
697     callback_timestamps_.emplace(callback, grpc_core::Timestamp::InfPast());
698     for (const auto& handle : callback->metrics()) {
699       grpc_core::Match(
700           handle,
701           [&](const grpc_core::GlobalInstrumentsRegistry::
702                   GlobalCallbackInt64GaugeHandle& handle) {
703             const auto& instrument_data = instruments_data_.at(handle.index);
704             if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
705               // This instrument is disabled.
706               return;
707             }
708             auto* callback_gauge_state =
709                 absl::get_if<std::unique_ptr<CallbackGaugeState<int64_t>>>(
710                     &instrument_data.instrument);
711             GPR_ASSERT(callback_gauge_state != nullptr);
712             (*callback_gauge_state)
713                 ->caches.emplace(callback,
714                                  CallbackGaugeState<int64_t>::Cache{});
715             if (!std::exchange((*callback_gauge_state)->ot_callback_registered,
716                                true)) {
717               gauges_that_need_to_add_callback.push_back(
718                   callback_gauge_state->get());
719             }
720           },
721           [&](const grpc_core::GlobalInstrumentsRegistry::
722                   GlobalCallbackDoubleGaugeHandle& handle) {
723             const auto& instrument_data = instruments_data_.at(handle.index);
724             if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
725               // This instrument is disabled.
726               return;
727             }
728             auto* callback_gauge_state =
729                 absl::get_if<std::unique_ptr<CallbackGaugeState<double>>>(
730                     &instrument_data.instrument);
731             GPR_ASSERT(callback_gauge_state != nullptr);
732             (*callback_gauge_state)
733                 ->caches.emplace(callback, CallbackGaugeState<double>::Cache{});
734             if (!std::exchange((*callback_gauge_state)->ot_callback_registered,
735                                true)) {
736               gauges_that_need_to_add_callback.push_back(
737                   callback_gauge_state->get());
738             }
739           });
740     }
741   }
742   // AddCallback internally grabs OpenTelemetry's observable_registry's lock. So
743   // we need to call it without our plugin lock otherwise we may deadlock.
744   for (const auto& gauge : gauges_that_need_to_add_callback) {
745     grpc_core::Match(
746         gauge,
747         [](CallbackGaugeState<int64_t>* gauge) {
748           gauge->instrument->AddCallback(
749               &CallbackGaugeState<int64_t>::CallbackGaugeCallback, gauge);
750         },
751         [](CallbackGaugeState<double>* gauge) {
752           gauge->instrument->AddCallback(
753               &CallbackGaugeState<double>::CallbackGaugeCallback, gauge);
754         });
755   }
756 }
757 
RemoveCallback(grpc_core::RegisteredMetricCallback * callback)758 void OpenTelemetryPlugin::RemoveCallback(
759     grpc_core::RegisteredMetricCallback* callback) {
760   std::vector<
761       absl::variant<CallbackGaugeState<int64_t>*, CallbackGaugeState<double>*>>
762       gauges_that_need_to_remove_callback;
763   {
764     grpc_core::MutexLock lock(&mu_);
765     callback_timestamps_.erase(callback);
766     for (const auto& handle : callback->metrics()) {
767       grpc_core::Match(
768           handle,
769           [&](const grpc_core::GlobalInstrumentsRegistry::
770                   GlobalCallbackInt64GaugeHandle& handle) {
771             const auto& instrument_data = instruments_data_.at(handle.index);
772             if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
773               // This instrument is disabled.
774               return;
775             }
776             auto* callback_gauge_state =
777                 absl::get_if<std::unique_ptr<CallbackGaugeState<int64_t>>>(
778                     &instrument_data.instrument);
779             GPR_ASSERT(callback_gauge_state != nullptr);
780             GPR_ASSERT((*callback_gauge_state)->ot_callback_registered);
781             GPR_ASSERT((*callback_gauge_state)->caches.erase(callback) == 1);
782             if ((*callback_gauge_state)->caches.empty()) {
783               gauges_that_need_to_remove_callback.push_back(
784                   callback_gauge_state->get());
785               (*callback_gauge_state)->ot_callback_registered = false;
786             }
787           },
788           [&](const grpc_core::GlobalInstrumentsRegistry::
789                   GlobalCallbackDoubleGaugeHandle& handle) {
790             const auto& instrument_data = instruments_data_.at(handle.index);
791             if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
792               // This instrument is disabled.
793               return;
794             }
795             auto* callback_gauge_state =
796                 absl::get_if<std::unique_ptr<CallbackGaugeState<double>>>(
797                     &instrument_data.instrument);
798             GPR_ASSERT(callback_gauge_state != nullptr);
799             GPR_ASSERT((*callback_gauge_state)->ot_callback_registered);
800             GPR_ASSERT((*callback_gauge_state)->caches.erase(callback) == 1);
801             if ((*callback_gauge_state)->caches.empty()) {
802               gauges_that_need_to_remove_callback.push_back(
803                   callback_gauge_state->get());
804               (*callback_gauge_state)->ot_callback_registered = false;
805             }
806           });
807     }
808   }
809   // RemoveCallback internally grabs OpenTelemetry's observable_registry's lock.
810   // So we need to call it without our plugin lock otherwise we may deadlock.
811   for (const auto& gauge : gauges_that_need_to_remove_callback) {
812     grpc_core::Match(
813         gauge,
814         [](CallbackGaugeState<int64_t>* gauge) {
815           gauge->instrument->RemoveCallback(
816               &CallbackGaugeState<int64_t>::CallbackGaugeCallback, gauge);
817         },
818         [](CallbackGaugeState<double>* gauge) {
819           gauge->instrument->RemoveCallback(
820               &CallbackGaugeState<double>::CallbackGaugeCallback, gauge);
821         });
822   }
823 }
824 
825 template <typename ValueType>
Observe(opentelemetry::metrics::ObserverResult & result,const Cache & cache)826 void OpenTelemetryPlugin::CallbackGaugeState<ValueType>::Observe(
827     opentelemetry::metrics::ObserverResult& result, const Cache& cache) {
828   const auto& descriptor =
829       grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor({id});
830   for (const auto& pair : cache) {
831     GPR_ASSERT(pair.first.size() <= (descriptor.label_keys.size() +
832                                      descriptor.optional_label_keys.size()));
833     auto& instrument_data = ot_plugin->instruments_data_.at(id);
834     opentelemetry::nostd::get<opentelemetry::nostd::shared_ptr<
835         opentelemetry::metrics::ObserverResultT<ValueType>>>(result)
836         ->Observe(pair.second,
837                   NPCMetricsKeyValueIterable(
838                       descriptor.label_keys,
839                       absl::FixedArray<absl::string_view>(
840                           pair.first.begin(),
841                           pair.first.begin() + descriptor.label_keys.size()),
842                       descriptor.optional_label_keys,
843                       absl::FixedArray<absl::string_view>(
844                           pair.first.begin() + descriptor.label_keys.size(),
845                           pair.first.end()),
846                       instrument_data.optional_labels_bits));
847   }
848 }
849 
850 // OpenTelemetry calls our callback with its observable_registry's lock held.
851 template <typename ValueType>
CallbackGaugeCallback(opentelemetry::metrics::ObserverResult result,void * arg)852 void OpenTelemetryPlugin::CallbackGaugeState<ValueType>::CallbackGaugeCallback(
853     opentelemetry::metrics::ObserverResult result, void* arg) {
854   auto* callback_gauge_state = static_cast<CallbackGaugeState<ValueType>*>(arg);
855   auto now = grpc_core::Timestamp::Now();
856   grpc_core::MutexLock plugin_lock(&callback_gauge_state->ot_plugin->mu_);
857   for (auto& elem : callback_gauge_state->caches) {
858     auto* registered_metric_callback = elem.first;
859     auto iter = callback_gauge_state->ot_plugin->callback_timestamps_.find(
860         registered_metric_callback);
861     GPR_ASSERT(iter !=
862                callback_gauge_state->ot_plugin->callback_timestamps_.end());
863     if (now - iter->second < registered_metric_callback->min_interval()) {
864       // Use cached value.
865       callback_gauge_state->Observe(result, elem.second);
866       continue;
867     }
868     // Otherwise update and use the cache.
869     iter->second = now;
870     CallbackMetricReporter reporter(callback_gauge_state->ot_plugin,
871                                     registered_metric_callback);
872     registered_metric_callback->Run(reporter);
873     callback_gauge_state->Observe(result, elem.second);
874   }
875 }
876 
GetClientCallTracer(const grpc_core::Slice & path,bool registered_method,std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig> scope_config)877 grpc_core::ClientCallTracer* OpenTelemetryPlugin::GetClientCallTracer(
878     const grpc_core::Slice& path, bool registered_method,
879     std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig> scope_config) {
880   return grpc_core::GetContext<grpc_core::Arena>()
881       ->ManagedNew<ClientCallTracer>(
882           path, grpc_core::GetContext<grpc_core::Arena>(), registered_method,
883           this,
884           std::static_pointer_cast<OpenTelemetryPlugin::ClientScopeConfig>(
885               scope_config));
886 }
887 
GetServerCallTracer(std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig> scope_config)888 grpc_core::ServerCallTracer* OpenTelemetryPlugin::GetServerCallTracer(
889     std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig> scope_config) {
890   return grpc_core::GetContext<grpc_core::Arena>()
891       ->ManagedNew<ServerCallTracer>(
892           this,
893           std::static_pointer_cast<OpenTelemetryPlugin::ServerScopeConfig>(
894               scope_config));
895 }
896 
897 }  // namespace internal
898 
899 constexpr absl::string_view
900     OpenTelemetryPluginBuilder::kClientAttemptStartedInstrumentName;
901 constexpr absl::string_view
902     OpenTelemetryPluginBuilder::kClientAttemptDurationInstrumentName;
903 constexpr absl::string_view OpenTelemetryPluginBuilder::
904     kClientAttemptSentTotalCompressedMessageSizeInstrumentName;
905 constexpr absl::string_view OpenTelemetryPluginBuilder::
906     kClientAttemptRcvdTotalCompressedMessageSizeInstrumentName;
907 constexpr absl::string_view
908     OpenTelemetryPluginBuilder::kServerCallStartedInstrumentName;
909 constexpr absl::string_view
910     OpenTelemetryPluginBuilder::kServerCallDurationInstrumentName;
911 constexpr absl::string_view OpenTelemetryPluginBuilder::
912     kServerCallSentTotalCompressedMessageSizeInstrumentName;
913 constexpr absl::string_view OpenTelemetryPluginBuilder::
914     kServerCallRcvdTotalCompressedMessageSizeInstrumentName;
915 
916 //
917 // OpenTelemetryPluginBuilder
918 //
919 
OpenTelemetryPluginBuilder()920 OpenTelemetryPluginBuilder::OpenTelemetryPluginBuilder()
921     : impl_(std::make_unique<internal::OpenTelemetryPluginBuilderImpl>()) {}
922 
923 OpenTelemetryPluginBuilder::~OpenTelemetryPluginBuilder() = default;
924 
SetMeterProvider(std::shared_ptr<opentelemetry::metrics::MeterProvider> meter_provider)925 OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::SetMeterProvider(
926     std::shared_ptr<opentelemetry::metrics::MeterProvider> meter_provider) {
927   impl_->SetMeterProvider(std::move(meter_provider));
928   return *this;
929 }
930 
931 OpenTelemetryPluginBuilder&
SetTargetAttributeFilter(absl::AnyInvocable<bool (absl::string_view)const> target_attribute_filter)932 OpenTelemetryPluginBuilder::SetTargetAttributeFilter(
933     absl::AnyInvocable<bool(absl::string_view /*target*/) const>
934         target_attribute_filter) {
935   impl_->SetTargetAttributeFilter(std::move(target_attribute_filter));
936   return *this;
937 }
938 
939 OpenTelemetryPluginBuilder&
SetGenericMethodAttributeFilter(absl::AnyInvocable<bool (absl::string_view)const> generic_method_attribute_filter)940 OpenTelemetryPluginBuilder::SetGenericMethodAttributeFilter(
941     absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>
942         generic_method_attribute_filter) {
943   impl_->SetGenericMethodAttributeFilter(
944       std::move(generic_method_attribute_filter));
945   return *this;
946 }
947 
EnableMetrics(absl::Span<const absl::string_view> metric_names)948 OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::EnableMetrics(
949     absl::Span<const absl::string_view> metric_names) {
950   impl_->EnableMetrics(metric_names);
951   return *this;
952 }
953 
DisableMetrics(absl::Span<const absl::string_view> metric_names)954 OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::DisableMetrics(
955     absl::Span<const absl::string_view> metric_names) {
956   impl_->DisableMetrics(metric_names);
957   return *this;
958 }
959 
DisableAllMetrics()960 OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::DisableAllMetrics() {
961   impl_->DisableAllMetrics();
962   return *this;
963 }
964 
AddPluginOption(std::unique_ptr<OpenTelemetryPluginOption> option)965 OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::AddPluginOption(
966     std::unique_ptr<OpenTelemetryPluginOption> option) {
967   impl_->AddPluginOption(
968       std::unique_ptr<grpc::internal::InternalOpenTelemetryPluginOption>(
969           static_cast<grpc::internal::InternalOpenTelemetryPluginOption*>(
970               option.release())));
971   return *this;
972 }
973 
AddOptionalLabel(absl::string_view optional_label_key)974 OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::AddOptionalLabel(
975     absl::string_view optional_label_key) {
976   impl_->AddOptionalLabel(optional_label_key);
977   return *this;
978 }
979 
SetChannelScopeFilter(absl::AnyInvocable<bool (const ChannelScope &)const> channel_scope_filter)980 OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::SetChannelScopeFilter(
981     absl::AnyInvocable<bool(const ChannelScope& /*scope*/) const>
982         channel_scope_filter) {
983   impl_->SetChannelScopeFilter(std::move(channel_scope_filter));
984   return *this;
985 }
986 
BuildAndRegisterGlobal()987 absl::Status OpenTelemetryPluginBuilder::BuildAndRegisterGlobal() {
988   return impl_->BuildAndRegisterGlobal();
989 }
990 
991 }  // namespace grpc
992