• 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_KEY_VALUE_ITERABLE_H
20 #define GRPC_SRC_CPP_EXT_OTEL_KEY_VALUE_ITERABLE_H
21 
22 #include <grpc/support/port_platform.h>
23 #include <stddef.h>
24 
25 #include <utility>
26 
27 #include "absl/log/check.h"
28 #include "absl/strings/string_view.h"
29 #include "absl/types/optional.h"
30 #include "absl/types/span.h"
31 #include "opentelemetry/common/attribute_value.h"
32 #include "opentelemetry/common/key_value_iterable.h"
33 #include "opentelemetry/nostd/function_ref.h"
34 #include "opentelemetry/nostd/string_view.h"
35 #include "src/cpp/ext/otel/otel_plugin.h"
36 
37 namespace grpc {
38 namespace internal {
39 
AbslStrViewToOpenTelemetryStrView(absl::string_view str)40 inline opentelemetry::nostd::string_view AbslStrViewToOpenTelemetryStrView(
41     absl::string_view str) {
42   return opentelemetry::nostd::string_view(str.data(), str.size());
43 }
44 
45 // An iterable class based on opentelemetry::common::KeyValueIterable that
46 // allows gRPC to iterate on its various sources of attributes and avoid an
47 // allocation in cases wherever possible.
48 class OpenTelemetryPluginImpl::KeyValueIterable
49     : public opentelemetry::common::KeyValueIterable {
50  public:
KeyValueIterable(const std::vector<std::unique_ptr<LabelsIterable>> & injected_labels_from_plugin_options,absl::Span<const std::pair<absl::string_view,absl::string_view>> additional_labels,const OpenTelemetryPluginImpl::ActivePluginOptionsView * active_plugin_options_view,absl::Span<const grpc_core::RefCountedStringValue> optional_labels,bool is_client,const OpenTelemetryPluginImpl * otel_plugin)51   KeyValueIterable(
52       const std::vector<std::unique_ptr<LabelsIterable>>&
53           injected_labels_from_plugin_options,
54       absl::Span<const std::pair<absl::string_view, absl::string_view>>
55           additional_labels,
56       const OpenTelemetryPluginImpl::ActivePluginOptionsView*
57           active_plugin_options_view,
58       absl::Span<const grpc_core::RefCountedStringValue> optional_labels,
59       bool is_client, const OpenTelemetryPluginImpl* otel_plugin)
60       : injected_labels_from_plugin_options_(
61             injected_labels_from_plugin_options),
62         additional_labels_(additional_labels),
63         active_plugin_options_view_(active_plugin_options_view),
64         optional_labels_(optional_labels),
65         is_client_(is_client),
66         otel_plugin_(otel_plugin) {}
67 
ForEachKeyValue(opentelemetry::nostd::function_ref<bool (opentelemetry::nostd::string_view,opentelemetry::common::AttributeValue)> callback)68   bool ForEachKeyValue(opentelemetry::nostd::function_ref<
69                        bool(opentelemetry::nostd::string_view,
70                             opentelemetry::common::AttributeValue)>
71                            callback) const noexcept override {
72     if (active_plugin_options_view_ != nullptr &&
73         !active_plugin_options_view_->ForEach(
74             [callback, this](
75                 const InternalOpenTelemetryPluginOption& plugin_option,
76                 size_t /*index*/) {
77               return plugin_option.labels_injector()->AddOptionalLabels(
78                   is_client_, optional_labels_, callback);
79             },
80             otel_plugin_)) {
81       return false;
82     }
83     for (const auto& plugin_option_injected_iterable :
84          injected_labels_from_plugin_options_) {
85       if (plugin_option_injected_iterable != nullptr) {
86         plugin_option_injected_iterable->ResetIteratorPosition();
87         while (const auto& pair = plugin_option_injected_iterable->Next()) {
88           if (!callback(AbslStrViewToOpenTelemetryStrView(pair->first),
89                         AbslStrViewToOpenTelemetryStrView(pair->second))) {
90             return false;
91           }
92         }
93       }
94     }
95     for (const auto& pair : additional_labels_) {
96       if (!callback(AbslStrViewToOpenTelemetryStrView(pair.first),
97                     AbslStrViewToOpenTelemetryStrView(pair.second))) {
98         return false;
99       }
100     }
101     // Add per-call optional labels
102     if (!optional_labels_.empty()) {
103       CHECK(optional_labels_.size() ==
104             static_cast<size_t>(grpc_core::ClientCallTracer::CallAttemptTracer::
105                                     OptionalLabelKey::kSize));
106       for (size_t i = 0; i < optional_labels_.size(); ++i) {
107         if (!otel_plugin_->per_call_optional_label_bits_.test(i)) {
108           continue;
109         }
110         if (!callback(
111                 AbslStrViewToOpenTelemetryStrView(OptionalLabelKeyToString(
112                     static_cast<grpc_core::ClientCallTracer::CallAttemptTracer::
113                                     OptionalLabelKey>(i))),
114                 AbslStrViewToOpenTelemetryStrView(
115                     optional_labels_[i].as_string_view()))) {
116           return false;
117         }
118       }
119     }
120     return true;
121   }
122 
size()123   size_t size() const noexcept override {
124     size_t size = 0;
125     for (const auto& plugin_option_injected_iterable :
126          injected_labels_from_plugin_options_) {
127       if (plugin_option_injected_iterable != nullptr) {
128         size += plugin_option_injected_iterable->Size();
129       }
130     }
131     size += additional_labels_.size();
132     if (active_plugin_options_view_ != nullptr) {
133       active_plugin_options_view_->ForEach(
134           [&size, this](const InternalOpenTelemetryPluginOption& plugin_option,
135                         size_t /*index*/) {
136             size += plugin_option.labels_injector()->GetOptionalLabelsSize(
137                 is_client_, optional_labels_);
138             return true;
139           },
140           otel_plugin_);
141     }
142     return size;
143   }
144 
145  private:
146   const std::vector<std::unique_ptr<LabelsIterable>>&
147       injected_labels_from_plugin_options_;
148   absl::Span<const std::pair<absl::string_view, absl::string_view>>
149       additional_labels_;
150   const OpenTelemetryPluginImpl::ActivePluginOptionsView*
151       active_plugin_options_view_;
152   absl::Span<const grpc_core::RefCountedStringValue> optional_labels_;
153   bool is_client_;
154   const OpenTelemetryPluginImpl* otel_plugin_;
155 };
156 
157 }  // namespace internal
158 }  // namespace grpc
159 
160 #endif  // GRPC_SRC_CPP_EXT_OTEL_KEY_VALUE_ITERABLE_H
161