blob: d515c2114831d331e80b85859643995f3acf95fc [file] [log] [blame]
//
//
// Copyright 2023 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#ifndef GRPC_SRC_CPP_EXT_OTEL_KEY_VALUE_ITERABLE_H
#define GRPC_SRC_CPP_EXT_OTEL_KEY_VALUE_ITERABLE_H
#include <grpc/support/port_platform.h>
#include <stddef.h>
#include <utility>
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "absl/types/span.h"
#include "opentelemetry/common/attribute_value.h"
#include "opentelemetry/common/key_value_iterable.h"
#include "opentelemetry/nostd/function_ref.h"
#include "opentelemetry/nostd/string_view.h"
#include "src/cpp/ext/otel/otel_plugin.h"
namespace grpc {
namespace internal {
inline opentelemetry::nostd::string_view AbslStrViewToOpenTelemetryStrView(
absl::string_view str) {
return opentelemetry::nostd::string_view(str.data(), str.size());
}
// An iterable class based on opentelemetry::common::KeyValueIterable that
// allows gRPC to iterate on its various sources of attributes and avoid an
// allocation in cases wherever possible.
class OpenTelemetryPlugin::KeyValueIterable
: public opentelemetry::common::KeyValueIterable {
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)
: injected_labels_from_plugin_options_(
injected_labels_from_plugin_options),
additional_labels_(additional_labels),
active_plugin_options_view_(active_plugin_options_view),
optional_labels_(optional_labels),
is_client_(is_client),
otel_plugin_(otel_plugin) {}
bool ForEachKeyValue(opentelemetry::nostd::function_ref<
bool(opentelemetry::nostd::string_view,
opentelemetry::common::AttributeValue)>
callback) const noexcept override {
if (active_plugin_options_view_ != nullptr &&
!active_plugin_options_view_->ForEach(
[callback, this](
const InternalOpenTelemetryPluginOption& plugin_option,
size_t /*index*/) {
return plugin_option.labels_injector()->AddOptionalLabels(
is_client_, optional_labels_, callback);
},
otel_plugin_)) {
return false;
}
for (const auto& plugin_option_injected_iterable :
injected_labels_from_plugin_options_) {
if (plugin_option_injected_iterable != nullptr) {
plugin_option_injected_iterable->ResetIteratorPosition();
while (const auto& pair = plugin_option_injected_iterable->Next()) {
if (!callback(AbslStrViewToOpenTelemetryStrView(pair->first),
AbslStrViewToOpenTelemetryStrView(pair->second))) {
return false;
}
}
}
}
for (const auto& pair : additional_labels_) {
if (!callback(AbslStrViewToOpenTelemetryStrView(pair.first),
AbslStrViewToOpenTelemetryStrView(pair.second))) {
return false;
}
}
// Add per-call optional labels
if (!optional_labels_.empty()) {
GPR_ASSERT(
optional_labels_.size() ==
static_cast<size_t>(grpc_core::ClientCallTracer::CallAttemptTracer::
OptionalLabelKey::kSize));
for (size_t i = 0; i < optional_labels_.size(); ++i) {
if (!otel_plugin_->per_call_optional_label_bits_.test(i)) {
continue;
}
if (!callback(
AbslStrViewToOpenTelemetryStrView(OptionalLabelKeyToString(
static_cast<grpc_core::ClientCallTracer::CallAttemptTracer::
OptionalLabelKey>(i))),
AbslStrViewToOpenTelemetryStrView(
optional_labels_[i].as_string_view()))) {
return false;
}
}
}
return true;
}
size_t size() const noexcept override {
size_t size = 0;
for (const auto& plugin_option_injected_iterable :
injected_labels_from_plugin_options_) {
if (plugin_option_injected_iterable != nullptr) {
size += plugin_option_injected_iterable->Size();
}
}
size += additional_labels_.size();
if (active_plugin_options_view_ != nullptr) {
active_plugin_options_view_->ForEach(
[&size, this](const InternalOpenTelemetryPluginOption& plugin_option,
size_t /*index*/) {
size += plugin_option.labels_injector()->GetOptionalLabelsSize(
is_client_, optional_labels_);
return true;
},
otel_plugin_);
}
return size;
}
private:
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_;
};
} // namespace internal
} // namespace grpc
#endif // GRPC_SRC_CPP_EXT_OTEL_KEY_VALUE_ITERABLE_H