summaryrefslogtreecommitdiffstats
path: root/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
commite6918187568dbd01842d8d1d2c808ce16a894239 (patch)
tree64f88b554b444a49f656b6c656111a145cbbaa28 /src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage
parentInitial commit. (diff)
downloadceph-e6918187568dbd01842d8d1d2c808ce16a894239.tar.xz
ceph-e6918187568dbd01842d8d1d2c808ce16a894239.zip
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage')
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/baggage.h299
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/baggage_context.h39
-rw-r--r--src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/propagation/baggage_propagator.h54
3 files changed, 392 insertions, 0 deletions
diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/baggage.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/baggage.h
new file mode 100644
index 000000000..eb5e4dcc7
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/baggage.h
@@ -0,0 +1,299 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <cctype>
+
+#include "opentelemetry/common/kv_properties.h"
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+
+namespace baggage
+{
+
+class Baggage
+{
+public:
+ static constexpr size_t kMaxKeyValuePairs = 180;
+ static constexpr size_t kMaxKeyValueSize = 4096;
+ static constexpr size_t kMaxSize = 8192;
+ static constexpr char kKeyValueSeparator = '=';
+ static constexpr char kMembersSeparator = ',';
+ static constexpr char kMetadataSeparator = ';';
+
+ Baggage() noexcept : kv_properties_(new opentelemetry::common::KeyValueProperties()) {}
+ Baggage(size_t size) noexcept
+ : kv_properties_(new opentelemetry::common::KeyValueProperties(size)){};
+
+ template <class T>
+ Baggage(const T &keys_and_values) noexcept
+ : kv_properties_(new opentelemetry::common::KeyValueProperties(keys_and_values))
+ {}
+
+ static nostd::shared_ptr<Baggage> GetDefault()
+ {
+ static nostd::shared_ptr<Baggage> baggage{new Baggage()};
+ return baggage;
+ }
+
+ /* Get value for key in the baggage
+ @returns true if key is found, false otherwise
+ */
+ bool GetValue(nostd::string_view key, std::string &value) const noexcept
+ {
+ return kv_properties_->GetValue(key, value);
+ }
+
+ /* Returns shared_ptr of new baggage object which contains new key-value pair. If key or value is
+ invalid, copy of current baggage is returned
+ */
+ nostd::shared_ptr<Baggage> Set(const nostd::string_view &key,
+ const nostd::string_view &value) noexcept
+ {
+
+ nostd::shared_ptr<Baggage> baggage(new Baggage(kv_properties_->Size() + 1));
+ const bool valid_kv = IsValidKey(key) && IsValidValue(value);
+
+ if (valid_kv)
+ {
+ baggage->kv_properties_->AddEntry(key, value);
+ }
+
+ // add rest of the fields.
+ kv_properties_->GetAllEntries(
+ [&baggage, &key, &valid_kv](nostd::string_view e_key, nostd::string_view e_value) {
+ // if key or value was not valid, add all the entries. Add only remaining entries
+ // otherwise.
+ if (!valid_kv || key != e_key)
+ {
+ baggage->kv_properties_->AddEntry(e_key, e_value);
+ }
+
+ return true;
+ });
+
+ return baggage;
+ }
+
+ // @return all key-values entries by repeatedly invoking the function reference passed as argument
+ // for each entry
+ bool GetAllEntries(
+ nostd::function_ref<bool(nostd::string_view, nostd::string_view)> callback) const noexcept
+ {
+ return kv_properties_->GetAllEntries(callback);
+ }
+
+ // delete key from the baggage if it exists. Returns shared_ptr of new baggage object.
+ // if key does not exist, copy of current baggage is returned.
+ // Validity of key is not checked as invalid keys should never be populated in baggage in the
+ // first place.
+ nostd::shared_ptr<Baggage> Delete(nostd::string_view key) noexcept
+ {
+ // keeping size of baggage same as key might not be found in it
+ nostd::shared_ptr<Baggage> baggage(new Baggage(kv_properties_->Size()));
+ kv_properties_->GetAllEntries(
+ [&baggage, &key](nostd::string_view e_key, nostd::string_view e_value) {
+ if (key != e_key)
+ baggage->kv_properties_->AddEntry(e_key, e_value);
+ return true;
+ });
+ return baggage;
+ }
+
+ // Returns shared_ptr of baggage after extracting key-value pairs from header
+ static nostd::shared_ptr<Baggage> FromHeader(nostd::string_view header) noexcept
+ {
+ if (header.size() > kMaxSize)
+ {
+ // header size exceeds maximum threshold, return empty baggage
+ return GetDefault();
+ }
+
+ common::KeyValueStringTokenizer kv_str_tokenizer(header);
+ size_t cnt = kv_str_tokenizer.NumTokens(); // upper bound on number of kv pairs
+ if (cnt > kMaxKeyValuePairs)
+ {
+ cnt = kMaxKeyValuePairs;
+ }
+
+ nostd::shared_ptr<Baggage> baggage(new Baggage(cnt));
+ bool kv_valid;
+ nostd::string_view key, value;
+
+ while (kv_str_tokenizer.next(kv_valid, key, value) && baggage->kv_properties_->Size() < cnt)
+ {
+ if (!kv_valid || (key.size() + value.size() > kMaxKeyValueSize))
+ {
+ // if kv pair is not valid, skip it
+ continue;
+ }
+
+ // NOTE : metadata is kept as part of value only as it does not have any semantic meaning.
+ // but, we need to extract it (else Decode on value will return error)
+ nostd::string_view metadata;
+ auto metadata_separator = value.find(kMetadataSeparator);
+ if (metadata_separator != std::string::npos)
+ {
+ metadata = value.substr(metadata_separator);
+ value = value.substr(0, metadata_separator);
+ }
+
+ bool err = 0;
+ auto key_str = UrlDecode(common::StringUtil::Trim(key), err);
+ auto value_str = UrlDecode(common::StringUtil::Trim(value), err);
+
+ if (err == false && IsValidKey(key_str) && IsValidValue(value_str))
+ {
+ if (!metadata.empty())
+ {
+ value_str.append(metadata.data(), metadata.size());
+ }
+ baggage->kv_properties_->AddEntry(key_str, value_str);
+ }
+ }
+
+ return baggage;
+ }
+
+ // Creates string from baggage object.
+ std::string ToHeader() const noexcept
+ {
+ std::string header_s;
+ bool first = true;
+ kv_properties_->GetAllEntries([&](nostd::string_view key, nostd::string_view value) {
+ if (!first)
+ {
+ header_s.push_back(kMembersSeparator);
+ }
+ else
+ {
+ first = false;
+ }
+ header_s.append(UrlEncode(key));
+ header_s.push_back(kKeyValueSeparator);
+
+ // extracting metadata from value. We do not encode metadata
+ auto metadata_separator = value.find(kMetadataSeparator);
+ if (metadata_separator != std::string::npos)
+ {
+ header_s.append(UrlEncode(value.substr(0, metadata_separator)));
+ auto metadata = value.substr(metadata_separator);
+ header_s.append(std::string(metadata.data(), metadata.size()));
+ }
+ else
+ {
+ header_s.append(UrlEncode(value));
+ }
+ return true;
+ });
+ return header_s;
+ }
+
+private:
+ static bool IsPrintableString(nostd::string_view str)
+ {
+ for (const auto ch : str)
+ {
+ if (ch < ' ' || ch > '~')
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ static bool IsValidKey(nostd::string_view key) { return key.size() && IsPrintableString(key); }
+
+ static bool IsValidValue(nostd::string_view value) { return IsPrintableString(value); }
+
+ // Uri encode key value pairs before injecting into header
+ // Implementation inspired from : https://golang.org/src/net/url/url.go?s=7851:7884#L264
+ static std::string UrlEncode(nostd::string_view str)
+ {
+ auto to_hex = [](char c) -> char {
+ static const char *hex = "0123456789ABCDEF";
+ return hex[c & 15];
+ };
+
+ std::string ret;
+
+ for (auto c : str)
+ {
+ if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~')
+ {
+ ret.push_back(c);
+ }
+ else if (c == ' ')
+ {
+ ret.push_back('+');
+ }
+ else
+ {
+ ret.push_back('%');
+ ret.push_back(to_hex(c >> 4));
+ ret.push_back(to_hex(c & 15));
+ }
+ }
+
+ return ret;
+ }
+
+ // Uri decode key value pairs after extracting from header
+ static std::string UrlDecode(nostd::string_view str, bool &err)
+ {
+ auto IsHex = [](char c) {
+ return std::isdigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
+ };
+
+ auto from_hex = [](char c) -> char {
+ // c - '0' produces integer type which could trigger error/warning when casting to char,
+ // but the cast is safe here.
+ return static_cast<char>(std::isdigit(c) ? c - '0' : std::toupper(c) - 'A' + 10);
+ };
+
+ std::string ret;
+
+ for (size_t i = 0; i < str.size(); i++)
+ {
+ if (str[i] == '%')
+ {
+ if (i + 2 >= str.size() || !IsHex(str[i + 1]) || !IsHex(str[i + 2]))
+ {
+ err = 1;
+ return "";
+ }
+ ret.push_back(from_hex(str[i + 1]) << 4 | from_hex(str[i + 2]));
+ i += 2;
+ }
+ else if (str[i] == '+')
+ {
+ ret.push_back(' ');
+ }
+ else if (std::isalnum(str[i]) || str[i] == '-' || str[i] == '_' || str[i] == '.' ||
+ str[i] == '~')
+ {
+ ret.push_back(str[i]);
+ }
+ else
+ {
+ err = 1;
+ return "";
+ }
+ }
+
+ return ret;
+ }
+
+private:
+ // Store entries in a C-style array to avoid using std::array or std::vector.
+ nostd::unique_ptr<opentelemetry::common::KeyValueProperties> kv_properties_;
+};
+
+} // namespace baggage
+
+OPENTELEMETRY_END_NAMESPACE
diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/baggage_context.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/baggage_context.h
new file mode 100644
index 000000000..9a92bac77
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/baggage_context.h
@@ -0,0 +1,39 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/baggage/baggage.h"
+#include "opentelemetry/context/context.h"
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+
+namespace baggage
+{
+
+static const std::string kBaggageHeader = "baggage";
+
+inline nostd::shared_ptr<opentelemetry::baggage::Baggage> GetBaggage(
+ const opentelemetry::context::Context &context) noexcept
+{
+ context::ContextValue context_value = context.GetValue(kBaggageHeader);
+ if (nostd::holds_alternative<nostd::shared_ptr<opentelemetry::baggage::Baggage>>(context_value))
+ {
+ return nostd::get<nostd::shared_ptr<opentelemetry::baggage::Baggage>>(context_value);
+ }
+ static nostd::shared_ptr<opentelemetry::baggage::Baggage> empty_baggage{
+ new opentelemetry::baggage::Baggage()};
+ return empty_baggage;
+}
+
+inline context::Context SetBaggage(
+ opentelemetry::context::Context &context,
+ nostd::shared_ptr<opentelemetry::baggage::Baggage> baggage) noexcept
+{
+ return context.SetValue(kBaggageHeader, baggage);
+}
+
+} // namespace baggage
+OPENTELEMETRY_END_NAMESPACE
diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/propagation/baggage_propagator.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/propagation/baggage_propagator.h
new file mode 100644
index 000000000..3de60860b
--- /dev/null
+++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/propagation/baggage_propagator.h
@@ -0,0 +1,54 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/baggage/baggage.h"
+#include "opentelemetry/baggage/baggage_context.h"
+#include "opentelemetry/context/propagation/text_map_propagator.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace baggage
+{
+namespace propagation
+{
+
+class BaggagePropagator : public opentelemetry::context::propagation::TextMapPropagator
+{
+public:
+ void Inject(opentelemetry::context::propagation::TextMapCarrier &carrier,
+ const opentelemetry::context::Context &context) noexcept override
+ {
+ auto baggage = opentelemetry::baggage::GetBaggage(context);
+ auto header = baggage->ToHeader();
+ if (header.size())
+ {
+ carrier.Set(kBaggageHeader, header);
+ }
+ }
+
+ context::Context Extract(const opentelemetry::context::propagation::TextMapCarrier &carrier,
+ opentelemetry::context::Context &context) noexcept override
+ {
+ nostd::string_view baggage_str = carrier.Get(opentelemetry::baggage::kBaggageHeader);
+ auto baggage = opentelemetry::baggage::Baggage::FromHeader(baggage_str);
+
+ if (baggage->ToHeader().size())
+ {
+ return opentelemetry::baggage::SetBaggage(context, baggage);
+ }
+ else
+ {
+ return context;
+ }
+ }
+
+ bool Fields(nostd::function_ref<bool(nostd::string_view)> callback) const noexcept override
+ {
+ return callback(kBaggageHeader);
+ }
+};
+} // namespace propagation
+} // namespace baggage
+OPENTELEMETRY_END_NAMESPACE