xref: /aosp_15_r20/external/grpc-grpc/src/cpp/ext/csm/csm_observability.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/csm/csm_observability.h"
22 
23 #include <memory>
24 #include <string>
25 #include <utility>
26 
27 #include "absl/functional/any_invocable.h"
28 #include "absl/status/statusor.h"
29 #include "absl/types/optional.h"
30 #include "google/cloud/opentelemetry/resource_detector.h"
31 #include "opentelemetry/sdk/metrics/meter_provider.h"
32 #include "opentelemetry/sdk/resource/resource.h"
33 #include "opentelemetry/sdk/resource/resource_detector.h"
34 
35 #include <grpc/support/log.h>
36 #include <grpcpp/ext/csm_observability.h>
37 
38 #include "src/core/ext/xds/xds_enabled_server.h"
39 #include "src/core/lib/channel/channel_args.h"
40 #include "src/core/lib/uri/uri_parser.h"
41 #include "src/cpp/ext/csm/metadata_exchange.h"
42 #include "src/cpp/ext/otel/otel_plugin.h"
43 
44 namespace grpc {
45 
46 namespace internal {
47 
48 namespace {
49 std::atomic<bool> g_csm_plugin_enabled(false);
50 }
51 
CsmServerSelector(const grpc_core::ChannelArgs & args)52 bool CsmServerSelector(const grpc_core::ChannelArgs& args) {
53   return g_csm_plugin_enabled &&
54          args.GetBool(GRPC_ARG_XDS_ENABLED_SERVER).value_or(false);
55 }
56 
CsmChannelTargetSelector(absl::string_view target)57 bool CsmChannelTargetSelector(absl::string_view target) {
58   if (!g_csm_plugin_enabled) return false;
59   auto uri = grpc_core::URI::Parse(target);
60   if (!uri.ok()) {
61     gpr_log(GPR_ERROR, "Failed to parse URI: %s", std::string(target).c_str());
62     return false;
63   }
64   // CSM channels should have an "xds" scheme
65   if (uri->scheme() != "xds") {
66     return false;
67   }
68   // If set, the authority should be TD
69   if (!uri->authority().empty() &&
70       uri->authority() != "traffic-director-global.xds.googleapis.com") {
71     return false;
72   }
73   return true;
74 }
75 
76 class CsmOpenTelemetryPluginOption
77     : public grpc::internal::InternalOpenTelemetryPluginOption {
78  public:
CsmOpenTelemetryPluginOption()79   CsmOpenTelemetryPluginOption()
80       : labels_injector_(std::make_unique<internal::ServiceMeshLabelsInjector>(
81             google::cloud::otel::MakeResourceDetector()
82                 ->Detect()
83                 .GetAttributes())) {}
84 
IsActiveOnClientChannel(absl::string_view target) const85   bool IsActiveOnClientChannel(absl::string_view target) const override {
86     return CsmChannelTargetSelector(target);
87   }
88 
IsActiveOnServer(const grpc_core::ChannelArgs & args) const89   bool IsActiveOnServer(const grpc_core::ChannelArgs& args) const override {
90     return CsmServerSelector(args);
91   }
92 
labels_injector() const93   const grpc::internal::LabelsInjector* labels_injector() const override {
94     return labels_injector_.get();
95   }
96 
97  private:
98   std::unique_ptr<internal::ServiceMeshLabelsInjector> labels_injector_;
99 };
100 
101 }  // namespace internal
102 
103 //
104 // CsmObservability
105 //
106 
~CsmObservability()107 CsmObservability::~CsmObservability() {
108   if (valid_) {
109     internal::g_csm_plugin_enabled = false;
110   }
111 }
112 
CsmObservability(CsmObservability && other)113 CsmObservability::CsmObservability(CsmObservability&& other) noexcept {
114   other.valid_ = false;
115 }
operator =(CsmObservability && other)116 CsmObservability& CsmObservability::operator=(
117     CsmObservability&& other) noexcept {
118   other.valid_ = false;
119   return *this;
120 }
121 
122 //
123 // CsmObservabilityBuilder
124 //
125 
CsmObservabilityBuilder()126 CsmObservabilityBuilder::CsmObservabilityBuilder()
127     : builder_(
128           std::make_unique<grpc::internal::OpenTelemetryPluginBuilderImpl>()) {}
129 
130 CsmObservabilityBuilder::~CsmObservabilityBuilder() = default;
131 
SetMeterProvider(std::shared_ptr<opentelemetry::metrics::MeterProvider> meter_provider)132 CsmObservabilityBuilder& CsmObservabilityBuilder::SetMeterProvider(
133     std::shared_ptr<opentelemetry::metrics::MeterProvider> meter_provider) {
134   builder_->SetMeterProvider(meter_provider);
135   return *this;
136 }
137 
SetTargetAttributeFilter(absl::AnyInvocable<bool (absl::string_view)const> target_attribute_filter)138 CsmObservabilityBuilder& CsmObservabilityBuilder::SetTargetAttributeFilter(
139     absl::AnyInvocable<bool(absl::string_view /*target*/) const>
140         target_attribute_filter) {
141   builder_->SetTargetAttributeFilter(std::move(target_attribute_filter));
142   return *this;
143 }
144 
145 CsmObservabilityBuilder&
SetGenericMethodAttributeFilter(absl::AnyInvocable<bool (absl::string_view)const> generic_method_attribute_filter)146 CsmObservabilityBuilder::SetGenericMethodAttributeFilter(
147     absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>
148         generic_method_attribute_filter) {
149   builder_->SetGenericMethodAttributeFilter(
150       std::move(generic_method_attribute_filter));
151   return *this;
152 }
153 
BuildAndRegister()154 absl::StatusOr<CsmObservability> CsmObservabilityBuilder::BuildAndRegister() {
155   builder_->AddPluginOption(
156       std::make_unique<grpc::internal::CsmOpenTelemetryPluginOption>());
157   auto status = builder_->BuildAndRegisterGlobal();
158   internal::g_csm_plugin_enabled = true;
159   if (!status.ok()) {
160     return status;
161   }
162   return CsmObservability();
163 }
164 
165 }  // namespace grpc
166