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 GRPCPP_EXT_OTEL_PLUGIN_H 20 #define GRPCPP_EXT_OTEL_PLUGIN_H 21 22 #include <grpc/support/metrics.h> 23 #include <grpc/support/port_platform.h> 24 #include <grpcpp/server_builder.h> 25 #include <grpcpp/support/channel_arguments.h> 26 #include <stddef.h> 27 #include <stdint.h> 28 29 #include <memory> 30 31 #include "absl/functional/any_invocable.h" 32 #include "absl/status/status.h" 33 #include "absl/status/statusor.h" 34 #include "absl/strings/string_view.h" 35 #include "opentelemetry/metrics/meter_provider.h" 36 37 namespace grpc { 38 namespace internal { 39 class OpenTelemetryPluginBuilderImpl; 40 } // namespace internal 41 42 class OpenTelemetryPluginOption { 43 public: 44 virtual ~OpenTelemetryPluginOption() = default; 45 }; 46 47 namespace experimental { 48 /// EXPERIMENTAL API 49 class OpenTelemetryPlugin { 50 public: 51 virtual ~OpenTelemetryPlugin() = default; 52 /// EXPERIMENTAL API 53 /// Adds this OpenTelemetryPlugin to the channel args \a args. 54 virtual void AddToChannelArguments(grpc::ChannelArguments* args) = 0; 55 /// EXPERIMENTAL API 56 /// Adds this OpenTelemetryPlugin to the channel arguments that will be used 57 /// to create the server through \a builder. 58 virtual void AddToServerBuilder(grpc::ServerBuilder* builder) = 0; 59 }; 60 } // namespace experimental 61 62 /// The most common way to use this API is - 63 /// 64 /// OpenTelemetryPluginBuilder().SetMeterProvider(provider).BuildAndRegister(); 65 /// 66 /// The set of instruments available are - 67 /// grpc.client.attempt.started 68 /// grpc.client.attempt.duration 69 /// grpc.client.attempt.sent_total_compressed_message_size 70 /// grpc.client.attempt.rcvd_total_compressed_message_size 71 /// grpc.server.call.started 72 /// grpc.server.call.duration 73 /// grpc.server.call.sent_total_compressed_message_size 74 /// grpc.server.call.rcvd_total_compressed_message_size 75 class OpenTelemetryPluginBuilder { 76 public: 77 using ChannelScope = grpc_core::experimental::StatsPluginChannelScope; 78 79 /// Metrics 80 static constexpr absl::string_view kClientAttemptStartedInstrumentName = 81 "grpc.client.attempt.started"; 82 static constexpr absl::string_view kClientAttemptDurationInstrumentName = 83 "grpc.client.attempt.duration"; 84 static constexpr absl::string_view 85 kClientAttemptSentTotalCompressedMessageSizeInstrumentName = 86 "grpc.client.attempt.sent_total_compressed_message_size"; 87 static constexpr absl::string_view 88 kClientAttemptRcvdTotalCompressedMessageSizeInstrumentName = 89 "grpc.client.attempt.rcvd_total_compressed_message_size"; 90 static constexpr absl::string_view kServerCallStartedInstrumentName = 91 "grpc.server.call.started"; 92 static constexpr absl::string_view kServerCallDurationInstrumentName = 93 "grpc.server.call.duration"; 94 static constexpr absl::string_view 95 kServerCallSentTotalCompressedMessageSizeInstrumentName = 96 "grpc.server.call.sent_total_compressed_message_size"; 97 static constexpr absl::string_view 98 kServerCallRcvdTotalCompressedMessageSizeInstrumentName = 99 "grpc.server.call.rcvd_total_compressed_message_size"; 100 101 OpenTelemetryPluginBuilder(); 102 ~OpenTelemetryPluginBuilder(); 103 /// If `SetMeterProvider()` is not called, no metrics are collected. 104 OpenTelemetryPluginBuilder& SetMeterProvider( 105 std::shared_ptr<opentelemetry::metrics::MeterProvider> meter_provider); 106 /// DEPRECATED: If set, \a target_attribute_filter is called per channel to 107 /// decide whether to record the target attribute on client or to replace it 108 /// with "other". This helps reduce the cardinality on metrics in cases where 109 /// many channels are created with different targets in the same binary (which 110 /// might happen for example, if the channel target string uses IP addresses 111 /// directly). 112 /// This filtration only works for the per-call metrics - 113 /// grpc.client.attempt.started 114 /// grpc.client.attempt.duration 115 /// grpc.client.attempt.sent_total_compressed_message_size 116 /// grpc.client.attempt.rcvd_total_compressed_message_size 117 /// For example, the grpc.target attribute on pick first lb policy metrics 118 /// defined in 119 /// https://github.com/grpc/proposal/blob/master/A78-grpc-metrics-wrr-pf-xds.md 120 /// will not be filtered. Please contact the grpc team if this filtration is 121 /// of interest to you. 122 GRPC_DEPRECATED( 123 "Does not work as expected. Please raise an issue on " 124 "https://github.com/grpc/grpc if this would be of use to you.") 125 OpenTelemetryPluginBuilder& SetTargetAttributeFilter( 126 absl::AnyInvocable<bool(absl::string_view /*target*/) const> 127 target_attribute_filter); 128 /// If set, \a generic_method_attribute_filter is called per call with a 129 /// generic method type to decide whether to record the method name or to 130 /// replace it with "other". Non-generic or pre-registered methods remain 131 /// unaffected. If not set, by default, generic method names are replaced 132 /// with "other" when recording metrics. 133 OpenTelemetryPluginBuilder& SetGenericMethodAttributeFilter( 134 absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const> 135 generic_method_attribute_filter); 136 // Methods to manipulate which instruments are enabled in the OpenTelemetry 137 // Stats Plugin. 138 OpenTelemetryPluginBuilder& EnableMetrics( 139 absl::Span<const absl::string_view> metric_names); 140 OpenTelemetryPluginBuilder& DisableMetrics( 141 absl::Span<const absl::string_view> metric_names); 142 OpenTelemetryPluginBuilder& DisableAllMetrics(); 143 /// Add a plugin option to add to the opentelemetry plugin being built. At 144 /// present, this type is an opaque type. Ownership of \a option is 145 /// transferred when `AddPluginOption` is invoked. A maximum of 64 plugin 146 /// options can be added. 147 OpenTelemetryPluginBuilder& AddPluginOption( 148 std::unique_ptr<OpenTelemetryPluginOption> option); 149 /// Records \a optional_label_key on all metrics that provide it. 150 OpenTelemetryPluginBuilder& AddOptionalLabel( 151 absl::string_view optional_label_key); 152 /// Set scope filter to choose which channels are recorded by this plugin. 153 /// Server-side recording remains unaffected. 154 OpenTelemetryPluginBuilder& SetChannelScopeFilter( 155 absl::AnyInvocable<bool(const ChannelScope& /*scope*/) const> 156 channel_scope_filter); 157 /// Builds and registers a global plugin that acts on all channels and servers 158 /// running on the process. Must be called no more than once and must not be 159 /// called if Build() is called. 160 absl::Status BuildAndRegisterGlobal(); 161 /// EXPERIMENTAL API 162 /// Builds an open telemetry plugin, returns the plugin object when succeeded 163 /// or an error status when failed. Must be called no more than once and must 164 /// not be called if BuildAndRegisterGlobal() is called. 165 GRPC_MUST_USE_RESULT 166 absl::StatusOr<std::shared_ptr<experimental::OpenTelemetryPlugin>> Build(); 167 168 private: 169 std::unique_ptr<internal::OpenTelemetryPluginBuilderImpl> impl_; 170 }; 171 172 namespace experimental { 173 // TODO(yashykt): Delete this after the 1.62 release. 174 GRPC_DEPRECATED( 175 "Use grpc::OpenTelemetryPluginBuilder instead. The experimental version " 176 "will be deleted after the 1.62 release.") 177 typedef grpc::OpenTelemetryPluginBuilder OpenTelemetryPluginBuilder; 178 } // namespace experimental 179 180 } // namespace grpc 181 182 #endif // GRPCPP_EXT_OTEL_PLUGIN_H 183