• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef GRPC_SRC_CPP_EXT_OTEL_OTEL_PLUGIN_H
20 #define GRPC_SRC_CPP_EXT_OTEL_OTEL_PLUGIN_H
21 
22 #include <grpc/support/port_platform.h>
23 #include <grpcpp/ext/otel_plugin.h>
24 #include <grpcpp/impl/server_builder_option.h>
25 #include <stddef.h>
26 #include <stdint.h>
27 
28 #include <bitset>
29 #include <memory>
30 #include <string>
31 #include <utility>
32 
33 #include "absl/container/flat_hash_map.h"
34 #include "absl/container/flat_hash_set.h"
35 #include "absl/functional/any_invocable.h"
36 #include "absl/strings/string_view.h"
37 #include "absl/types/optional.h"
38 #include "opentelemetry/metrics/async_instruments.h"
39 #include "opentelemetry/metrics/meter_provider.h"
40 #include "opentelemetry/metrics/observer_result.h"
41 #include "opentelemetry/metrics/sync_instruments.h"
42 #include "opentelemetry/nostd/shared_ptr.h"
43 #include "src/core/lib/channel/channel_args.h"
44 #include "src/core/lib/transport/metadata_batch.h"
45 #include "src/core/telemetry/metrics.h"
46 
47 namespace grpc {
48 namespace internal {
49 
50 // An iterable container interface that can be used as a return type for the
51 // OpenTelemetry plugin's label injector.
52 class LabelsIterable {
53  public:
54   virtual ~LabelsIterable() = default;
55 
56   // Returns the key-value label at the current position or absl::nullopt if the
57   // iterator has reached the end.
58   virtual absl::optional<std::pair<absl::string_view, absl::string_view>>
59   Next() = 0;
60 
61   virtual size_t Size() const = 0;
62 
63   // Resets position of iterator to the start.
64   virtual void ResetIteratorPosition() = 0;
65 };
66 
67 // An interface that allows you to add additional labels on the calls traced
68 // through the OpenTelemetry plugin.
69 class LabelsInjector {
70  public:
~LabelsInjector()71   virtual ~LabelsInjector() {}
72   // Read the incoming initial metadata to get the set of labels to be added to
73   // metrics.
74   virtual std::unique_ptr<LabelsIterable> GetLabels(
75       grpc_metadata_batch* incoming_initial_metadata) const = 0;
76 
77   // Modify the outgoing initial metadata with metadata information to be sent
78   // to the peer. On the server side, \a labels_from_incoming_metadata returned
79   // from `GetLabels` should be provided as input here. On the client side, this
80   // should be nullptr.
81   virtual void AddLabels(
82       grpc_metadata_batch* outgoing_initial_metadata,
83       LabelsIterable* labels_from_incoming_metadata) const = 0;
84 
85   // Adds optional labels to the traced calls. Each entry in the span
86   // corresponds to the CallAttemptTracer::OptionalLabelComponent enum. Returns
87   // false when callback returns false.
88   virtual bool AddOptionalLabels(
89       bool is_client,
90       absl::Span<const grpc_core::RefCountedStringValue> optional_labels,
91       opentelemetry::nostd::function_ref<
92           bool(opentelemetry::nostd::string_view,
93                opentelemetry::common::AttributeValue)>
94           callback) const = 0;
95 
96   // Gets the actual size of the optional labels that the Plugin is going to
97   // produce through the AddOptionalLabels method.
98   virtual size_t GetOptionalLabelsSize(
99       bool is_client,
100       absl::Span<const grpc_core::RefCountedStringValue> optional_labels)
101       const = 0;
102 };
103 
104 class InternalOpenTelemetryPluginOption
105     : public grpc::OpenTelemetryPluginOption {
106  public:
107   ~InternalOpenTelemetryPluginOption() override = default;
108   // Determines whether a plugin option is active on a given channel target
109   virtual bool IsActiveOnClientChannel(absl::string_view target) const = 0;
110   // Determines whether a plugin option is active on a given server
111   virtual bool IsActiveOnServer(const grpc_core::ChannelArgs& args) const = 0;
112   // Returns the LabelsInjector used by this plugin option, nullptr if none.
113   virtual const grpc::internal::LabelsInjector* labels_injector() const = 0;
114 };
115 
116 // Tags
117 absl::string_view OpenTelemetryMethodKey();
118 absl::string_view OpenTelemetryStatusKey();
119 absl::string_view OpenTelemetryTargetKey();
120 
121 class OpenTelemetryPluginBuilderImpl {
122  public:
123   OpenTelemetryPluginBuilderImpl();
124   ~OpenTelemetryPluginBuilderImpl();
125   // If `SetMeterProvider()` is not called, no metrics are collected.
126   OpenTelemetryPluginBuilderImpl& SetMeterProvider(
127       std::shared_ptr<opentelemetry::metrics::MeterProvider> meter_provider);
128   // Methods to manipulate which instruments are enabled in the OpenTelemetry
129   // Stats Plugin. The default set of instruments are -
130   // grpc.client.attempt.started
131   // grpc.client.attempt.duration
132   // grpc.client.attempt.sent_total_compressed_message_size
133   // grpc.client.attempt.rcvd_total_compressed_message_size
134   // grpc.server.call.started
135   // grpc.server.call.duration
136   // grpc.server.call.sent_total_compressed_message_size
137   // grpc.server.call.rcvd_total_compressed_message_size
138   OpenTelemetryPluginBuilderImpl& EnableMetrics(
139       absl::Span<const absl::string_view> metric_names);
140   OpenTelemetryPluginBuilderImpl& DisableMetrics(
141       absl::Span<const absl::string_view> metric_names);
142   OpenTelemetryPluginBuilderImpl& DisableAllMetrics();
143   // If set, \a server_selector is called per incoming call on the server
144   // to decide whether to collect metrics on that call or not.
145   // TODO(yashkt): We should only need to do this per server connection or even
146   // per server. Change this when we have a ServerTracer.
147   OpenTelemetryPluginBuilderImpl& SetServerSelector(
148       absl::AnyInvocable<bool(const grpc_core::ChannelArgs& /*args*/) const>
149           server_selector);
150   // If set, \a target_attribute_filter is called per channel to decide whether
151   // to record the target attribute on client or to replace it with "other".
152   // This helps reduce the cardinality on metrics in cases where many channels
153   // are created with different targets in the same binary (which might happen
154   // for example, if the channel target string uses IP addresses directly).
155   OpenTelemetryPluginBuilderImpl& SetTargetAttributeFilter(
156       absl::AnyInvocable<bool(absl::string_view /*target*/) const>
157           target_attribute_filter);
158   // If set, \a generic_method_attribute_filter is called per call with a
159   // generic method type to decide whether to record the method name or to
160   // replace it with "other". Non-generic or pre-registered methods remain
161   // unaffected. If not set, by default, generic method names are replaced with
162   // "other" when recording metrics.
163   OpenTelemetryPluginBuilderImpl& SetGenericMethodAttributeFilter(
164       absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>
165           generic_method_attribute_filter);
166   OpenTelemetryPluginBuilderImpl& AddPluginOption(
167       std::unique_ptr<InternalOpenTelemetryPluginOption> option);
168   // Records \a optional_label_key on all metrics that provide it.
169   OpenTelemetryPluginBuilderImpl& AddOptionalLabel(
170       absl::string_view optional_label_key);
171   // Set scope filter to choose which channels are recorded by this plugin.
172   // Server-side recording remains unaffected.
173   OpenTelemetryPluginBuilderImpl& SetChannelScopeFilter(
174       absl::AnyInvocable<
175           bool(const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) const>
176           channel_scope_filter);
177   absl::Status BuildAndRegisterGlobal();
178   absl::StatusOr<std::shared_ptr<grpc::experimental::OpenTelemetryPlugin>>
179   Build();
180 
TestOnlyEnabledMetrics()181   const absl::flat_hash_set<std::string>& TestOnlyEnabledMetrics() {
182     return metrics_;
183   }
184 
185  private:
186   std::shared_ptr<opentelemetry::metrics::MeterProvider> meter_provider_;
187   std::unique_ptr<LabelsInjector> labels_injector_;
188   absl::AnyInvocable<bool(absl::string_view /*target*/) const>
189       target_attribute_filter_;
190   absl::flat_hash_set<std::string> metrics_;
191   absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>
192       generic_method_attribute_filter_;
193   absl::AnyInvocable<bool(const grpc_core::ChannelArgs& /*args*/) const>
194       server_selector_;
195   std::vector<std::unique_ptr<InternalOpenTelemetryPluginOption>>
196       plugin_options_;
197   std::set<absl::string_view> optional_label_keys_;
198   absl::AnyInvocable<bool(
199       const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) const>
200       channel_scope_filter_;
201 };
202 
203 class OpenTelemetryPluginImpl
204     : public grpc::experimental::OpenTelemetryPlugin,
205       public grpc_core::StatsPlugin,
206       public std::enable_shared_from_this<OpenTelemetryPluginImpl> {
207  public:
208   OpenTelemetryPluginImpl(
209       const absl::flat_hash_set<std::string>& metrics,
210       opentelemetry::nostd::shared_ptr<opentelemetry::metrics::MeterProvider>
211           meter_provider,
212       absl::AnyInvocable<bool(absl::string_view /*target*/) const>
213           target_attribute_filter,
214       absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>
215           generic_method_attribute_filter,
216       absl::AnyInvocable<bool(const grpc_core::ChannelArgs& /*args*/) const>
217           server_selector,
218       std::vector<std::unique_ptr<InternalOpenTelemetryPluginOption>>
219           plugin_options,
220       const std::set<absl::string_view>& optional_label_keys,
221       absl::AnyInvocable<
222           bool(const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) const>
223           channel_scope_filter);
224   ~OpenTelemetryPluginImpl() override;
225 
226  private:
227   class ClientCallTracer;
228   class KeyValueIterable;
229   class NPCMetricsKeyValueIterable;
230   class ServerCallTracer;
231 
232   // Creates a convenience wrapper to help iterate over only those plugin
233   // options that are active over a given channel/server.
234   class ActivePluginOptionsView {
235    public:
MakeForClient(absl::string_view target,const OpenTelemetryPluginImpl * otel_plugin)236     static ActivePluginOptionsView MakeForClient(
237         absl::string_view target, const OpenTelemetryPluginImpl* otel_plugin) {
238       return ActivePluginOptionsView(
239           [target](const InternalOpenTelemetryPluginOption& plugin_option) {
240             return plugin_option.IsActiveOnClientChannel(target);
241           },
242           otel_plugin);
243     }
244 
MakeForServer(const grpc_core::ChannelArgs & args,const OpenTelemetryPluginImpl * otel_plugin)245     static ActivePluginOptionsView MakeForServer(
246         const grpc_core::ChannelArgs& args,
247         const OpenTelemetryPluginImpl* otel_plugin) {
248       return ActivePluginOptionsView(
249           [&args](const InternalOpenTelemetryPluginOption& plugin_option) {
250             return plugin_option.IsActiveOnServer(args);
251           },
252           otel_plugin);
253     }
254 
ForEach(absl::FunctionRef<bool (const InternalOpenTelemetryPluginOption &,size_t)> func,const OpenTelemetryPluginImpl * otel_plugin)255     bool ForEach(absl::FunctionRef<
256                      bool(const InternalOpenTelemetryPluginOption&, size_t)>
257                      func,
258                  const OpenTelemetryPluginImpl* otel_plugin) const {
259       for (size_t i = 0; i < otel_plugin->plugin_options().size(); ++i) {
260         const auto& plugin_option = otel_plugin->plugin_options()[i];
261         if (active_mask_[i] && !func(*plugin_option, i)) {
262           return false;
263         }
264       }
265       return true;
266     }
267 
268    private:
ActivePluginOptionsView(absl::FunctionRef<bool (const InternalOpenTelemetryPluginOption &)> func,const OpenTelemetryPluginImpl * otel_plugin)269     explicit ActivePluginOptionsView(
270         absl::FunctionRef<bool(const InternalOpenTelemetryPluginOption&)> func,
271         const OpenTelemetryPluginImpl* otel_plugin) {
272       for (size_t i = 0; i < otel_plugin->plugin_options().size(); ++i) {
273         const auto& plugin_option = otel_plugin->plugin_options()[i];
274         if (plugin_option != nullptr && func(*plugin_option)) {
275           active_mask_.set(i);
276         }
277       }
278     }
279 
280     std::bitset<64> active_mask_;
281   };
282 
283   class ClientScopeConfig : public grpc_core::StatsPlugin::ScopeConfig {
284    public:
ClientScopeConfig(const OpenTelemetryPluginImpl * otel_plugin,const OpenTelemetryPluginBuilder::ChannelScope & scope)285     ClientScopeConfig(const OpenTelemetryPluginImpl* otel_plugin,
286                       const OpenTelemetryPluginBuilder::ChannelScope& scope)
287         : active_plugin_options_view_(ActivePluginOptionsView::MakeForClient(
288               scope.target(), otel_plugin)),
289           filtered_target_(
290               // Use the original target string only if a filter on the
291               // attribute is not registered or if the filter returns true,
292               // otherwise use "other".
293               otel_plugin->target_attribute_filter() == nullptr ||
294                       otel_plugin->target_attribute_filter()(scope.target())
295                   ? scope.target()
296                   : "other") {}
297 
active_plugin_options_view()298     const ActivePluginOptionsView& active_plugin_options_view() const {
299       return active_plugin_options_view_;
300     }
301 
filtered_target()302     absl::string_view filtered_target() const { return filtered_target_; }
303 
304    private:
305     ActivePluginOptionsView active_plugin_options_view_;
306     std::string filtered_target_;
307   };
308   class ServerScopeConfig : public grpc_core::StatsPlugin::ScopeConfig {
309    public:
ServerScopeConfig(const OpenTelemetryPluginImpl * otel_plugin,const grpc_core::ChannelArgs & args)310     ServerScopeConfig(const OpenTelemetryPluginImpl* otel_plugin,
311                       const grpc_core::ChannelArgs& args)
312         : active_plugin_options_view_(
313               ActivePluginOptionsView::MakeForServer(args, otel_plugin)) {}
314 
active_plugin_options_view()315     const ActivePluginOptionsView& active_plugin_options_view() const {
316       return active_plugin_options_view_;
317     }
318 
319    private:
320     ActivePluginOptionsView active_plugin_options_view_;
321   };
322 
323   struct ClientMetrics {
324     struct Attempt {
325       std::unique_ptr<opentelemetry::metrics::Counter<uint64_t>> started;
326       std::unique_ptr<opentelemetry::metrics::Histogram<double>> duration;
327       std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>
328           sent_total_compressed_message_size;
329       std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>
330           rcvd_total_compressed_message_size;
331     } attempt;
332   };
333   struct ServerMetrics {
334     struct Call {
335       std::unique_ptr<opentelemetry::metrics::Counter<uint64_t>> started;
336       std::unique_ptr<opentelemetry::metrics::Histogram<double>> duration;
337       std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>
338           sent_total_compressed_message_size;
339       std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>
340           rcvd_total_compressed_message_size;
341     } call;
342   };
343 
344   // This object should be used inline.
345   class CallbackMetricReporter : public grpc_core::CallbackMetricReporter {
346    public:
347     CallbackMetricReporter(OpenTelemetryPluginImpl* ot_plugin,
348                            grpc_core::RegisteredMetricCallback* key)
349         ABSL_EXCLUSIVE_LOCKS_REQUIRED(ot_plugin->mu_);
350 
351    private:
352     void ReportInt64(
353         grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle handle,
354         int64_t value, absl::Span<const absl::string_view> label_values,
355         absl::Span<const absl::string_view> optional_values)
356         ABSL_EXCLUSIVE_LOCKS_REQUIRED(
357             CallbackGaugeState<int64_t>::ot_plugin->mu_) override;
358     void ReportDouble(
359         grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle handle,
360         double value, absl::Span<const absl::string_view> label_values,
361         absl::Span<const absl::string_view> optional_values)
362         ABSL_EXCLUSIVE_LOCKS_REQUIRED(
363             CallbackGaugeState<double>::ot_plugin->mu_) override;
364 
365     OpenTelemetryPluginImpl* ot_plugin_;
366     grpc_core::RegisteredMetricCallback* key_;
367   };
368 
369   class ServerBuilderOption : public grpc::ServerBuilderOption {
370    public:
ServerBuilderOption(std::shared_ptr<OpenTelemetryPluginImpl> plugin)371     explicit ServerBuilderOption(
372         std::shared_ptr<OpenTelemetryPluginImpl> plugin)
373         : plugin_(std::move(plugin)) {}
374     void UpdateArguments(grpc::ChannelArguments* args) override;
UpdatePlugins(std::vector<std::unique_ptr<grpc::ServerBuilderPlugin>> *)375     void UpdatePlugins(std::vector<std::unique_ptr<grpc::ServerBuilderPlugin>>*
376                        /*plugins*/) override {}
377 
378    private:
379     std::shared_ptr<OpenTelemetryPluginImpl> plugin_;
380   };
381 
382   // Returns the string form of \a key
383   static absl::string_view OptionalLabelKeyToString(
384       grpc_core::ClientCallTracer::CallAttemptTracer::OptionalLabelKey key);
385 
386   // Returns the OptionalLabelKey form of \a key if \a key is recognized and
387   // is public, absl::nullopt otherwise.
388   static absl::optional<
389       grpc_core::ClientCallTracer::CallAttemptTracer::OptionalLabelKey>
390   OptionalLabelStringToKey(absl::string_view key);
391 
392   // grpc::OpenTelemetryPlugin:
393   void AddToChannelArguments(grpc::ChannelArguments* args) override;
394   void AddToServerBuilder(grpc::ServerBuilder* builder) override;
395 
396   // StatsPlugin:
397   std::pair<bool, std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig>>
398   IsEnabledForChannel(
399       const OpenTelemetryPluginBuilder::ChannelScope& scope) const override;
400   std::pair<bool, std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig>>
401   IsEnabledForServer(const grpc_core::ChannelArgs& args) const override;
402   std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig> GetChannelScopeConfig(
403       const OpenTelemetryPluginBuilder::ChannelScope& scope) const override;
404   std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig> GetServerScopeConfig(
405       const grpc_core::ChannelArgs& args) const override;
406   void AddCounter(
407       grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle handle,
408       uint64_t value, absl::Span<const absl::string_view> label_values,
409       absl::Span<const absl::string_view> optional_values) override;
410   void AddCounter(
411       grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle handle,
412       double value, absl::Span<const absl::string_view> label_values,
413       absl::Span<const absl::string_view> optional_values) override;
414   void RecordHistogram(
415       grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle handle,
416       uint64_t value, absl::Span<const absl::string_view> label_values,
417       absl::Span<const absl::string_view> optional_values) override;
418   void RecordHistogram(
419       grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle handle,
420       double value, absl::Span<const absl::string_view> label_values,
421       absl::Span<const absl::string_view> optional_values) override;
422   void AddCallback(grpc_core::RegisteredMetricCallback* callback)
423       ABSL_LOCKS_EXCLUDED(mu_) override;
424   void RemoveCallback(grpc_core::RegisteredMetricCallback* callback)
425       ABSL_LOCKS_EXCLUDED(mu_) override;
426   grpc_core::ClientCallTracer* GetClientCallTracer(
427       const grpc_core::Slice& path, bool registered_method,
428       std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig> scope_config)
429       override;
430   grpc_core::ServerCallTracer* GetServerCallTracer(
431       std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig> scope_config)
432       override;
433   bool IsInstrumentEnabled(
434       grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle handle)
435       const override;
436 
437   const absl::AnyInvocable<bool(const grpc_core::ChannelArgs& /*args*/) const>&
server_selector()438   server_selector() const {
439     return server_selector_;
440   }
441   const absl::AnyInvocable<bool(absl::string_view /*target*/) const>&
target_attribute_filter()442   target_attribute_filter() const {
443     return target_attribute_filter_;
444   }
445   const absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>&
generic_method_attribute_filter()446   generic_method_attribute_filter() const {
447     return generic_method_attribute_filter_;
448   }
449   const std::vector<std::unique_ptr<InternalOpenTelemetryPluginOption>>&
plugin_options()450   plugin_options() const {
451     return plugin_options_;
452   }
453 
454   template <typename ValueType>
455   struct CallbackGaugeState {
456     // It's possible to set values for multiple sets of labels at the same time
457     // in a single callback. Key is a vector of label values and enabled
458     // optional label values.
459     using Cache = absl::flat_hash_map<std::vector<std::string>, ValueType>;
460     grpc_core::GlobalInstrumentsRegistry::InstrumentID id;
461     opentelemetry::nostd::shared_ptr<
462         opentelemetry::metrics::ObservableInstrument>
463         instrument;
464     bool ot_callback_registered ABSL_GUARDED_BY(ot_plugin->mu_);
465     // instrument1 ----- RegisteredMetricCallback1
466     //               x
467     // instrument2 ----- RegisteredMetricCallback2
468     // One instrument can be registered by multiple callbacks.
469     absl::flat_hash_map<grpc_core::RegisteredMetricCallback*, Cache> caches
470         ABSL_GUARDED_BY(ot_plugin->mu_);
471     OpenTelemetryPluginImpl* ot_plugin;
472 
473     static void CallbackGaugeCallback(
474         opentelemetry::metrics::ObserverResult result, void* arg)
475         ABSL_LOCKS_EXCLUDED(ot_plugin->mu_);
476 
477     void Observe(opentelemetry::metrics::ObserverResult& result,
478                  const Cache& cache)
479         ABSL_EXCLUSIVE_LOCKS_REQUIRED(ot_plugin->mu_);
480   };
481 
482   // Instruments for per-call metrics.
483   ClientMetrics client_;
484   ServerMetrics server_;
485   static constexpr int kOptionalLabelsSizeLimit = 64;
486   using OptionalLabelsBitSet = std::bitset<kOptionalLabelsSizeLimit>;
487   OptionalLabelsBitSet per_call_optional_label_bits_;
488   // Instruments for non-per-call metrics.
489   struct Disabled {};
490   using Instrument = absl::variant<
491       Disabled, std::unique_ptr<opentelemetry::metrics::Counter<uint64_t>>,
492       std::unique_ptr<opentelemetry::metrics::Counter<double>>,
493       std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>,
494       std::unique_ptr<opentelemetry::metrics::Histogram<double>>,
495       std::unique_ptr<CallbackGaugeState<int64_t>>,
496       std::unique_ptr<CallbackGaugeState<double>>>;
497   struct InstrumentData {
498     Instrument instrument;
499     OptionalLabelsBitSet optional_labels_bits;
500   };
501   std::vector<InstrumentData> instruments_data_;
502   grpc_core::Mutex mu_;
503   absl::flat_hash_map<grpc_core::RegisteredMetricCallback*,
504                       grpc_core::Timestamp>
505       callback_timestamps_ ABSL_GUARDED_BY(mu_);
506   opentelemetry::nostd::shared_ptr<opentelemetry::metrics::MeterProvider>
507       meter_provider_;
508   absl::AnyInvocable<bool(const grpc_core::ChannelArgs& /*args*/) const>
509       server_selector_;
510   absl::AnyInvocable<bool(absl::string_view /*target*/) const>
511       target_attribute_filter_;
512   absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>
513       generic_method_attribute_filter_;
514   std::vector<std::unique_ptr<InternalOpenTelemetryPluginOption>>
515       plugin_options_;
516   absl::AnyInvocable<bool(
517       const OpenTelemetryPluginBuilder::ChannelScope& /*scope*/) const>
518       channel_scope_filter_;
519 };
520 
521 }  // namespace internal
522 }  // namespace grpc
523 
524 #endif  // GRPC_SRC_CPP_EXT_OTEL_OTEL_PLUGIN_H
525