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