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