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