Browse Source

include the otel header-only part directly for ease of use

Grant Limberg 3 weeks ago
parent
commit
7f835b414a
100 changed files with 16283 additions and 0 deletions
  1. 299 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/baggage/baggage.h
  2. 36 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/baggage/baggage_context.h
  3. 60 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/baggage/propagation/baggage_propagator.h
  4. 82 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/common/attribute_value.h
  5. 64 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/common/key_value_iterable.h
  6. 146 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/common/key_value_iterable_view.h
  7. 272 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/common/kv_properties.h
  8. 523 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/common/macros.h
  9. 133 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/common/spin_lock_mutex.h
  10. 42 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/common/string_util.h
  11. 206 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/common/timestamp.h
  12. 19 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/config.h
  13. 171 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/context/context.h
  14. 35 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/context/context_value.h
  15. 93 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/context/propagation/composite_propagator.h
  16. 57 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/context/propagation/global_propagator.h
  17. 40 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/context/propagation/noop_propagator.h
  18. 59 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/context/propagation/text_map_propagator.h
  19. 340 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/context/runtime_context.h
  20. 25 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/detail/preprocessor.h
  21. 37 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/event_id.h
  22. 82 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/event_logger.h
  23. 37 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/event_logger_provider.h
  24. 92 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/log_record.h
  25. 492 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/logger.h
  26. 71 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/logger_provider.h
  27. 204 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/logger_type_traits.h
  28. 131 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/noop.h
  29. 100 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/provider.h
  30. 67 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/severity.h
  31. 33 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/metrics/async_instruments.h
  32. 174 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/metrics/meter.h
  33. 148 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/metrics/meter_provider.h
  34. 271 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/metrics/noop.h
  35. 54 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/metrics/observer_result.h
  36. 60 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/metrics/provider.h
  37. 328 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/metrics/sync_instruments.h
  38. 21 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/all.h
  39. 16 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/decay.h
  40. 20 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/dependent_type.h
  41. 66 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/functional.h
  42. 163 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/invoke.h
  43. 75 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/trait.h
  44. 53 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/type_pack_element.h
  45. 14 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/valueless.h
  46. 40 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/variant_alternative.h
  47. 14 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/variant_fwd.h
  48. 33 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/variant_size.h
  49. 28 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/void.h
  50. 94 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/function_ref.h
  51. 621 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/attributes.h
  52. 671 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/config.h
  53. 37 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/internal/identity.h
  54. 107 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/internal/inline_variable.h
  55. 188 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/internal/invoke.h
  56. 220 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/macros.h
  57. 181 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/optimization.h
  58. 216 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/options.h
  59. 115 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/policy_checks.h
  60. 26 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/port.h
  61. 779 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/meta/type_traits.h
  62. 94 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/types/bad_variant_access.h
  63. 1649 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/types/internal/variant.h
  64. 866 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/types/variant.h
  65. 350 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/utility/utility.h
  66. 210 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/shared_ptr.h
  67. 274 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/span.h
  68. 226 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/string_view.h
  69. 172 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/type_traits.h
  70. 180 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/unique_ptr.h
  71. 160 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/utility.h
  72. 85 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/variant.h
  73. 20 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/detail/dynamic_library_handle.h
  74. 73 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/detail/dynamic_load_unix.h
  75. 96 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/detail/dynamic_load_windows.h
  76. 24 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/detail/loader_info.h
  77. 27 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/detail/tracer_handle.h
  78. 36 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/detail/utility.h
  79. 30 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/dynamic_load.h
  80. 65 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/factory.h
  81. 51 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/hook.h
  82. 133 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/tracer.h
  83. 97 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/azure_metrics.h
  84. 213 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/cicd_metrics.h
  85. 41 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/client_attributes.h
  86. 81 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/code_attributes.h
  87. 266 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/container_metrics.h
  88. 141 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/cpu_metrics.h
  89. 349 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/db_attributes.h
  90. 53 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/db_metrics.h
  91. 49 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/dns_metrics.h
  92. 57 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/error_attributes.h
  93. 50 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/exception_attributes.h
  94. 287 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/faas_metrics.h
  95. 157 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/gen_ai_metrics.h
  96. 164 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/http_attributes.h
  97. 77 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/http_metrics.h
  98. 344 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/hw_metrics.h
  99. 76 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/incubating/app_attributes.h
  100. 79 0
      ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/incubating/artifact_attributes.h

+ 299 - 0
ext/opentelemetry-cpp-api-only/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/common/macros.h"
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+
+namespace baggage
+{
+
+class OPENTELEMETRY_EXPORT 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 common::KeyValueProperties()) {}
+  Baggage(size_t size) noexcept : kv_properties_(new common::KeyValueProperties(size)) {}
+
+  template <class T>
+  Baggage(const T &keys_and_values) noexcept
+      : kv_properties_(new common::KeyValueProperties(keys_and_values))
+  {}
+
+  OPENTELEMETRY_API_SINGLETON 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<common::KeyValueProperties> kv_properties_;
+};
+
+}  // namespace baggage
+
+OPENTELEMETRY_END_NAMESPACE

+ 36 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/baggage/baggage_context.h

@@ -0,0 +1,36 @@
+// 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<Baggage> GetBaggage(const context::Context &context) noexcept
+{
+  context::ContextValue context_value = context.GetValue(kBaggageHeader);
+  if (nostd::holds_alternative<nostd::shared_ptr<Baggage>>(context_value))
+  {
+    return nostd::get<nostd::shared_ptr<Baggage>>(context_value);
+  }
+  static nostd::shared_ptr<Baggage> empty_baggage{new Baggage()};
+  return empty_baggage;
+}
+
+inline context::Context SetBaggage(context::Context &context,
+                                   const nostd::shared_ptr<Baggage> &baggage) noexcept
+{
+  return context.SetValue(kBaggageHeader, baggage);
+}
+
+}  // namespace baggage
+OPENTELEMETRY_END_NAMESPACE

+ 60 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/baggage/propagation/baggage_propagator.h

@@ -0,0 +1,60 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "opentelemetry/baggage/baggage.h"
+#include "opentelemetry/baggage/baggage_context.h"
+#include "opentelemetry/context/context.h"
+#include "opentelemetry/context/propagation/text_map_propagator.h"
+#include "opentelemetry/nostd/function_ref.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace baggage
+{
+namespace propagation
+{
+
+class BaggagePropagator : public context::propagation::TextMapPropagator
+{
+public:
+  void Inject(context::propagation::TextMapCarrier &carrier,
+              const context::Context &context) noexcept override
+  {
+    auto baggage = baggage::GetBaggage(context);
+    auto header  = baggage->ToHeader();
+    if (header.size())
+    {
+      carrier.Set(kBaggageHeader, header);
+    }
+  }
+
+  context::Context Extract(const context::propagation::TextMapCarrier &carrier,
+                           context::Context &context) noexcept override
+  {
+    nostd::string_view baggage_str = carrier.Get(baggage::kBaggageHeader);
+    auto baggage                   = baggage::Baggage::FromHeader(baggage_str);
+
+    if (baggage->ToHeader().size())
+    {
+      return 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

+ 82 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/common/attribute_value.h

@@ -0,0 +1,82 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <cstdint>
+
+#include "opentelemetry/nostd/span.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/nostd/variant.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace common
+{
+/// OpenTelemetry signals can be enriched by adding attributes. The
+/// \c AttributeValue type is defined as a variant of all attribute value
+/// types the OpenTelemetry C++ API supports.
+///
+/// The following attribute value types are supported by the OpenTelemetry
+/// specification:
+///  - Primitive types: string, boolean, double precision floating point
+///    (IEEE 754-1985) or signed 64 bit integer.
+///  - Homogenous arrays of primitive type values.
+///
+/// \warning
+/// \parblock The OpenTelemetry C++ API currently supports several attribute
+/// value types that are not covered by the OpenTelemetry specification:
+///  - \c uint64_t
+///  - \c nostd::span<const uint64_t>
+///  - \c nostd::span<uint8_t>
+///
+/// Those types are reserved for future use and currently should not be
+/// used. There are no guarantees around how those values are handled by
+/// exporters.
+/// \endparblock
+using AttributeValue =
+    nostd::variant<bool,
+                   int32_t,
+                   int64_t,
+                   uint32_t,
+                   double,
+                   const char *,
+                   nostd::string_view,
+                   nostd::span<const bool>,
+                   nostd::span<const int32_t>,
+                   nostd::span<const int64_t>,
+                   nostd::span<const uint32_t>,
+                   nostd::span<const double>,
+                   nostd::span<const nostd::string_view>,
+                   // Not currently supported by the specification, but reserved for future use.
+                   // Added to provide support for all primitive C++ types.
+                   uint64_t,
+                   // Not currently supported by the specification, but reserved for future use.
+                   // Added to provide support for all primitive C++ types.
+                   nostd::span<const uint64_t>,
+                   // Not currently supported by the specification, but reserved for future use.
+                   // See https://github.com/open-telemetry/opentelemetry-specification/issues/780
+                   nostd::span<const uint8_t>>;
+
+enum AttributeType
+{
+  kTypeBool,
+  kTypeInt,
+  kTypeInt64,
+  kTypeUInt,
+  kTypeDouble,
+  kTypeCString,
+  kTypeString,
+  kTypeSpanBool,
+  kTypeSpanInt,
+  kTypeSpanInt64,
+  kTypeSpanUInt,
+  kTypeSpanDouble,
+  kTypeSpanString,
+  kTypeUInt64,
+  kTypeSpanUInt64,
+  kTypeSpanByte
+};
+
+}  // namespace common
+OPENTELEMETRY_END_NAMESPACE

+ 64 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/common/key_value_iterable.h

@@ -0,0 +1,64 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/common/attribute_value.h"
+#include "opentelemetry/nostd/function_ref.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace common
+{
+/**
+ * Supports internal iteration over a collection of key-value pairs.
+ */
+class KeyValueIterable
+{
+public:
+  virtual ~KeyValueIterable() = default;
+
+  /**
+   * Iterate over key-value pairs
+   * @param callback a callback to invoke for each key-value. If the callback returns false,
+   * the iteration is aborted.
+   * @return true if every key-value pair was iterated over
+   */
+  virtual bool ForEachKeyValue(nostd::function_ref<bool(nostd::string_view, common::AttributeValue)>
+                                   callback) const noexcept = 0;
+
+  /**
+   * @return the number of key-value pairs
+   */
+  virtual size_t size() const noexcept = 0;
+};
+
+/**
+ * Supports internal iteration over a collection of key-value pairs.
+ */
+class NoopKeyValueIterable : public KeyValueIterable
+{
+public:
+  ~NoopKeyValueIterable() override = default;
+
+  /**
+   * Iterate over key-value pairs
+   * @param callback a callback to invoke for each key-value. If the callback returns false,
+   * the iteration is aborted.
+   * @return true if every key-value pair was iterated over
+   */
+  bool ForEachKeyValue(
+      nostd::function_ref<bool(nostd::string_view, common::AttributeValue)>) const noexcept override
+  {
+    return true;
+  }
+
+  /**
+   * @return the number of key-value pairs
+   */
+  size_t size() const noexcept override { return 0; }
+};
+
+}  // namespace common
+OPENTELEMETRY_END_NAMESPACE

+ 146 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/common/key_value_iterable_view.h

@@ -0,0 +1,146 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <stddef.h>
+#include <initializer_list>
+#include <iterator>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "opentelemetry/common/attribute_value.h"
+#include "opentelemetry/common/key_value_iterable.h"
+#include "opentelemetry/nostd/function_ref.h"
+#include "opentelemetry/nostd/span.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/nostd/type_traits.h"
+#include "opentelemetry/nostd/utility.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace common
+{
+// NOTE - code within `detail` namespace implements internal details, and not part
+// of the public interface.
+namespace detail
+{
+inline void take_key_value(nostd::string_view, common::AttributeValue) {}
+
+template <class T>
+auto is_key_value_iterable_impl(T iterable)
+    -> decltype(take_key_value(std::begin(iterable)->first, std::begin(iterable)->second),
+                nostd::size(iterable),
+                std::true_type{});
+
+std::false_type is_key_value_iterable_impl(...);
+
+template <class T>
+struct is_key_value_iterable
+{
+  static const bool value = decltype(detail::is_key_value_iterable_impl(std::declval<T>()))::value;
+};
+}  // namespace detail
+
+/**
+ * @brief Container for key-value pairs that can transform every value in it to one of types
+ * listed in common::AttributeValue. It may contain value types that are not directly map'able
+ * to primitive value types. In that case the `ForEachKeyValue` method acts as a transform to
+ * convert the value type to one listed under AtributeValue (bool, int32_t, int64_t, uint32_t,
+ * uint64_t, double, nostd::string_view, or arrays of primite types). For example, if UUID,
+ * GUID, or UTF-16 string type is passed as one of values stored inside this container, the
+ * container itself may provide a custom implementation of `ForEachKeyValue` to transform the
+ * 'non-standard' type to one of the standard types.
+ */
+template <class T>
+class KeyValueIterableView final : public KeyValueIterable
+{
+
+public:
+  explicit KeyValueIterableView(const T &container) noexcept : container_{&container} {}
+
+  // KeyValueIterable
+  bool ForEachKeyValue(nostd::function_ref<bool(nostd::string_view, common::AttributeValue)>
+                           callback) const noexcept override
+  {
+    auto iter = std::begin(*container_);
+    auto last = std::end(*container_);
+    for (; iter != last; ++iter)
+    {
+      if (!callback(iter->first, iter->second))
+      {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  size_t size() const noexcept override { return nostd::size(*container_); }
+
+private:
+  const T *container_;
+};
+
+template <class T, nostd::enable_if_t<detail::is_key_value_iterable<T>::value> * = nullptr>
+KeyValueIterableView<T> MakeKeyValueIterableView(const T &container) noexcept
+{
+  return KeyValueIterableView<T>(container);
+}
+
+/**
+ * Utility function to help to make a attribute view from initializer_list
+ *
+ * @param attributes
+ * @return nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>
+ */
+inline static nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>
+MakeAttributes(std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
+                   attributes) noexcept
+{
+  return nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
+      attributes.begin(), attributes.end()};
+}
+
+/**
+ * Utility function to help to make a attribute view from a span
+ *
+ * @param attributes
+ * @return nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>
+ */
+inline static nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>
+MakeAttributes(
+    nostd::span<const std::pair<nostd::string_view, common::AttributeValue>> attributes) noexcept
+{
+  return attributes;
+}
+
+/**
+ * Utility function to help to make a attribute view from a KeyValueIterable
+ *
+ * @param attributes
+ * @return common::KeyValueIterable
+ */
+inline static const common::KeyValueIterable &MakeAttributes(
+    const common::KeyValueIterable &attributes) noexcept
+{
+  return attributes;
+}
+
+/**
+ * Utility function to help to make a attribute view from a key-value iterable object
+ *
+ * @param attributes
+ * @return nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>
+ */
+template <
+    class ArgumentType,
+    nostd::enable_if_t<common::detail::is_key_value_iterable<ArgumentType>::value> * = nullptr>
+inline static common::KeyValueIterableView<ArgumentType> MakeAttributes(
+    const ArgumentType &arg) noexcept
+{
+  return common::KeyValueIterableView<ArgumentType>(arg);
+}
+
+}  // namespace common
+OPENTELEMETRY_END_NAMESPACE

+ 272 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/common/kv_properties.h

@@ -0,0 +1,272 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/common/key_value_iterable_view.h"
+#include "opentelemetry/common/string_util.h"
+#include "opentelemetry/nostd/function_ref.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/nostd/unique_ptr.h"
+#include "opentelemetry/version.h"
+
+#include <cstring>
+#include <string>
+#include <type_traits>
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace common
+{
+
+// Constructor parameter for KeyValueStringTokenizer
+struct KeyValueStringTokenizerOptions
+{
+  char member_separator     = ',';
+  char key_value_separator  = '=';
+  bool ignore_empty_members = true;
+};
+
+// Tokenizer for key-value headers
+class KeyValueStringTokenizer
+{
+public:
+  KeyValueStringTokenizer(
+      nostd::string_view str,
+      const KeyValueStringTokenizerOptions &opts = KeyValueStringTokenizerOptions()) noexcept
+      : str_(str), opts_(opts), index_(0)
+  {}
+
+  static nostd::string_view GetDefaultKeyOrValue()
+  {
+    static std::string default_str = "";
+    return default_str;
+  }
+
+  // Returns next key value in the string header
+  // @param valid_kv : if the found kv pair is valid or not
+  // @param key : key in kv pair
+  // @param key : value in kv pair
+  // @returns true if next kv pair was found, false otherwise.
+  bool next(bool &valid_kv, nostd::string_view &key, nostd::string_view &value) noexcept
+  {
+    valid_kv = true;
+    while (index_ < str_.size())
+    {
+      bool is_empty_pair = false;
+      size_t end         = str_.find(opts_.member_separator, index_);
+      if (end == std::string::npos)
+      {
+        end = str_.size() - 1;
+      }
+      else if (end == index_)  // empty pair. do not update end
+      {
+        is_empty_pair = true;
+      }
+      else
+      {
+        end--;
+      }
+
+      auto list_member = StringUtil::Trim(str_, index_, end);
+      if (list_member.size() == 0 || is_empty_pair)
+      {
+        // empty list member
+        index_ = end + 2 - is_empty_pair;
+        if (opts_.ignore_empty_members)
+        {
+          continue;
+        }
+
+        valid_kv = true;
+        key      = GetDefaultKeyOrValue();
+        value    = GetDefaultKeyOrValue();
+        return true;
+      }
+
+      auto key_end_pos = list_member.find(opts_.key_value_separator);
+      if (key_end_pos == std::string::npos)
+      {
+        // invalid member
+        valid_kv = false;
+      }
+      else
+      {
+        key   = list_member.substr(0, key_end_pos);
+        value = list_member.substr(key_end_pos + 1);
+      }
+
+      index_ = end + 2;
+
+      return true;
+    }
+
+    // no more entries remaining
+    return false;
+  }
+
+  // Returns total number of tokens in header string
+  size_t NumTokens() const noexcept
+  {
+    size_t cnt = 0, begin = 0;
+    while (begin < str_.size())
+    {
+      ++cnt;
+      size_t end = str_.find(opts_.member_separator, begin);
+      if (end == std::string::npos)
+      {
+        break;
+      }
+
+      begin = end + 1;
+    }
+
+    return cnt;
+  }
+
+  // Resets the iterator
+  void reset() noexcept { index_ = 0; }
+
+private:
+  nostd::string_view str_;
+  KeyValueStringTokenizerOptions opts_;
+  size_t index_;
+};
+
+// Class to store fixed size array of key-value pairs of string type
+class KeyValueProperties
+{
+  // Class to store key-value pairs of string types
+public:
+  class Entry
+  {
+  public:
+    Entry() : key_(nullptr), value_(nullptr) {}
+
+    // Copy constructor
+    Entry(const Entry &copy)
+    {
+      key_   = CopyStringToPointer(copy.key_.get());
+      value_ = CopyStringToPointer(copy.value_.get());
+    }
+
+    // Copy assignment operator
+    Entry &operator=(Entry &other)
+    {
+      key_   = CopyStringToPointer(other.key_.get());
+      value_ = CopyStringToPointer(other.value_.get());
+      return *this;
+    }
+
+    // Move contructor and assignment operator
+    Entry(Entry &&other)            = default;
+    Entry &operator=(Entry &&other) = default;
+
+    // Creates an Entry for a given key-value pair.
+    Entry(nostd::string_view key, nostd::string_view value)
+    {
+      key_   = CopyStringToPointer(key);
+      value_ = CopyStringToPointer(value);
+    }
+
+    // Gets the key associated with this entry.
+    nostd::string_view GetKey() const noexcept { return key_.get(); }
+
+    // Gets the value associated with this entry.
+    nostd::string_view GetValue() const noexcept { return value_.get(); }
+
+    // Sets the value for this entry. This overrides the previous value.
+    void SetValue(nostd::string_view value) noexcept { value_ = CopyStringToPointer(value); }
+
+  private:
+    // Store key and value as raw char pointers to avoid using std::string.
+    nostd::unique_ptr<const char[]> key_;
+    nostd::unique_ptr<const char[]> value_;
+
+    // Copies string into a buffer and returns a unique_ptr to the buffer.
+    // This is a workaround for the fact that memcpy doesn't accept a const destination.
+    nostd::unique_ptr<const char[]> CopyStringToPointer(nostd::string_view str)
+    {
+      char *temp = new char[str.size() + 1];
+      memcpy(temp, str.data(), str.size());
+      temp[str.size()] = '\0';
+      return nostd::unique_ptr<const char[]>(temp);
+    }
+  };
+
+  // Maintain the number of entries in entries_.
+  size_t num_entries_;
+
+  // Max size of allocated array
+  size_t max_num_entries_;
+
+  // Store entries in a C-style array to avoid using std::array or std::vector.
+  nostd::unique_ptr<Entry[]> entries_;
+
+public:
+  // Create Key-value list of given size
+  // @param size : Size of list.
+  KeyValueProperties(size_t size) noexcept
+      : num_entries_(0), max_num_entries_(size), entries_(new Entry[size])
+  {}
+
+  // Create Empty Key-Value list
+  KeyValueProperties() noexcept : num_entries_(0), max_num_entries_(0), entries_(nullptr) {}
+
+  template <class T, class = typename std::enable_if<detail::is_key_value_iterable<T>::value>::type>
+  KeyValueProperties(const T &keys_and_values) noexcept
+      : num_entries_(0),
+        max_num_entries_(keys_and_values.size()),
+        entries_(new Entry[max_num_entries_])
+  {
+    for (auto &e : keys_and_values)
+    {
+      Entry entry(e.first, e.second);
+      (entries_.get())[num_entries_++] = std::move(entry);
+    }
+  }
+
+  // Adds new kv pair into kv properties
+  void AddEntry(nostd::string_view key, nostd::string_view value) noexcept
+  {
+    if (num_entries_ < max_num_entries_)
+    {
+      Entry entry(key, value);
+      (entries_.get())[num_entries_++] = std::move(entry);
+    }
+  }
+
+  // Returns all kv pair entries
+  bool GetAllEntries(
+      nostd::function_ref<bool(nostd::string_view, nostd::string_view)> callback) const noexcept
+  {
+    for (size_t i = 0; i < num_entries_; i++)
+    {
+      auto &entry = (entries_.get())[i];
+      if (!callback(entry.GetKey(), entry.GetValue()))
+      {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  // Return value for key if exists, return false otherwise
+  bool GetValue(nostd::string_view key, std::string &value) const noexcept
+  {
+    for (size_t i = 0; i < num_entries_; i++)
+    {
+      auto &entry = (entries_.get())[i];
+      if (entry.GetKey() == key)
+      {
+        const auto &entry_value = entry.GetValue();
+        value                   = std::string(entry_value.data(), entry_value.size());
+        return true;
+      }
+    }
+    return false;
+  }
+
+  size_t Size() const noexcept { return num_entries_; }
+};
+}  // namespace common
+OPENTELEMETRY_END_NAMESPACE

+ 523 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/common/macros.h

@@ -0,0 +1,523 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+/*
+   OPENTELEMETRY_HAVE_BUILTIN&OPENTELEMETRY_HAVE_FEATURE
+
+   Checks whether the compiler supports a Clang Feature Checking Macro, and if
+   so, checks whether it supports the provided builtin function "x" where x
+   is one of the functions noted in
+   https://clang.llvm.org/docs/LanguageExtensions.html
+
+   Note: Use this macro to avoid an extra level of #ifdef __has_builtin check.
+   http://releases.llvm.org/3.3/tools/clang/docs/LanguageExtensions.html
+*/
+#if !defined(OPENTELEMETRY_HAVE_BUILTIN)
+#  ifdef __has_builtin
+#    define OPENTELEMETRY_HAVE_BUILTIN(x) __has_builtin(x)
+#  else
+#    define OPENTELEMETRY_HAVE_BUILTIN(x) 0
+#  endif
+#endif
+
+#if !defined(OPENTELEMETRY_HAVE_FEATURE)
+#  ifdef __has_feature
+#    define OPENTELEMETRY_HAVE_FEATURE(f) __has_feature(f)
+#  else
+#    define OPENTELEMETRY_HAVE_FEATURE(f) 0
+#  endif
+#endif
+
+/*
+   has feature
+
+   OPENTELEMETRY_HAVE_ATTRIBUTE
+
+   A function-like feature checking macro that is a wrapper around
+   `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a
+   nonzero constant integer if the attribute is supported or 0 if not.
+
+   It evaluates to zero if `__has_attribute` is not defined by the compiler.
+
+   GCC: https://gcc.gnu.org/gcc-5/changes.html
+   Clang: https://clang.llvm.org/docs/LanguageExtensions.html
+*/
+#if !defined(OPENTELEMETRY_HAVE_ATTRIBUTE)
+#  ifdef __has_attribute
+#    define OPENTELEMETRY_HAVE_ATTRIBUTE(x) __has_attribute(x)
+#  else
+#    define OPENTELEMETRY_HAVE_ATTRIBUTE(x) 0
+#  endif
+#endif
+
+/*
+   OPENTELEMETRY_HAVE_CPP_ATTRIBUTE
+
+   A function-like feature checking macro that accepts C++11 style attributes.
+   It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6
+   (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
+   find `__has_cpp_attribute`, will evaluate to 0.
+*/
+#if !defined(OPENTELEMETRY_HAVE_CPP_ATTRIBUTE)
+#  if defined(__cplusplus) && defined(__has_cpp_attribute)
+// NOTE: requiring __cplusplus above should not be necessary, but
+// works around https://bugs.llvm.org/show_bug.cgi?id=23435.
+#    define OPENTELEMETRY_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
+#  else
+#    define OPENTELEMETRY_HAVE_CPP_ATTRIBUTE(x) 0
+#  endif
+#endif
+
+/*
+   Expected usage pattern:
+
+   if OPENTELEMETRY_LIKELY_CONDITION (ptr != nullptr)
+   {
+     do_something_likely();
+   } else {
+     do_something_unlikely();
+   }
+
+   This pattern works with gcc/clang and __builtin_expect(),
+   as well as with C++20.
+   It is unclear if __builtin_expect() will be deprecated
+   in favor of C++20 [[likely]] or not.
+
+   OPENTELEMETRY_LIKELY_CONDITION is preferred over OPENTELEMETRY_LIKELY,
+   to be revisited when C++20 is required.
+*/
+
+#if !defined(OPENTELEMETRY_LIKELY_CONDITION) && defined(__cplusplus)
+// Only use likely with C++20
+#  if __cplusplus >= 202002L
+// GCC 9 has likely attribute but do not support declare it at the beginning of statement
+#    if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9)
+#      if __has_cpp_attribute(likely)
+#        define OPENTELEMETRY_LIKELY_CONDITION(C) (C) [[likely]]
+#      endif
+#    endif
+#  endif
+#endif
+#if !defined(OPENTELEMETRY_LIKELY_CONDITION) && (defined(__clang__) || defined(__GNUC__))
+// Only use if supported by the compiler
+#  define OPENTELEMETRY_LIKELY_CONDITION(C) (__builtin_expect(!!(C), true))
+#endif
+#ifndef OPENTELEMETRY_LIKELY_CONDITION
+// Do not use likely annotations
+#  define OPENTELEMETRY_LIKELY_CONDITION(C) (C)
+#endif
+
+#if !defined(OPENTELEMETRY_UNLIKELY_CONDITION) && defined(__cplusplus)
+// Only use unlikely with C++20
+#  if __cplusplus >= 202002L
+// GCC 9 has unlikely attribute but do not support declare it at the beginning of statement
+#    if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9)
+#      if __has_cpp_attribute(unlikely)
+#        define OPENTELEMETRY_UNLIKELY_CONDITION(C) (C) [[unlikely]]
+#      endif
+#    endif
+#  endif
+#endif
+#if !defined(OPENTELEMETRY_UNLIKELY_CONDITION) && (defined(__clang__) || defined(__GNUC__))
+// Only use if supported by the compiler
+#  define OPENTELEMETRY_UNLIKELY_CONDITION(C) (__builtin_expect(!!(C), false))
+#endif
+#ifndef OPENTELEMETRY_UNLIKELY_CONDITION
+// Do not use unlikely annotations
+#  define OPENTELEMETRY_UNLIKELY_CONDITION(C) (C)
+#endif
+
+/*
+   Expected usage pattern:
+
+   if (ptr != nullptr)
+   OPENTELEMETRY_LIKELY
+   {
+     do_something_likely();
+   } else {
+     do_something_unlikely();
+   }
+
+   This pattern works starting with C++20.
+   See https://en.cppreference.com/w/cpp/language/attributes/likely
+
+   Please use OPENTELEMETRY_LIKELY_CONDITION instead for now.
+*/
+
+#if !defined(OPENTELEMETRY_LIKELY) && defined(__cplusplus)
+// Only use likely with C++20
+#  if __cplusplus >= 202002L
+// GCC 9 has likely attribute but do not support declare it at the beginning of statement
+#    if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9)
+#      if __has_cpp_attribute(likely)
+#        define OPENTELEMETRY_LIKELY [[likely]]
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifndef OPENTELEMETRY_LIKELY
+#  define OPENTELEMETRY_LIKELY
+#endif
+
+#if !defined(OPENTELEMETRY_UNLIKELY) && defined(__cplusplus)
+// Only use unlikely with C++20
+#  if __cplusplus >= 202002L
+// GCC 9 has unlikely attribute but do not support declare it at the beginning of statement
+#    if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9)
+#      if __has_cpp_attribute(unlikely)
+#        define OPENTELEMETRY_UNLIKELY [[unlikely]]
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifndef OPENTELEMETRY_UNLIKELY
+#  define OPENTELEMETRY_UNLIKELY
+#endif
+
+/// \brief Declare variable as maybe unused
+/// usage:
+///   OPENTELEMETRY_MAYBE_UNUSED int a;
+///   class OPENTELEMETRY_MAYBE_UNUSED a;
+///   OPENTELEMETRY_MAYBE_UNUSED int a();
+///
+#if defined(__cplusplus) && __cplusplus >= 201703L
+#  define OPENTELEMETRY_MAYBE_UNUSED [[maybe_unused]]
+#elif defined(__clang__)
+#  define OPENTELEMETRY_MAYBE_UNUSED __attribute__((unused))
+#elif defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
+#  define OPENTELEMETRY_MAYBE_UNUSED __attribute__((unused))
+#elif (defined(_MSC_VER) && _MSC_VER >= 1910) && (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
+#  define OPENTELEMETRY_MAYBE_UNUSED [[maybe_unused]]
+#else
+#  define OPENTELEMETRY_MAYBE_UNUSED
+#endif
+
+#ifndef OPENTELEMETRY_RTTI_ENABLED
+#  if defined(__clang__)
+#    if __has_feature(cxx_rtti)
+#      define OPENTELEMETRY_RTTI_ENABLED
+#    endif
+#  elif defined(__GNUG__)
+#    if defined(__GXX_RTTI)
+#      define OPENTELEMETRY_RTTI_ENABLED
+#    endif
+#  elif defined(_MSC_VER)
+#    if defined(_CPPRTTI)
+#      define OPENTELEMETRY_RTTI_ENABLED
+#    endif
+#  endif
+#endif
+
+#if defined(__cplusplus) && __cplusplus >= 201402L
+#  define OPENTELEMETRY_DEPRECATED [[deprecated]]
+#elif defined(__clang__)
+#  define OPENTELEMETRY_DEPRECATED __attribute__((deprecated))
+#elif defined(__GNUC__)
+#  define OPENTELEMETRY_DEPRECATED __attribute__((deprecated))
+#elif defined(_MSC_VER)
+#  if _MSC_VER >= 1910 && defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
+#    define OPENTELEMETRY_DEPRECATED [[deprecated]]
+#  else
+#    define OPENTELEMETRY_DEPRECATED __declspec(deprecated)
+#  endif
+#else
+#  define OPENTELEMETRY_DEPRECATED
+#endif
+
+#if defined(__cplusplus) && __cplusplus >= 201402L
+#  define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) [[deprecated(msg)]]
+#elif defined(__clang__)
+#  define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) __attribute__((deprecated(msg)))
+#elif defined(__GNUC__)
+#  define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) __attribute__((deprecated(msg)))
+#elif defined(_MSC_VER)
+#  if _MSC_VER >= 1910 && defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
+#    define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) [[deprecated(msg)]]
+#  else
+#    define OPENTELEMETRY_DEPRECATED_MESSAGE(msg) __declspec(deprecated(msg))
+#  endif
+#else
+#  define OPENTELEMETRY_DEPRECATED_MESSAGE(msg)
+#endif
+
+// Regex support
+#if (__GNUC__ == 4 && (__GNUC_MINOR__ == 8 || __GNUC_MINOR__ == 9))
+#  define OPENTELEMETRY_HAVE_WORKING_REGEX 0
+#else
+#  define OPENTELEMETRY_HAVE_WORKING_REGEX 1
+#endif
+
+/* clang-format off */
+
+/**
+  @page HEADER_ONLY_SINGLETON Header only singleton.
+
+  @section ELF_SINGLETON
+
+  For clang and gcc, the desired coding pattern is as follows.
+
+  @verbatim
+  class Foo
+  {
+    // (a)
+    __attribute__((visibility("default")))
+    // (b)
+    T& get_singleton()
+    {
+      // (c)
+      static T singleton;
+      return singleton;
+    }
+  };
+  @endverbatim
+
+  (a) is needed when the code is build with
+  @code -fvisibility="hidden" @endcode
+  to ensure that all instances of (b) are visible to the linker.
+
+  What is duplicated in the binary is @em code, in (b).
+
+  The linker will make sure only one instance
+  of all the (b) methods is used.
+
+  (c) is a singleton implemented inside a method.
+
+  This is very desirable, because:
+
+  - the C++ compiler guarantees that construction
+    of the variable (c) is thread safe.
+
+  - constructors for (c) singletons are executed in code path order,
+    or not at all if the singleton is never used.
+
+  @section OTHER_SINGLETON
+
+  For other platforms, header only singletons are not supported at this
+point.
+
+  @section CODING_PATTERN
+
+  The coding pattern to use in the source code is as follows
+
+  @verbatim
+  class Foo
+  {
+    OPENTELEMETRY_API_SINGLETON
+    T& get_singleton()
+    {
+      static T singleton;
+      return singleton;
+    }
+  };
+  @endverbatim
+*/
+
+/* clang-format on */
+
+#if defined(__clang__)
+
+#  define OPENTELEMETRY_API_SINGLETON __attribute__((visibility("default")))
+#  define OPENTELEMETRY_LOCAL_SYMBOL __attribute__((visibility("hidden")))
+
+#elif defined(__GNUC__)
+
+#  define OPENTELEMETRY_API_SINGLETON __attribute__((visibility("default")))
+#  define OPENTELEMETRY_LOCAL_SYMBOL __attribute__((visibility("hidden")))
+
+#else
+
+/* Add support for other compilers here. */
+
+#  define OPENTELEMETRY_API_SINGLETON
+#  define OPENTELEMETRY_LOCAL_SYMBOL
+
+#endif
+
+//
+// Atomic wrappers based on compiler intrinsics for memory read/write.
+// The tailing number is read/write length in bits.
+//
+// N.B. Compiler intrinsic is used because the usage of C++ standard library is restricted in the
+// OpenTelemetry C++ API.
+//
+#if defined(__GNUC__)
+
+#  define OPENTELEMETRY_ATOMIC_READ_8(ptr) __atomic_load_n(ptr, __ATOMIC_SEQ_CST)
+#  define OPENTELEMETRY_ATOMIC_WRITE_8(ptr, value) __atomic_store_n(ptr, value, __ATOMIC_SEQ_CST)
+
+#elif defined(_MSC_VER)
+
+#  include <intrin.h>
+
+#  define OPENTELEMETRY_ATOMIC_READ_8(ptr) \
+    static_cast<uint8_t>(_InterlockedCompareExchange8(reinterpret_cast<char *>(ptr), 0, 0))
+#  define OPENTELEMETRY_ATOMIC_WRITE_8(ptr, value) \
+    _InterlockedExchange8(reinterpret_cast<char *>(ptr), static_cast<char>(value))
+
+#else
+#  error port atomics read/write for the current platform
+#endif
+
+/* clang-format on */
+//
+// The if/elif order matters here. If both OPENTELEMETRY_BUILD_IMPORT_DLL and
+// OPENTELEMETRY_BUILD_EXPORT_DLL are defined, the former takes precedence.
+//
+// TODO: consider define OPENTELEMETRY_EXPORT for cygwin/gcc, see below link.
+// https://gcc.gnu.org/wiki/Visibility#How_to_use_the_new_C.2B-.2B-_visibility_support
+//
+#if defined(_MSC_VER) && defined(OPENTELEMETRY_BUILD_IMPORT_DLL)
+
+#  define OPENTELEMETRY_EXPORT __declspec(dllimport)
+
+#elif defined(_MSC_VER) && defined(OPENTELEMETRY_BUILD_EXPORT_DLL)
+
+#  define OPENTELEMETRY_EXPORT __declspec(dllexport)
+
+#else
+
+//
+// build OpenTelemetry as static library or not on Windows.
+//
+#  define OPENTELEMETRY_EXPORT
+
+#endif
+
+// OPENTELEMETRY_HAVE_EXCEPTIONS
+//
+// Checks whether the compiler both supports and enables exceptions. Many
+// compilers support a "no exceptions" mode that disables exceptions.
+//
+// Generally, when OPENTELEMETRY_HAVE_EXCEPTIONS is not defined:
+//
+// * Code using `throw` and `try` may not compile.
+// * The `noexcept` specifier will still compile and behave as normal.
+// * The `noexcept` operator may still return `false`.
+//
+// For further details, consult the compiler's documentation.
+#ifndef OPENTELEMETRY_HAVE_EXCEPTIONS
+#  if defined(__clang__) && ((__clang_major__ * 100) + __clang_minor__) < 306
+// Clang < 3.6
+// http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro
+#    if defined(__EXCEPTIONS) && OPENTELEMETRY_HAVE_FEATURE(cxx_exceptions)
+#      define OPENTELEMETRY_HAVE_EXCEPTIONS 1
+#    endif  // defined(__EXCEPTIONS) && OPENTELEMETRY_HAVE_FEATURE(cxx_exceptions)
+#  elif OPENTELEMETRY_HAVE_FEATURE(cxx_exceptions)
+#    define OPENTELEMETRY_HAVE_EXCEPTIONS 1
+// Handle remaining special cases and default to exceptions being supported.
+#  elif !(defined(__GNUC__) && !defined(__EXCEPTIONS) && !defined(__cpp_exceptions)) && \
+      !(defined(_MSC_VER) && !defined(_CPPUNWIND))
+#    define OPENTELEMETRY_HAVE_EXCEPTIONS 1
+#  endif
+#endif
+#ifndef OPENTELEMETRY_HAVE_EXCEPTIONS
+#  define OPENTELEMETRY_HAVE_EXCEPTIONS 0
+#endif
+
+/*
+   OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function
+   parameter or implicit object parameter is retained by the return value of the
+   annotated function (or, for a parameter of a constructor, in the value of the
+   constructed object). This attribute causes warnings to be produced if a
+   temporary object does not live long enough.
+
+   When applied to a reference parameter, the referenced object is assumed to be
+   retained by the return value of the function. When applied to a non-reference
+   parameter (for example, a pointer or a class type), all temporaries
+   referenced by the parameter are assumed to be retained by the return value of
+   the function.
+
+   See also the upstream documentation:
+   https://clang.llvm.org/docs/AttributeReference.html#lifetimebound
+*/
+#ifndef OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND
+#  if OPENTELEMETRY_HAVE_CPP_ATTRIBUTE(clang::lifetimebound)
+#    define OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]]
+#  elif OPENTELEMETRY_HAVE_ATTRIBUTE(lifetimebound)
+#    define OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound))
+#  else
+#    define OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND
+#  endif
+#endif
+
+// OPENTELEMETRY_HAVE_MEMORY_SANITIZER
+//
+// MemorySanitizer (MSan) is a detector of uninitialized reads. It consists of
+// a compiler instrumentation module and a run-time library.
+#ifndef OPENTELEMETRY_HAVE_MEMORY_SANITIZER
+#  if !defined(__native_client__) && OPENTELEMETRY_HAVE_FEATURE(memory_sanitizer)
+#    define OPENTELEMETRY_HAVE_MEMORY_SANITIZER 1
+#  else
+#    define OPENTELEMETRY_HAVE_MEMORY_SANITIZER 0
+#  endif
+#endif
+
+#if OPENTELEMETRY_HAVE_MEMORY_SANITIZER && OPENTELEMETRY_HAVE_ATTRIBUTE(no_sanitize_memory)
+#  define OPENTELEMETRY_SANITIZER_NO_MEMORY \
+    __attribute__((no_sanitize_memory))  // __attribute__((no_sanitize("memory")))
+#else
+#  define OPENTELEMETRY_SANITIZER_NO_MEMORY
+#endif
+
+// OPENTELEMETRY_HAVE_THREAD_SANITIZER
+//
+// ThreadSanitizer (TSan) is a fast data race detector.
+#ifndef OPENTELEMETRY_HAVE_THREAD_SANITIZER
+#  if defined(__SANITIZE_THREAD__)
+#    define OPENTELEMETRY_HAVE_THREAD_SANITIZER 1
+#  elif OPENTELEMETRY_HAVE_FEATURE(thread_sanitizer)
+#    define OPENTELEMETRY_HAVE_THREAD_SANITIZER 1
+#  else
+#    define OPENTELEMETRY_HAVE_THREAD_SANITIZER 0
+#  endif
+#endif
+
+#if OPENTELEMETRY_HAVE_THREAD_SANITIZER && OPENTELEMETRY_HAVE_ATTRIBUTE(no_sanitize_thread)
+#  define OPENTELEMETRY_SANITIZER_NO_THREAD \
+    __attribute__((no_sanitize_thread))  // __attribute__((no_sanitize("thread")))
+#else
+#  define OPENTELEMETRY_SANITIZER_NO_THREAD
+#endif
+
+// OPENTELEMETRY_HAVE_ADDRESS_SANITIZER
+//
+// AddressSanitizer (ASan) is a fast memory error detector.
+#ifndef OPENTELEMETRY_HAVE_ADDRESS_SANITIZER
+#  if defined(__SANITIZE_ADDRESS__)
+#    define OPENTELEMETRY_HAVE_ADDRESS_SANITIZER 1
+#  elif OPENTELEMETRY_HAVE_FEATURE(address_sanitizer)
+#    define OPENTELEMETRY_HAVE_ADDRESS_SANITIZER 1
+#  else
+#    define OPENTELEMETRY_HAVE_ADDRESS_SANITIZER 0
+#  endif
+#endif
+
+// OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER
+//
+// Hardware-Assisted AddressSanitizer (or HWASAN) is even faster than asan
+// memory error detector which can use CPU features like ARM TBI, Intel LAM or
+// AMD UAI.
+#ifndef OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER
+#  if defined(__SANITIZE_HWADDRESS__)
+#    define OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER 1
+#  elif OPENTELEMETRY_HAVE_FEATURE(hwaddress_sanitizer)
+#    define OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER 1
+#  else
+#    define OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER 0
+#  endif
+#endif
+
+#if OPENTELEMETRY_HAVE_ADDRESS_SANITIZER && OPENTELEMETRY_HAVE_ATTRIBUTE(no_sanitize_address)
+#  define OPENTELEMETRY_SANITIZER_NO_ADDRESS \
+    __attribute__((no_sanitize_address))  // __attribute__((no_sanitize("address")))
+#elif OPENTELEMETRY_HAVE_ADDRESS_SANITIZER && defined(_MSC_VER) && _MSC_VER >= 1928
+#  define OPENTELEMETRY_SANITIZER_NO_ADDRESS __declspec(no_sanitize_address)
+#elif OPENTELEMETRY_HAVE_HWADDRESS_SANITIZER && OPENTELEMETRY_HAVE_ATTRIBUTE(no_sanitize)
+#  define OPENTELEMETRY_SANITIZER_NO_ADDRESS __attribute__((no_sanitize("hwaddress")))
+#else
+#  define OPENTELEMETRY_SANITIZER_NO_ADDRESS
+#endif

+ 133 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/common/spin_lock_mutex.h

@@ -0,0 +1,133 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <atomic>
+#include <chrono>
+#include <thread>
+
+#include "opentelemetry/version.h"
+
+#if defined(_MSC_VER)
+#  define _WINSOCKAPI_  // stops including winsock.h
+#  include <windows.h>
+#elif defined(__i386__) || defined(__x86_64__)
+#  if defined(__clang__)
+#    include <emmintrin.h>
+#  elif defined(__INTEL_COMPILER)
+#    include <immintrin.h>
+#  endif
+#endif
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace common
+{
+
+constexpr int SPINLOCK_FAST_ITERATIONS = 100;
+constexpr int SPINLOCK_SLEEP_MS        = 1;
+
+/**
+ * A Mutex which uses atomic flags and spin-locks instead of halting threads.
+ *
+ * This mutex uses an incremental back-off strategy with the following phases:
+ * 1. A tight spin-lock loop (pending: using hardware PAUSE/YIELD instructions)
+ * 2. A loop where the current thread yields control after checking the lock.
+ * 3. Issuing a thread-sleep call before starting back in phase 1.
+ *
+ * This is meant to give a good balance of perofrmance and CPU consumption in
+ * practice.
+ *
+ * This mutex uses an incremental back-off strategy with the following phases:
+ * 1. A tight spin-lock loop (pending: using hardware PAUSE/YIELD instructions)
+ * 2. A loop where the current thread yields control after checking the lock.
+ * 3. Issuing a thread-sleep call before starting back in phase 1.
+ *
+ * This is meant to give a good balance of perofrmance and CPU consumption in
+ * practice.
+ *
+ * This class implements the `BasicLockable` specification:
+ * https://en.cppreference.com/w/cpp/named_req/BasicLockable
+ */
+class SpinLockMutex
+{
+public:
+  SpinLockMutex() noexcept {}
+  ~SpinLockMutex() noexcept                       = default;
+  SpinLockMutex(const SpinLockMutex &)            = delete;
+  SpinLockMutex &operator=(const SpinLockMutex &) = delete;
+
+  static inline void fast_yield() noexcept
+  {
+// Issue a Pause/Yield instruction while spinning.
+#if defined(_MSC_VER)
+    YieldProcessor();
+#elif defined(__i386__) || defined(__x86_64__)
+#  if defined(__clang__) || defined(__INTEL_COMPILER)
+    _mm_pause();
+#  else
+    __builtin_ia32_pause();
+#  endif
+#elif defined(__armel__) || defined(__ARMEL__)
+    asm volatile("nop" ::: "memory");
+#elif defined(__arm__) || defined(__aarch64__)  // arm big endian / arm64
+    __asm__ __volatile__("yield" ::: "memory");
+#else
+    // TODO: Issue PAGE/YIELD on other architectures.
+#endif
+  }
+
+  /**
+   * Attempts to lock the mutex.  Return immediately with `true` (success) or `false` (failure).
+   */
+  bool try_lock() noexcept
+  {
+    return !flag_.load(std::memory_order_relaxed) &&
+           !flag_.exchange(true, std::memory_order_acquire);
+  }
+
+  /**
+   * Blocks until a lock can be obtained for the current thread.
+   *
+   * This mutex will spin the current CPU waiting for the lock to be available.  This can have
+   * decent performance in scenarios where there is low lock contention and lock-holders achieve
+   * their work quickly.  It degrades in scenarios where locked tasks take a long time.
+   */
+  void lock() noexcept
+  {
+    for (;;)
+    {
+      // Try once
+      if (!flag_.exchange(true, std::memory_order_acquire))
+      {
+        return;
+      }
+      // Spin-Fast (goal ~10ns)
+      for (std::size_t i = 0; i < SPINLOCK_FAST_ITERATIONS; ++i)
+      {
+        if (try_lock())
+        {
+          return;
+        }
+        fast_yield();
+      }
+      // Yield then try again (goal ~100ns)
+      std::this_thread::yield();
+      if (try_lock())
+      {
+        return;
+      }
+      // Sleep and then start the whole process again. (goal ~1000ns)
+      std::this_thread::sleep_for(std::chrono::milliseconds(SPINLOCK_SLEEP_MS));
+    }
+    return;
+  }
+  /** Releases the lock held by the execution agent. Throws no exceptions. */
+  void unlock() noexcept { flag_.store(false, std::memory_order_release); }
+
+private:
+  std::atomic<bool> flag_{false};
+};
+
+}  // namespace common
+OPENTELEMETRY_END_NAMESPACE

+ 42 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/common/string_util.h

@@ -0,0 +1,42 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace common
+{
+
+class StringUtil
+{
+public:
+  static nostd::string_view Trim(nostd::string_view str, size_t left, size_t right) noexcept
+  {
+    while (left <= right && isspace(str[left]))
+    {
+      left++;
+    }
+    while (left <= right && isspace(str[right]))
+    {
+      right--;
+    }
+    return str.substr(left, 1 + right - left);
+  }
+
+  static nostd::string_view Trim(nostd::string_view str) noexcept
+  {
+    if (str.empty())
+    {
+      return str;
+    }
+
+    return Trim(str, 0, str.size() - 1);
+  }
+};
+
+}  // namespace common
+
+OPENTELEMETRY_END_NAMESPACE

+ 206 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/common/timestamp.h

@@ -0,0 +1,206 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <chrono>
+#include <cstdint>
+
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace common
+{
+/**
+ * @brief A timepoint relative to the system clock epoch.
+ *
+ * This is used for marking the beginning and end of an operation.
+ */
+class SystemTimestamp
+{
+public:
+  /**
+   * @brief Initializes a system timestamp pointing to the start of the epoch.
+   */
+  SystemTimestamp() noexcept : nanos_since_epoch_{0} {}
+
+  /**
+   * @brief Initializes a system timestamp from a duration.
+   *
+   * @param time_since_epoch Time elapsed since the beginning of the epoch.
+   */
+  template <class Rep, class Period>
+  explicit SystemTimestamp(const std::chrono::duration<Rep, Period> &time_since_epoch) noexcept
+      : nanos_since_epoch_{static_cast<int64_t>(
+            std::chrono::duration_cast<std::chrono::nanoseconds>(time_since_epoch).count())}
+  {}
+
+  /**
+   * @brief Initializes a system timestamp based on a point in time.
+   *
+   * @param time_point A point in time.
+   */
+  /*implicit*/ SystemTimestamp(const std::chrono::system_clock::time_point &time_point) noexcept
+      : SystemTimestamp{time_point.time_since_epoch()}
+  {}
+
+  /**
+   * @brief Returns a time point for the time stamp.
+   *
+   * @return A time point corresponding to the time stamp.
+   */
+  operator std::chrono::system_clock::time_point() const noexcept
+  {
+    return std::chrono::system_clock::time_point{
+        std::chrono::duration_cast<std::chrono::system_clock::duration>(
+            std::chrono::nanoseconds{nanos_since_epoch_})};
+  }
+
+  /**
+   * @brief Returns the nanoseconds since the beginning of the epoch.
+   *
+   * @return Elapsed nanoseconds since the beginning of the epoch for this timestamp.
+   */
+  std::chrono::nanoseconds time_since_epoch() const noexcept
+  {
+    return std::chrono::nanoseconds{nanos_since_epoch_};
+  }
+
+  /**
+   * @brief Compare two steady time stamps.
+   *
+   * @return true if the two time stamps are equal.
+   */
+  bool operator==(const SystemTimestamp &other) const noexcept
+  {
+    return nanos_since_epoch_ == other.nanos_since_epoch_;
+  }
+
+  /**
+   * @brief Compare two steady time stamps for inequality.
+   *
+   * @return true if the two time stamps are not equal.
+   */
+  bool operator!=(const SystemTimestamp &other) const noexcept
+  {
+    return nanos_since_epoch_ != other.nanos_since_epoch_;
+  }
+
+private:
+  int64_t nanos_since_epoch_;
+};
+
+/**
+ * @brief A timepoint relative to the monotonic clock epoch
+ *
+ * This is used for calculating the duration of an operation.
+ */
+class SteadyTimestamp
+{
+public:
+  /**
+   * @brief Initializes a monotonic timestamp pointing to the start of the epoch.
+   */
+  SteadyTimestamp() noexcept : nanos_since_epoch_{0} {}
+
+  /**
+   * @brief Initializes a monotonic timestamp from a duration.
+   *
+   * @param time_since_epoch Time elapsed since the beginning of the epoch.
+   */
+  template <class Rep, class Period>
+  explicit SteadyTimestamp(const std::chrono::duration<Rep, Period> &time_since_epoch) noexcept
+      : nanos_since_epoch_{static_cast<int64_t>(
+            std::chrono::duration_cast<std::chrono::nanoseconds>(time_since_epoch).count())}
+  {}
+
+  /**
+   * @brief Initializes a monotonic timestamp based on a point in time.
+   *
+   * @param time_point A point in time.
+   */
+  /*implicit*/ SteadyTimestamp(const std::chrono::steady_clock::time_point &time_point) noexcept
+      : SteadyTimestamp{time_point.time_since_epoch()}
+  {}
+
+  /**
+   * @brief Returns a time point for the time stamp.
+   *
+   * @return A time point corresponding to the time stamp.
+   */
+  operator std::chrono::steady_clock::time_point() const noexcept
+  {
+    return std::chrono::steady_clock::time_point{
+        std::chrono::duration_cast<std::chrono::steady_clock::duration>(
+            std::chrono::nanoseconds{nanos_since_epoch_})};
+  }
+
+  /**
+   * @brief Returns the nanoseconds since the beginning of the epoch.
+   *
+   * @return Elapsed nanoseconds since the beginning of the epoch for this timestamp.
+   */
+  std::chrono::nanoseconds time_since_epoch() const noexcept
+  {
+    return std::chrono::nanoseconds{nanos_since_epoch_};
+  }
+
+  /**
+   * @brief Compare two steady time stamps.
+   *
+   * @return true if the two time stamps are equal.
+   */
+  bool operator==(const SteadyTimestamp &other) const noexcept
+  {
+    return nanos_since_epoch_ == other.nanos_since_epoch_;
+  }
+
+  /**
+   * @brief Compare two steady time stamps for inequality.
+   *
+   * @return true if the two time stamps are not equal.
+   */
+  bool operator!=(const SteadyTimestamp &other) const noexcept
+  {
+    return nanos_since_epoch_ != other.nanos_since_epoch_;
+  }
+
+private:
+  int64_t nanos_since_epoch_;
+};
+
+class DurationUtil
+{
+public:
+  template <class Rep, class Period>
+  static std::chrono::duration<Rep, Period> AdjustWaitForTimeout(
+      std::chrono::duration<Rep, Period> timeout,
+      std::chrono::duration<Rep, Period> indefinite_value) noexcept
+  {
+    // Do not call now() when this duration is max value, now() may have a expensive cost.
+    if (timeout == (std::chrono::duration<Rep, Period>::max)())
+    {
+      return indefinite_value;
+    }
+
+    // std::future<T>::wait_for, std::this_thread::sleep_for, and std::condition_variable::wait_for
+    // may use steady_clock or system_clock.We need make sure now() + timeout do not overflow.
+    auto max_timeout = std::chrono::duration_cast<std::chrono::duration<Rep, Period>>(
+        (std::chrono::steady_clock::time_point::max)() - std::chrono::steady_clock::now());
+    if (timeout >= max_timeout)
+    {
+      return indefinite_value;
+    }
+    max_timeout = std::chrono::duration_cast<std::chrono::duration<Rep, Period>>(
+        (std::chrono::system_clock::time_point::max)() - std::chrono::system_clock::now());
+    if (timeout >= max_timeout)
+    {
+      return indefinite_value;
+    }
+
+    return timeout;
+  }
+};
+
+}  // namespace common
+OPENTELEMETRY_END_NAMESPACE

+ 19 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/config.h

@@ -0,0 +1,19 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <type_traits>  // IWYU pragma: keep
+
+#if defined(OPENTELEMETRY_ABI_VERSION_NO) && OPENTELEMETRY_ABI_VERSION_NO >= 2
+#  error \
+      "opentelemetry/config.h is removed in ABI version 2 and later. Please use opentelemetry/version.h instead."
+#else
+#  if defined(__clang__) || defined(__GNUC__)
+#    pragma GCC warning \
+        "opentelemetry/config.h is deprecated. Please use opentelemetry/version.h instead."
+#  elif defined(_MSC_VER)
+#    pragma message( \
+        "[WARNING]: opentelemetry/config.h is deprecated. Please use opentelemetry/version.h instead.")
+#  endif
+#endif

+ 171 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/context/context.h

@@ -0,0 +1,171 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <cstring>
+#include <utility>
+
+#include "opentelemetry/context/context_value.h"
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/nostd/variant.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace context
+{
+
+// The context class provides a context identifier. Is built as a linked list
+// of DataList nodes and each context holds a shared_ptr to a place within
+// the list that determines which keys and values it has access to. All that
+// come before and none that come after.
+class Context
+{
+
+public:
+  Context() = default;
+  // Creates a context object from a map of keys and identifiers, this will
+  // hold a shared_ptr to the head of the DataList linked list
+  template <class T>
+  Context(const T &keys_and_values) noexcept
+      : head_{nostd::shared_ptr<DataList>{new DataList(keys_and_values)}}
+  {}
+
+  // Creates a context object from a key and value, this will
+  // hold a shared_ptr to the head of the DataList linked list
+  Context(nostd::string_view key, ContextValue value) noexcept
+      : head_{nostd::shared_ptr<DataList>{new DataList(key, value)}}
+  {}
+
+  // Accepts a new iterable and then returns a new context that
+  // contains the new key and value data. It attaches the
+  // exisiting list to the end of the new list.
+  template <class T>
+  Context SetValues(T &values) noexcept
+  {
+    Context context                  = Context(values);
+    nostd::shared_ptr<DataList> last = context.head_;
+    while (last->next_ != nullptr)
+    {
+      last = last->next_;
+    }
+    last->next_ = head_;
+    return context;
+  }
+
+  // Accepts a new iterable and then returns a new context that
+  // contains the new key and value data. It attaches the
+  // exisiting list to the end of the new list.
+  Context SetValue(nostd::string_view key, ContextValue value) noexcept
+  {
+    Context context      = Context(key, value);
+    context.head_->next_ = head_;
+    return context;
+  }
+
+  // Returns the value associated with the passed in key.
+  context::ContextValue GetValue(const nostd::string_view key) const noexcept
+  {
+    for (DataList *data = head_.get(); data != nullptr; data = data->next_.get())
+    {
+      if (key.size() == data->key_length_)
+      {
+        if (std::memcmp(key.data(), data->key_, data->key_length_) == 0)
+        {
+          return data->value_;
+        }
+      }
+    }
+    return ContextValue{};
+  }
+
+  // Checks for key and returns true if found
+  bool HasKey(const nostd::string_view key) const noexcept
+  {
+    return !nostd::holds_alternative<nostd::monostate>(GetValue(key));
+  }
+
+  bool operator==(const Context &other) const noexcept { return (head_ == other.head_); }
+
+private:
+  // A linked list to contain the keys and values of this context node
+  struct DataList
+  {
+    char *key_ = nullptr;
+
+    nostd::shared_ptr<DataList> next_{nullptr};
+
+    size_t key_length_ = 0UL;
+
+    ContextValue value_;
+
+    DataList() = default;
+
+    // Builds a data list off of a key and value iterable and returns the head
+    template <class T>
+    DataList(const T &keys_and_vals)
+    {
+      bool first = true;
+      auto *node = this;
+      for (auto &iter : keys_and_vals)
+      {
+        if (first)
+        {
+          *node = DataList(iter.first, iter.second);
+          first = false;
+        }
+        else
+        {
+          node->next_ = nostd::shared_ptr<DataList>(new DataList(iter.first, iter.second));
+          node        = node->next_.get();
+        }
+      }
+    }
+
+    // Builds a data list with just a key and value, so it will just be the head
+    // and returns that head.
+    DataList(nostd::string_view key, const ContextValue &value)
+    {
+      key_        = new char[key.size()];
+      key_length_ = key.size();
+      std::memcpy(key_, key.data(), key.size() * sizeof(char));
+      next_  = nostd::shared_ptr<DataList>{nullptr};
+      value_ = value;
+    }
+
+    DataList(const DataList &other)
+        : key_(new char[other.key_length_]),
+          next_(other.next_),
+          key_length_(other.key_length_),
+          value_(other.value_)
+    {
+      std::memcpy(key_, other.key_, other.key_length_ * sizeof(char));
+    }
+
+    DataList &operator=(DataList &&other) noexcept
+    {
+      key_length_ = other.key_length_;
+      value_      = std::move(other.value_);
+      next_       = std::move(other.next_);
+
+      key_       = other.key_;
+      other.key_ = nullptr;
+
+      return *this;
+    }
+
+    ~DataList()
+    {
+      if (key_ != nullptr)
+      {
+        delete[] key_;
+      }
+    }
+  };
+
+  // Head of the list which holds the keys and values of this context
+  nostd::shared_ptr<DataList> head_;
+};
+}  // namespace context
+OPENTELEMETRY_END_NAMESPACE

+ 35 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/context/context_value.h

@@ -0,0 +1,35 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <cstdint>
+
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/nostd/variant.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace baggage
+{
+class Baggage;
+}  // namespace baggage
+
+namespace trace
+{
+class Span;
+class SpanContext;
+}  // namespace trace
+
+namespace context
+{
+using ContextValue = nostd::variant<nostd::monostate,
+                                    bool,
+                                    int64_t,
+                                    uint64_t,
+                                    double,
+                                    nostd::shared_ptr<trace::Span>,
+                                    nostd::shared_ptr<trace::SpanContext>,
+                                    nostd::shared_ptr<baggage::Baggage>>;
+}  // namespace context
+OPENTELEMETRY_END_NAMESPACE

+ 93 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/context/propagation/composite_propagator.h

@@ -0,0 +1,93 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <memory>
+#include <vector>
+
+#include "opentelemetry/context/propagation/text_map_propagator.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace context
+{
+namespace propagation
+{
+
+class CompositePropagator : public TextMapPropagator
+{
+public:
+  CompositePropagator(std::vector<std::unique_ptr<TextMapPropagator>> propagators)
+      : propagators_(std::move(propagators))
+  {}
+
+  /**
+   * Run each of the configured propagators with the given context and carrier.
+   * Propagators are run in the order they are configured, so if multiple
+   * propagators write the same carrier key, the propagator later in the list
+   * will "win".
+   *
+   * @param carrier Carrier into which context will be injected
+   * @param context Context to inject
+   *
+   */
+
+  void Inject(TextMapCarrier &carrier, const context::Context &context) noexcept override
+  {
+    for (auto &p : propagators_)
+    {
+      p->Inject(carrier, context);
+    }
+  }
+
+  /**
+   * Run each of the configured propagators with the given context and carrier.
+   * Propagators are run in the order they are configured, so if multiple
+   * propagators write the same context key, the propagator later in the list
+   * will "win".
+   *
+   * @param carrier Carrier from which to extract context
+   * @param context Context to add values to
+   */
+  context::Context Extract(const TextMapCarrier &carrier,
+                           context::Context &context) noexcept override
+  {
+    auto first = true;
+    context::Context tmp_context;
+    for (auto &p : propagators_)
+    {
+      if (first)
+      {
+        tmp_context = p->Extract(carrier, context);
+        first       = false;
+      }
+      else
+      {
+        tmp_context = p->Extract(carrier, tmp_context);
+      }
+    }
+    return propagators_.size() ? tmp_context : context;
+  }
+
+  /**
+   * Invoke callback with  fields set to carrier by `inject` method for all the
+   * configured propagators
+   * Returns true if all invocation return true
+   */
+  bool Fields(nostd::function_ref<bool(nostd::string_view)> callback) const noexcept override
+  {
+    bool status = true;
+    for (auto &p : propagators_)
+    {
+      status = status && p->Fields(callback);
+    }
+    return status;
+  }
+
+private:
+  std::vector<std::unique_ptr<TextMapPropagator>> propagators_;
+};
+}  // namespace propagation
+}  // namespace context
+OPENTELEMETRY_END_NAMESPACE

+ 57 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/context/propagation/global_propagator.h

@@ -0,0 +1,57 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <mutex>
+
+#include "opentelemetry/context/propagation/noop_propagator.h"
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/common/spin_lock_mutex.h"
+#include "opentelemetry/nostd/shared_ptr.h"
+
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace context
+{
+namespace propagation
+{
+
+class TextMapPropagator;
+
+/* Stores the singleton TextMapPropagator */
+
+class OPENTELEMETRY_EXPORT GlobalTextMapPropagator
+{
+public:
+  static nostd::shared_ptr<TextMapPropagator> GetGlobalPropagator() noexcept
+  {
+    std::lock_guard<common::SpinLockMutex> guard(GetLock());
+    return nostd::shared_ptr<TextMapPropagator>(GetPropagator());
+  }
+
+  static void SetGlobalPropagator(const nostd::shared_ptr<TextMapPropagator> &prop) noexcept
+  {
+    std::lock_guard<common::SpinLockMutex> guard(GetLock());
+    GetPropagator() = prop;
+  }
+
+private:
+  OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr<TextMapPropagator> &GetPropagator() noexcept
+  {
+    static nostd::shared_ptr<TextMapPropagator> propagator(new NoOpPropagator());
+    return propagator;
+  }
+
+  OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept
+  {
+    static common::SpinLockMutex lock;
+    return lock;
+  }
+};
+
+}  // namespace propagation
+}  // namespace context
+OPENTELEMETRY_END_NAMESPACE

+ 40 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/context/propagation/noop_propagator.h

@@ -0,0 +1,40 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/context/propagation/text_map_propagator.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace context
+{
+namespace propagation
+{
+
+/**
+ * No-op implementation TextMapPropagator
+ */
+class NoOpPropagator : public TextMapPropagator
+{
+public:
+  /** Noop extract function does nothing and returns the input context */
+  context::Context Extract(const TextMapCarrier & /*carrier*/,
+                           context::Context &context) noexcept override
+  {
+    return context;
+  }
+
+  /** Noop inject function does nothing */
+  void Inject(TextMapCarrier & /*carrier*/,
+              const context::Context & /* context */) noexcept override
+  {}
+
+  bool Fields(nostd::function_ref<bool(nostd::string_view)> /* callback */) const noexcept override
+  {
+    return true;
+  }
+};
+}  // namespace propagation
+}  // namespace context
+OPENTELEMETRY_END_NAMESPACE

+ 59 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/context/propagation/text_map_propagator.h

@@ -0,0 +1,59 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/context/context.h"
+#include "opentelemetry/nostd/function_ref.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace context
+{
+namespace propagation
+{
+
+// TextMapCarrier is the storage medium used by TextMapPropagator.
+class TextMapCarrier
+{
+public:
+  // returns the value associated with the passed key.
+  virtual nostd::string_view Get(nostd::string_view key) const noexcept = 0;
+
+  // stores the key-value pair.
+  virtual void Set(nostd::string_view key, nostd::string_view value) noexcept = 0;
+
+  /* list of all the keys in the carrier.
+   By default, it returns true without invoking callback */
+  virtual bool Keys(nostd::function_ref<bool(nostd::string_view)> /* callback */) const noexcept
+  {
+    return true;
+  }
+  virtual ~TextMapCarrier() = default;
+};
+
+// The TextMapPropagator class provides an interface that enables extracting and injecting
+// context into carriers that travel in-band across process boundaries. HTTP frameworks and clients
+// can integrate with TextMapPropagator by providing the object containing the
+// headers, and a getter and setter function for the extraction and
+// injection of values, respectively.
+
+class TextMapPropagator
+{
+public:
+  // Returns the context that is stored in the carrier with the TextMapCarrier as extractor.
+  virtual context::Context Extract(const TextMapCarrier &carrier,
+                                   context::Context &context) noexcept = 0;
+
+  // Sets the context for carrier with self defined rules.
+  virtual void Inject(TextMapCarrier &carrier, const context::Context &context) noexcept = 0;
+
+  // Gets the fields set in the carrier by the `inject` method
+  virtual bool Fields(nostd::function_ref<bool(nostd::string_view)> callback) const noexcept = 0;
+
+  virtual ~TextMapPropagator() = default;
+};
+}  // namespace propagation
+}  // namespace context
+OPENTELEMETRY_END_NAMESPACE

+ 340 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/context/runtime_context.h

@@ -0,0 +1,340 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <stddef.h>
+#include <algorithm>
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/context/context.h"
+#include "opentelemetry/context/context_value.h"
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/nostd/unique_ptr.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace context
+{
+// The Token object provides is returned when attaching objects to the
+// RuntimeContext object and is associated with a context object, and
+// can be provided to the RuntimeContext Detach method to remove the
+// associated context from the RuntimeContext.
+class Token
+{
+public:
+  bool operator==(const Context &other) const noexcept { return context_ == other; }
+
+  ~Token() noexcept;
+
+private:
+  friend class RuntimeContextStorage;
+
+  // A constructor that sets the token's Context object to the
+  // one that was passed in.
+  Token(const Context &context) : context_(context) {}
+
+  const Context context_;
+};
+
+/**
+ * RuntimeContextStorage is used by RuntimeContext to store Context frames.
+ *
+ * Custom context management strategies can be implemented by deriving from
+ * this class and passing an initialized RuntimeContextStorage object to
+ * RuntimeContext::SetRuntimeContextStorage.
+ */
+class OPENTELEMETRY_EXPORT RuntimeContextStorage
+{
+public:
+  /**
+   * Return the current context.
+   * @return the current context
+   */
+  virtual Context GetCurrent() noexcept = 0;
+
+  /**
+   * Set the current context.
+   * @param the new current context
+   * @return a token for the new current context. This never returns a nullptr.
+   */
+  virtual nostd::unique_ptr<Token> Attach(const Context &context) noexcept = 0;
+
+  /**
+   * Detach the context related to the given token.
+   * @param token a token related to a context
+   * @return true if the context could be detached
+   */
+  virtual bool Detach(Token &token) noexcept = 0;
+
+  virtual ~RuntimeContextStorage() {}
+
+protected:
+  nostd::unique_ptr<Token> CreateToken(const Context &context) noexcept
+  {
+    return nostd::unique_ptr<Token>(new Token(context));
+  }
+};
+
+/**
+ * Construct and return the default RuntimeContextStorage
+ * @return a ThreadLocalContextStorage
+ */
+static RuntimeContextStorage *GetDefaultStorage() noexcept;
+
+// Provides a wrapper for propagating the context object globally.
+//
+// By default, a thread-local runtime context storage is used.
+class OPENTELEMETRY_EXPORT RuntimeContext
+{
+public:
+  // Return the current context.
+  static Context GetCurrent() noexcept { return GetRuntimeContextStorage()->GetCurrent(); }
+
+  // Sets the current 'Context' object. Returns a token
+  // that can be used to reset to the previous Context.
+  static nostd::unique_ptr<Token> Attach(const Context &context) noexcept
+  {
+    return GetRuntimeContextStorage()->Attach(context);
+  }
+
+  // Resets the context to a previous value stored in the
+  // passed in token. Returns true if successful, false otherwise
+  static bool Detach(Token &token) noexcept { return GetRuntimeContextStorage()->Detach(token); }
+
+  // Sets the Key and Value into the passed in context or if a context is not
+  // passed in, the RuntimeContext.
+  // Should be used to SetValues to the current RuntimeContext, is essentially
+  // equivalent to RuntimeContext::GetCurrent().SetValue(key,value). Keep in
+  // mind that the current RuntimeContext will not be changed, and the new
+  // context will be returned.
+  static Context SetValue(nostd::string_view key,
+                          const ContextValue &value,
+                          Context *context = nullptr) noexcept
+  {
+    Context temp_context;
+    if (context == nullptr)
+    {
+      temp_context = GetCurrent();
+    }
+    else
+    {
+      temp_context = *context;
+    }
+    return temp_context.SetValue(key, value);
+  }
+
+  // Returns the value associated with the passed in key and either the
+  // passed in context* or the runtime context if a context is not passed in.
+  // Should be used to get values from the current RuntimeContext, is
+  // essentially equivalent to RuntimeContext::GetCurrent().GetValue(key).
+  static ContextValue GetValue(nostd::string_view key, Context *context = nullptr) noexcept
+  {
+    Context temp_context;
+    if (context == nullptr)
+    {
+      temp_context = GetCurrent();
+    }
+    else
+    {
+      temp_context = *context;
+    }
+    return temp_context.GetValue(key);
+  }
+
+  /**
+   * Provide a custom runtime context storage.
+   *
+   * This provides a possibility to override the default thread-local runtime
+   * context storage. This has to be set before any spans are created by the
+   * application, otherwise the behavior is undefined.
+   *
+   * @param storage a custom runtime context storage
+   */
+  static void SetRuntimeContextStorage(
+      const nostd::shared_ptr<RuntimeContextStorage> &storage) noexcept
+  {
+    GetStorage() = storage;
+  }
+
+  /**
+   * Provide a pointer to const runtime context storage.
+   *
+   * The returned pointer can only be used for extending the lifetime of the runtime context
+   * storage.
+   *
+   */
+  static nostd::shared_ptr<const RuntimeContextStorage> GetConstRuntimeContextStorage() noexcept
+  {
+    return GetRuntimeContextStorage();
+  }
+
+private:
+  static nostd::shared_ptr<RuntimeContextStorage> GetRuntimeContextStorage() noexcept
+  {
+    return GetStorage();
+  }
+
+  OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr<RuntimeContextStorage> &GetStorage() noexcept
+  {
+    static nostd::shared_ptr<RuntimeContextStorage> context(GetDefaultStorage());
+    return context;
+  }
+};
+
+inline Token::~Token() noexcept
+{
+  context::RuntimeContext::Detach(*this);
+}
+
+// The ThreadLocalContextStorage class is a derived class from
+// RuntimeContextStorage and provides a wrapper for propagating context through
+// cpp thread locally. This file must be included to use the RuntimeContext
+// class if another implementation has not been registered.
+class ThreadLocalContextStorage : public RuntimeContextStorage
+{
+public:
+  ThreadLocalContextStorage() noexcept = default;
+
+  // Return the current context.
+  Context GetCurrent() noexcept override { return GetStack().Top(); }
+
+  // Resets the context to the value previous to the passed in token. This will
+  // also detach all child contexts of the passed in token.
+  // Returns true if successful, false otherwise.
+  bool Detach(Token &token) noexcept override
+  {
+    // In most cases, the context to be detached is on the top of the stack.
+    if (token == GetStack().Top())
+    {
+      GetStack().Pop();
+      return true;
+    }
+
+    if (!GetStack().Contains(token))
+    {
+      return false;
+    }
+
+    while (!(token == GetStack().Top()))
+    {
+      GetStack().Pop();
+    }
+
+    GetStack().Pop();
+
+    return true;
+  }
+
+  // Sets the current 'Context' object. Returns a token
+  // that can be used to reset to the previous Context.
+  nostd::unique_ptr<Token> Attach(const Context &context) noexcept override
+  {
+    GetStack().Push(context);
+    return CreateToken(context);
+  }
+
+private:
+  // A nested class to store the attached contexts in a stack.
+  class Stack
+  {
+    friend class ThreadLocalContextStorage;
+
+    Stack() noexcept : size_(0), capacity_(0), base_(nullptr) {}
+
+    // Pops the top Context off the stack.
+    void Pop() noexcept
+    {
+      if (size_ == 0)
+      {
+        return;
+      }
+      // Store empty Context before decrementing `size`, to ensure
+      // the shared_ptr object (if stored in prev context object ) are released.
+      // The stack is not resized, and the unused memory would be reutilised
+      // for subsequent context storage.
+      base_[size_ - 1] = Context();
+      size_ -= 1;
+    }
+
+    bool Contains(const Token &token) const noexcept
+    {
+      for (size_t pos = size_; pos > 0; --pos)
+      {
+        if (token == base_[pos - 1])
+        {
+          return true;
+        }
+      }
+
+      return false;
+    }
+
+    // Returns the Context at the top of the stack.
+    Context Top() const noexcept
+    {
+      if (size_ == 0)
+      {
+        return Context();
+      }
+      return base_[size_ - 1];
+    }
+
+    // Pushes the passed in context pointer to the top of the stack
+    // and resizes if necessary.
+    void Push(const Context &context) noexcept
+    {
+      size_++;
+      if (size_ > capacity_)
+      {
+        Resize(size_ * 2);
+      }
+      base_[size_ - 1] = context;
+    }
+
+    // Reallocates the storage array to the pass in new capacity size.
+    void Resize(size_t new_capacity) noexcept
+    {
+      size_t old_size = size_ - 1;
+      if (new_capacity == 0)
+      {
+        new_capacity = 2;
+      }
+      Context *temp = new Context[new_capacity];
+      if (base_ != nullptr)
+      {
+        // vs2015 does not like this construct considering it unsafe:
+        // - std::copy(base_, base_ + old_size, temp);
+        // Ref.
+        // https://stackoverflow.com/questions/12270224/xutility2227-warning-c4996-std-copy-impl
+        for (size_t i = 0; i < (std::min)(old_size, new_capacity); i++)
+        {
+          temp[i] = base_[i];
+        }
+        delete[] base_;
+      }
+      base_     = temp;
+      capacity_ = new_capacity;
+    }
+
+    ~Stack() noexcept { delete[] base_; }
+
+    size_t size_;
+    size_t capacity_;
+    Context *base_;
+  };
+
+  OPENTELEMETRY_API_SINGLETON Stack &GetStack()
+  {
+    static thread_local Stack stack_ = Stack();
+    return stack_;
+  }
+};
+
+static RuntimeContextStorage *GetDefaultStorage() noexcept
+{
+  return new ThreadLocalContextStorage();
+}
+}  // namespace context
+OPENTELEMETRY_END_NAMESPACE

+ 25 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/detail/preprocessor.h

@@ -0,0 +1,25 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+// NOTE - code within detail namespace implements internal details, and not part
+// of the public interface.
+
+#pragma once
+
+#define OPENTELEMETRY_STRINGIFY(S) OPENTELEMETRY_STRINGIFY_(S)
+#define OPENTELEMETRY_STRINGIFY_(S) #S
+
+#define OPENTELEMETRY_CONCAT(A, B) OPENTELEMETRY_CONCAT_(A, B)
+#define OPENTELEMETRY_CONCAT_(A, B) A##B
+
+// Import the C++20 feature-test macros
+#ifdef __has_include
+#  if __has_include(<version>)
+#    include <version>
+#  endif
+#elif defined(_MSC_VER) && ((defined(__cplusplus) && __cplusplus >= 202002L) || \
+                            (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L))
+#  if _MSC_VER >= 1922
+#    include <version>
+#  endif
+#endif

+ 37 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/event_id.h

@@ -0,0 +1,37 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <algorithm>
+
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/nostd/unique_ptr.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace logs
+{
+
+/**
+ * EventId class which acts the Id of the event with an optional name.
+ */
+class EventId
+{
+public:
+  EventId(int64_t id, nostd::string_view name) noexcept
+      : id_{id}, name_{nostd::unique_ptr<char[]>{new char[name.length() + 1]}}
+  {
+    std::copy(name.begin(), name.end(), name_.get());
+    name_.get()[name.length()] = 0;
+  }
+
+  EventId(int64_t id) noexcept : id_{id}, name_{nullptr} {}
+
+public:
+  int64_t id_;
+  nostd::unique_ptr<char[]> name_;
+};
+
+}  // namespace logs
+OPENTELEMETRY_END_NAMESPACE

+ 82 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/event_logger.h

@@ -0,0 +1,82 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/logs/log_record.h"
+#include "opentelemetry/logs/logger.h"
+#include "opentelemetry/logs/logger_type_traits.h"
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/nostd/unique_ptr.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace logs
+{
+#if OPENTELEMETRY_ABI_VERSION_NO < 2
+/**
+ * Handles event log record creation.
+ **/
+class OPENTELEMETRY_DEPRECATED EventLogger
+{
+public:
+  virtual ~EventLogger() = default;
+
+  /* Returns the name of the logger */
+  virtual const nostd::string_view GetName() noexcept = 0;
+
+  /* Returns the delegate logger of this event logger */
+  virtual nostd::shared_ptr<Logger> GetDelegateLogger() noexcept = 0;
+
+  /**
+   * Emit a event Log Record object
+   *
+   * @param event_name Event name
+   * @param log_record Log record
+   */
+  virtual void EmitEvent(nostd::string_view event_name,
+                         nostd::unique_ptr<LogRecord> &&log_record) noexcept = 0;
+
+  /**
+   * Emit a event Log Record object with arguments
+   *
+   * @param event_name Event name
+   * @tparam args Arguments which can be used to set data of log record by type.
+   *  Severity                                -> severity, severity_text
+   *  string_view                             -> body
+   *  AttributeValue                          -> body
+   *  SpanContext                             -> span_id,tace_id and trace_flags
+   *  SpanId                                  -> span_id
+   *  TraceId                                 -> tace_id
+   *  TraceFlags                              -> trace_flags
+   *  SystemTimestamp                         -> timestamp
+   *  system_clock::time_point                -> timestamp
+   *  KeyValueIterable                        -> attributes
+   *  Key value iterable container            -> attributes
+   *  span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
+   */
+  template <class... ArgumentType>
+  void EmitEvent(nostd::string_view event_name, ArgumentType &&...args)
+  {
+    nostd::shared_ptr<Logger> delegate_logger = GetDelegateLogger();
+    if (!delegate_logger)
+    {
+      return;
+    }
+    nostd::unique_ptr<LogRecord> log_record = delegate_logger->CreateLogRecord();
+
+    IgnoreTraitResult(detail::LogRecordSetterTrait<typename std::decay<ArgumentType>::type>::Set(
+        log_record.get(), std::forward<ArgumentType>(args))...);
+
+    EmitEvent(event_name, std::move(log_record));
+  }
+
+private:
+  template <class... ValueType>
+  void IgnoreTraitResult(ValueType &&...)
+  {}
+};
+#endif
+}  // namespace logs
+OPENTELEMETRY_END_NAMESPACE

+ 37 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/event_logger_provider.h

@@ -0,0 +1,37 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace logs
+{
+
+class EventLogger;
+class Logger;
+
+#if OPENTELEMETRY_ABI_VERSION_NO < 2
+/**
+ * Creates new EventLogger instances.
+ */
+class OPENTELEMETRY_DEPRECATED EventLoggerProvider
+{
+public:
+  virtual ~EventLoggerProvider() = default;
+
+  /**
+   * Creates a named EventLogger instance.
+   *
+   */
+
+  virtual nostd::shared_ptr<EventLogger> CreateEventLogger(
+      nostd::shared_ptr<Logger> delegate_logger,
+      nostd::string_view event_domain) noexcept = 0;
+};
+#endif
+}  // namespace logs
+OPENTELEMETRY_END_NAMESPACE

+ 92 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/log_record.h

@@ -0,0 +1,92 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/common/attribute_value.h"
+#include "opentelemetry/common/timestamp.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace trace
+{
+class SpanId;
+class TraceId;
+class TraceFlags;
+}  // namespace trace
+
+namespace logs
+{
+
+enum class Severity : uint8_t;
+
+/**
+ * Maintains a representation of a log in a format that can be processed by a recorder.
+ *
+ * This class is thread-compatible.
+ */
+class LogRecord
+{
+public:
+  virtual ~LogRecord() = default;
+
+  /**
+   * Set the timestamp for this log.
+   * @param timestamp the timestamp to set
+   */
+  virtual void SetTimestamp(common::SystemTimestamp timestamp) noexcept = 0;
+
+  /**
+   * Set the observed timestamp for this log.
+   * @param timestamp the timestamp to set
+   */
+  virtual void SetObservedTimestamp(common::SystemTimestamp timestamp) noexcept = 0;
+
+  /**
+   * Set the severity for this log.
+   * @param severity the severity of the event
+   */
+  virtual void SetSeverity(logs::Severity severity) noexcept = 0;
+
+  /**
+   * Set body field for this log.
+   * @param message the body to set
+   */
+  virtual void SetBody(const common::AttributeValue &message) noexcept = 0;
+
+  /**
+   * Set an attribute of a log.
+   * @param key the name of the attribute
+   * @param value the attribute value
+   */
+  virtual void SetAttribute(nostd::string_view key,
+                            const common::AttributeValue &value) noexcept = 0;
+
+  /**
+   * Set the Event Id.
+   * @param id The event id to set
+   * @param name Optional event name to set
+   */
+  // TODO: mark this as pure virtual once all exporters have been updated
+  virtual void SetEventId(int64_t id, nostd::string_view name = {}) noexcept = 0;
+
+  /**
+   * Set the trace id for this log.
+   * @param trace_id the trace id to set
+   */
+  virtual void SetTraceId(const trace::TraceId &trace_id) noexcept = 0;
+
+  /**
+   * Set the span id for this log.
+   * @param span_id the span id to set
+   */
+  virtual void SetSpanId(const trace::SpanId &span_id) noexcept = 0;
+
+  /**
+   * Inject trace_flags for this log.
+   * @param trace_flags the trace flags to set
+   */
+  virtual void SetTraceFlags(const trace::TraceFlags &trace_flags) noexcept = 0;
+};
+}  // namespace logs
+OPENTELEMETRY_END_NAMESPACE

+ 492 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/logger.h

@@ -0,0 +1,492 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/logs/logger_type_traits.h"
+#include "opentelemetry/logs/severity.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/nostd/unique_ptr.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace common
+{
+class KeyValueIterable;
+}  // namespace common
+
+namespace logs
+{
+
+class EventId;
+class LogRecord;
+
+/**
+ * Handles log record creation.
+ **/
+class Logger
+{
+public:
+  virtual ~Logger() = default;
+
+  /* Returns the name of the logger */
+  virtual const nostd::string_view GetName() noexcept = 0;
+
+  /**
+   * Create a Log Record object
+   *
+   * @return nostd::unique_ptr<LogRecord>
+   */
+  virtual nostd::unique_ptr<LogRecord> CreateLogRecord() noexcept = 0;
+
+  /**
+   * Emit a Log Record object
+   *
+   * @param log_record Log record
+   */
+  virtual void EmitLogRecord(nostd::unique_ptr<LogRecord> &&log_record) noexcept = 0;
+
+  /**
+   * Emit a Log Record object with arguments
+   *
+   * @param log_record Log record
+   * @param args Arguments which can be used to set data of log record by type.
+   *  Severity                                -> severity, severity_text
+   *  string_view                             -> body
+   *  AttributeValue                          -> body
+   *  SpanContext                             -> span_id,trace_id and trace_flags
+   *  SpanId                                  -> span_id
+   *  TraceId                                 -> trace_id
+   *  TraceFlags                              -> trace_flags
+   *  SystemTimestamp                         -> timestamp
+   *  system_clock::time_point                -> timestamp
+   *  KeyValueIterable                        -> attributes
+   *  Key value iterable container            -> attributes
+   *  span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
+   */
+  template <class... ArgumentType>
+  void EmitLogRecord(nostd::unique_ptr<LogRecord> &&log_record, ArgumentType &&...args)
+  {
+    if (!log_record)
+    {
+      return;
+    }
+
+    //
+    // Keep the parameter pack unpacking order from left to right because left
+    // ones are usually more important like severity and event_id than the
+    // attributes. The left to right unpack order could pass the more important
+    // data to processors to avoid caching and memory allocating.
+    //
+#if __cplusplus <= 201402L
+    // C++14 does not support fold expressions for parameter pack expansion.
+    int dummy[] = {(detail::LogRecordSetterTrait<typename std::decay<ArgumentType>::type>::Set(
+                        log_record.get(), std::forward<ArgumentType>(args)),
+                    0)...};
+    IgnoreTraitResult(dummy);
+#else
+    IgnoreTraitResult((detail::LogRecordSetterTrait<typename std::decay<ArgumentType>::type>::Set(
+                           log_record.get(), std::forward<ArgumentType>(args)),
+                       ...));
+#endif
+
+    EmitLogRecord(std::move(log_record));
+  }
+
+  /**
+   * Emit a Log Record object with arguments
+   *
+   * @param args Arguments which can be used to set data of log record by type.
+   *  Severity                                -> severity, severity_text
+   *  string_view                             -> body
+   *  AttributeValue                          -> body
+   *  SpanContext                             -> span_id,trace_id and trace_flags
+   *  SpanId                                  -> span_id
+   *  TraceId                                 -> trace_id
+   *  TraceFlags                              -> trace_flags
+   *  SystemTimestamp                         -> timestamp
+   *  system_clock::time_point                -> timestamp
+   *  KeyValueIterable                        -> attributes
+   *  Key value iterable container            -> attributes
+   *  span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
+   */
+  template <class... ArgumentType>
+  void EmitLogRecord(ArgumentType &&...args)
+  {
+    nostd::unique_ptr<LogRecord> log_record = CreateLogRecord();
+
+    EmitLogRecord(std::move(log_record), std::forward<ArgumentType>(args)...);
+  }
+
+  /**
+   * Writes a log with a severity of trace.
+   * @param args Arguments which can be used to set data of log record by type.
+   *  string_view                             -> body
+   *  AttributeValue                          -> body
+   *  SpanContext                             -> span_id,trace_id and trace_flags
+   *  SpanId                                  -> span_id
+   *  TraceId                                 -> trace_id
+   *  TraceFlags                              -> trace_flags
+   *  SystemTimestamp                         -> timestamp
+   *  system_clock::time_point                -> timestamp
+   *  KeyValueIterable                        -> attributes
+   *  Key value iterable container            -> attributes
+   *  span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
+   */
+  template <class... ArgumentType>
+  void Trace(ArgumentType &&...args) noexcept
+  {
+    static_assert(
+        !detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
+        "Severity is already set.");
+    this->EmitLogRecord(Severity::kTrace, std::forward<ArgumentType>(args)...);
+  }
+
+  /**
+   * Writes a log with a severity of debug.
+   * @param args Arguments which can be used to set data of log record by type.
+   *  string_view                             -> body
+   *  AttributeValue                          -> body
+   *  SpanContext                             -> span_id,trace_id and trace_flags
+   *  SpanId                                  -> span_id
+   *  TraceId                                 -> trace_id
+   *  TraceFlags                              -> trace_flags
+   *  SystemTimestamp                         -> timestamp
+   *  system_clock::time_point                -> timestamp
+   *  KeyValueIterable                        -> attributes
+   *  Key value iterable container            -> attributes
+   *  span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
+   */
+  template <class... ArgumentType>
+  void Debug(ArgumentType &&...args) noexcept
+  {
+    static_assert(
+        !detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
+        "Severity is already set.");
+    this->EmitLogRecord(Severity::kDebug, std::forward<ArgumentType>(args)...);
+  }
+
+  /**
+   * Writes a log with a severity of info.
+   * @param args Arguments which can be used to set data of log record by type.
+   *  string_view                             -> body
+   *  AttributeValue                          -> body
+   *  SpanContext                             -> span_id,trace_id and trace_flags
+   *  SpanId                                  -> span_id
+   *  TraceId                                 -> trace_id
+   *  TraceFlags                              -> trace_flags
+   *  SystemTimestamp                         -> timestamp
+   *  system_clock::time_point                -> timestamp
+   *  KeyValueIterable                        -> attributes
+   *  Key value iterable container            -> attributes
+   *  span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
+   */
+  template <class... ArgumentType>
+  void Info(ArgumentType &&...args) noexcept
+  {
+    static_assert(
+        !detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
+        "Severity is already set.");
+    this->EmitLogRecord(Severity::kInfo, std::forward<ArgumentType>(args)...);
+  }
+
+  /**
+   * Writes a log with a severity of warn.
+   * @param args Arguments which can be used to set data of log record by type.
+   *  string_view                             -> body
+   *  AttributeValue                          -> body
+   *  SpanContext                             -> span_id,trace_id and trace_flags
+   *  SpanId                                  -> span_id
+   *  TraceId                                 -> trace_id
+   *  TraceFlags                              -> trace_flags
+   *  SystemTimestamp                         -> timestamp
+   *  system_clock::time_point                -> timestamp
+   *  KeyValueIterable                        -> attributes
+   *  Key value iterable container            -> attributes
+   *  span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
+   */
+  template <class... ArgumentType>
+  void Warn(ArgumentType &&...args) noexcept
+  {
+    static_assert(
+        !detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
+        "Severity is already set.");
+    this->EmitLogRecord(Severity::kWarn, std::forward<ArgumentType>(args)...);
+  }
+
+  /**
+   * Writes a log with a severity of error.
+   * @param args Arguments which can be used to set data of log record by type.
+   *  string_view                             -> body
+   *  AttributeValue                          -> body
+   *  SpanContext                             -> span_id,trace_id and trace_flags
+   *  SpanId                                  -> span_id
+   *  TraceId                                 -> trace_id
+   *  TraceFlags                              -> trace_flags
+   *  SystemTimestamp                         -> timestamp
+   *  system_clock::time_point                -> timestamp
+   *  KeyValueIterable                        -> attributes
+   *  Key value iterable container            -> attributes
+   *  span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
+   */
+  template <class... ArgumentType>
+  void Error(ArgumentType &&...args) noexcept
+  {
+    static_assert(
+        !detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
+        "Severity is already set.");
+    this->EmitLogRecord(Severity::kError, std::forward<ArgumentType>(args)...);
+  }
+
+  /**
+   * Writes a log with a severity of fatal.
+   * @param args Arguments which can be used to set data of log record by type.
+   *  string_view                             -> body
+   *  AttributeValue                          -> body
+   *  SpanContext                             -> span_id,trace_id and trace_flags
+   *  SpanId                                  -> span_id
+   *  TraceId                                 -> trace_id
+   *  TraceFlags                              -> trace_flags
+   *  SystemTimestamp                         -> timestamp
+   *  system_clock::time_point                -> timestamp
+   *  KeyValueIterable                        -> attributes
+   *  Key value iterable container            -> attributes
+   *  span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
+   */
+  template <class... ArgumentType>
+  void Fatal(ArgumentType &&...args) noexcept
+  {
+    static_assert(
+        !detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
+        "Severity is already set.");
+    this->EmitLogRecord(Severity::kFatal, std::forward<ArgumentType>(args)...);
+  }
+
+  //
+  // OpenTelemetry C++ user-facing Logs API
+  //
+
+  inline bool Enabled(Severity severity, const EventId &event_id) const noexcept
+  {
+    if OPENTELEMETRY_LIKELY_CONDITION (!Enabled(severity))
+    {
+      return false;
+    }
+    return EnabledImplementation(severity, event_id);
+  }
+
+  inline bool Enabled(Severity severity, int64_t event_id) const noexcept
+  {
+    if OPENTELEMETRY_LIKELY_CONDITION (!Enabled(severity))
+    {
+      return false;
+    }
+    return EnabledImplementation(severity, event_id);
+  }
+
+  inline bool Enabled(Severity severity) const noexcept
+  {
+    return static_cast<uint8_t>(severity) >= OPENTELEMETRY_ATOMIC_READ_8(&minimum_severity_);
+  }
+
+  /**
+   * Log an event
+   *
+   * @severity severity of the log
+   * @event_id event identifier of the log
+   * @format an utf-8 string following https://messagetemplates.org/
+   * @attributes key value pairs of the log
+   */
+  virtual void Log(Severity severity,
+                   const EventId &event_id,
+                   nostd::string_view format,
+                   const common::KeyValueIterable &attributes) noexcept
+  {
+    this->EmitLogRecord(severity, event_id, format, attributes);
+  }
+
+  virtual void Log(Severity severity,
+                   int64_t event_id,
+                   nostd::string_view format,
+                   const common::KeyValueIterable &attributes) noexcept
+  {
+    this->EmitLogRecord(severity, EventId{event_id}, format, attributes);
+  }
+
+  virtual void Log(Severity severity,
+                   nostd::string_view format,
+                   const common::KeyValueIterable &attributes) noexcept
+  {
+    this->EmitLogRecord(severity, format, attributes);
+  }
+
+  virtual void Log(Severity severity, nostd::string_view message) noexcept
+  {
+    this->EmitLogRecord(severity, message);
+  }
+
+  // Convenient wrappers based on virtual methods Log().
+  // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#field-severitynumber
+
+  inline void Trace(const EventId &event_id,
+                    nostd::string_view format,
+                    const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kTrace, event_id, format, attributes);
+  }
+
+  inline void Trace(int64_t event_id,
+                    nostd::string_view format,
+                    const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kTrace, EventId{event_id}, format, attributes);
+  }
+
+  inline void Trace(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kTrace, format, attributes);
+  }
+
+  inline void Trace(nostd::string_view message) noexcept { this->Log(Severity::kTrace, message); }
+
+  inline void Debug(const EventId &event_id,
+                    nostd::string_view format,
+                    const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kDebug, event_id, format, attributes);
+  }
+
+  inline void Debug(int64_t event_id,
+                    nostd::string_view format,
+                    const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kDebug, EventId{event_id}, format, attributes);
+  }
+
+  inline void Debug(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kDebug, format, attributes);
+  }
+
+  inline void Debug(nostd::string_view message) noexcept { this->Log(Severity::kDebug, message); }
+
+  inline void Info(const EventId &event_id,
+                   nostd::string_view format,
+                   const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kInfo, event_id, format, attributes);
+  }
+
+  inline void Info(int64_t event_id,
+                   nostd::string_view format,
+                   const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kInfo, EventId{event_id}, format, attributes);
+  }
+
+  inline void Info(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kInfo, format, attributes);
+  }
+
+  inline void Info(nostd::string_view message) noexcept { this->Log(Severity::kInfo, message); }
+
+  inline void Warn(const EventId &event_id,
+                   nostd::string_view format,
+                   const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kWarn, event_id, format, attributes);
+  }
+
+  inline void Warn(int64_t event_id,
+                   nostd::string_view format,
+                   const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kWarn, EventId{event_id}, format, attributes);
+  }
+
+  inline void Warn(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kWarn, format, attributes);
+  }
+
+  inline void Warn(nostd::string_view message) noexcept { this->Log(Severity::kWarn, message); }
+
+  inline void Error(const EventId &event_id,
+                    nostd::string_view format,
+                    const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kError, event_id, format, attributes);
+  }
+
+  inline void Error(int64_t event_id,
+                    nostd::string_view format,
+                    const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kError, EventId{event_id}, format, attributes);
+  }
+
+  inline void Error(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kError, format, attributes);
+  }
+
+  inline void Error(nostd::string_view message) noexcept { this->Log(Severity::kError, message); }
+
+  inline void Fatal(const EventId &event_id,
+                    nostd::string_view format,
+                    const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kFatal, event_id, format, attributes);
+  }
+
+  inline void Fatal(int64_t event_id,
+                    nostd::string_view format,
+                    const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kFatal, EventId{event_id}, format, attributes);
+  }
+
+  inline void Fatal(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
+  {
+    this->Log(Severity::kFatal, format, attributes);
+  }
+
+  inline void Fatal(nostd::string_view message) noexcept { this->Log(Severity::kFatal, message); }
+
+  //
+  // End of OpenTelemetry C++ user-facing Log API.
+  //
+
+protected:
+  // TODO: discuss with community about naming for internal methods.
+  virtual bool EnabledImplementation(Severity /*severity*/,
+                                     const EventId & /*event_id*/) const noexcept
+  {
+    return false;
+  }
+
+  virtual bool EnabledImplementation(Severity /*severity*/, int64_t /*event_id*/) const noexcept
+  {
+    return false;
+  }
+
+  void SetMinimumSeverity(uint8_t severity_or_max) noexcept
+  {
+    OPENTELEMETRY_ATOMIC_WRITE_8(&minimum_severity_, severity_or_max);
+  }
+
+private:
+  template <class... ValueType>
+  void IgnoreTraitResult(ValueType &&...)
+  {}
+
+  //
+  // minimum_severity_ can be updated concurrently by multiple threads/cores, so race condition on
+  // read/write should be handled. And std::atomic can not be used here because it is not ABI
+  // compatible for OpenTelemetry C++ API.
+  //
+  mutable uint8_t minimum_severity_{kMaxSeverity};
+};
+}  // namespace logs
+OPENTELEMETRY_END_NAMESPACE

+ 71 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/logger_provider.h

@@ -0,0 +1,71 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/common/key_value_iterable.h"
+#include "opentelemetry/common/key_value_iterable_view.h"
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/nostd/span.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/nostd/type_traits.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace logs
+{
+
+class Logger;
+
+/**
+ * Creates new Logger instances.
+ */
+class OPENTELEMETRY_EXPORT LoggerProvider
+{
+public:
+  virtual ~LoggerProvider() = default;
+
+  /**
+   * Gets or creates a named Logger instance.
+   *
+   * Optionally a version can be passed to create a named and versioned Logger
+   * instance.
+   *
+   * Optionally a configuration file name can be passed to create a configuration for
+   * the Logger instance.
+   *
+   */
+
+  virtual nostd::shared_ptr<Logger> GetLogger(
+      nostd::string_view logger_name,
+      nostd::string_view library_name            = "",
+      nostd::string_view library_version         = "",
+      nostd::string_view schema_url              = "",
+      const common::KeyValueIterable &attributes = common::NoopKeyValueIterable()) = 0;
+
+  nostd::shared_ptr<Logger> GetLogger(
+      nostd::string_view logger_name,
+      nostd::string_view library_name,
+      nostd::string_view library_version,
+      nostd::string_view schema_url,
+      std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes)
+  {
+    return GetLogger(logger_name, library_name, library_version, schema_url,
+                     nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
+                         attributes.begin(), attributes.end()});
+  }
+
+  template <class T,
+            nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr>
+  nostd::shared_ptr<Logger> GetLogger(nostd::string_view logger_name,
+                                      nostd::string_view library_name,
+                                      nostd::string_view library_version,
+                                      nostd::string_view schema_url,
+                                      const T &attributes)
+  {
+    return GetLogger(logger_name, library_name, library_version, schema_url,
+                     common::KeyValueIterableView<T>(attributes));
+  }
+};
+}  // namespace logs
+OPENTELEMETRY_END_NAMESPACE

+ 204 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/logger_type_traits.h

@@ -0,0 +1,204 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <chrono>
+#include <memory>
+#include <type_traits>
+
+#include "opentelemetry/common/attribute_value.h"
+#include "opentelemetry/common/key_value_iterable.h"
+#include "opentelemetry/common/timestamp.h"
+#include "opentelemetry/logs/event_id.h"
+#include "opentelemetry/logs/log_record.h"
+#include "opentelemetry/logs/severity.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/nostd/type_traits.h"
+#include "opentelemetry/trace/span_context.h"
+#include "opentelemetry/trace/span_id.h"
+#include "opentelemetry/trace/trace_flags.h"
+#include "opentelemetry/trace/trace_id.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace logs
+{
+namespace detail
+{
+template <class ValueType>
+struct LogRecordSetterTrait;
+
+template <>
+struct LogRecordSetterTrait<Severity>
+{
+  template <class ArgumentType>
+  inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
+  {
+    log_record->SetSeverity(std::forward<ArgumentType>(arg));
+
+    return log_record;
+  }
+};
+
+template <>
+struct LogRecordSetterTrait<EventId>
+{
+  template <class ArgumentType>
+  inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
+  {
+    log_record->SetEventId(arg.id_, nostd::string_view{arg.name_.get()});
+
+    return log_record;
+  }
+};
+
+template <>
+struct LogRecordSetterTrait<trace::SpanContext>
+{
+  template <class ArgumentType>
+  inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
+  {
+    log_record->SetSpanId(arg.span_id());
+    log_record->SetTraceId(arg.trace_id());
+    log_record->SetTraceFlags(arg.trace_flags());
+
+    return log_record;
+  }
+};
+
+template <>
+struct LogRecordSetterTrait<trace::SpanId>
+{
+  template <class ArgumentType>
+  inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
+  {
+    log_record->SetSpanId(std::forward<ArgumentType>(arg));
+
+    return log_record;
+  }
+};
+
+template <>
+struct LogRecordSetterTrait<trace::TraceId>
+{
+  template <class ArgumentType>
+  inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
+  {
+    log_record->SetTraceId(std::forward<ArgumentType>(arg));
+
+    return log_record;
+  }
+};
+
+template <>
+struct LogRecordSetterTrait<trace::TraceFlags>
+{
+  template <class ArgumentType>
+  inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
+  {
+    log_record->SetTraceFlags(std::forward<ArgumentType>(arg));
+
+    return log_record;
+  }
+};
+
+template <>
+struct LogRecordSetterTrait<common::SystemTimestamp>
+{
+  template <class ArgumentType>
+  inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
+  {
+    log_record->SetTimestamp(std::forward<ArgumentType>(arg));
+
+    return log_record;
+  }
+};
+
+template <>
+struct LogRecordSetterTrait<std::chrono::system_clock::time_point>
+{
+  template <class ArgumentType>
+  inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
+  {
+    log_record->SetTimestamp(common::SystemTimestamp(std::forward<ArgumentType>(arg)));
+
+    return log_record;
+  }
+};
+
+template <>
+struct LogRecordSetterTrait<common::KeyValueIterable>
+{
+  template <class ArgumentType>
+  inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
+  {
+    arg.ForEachKeyValue(
+        [&log_record](nostd::string_view key, common::AttributeValue value) noexcept {
+          log_record->SetAttribute(key, value);
+          return true;
+        });
+
+    return log_record;
+  }
+};
+
+template <class ValueType>
+struct LogRecordSetterTrait
+{
+  static_assert(!std::is_same<nostd::unique_ptr<LogRecord>, ValueType>::value &&
+                    !std::is_same<std::unique_ptr<LogRecord>, ValueType>::value,
+                "unique_ptr<LogRecord> is not allowed, please use std::move()");
+
+  template <class ArgumentType,
+            nostd::enable_if_t<std::is_convertible<ArgumentType, nostd::string_view>::value ||
+                                   std::is_convertible<ArgumentType, common::AttributeValue>::value,
+                               void> * = nullptr>
+  inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
+  {
+    log_record->SetBody(std::forward<ArgumentType>(arg));
+
+    return log_record;
+  }
+
+  template <class ArgumentType,
+            nostd::enable_if_t<std::is_base_of<common::KeyValueIterable, ArgumentType>::value, bool>
+                * = nullptr>
+  inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
+  {
+    return LogRecordSetterTrait<common::KeyValueIterable>::Set(log_record,
+                                                               std::forward<ArgumentType>(arg));
+  }
+
+  template <class ArgumentType,
+            nostd::enable_if_t<common::detail::is_key_value_iterable<ArgumentType>::value, int> * =
+                nullptr>
+  inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
+  {
+    for (auto &argv : arg)
+    {
+      log_record->SetAttribute(argv.first, argv.second);
+    }
+
+    return log_record;
+  }
+};
+
+template <class ValueType, class... ArgumentType>
+struct LogRecordHasType;
+
+template <class ValueType>
+struct LogRecordHasType<ValueType> : public std::false_type
+{};
+
+template <class ValueType, class TargetType, class... ArgumentType>
+struct LogRecordHasType<ValueType, TargetType, ArgumentType...>
+    : public std::conditional<std::is_same<ValueType, TargetType>::value,
+                              std::true_type,
+                              LogRecordHasType<ValueType, ArgumentType...>>::type
+{};
+
+}  // namespace detail
+
+}  // namespace logs
+OPENTELEMETRY_END_NAMESPACE

+ 131 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/noop.h

@@ -0,0 +1,131 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+// Please refer to provider.h for documentation on how to obtain a Logger object.
+//
+// This file is part of the internal implementation of OpenTelemetry. Nothing in this file should be
+// used directly. Please refer to logger.h for documentation on these interfaces.
+
+#include "opentelemetry/logs/event_logger.h"
+#include "opentelemetry/logs/event_logger_provider.h"
+#include "opentelemetry/logs/logger.h"
+#include "opentelemetry/logs/logger_provider.h"
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/nostd/unique_ptr.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace common
+{
+class KeyValueIterable;
+}  // namespace common
+
+namespace logs
+{
+/**
+ * No-op implementation of Logger. This class should not be used directly. It should only be
+ * instantiated using a LoggerProvider's GetLogger() call.
+ */
+class NoopLogger final : public Logger
+{
+public:
+  const nostd::string_view GetName() noexcept override { return "noop logger"; }
+
+  nostd::unique_ptr<LogRecord> CreateLogRecord() noexcept override
+  {
+    /*
+     * Do not return memory shared between threads,
+     * a `new` + `delete` for each noop record can not be avoided,
+     * due to the semantic of unique_ptr.
+     */
+    return nostd::unique_ptr<LogRecord>(new NoopLogRecord());
+  }
+
+  using Logger::EmitLogRecord;
+
+  void EmitLogRecord(nostd::unique_ptr<LogRecord> &&) noexcept override {}
+
+private:
+  class NoopLogRecord : public LogRecord
+  {
+  public:
+    NoopLogRecord()           = default;
+    ~NoopLogRecord() override = default;
+
+    void SetTimestamp(common::SystemTimestamp /* timestamp */) noexcept override {}
+    void SetObservedTimestamp(common::SystemTimestamp /* timestamp */) noexcept override {}
+    void SetSeverity(logs::Severity /* severity */) noexcept override {}
+    void SetBody(const common::AttributeValue & /* message */) noexcept override {}
+    void SetAttribute(nostd::string_view /* key */,
+                      const common::AttributeValue & /* value */) noexcept override
+    {}
+    void SetEventId(int64_t /* id */, nostd::string_view /* name */) noexcept override {}
+    void SetTraceId(const trace::TraceId & /* trace_id */) noexcept override {}
+    void SetSpanId(const trace::SpanId & /* span_id */) noexcept override {}
+    void SetTraceFlags(const trace::TraceFlags & /* trace_flags */) noexcept override {}
+  };
+};
+
+/**
+ * No-op implementation of a LoggerProvider.
+ */
+class NoopLoggerProvider final : public LoggerProvider
+{
+public:
+  NoopLoggerProvider() : logger_{nostd::shared_ptr<NoopLogger>(new NoopLogger())} {}
+
+  nostd::shared_ptr<Logger> GetLogger(nostd::string_view /* logger_name */,
+                                      nostd::string_view /* library_name */,
+                                      nostd::string_view /* library_version */,
+                                      nostd::string_view /* schema_url */,
+                                      const common::KeyValueIterable & /* attributes */) override
+  {
+    return logger_;
+  }
+
+private:
+  nostd::shared_ptr<Logger> logger_;
+};
+
+#if OPENTELEMETRY_ABI_VERSION_NO < 2
+class NoopEventLogger final : public EventLogger
+{
+public:
+  NoopEventLogger() : logger_{nostd::shared_ptr<NoopLogger>(new NoopLogger())} {}
+
+  const nostd::string_view GetName() noexcept override { return "noop event logger"; }
+
+  nostd::shared_ptr<Logger> GetDelegateLogger() noexcept override { return logger_; }
+
+  void EmitEvent(nostd::string_view, nostd::unique_ptr<LogRecord> &&) noexcept override {}
+
+private:
+  nostd::shared_ptr<Logger> logger_;
+};
+
+/**
+ * No-op implementation of a EventLoggerProvider.
+ */
+class NoopEventLoggerProvider final : public EventLoggerProvider
+{
+public:
+  NoopEventLoggerProvider() : event_logger_{nostd::shared_ptr<EventLogger>(new NoopEventLogger())}
+  {}
+
+  nostd::shared_ptr<EventLogger> CreateEventLogger(
+      nostd::shared_ptr<Logger> /*delegate_logger*/,
+      nostd::string_view /*event_domain*/) noexcept override
+  {
+    return event_logger_;
+  }
+
+private:
+  nostd::shared_ptr<EventLogger> event_logger_;
+};
+#endif
+
+}  // namespace logs
+OPENTELEMETRY_END_NAMESPACE

+ 100 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/provider.h

@@ -0,0 +1,100 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <mutex>
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/common/spin_lock_mutex.h"
+#include "opentelemetry/logs/noop.h"
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace logs
+{
+
+#if OPENTELEMETRY_ABI_VERSION_NO < 2
+class EventLoggerProvider;
+#endif
+class LoggerProvider;
+
+/**
+ * Stores the singleton global LoggerProvider.
+ */
+class OPENTELEMETRY_EXPORT Provider
+{
+public:
+  /**
+   * Returns the singleton LoggerProvider.
+   *
+   * By default, a no-op LoggerProvider is returned. This will never return a
+   * nullptr LoggerProvider.
+   */
+  static nostd::shared_ptr<LoggerProvider> GetLoggerProvider() noexcept
+  {
+    std::lock_guard<common::SpinLockMutex> guard(GetLock());
+    return nostd::shared_ptr<LoggerProvider>(GetProvider());
+  }
+
+  /**
+   * Changes the singleton LoggerProvider.
+   */
+  static void SetLoggerProvider(const nostd::shared_ptr<LoggerProvider> &tp) noexcept
+  {
+    std::lock_guard<common::SpinLockMutex> guard(GetLock());
+    GetProvider() = tp;
+  }
+
+#if OPENTELEMETRY_ABI_VERSION_NO < 2
+  /**
+   * Returns the singleton EventLoggerProvider.
+   *
+   * By default, a no-op EventLoggerProvider is returned. This will never return a
+   * nullptr EventLoggerProvider.
+   */
+  OPENTELEMETRY_DEPRECATED static nostd::shared_ptr<EventLoggerProvider>
+  GetEventLoggerProvider() noexcept
+  {
+    std::lock_guard<common::SpinLockMutex> guard(GetLock());
+    return nostd::shared_ptr<EventLoggerProvider>(GetEventProvider());
+  }
+
+  /**
+   * Changes the singleton EventLoggerProvider.
+   */
+  OPENTELEMETRY_DEPRECATED static void SetEventLoggerProvider(
+      const nostd::shared_ptr<EventLoggerProvider> &tp) noexcept
+  {
+    std::lock_guard<common::SpinLockMutex> guard(GetLock());
+    GetEventProvider() = tp;
+  }
+#endif
+
+private:
+  OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr<LoggerProvider> &GetProvider() noexcept
+  {
+    static nostd::shared_ptr<LoggerProvider> provider(new NoopLoggerProvider);
+    return provider;
+  }
+
+#if OPENTELEMETRY_ABI_VERSION_NO < 2
+  OPENTELEMETRY_DEPRECATED
+  OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr<EventLoggerProvider> &
+  GetEventProvider() noexcept
+  {
+    static nostd::shared_ptr<EventLoggerProvider> provider(new NoopEventLoggerProvider);
+    return provider;
+  }
+#endif
+
+  OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept
+  {
+    static common::SpinLockMutex lock;
+    return lock;
+  }
+};
+
+}  // namespace logs
+OPENTELEMETRY_END_NAMESPACE

+ 67 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/severity.h

@@ -0,0 +1,67 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <cstdint>
+
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace logs
+{
+
+/**
+ * Severity Levels assigned to log events, based on Log Data Model,
+ * with the addition of kInvalid (mapped to a severity number of 0).
+ *
+ * See
+ * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#field-severitynumber
+ */
+enum class Severity : uint8_t
+{
+  kInvalid = 0,
+  kTrace   = 1,
+  kTrace2  = 2,
+  kTrace3  = 3,
+  kTrace4  = 4,
+  kDebug   = 5,
+  kDebug2  = 6,
+  kDebug3  = 7,
+  kDebug4  = 8,
+  kInfo    = 9,
+  kInfo2   = 10,
+  kInfo3   = 11,
+  kInfo4   = 12,
+  kWarn    = 13,
+  kWarn2   = 14,
+  kWarn3   = 15,
+  kWarn4   = 16,
+  kError   = 17,
+  kError2  = 18,
+  kError3  = 19,
+  kError4  = 20,
+  kFatal   = 21,
+  kFatal2  = 22,
+  kFatal3  = 23,
+  kFatal4  = 24
+};
+
+const uint8_t kMaxSeverity = 255;
+
+/**
+ * Mapping of the severity enum above, to a severity text string (in all caps).
+ * This severity text can be printed out by exporters. Capital letters follow the
+ * spec naming convention.
+ *
+ * Included to follow the specification's recommendation to print both
+ * severity number and text in each log record.
+ */
+const nostd::string_view SeverityNumToText[25] = {
+    "INVALID", "TRACE",  "TRACE2", "TRACE3", "TRACE4", "DEBUG",  "DEBUG2", "DEBUG3", "DEBUG4",
+    "INFO",    "INFO2",  "INFO3",  "INFO4",  "WARN",   "WARN2",  "WARN3",  "WARN4",  "ERROR",
+    "ERROR2",  "ERROR3", "ERROR4", "FATAL",  "FATAL2", "FATAL3", "FATAL4"};
+
+}  // namespace logs
+OPENTELEMETRY_END_NAMESPACE

+ 33 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/metrics/async_instruments.h

@@ -0,0 +1,33 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/metrics/observer_result.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace metrics
+{
+
+using ObservableCallbackPtr = void (*)(ObserverResult, void *);
+
+class ObservableInstrument
+{
+public:
+  ObservableInstrument()          = default;
+  virtual ~ObservableInstrument() = default;
+
+  /**
+   * Sets up a function that will be called whenever a metric collection is initiated.
+   */
+  virtual void AddCallback(ObservableCallbackPtr, void *state) noexcept = 0;
+
+  /**
+   * Remove a function that was configured to be called whenever a metric collection is initiated.
+   */
+  virtual void RemoveCallback(ObservableCallbackPtr, void *state) noexcept = 0;
+};
+
+}  // namespace metrics
+OPENTELEMETRY_END_NAMESPACE

+ 174 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/metrics/meter.h

@@ -0,0 +1,174 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/nostd/unique_ptr.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace metrics
+{
+
+template <typename T>
+class Counter;
+
+template <typename T>
+class Histogram;
+
+template <typename T>
+class UpDownCounter;
+
+template <typename T>
+class Gauge;
+
+class ObservableInstrument;
+
+/**
+ * Handles instrument creation and provides a facility for batch recording.
+ *
+ * This class provides methods to create new metric instruments, record a
+ * batch of values to a specified set of instruments, and collect
+ * measurements from all instruments.
+ *
+ */
+class Meter
+{
+public:
+  virtual ~Meter() = default;
+
+  /**
+   * Creates a Counter with the passed characteristics and returns a unique_ptr to that Counter.
+   *
+   * @param name the name of the new Counter.
+   * @param description a brief description of what the Counter is used for.
+   * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html.
+   * @return a shared pointer to the created Counter.
+   */
+
+  virtual nostd::unique_ptr<Counter<uint64_t>> CreateUInt64Counter(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept = 0;
+
+  virtual nostd::unique_ptr<Counter<double>> CreateDoubleCounter(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept = 0;
+
+  /**
+   * Creates a Asynchronous (Observable) counter with the passed characteristics and returns a
+   * shared_ptr to that Observable Counter
+   *
+   * @param name the name of the new Observable Counter.
+   * @param description a brief description of what the Observable Counter is used for.
+   * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html.
+   */
+  virtual nostd::shared_ptr<ObservableInstrument> CreateInt64ObservableCounter(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept = 0;
+
+  virtual nostd::shared_ptr<ObservableInstrument> CreateDoubleObservableCounter(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept = 0;
+
+  /**
+   * Creates a Histogram with the passed characteristics and returns a unique_ptr to that Histogram.
+   *
+   * @param name the name of the new Histogram.
+   * @param description a brief description of what the Histogram is used for.
+   * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html.
+   * @return a shared pointer to the created Histogram.
+   */
+  virtual nostd::unique_ptr<Histogram<uint64_t>> CreateUInt64Histogram(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept = 0;
+
+  virtual nostd::unique_ptr<Histogram<double>> CreateDoubleHistogram(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept = 0;
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+  /**
+   * Creates a Gauge with the passed characteristics and returns a unique_ptr to that Gauge.
+   *
+   * @param name the name of the new Gauge.
+   * @param description a brief description of what the Gauge is used for.
+   * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html.
+   * @return a unique pointer to the created Gauge.
+   */
+
+  virtual nostd::unique_ptr<Gauge<int64_t>> CreateInt64Gauge(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept = 0;
+
+  virtual nostd::unique_ptr<Gauge<double>> CreateDoubleGauge(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept = 0;
+#endif
+
+  /**
+   * Creates a Asynchronous (Observable) Gauge with the passed characteristics and returns a
+   * shared_ptr to that Observable Gauge
+   *
+   * @param name the name of the new Observable Gauge.
+   * @param description a brief description of what the Observable Gauge is used for.
+   * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html.
+   */
+  virtual nostd::shared_ptr<ObservableInstrument> CreateInt64ObservableGauge(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept = 0;
+
+  virtual nostd::shared_ptr<ObservableInstrument> CreateDoubleObservableGauge(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept = 0;
+
+  /**
+   * Creates an UpDownCounter with the passed characteristics and returns a unique_ptr to that
+   * UpDownCounter.
+   *
+   * @param name the name of the new UpDownCounter.
+   * @param description a brief description of what the UpDownCounter is used for.
+   * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html.
+   * @return a shared pointer to the created UpDownCounter.
+   */
+  virtual nostd::unique_ptr<UpDownCounter<int64_t>> CreateInt64UpDownCounter(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept = 0;
+
+  virtual nostd::unique_ptr<UpDownCounter<double>> CreateDoubleUpDownCounter(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept = 0;
+
+  /**
+   * Creates a Asynchronous (Observable) UpDownCounter with the passed characteristics and returns
+   * a shared_ptr to that Observable UpDownCounter
+   *
+   * @param name the name of the new Observable UpDownCounter.
+   * @param description a brief description of what the Observable UpDownCounter is used for.
+   * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html.
+   */
+  virtual nostd::shared_ptr<ObservableInstrument> CreateInt64ObservableUpDownCounter(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept = 0;
+
+  virtual nostd::shared_ptr<ObservableInstrument> CreateDoubleObservableUpDownCounter(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept = 0;
+};
+}  // namespace metrics
+OPENTELEMETRY_END_NAMESPACE

+ 148 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/metrics/meter_provider.h

@@ -0,0 +1,148 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/common/key_value_iterable.h"
+#include "opentelemetry/common/key_value_iterable_view.h"
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/nostd/type_traits.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace metrics
+{
+
+class Meter;
+
+/**
+ * Creates new Meter instances.
+ */
+class MeterProvider
+{
+public:
+  virtual ~MeterProvider() = default;
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+
+  /**
+   * Gets or creates a named Meter instance (ABI).
+   *
+   * @since ABI_VERSION 2
+   *
+   * @param[in] name Meter instrumentation scope
+   * @param[in] version Instrumentation scope version
+   * @param[in] schema_url Instrumentation scope schema URL
+   * @param[in] attributes Instrumentation scope attributes (optional, may be nullptr)
+   */
+  virtual nostd::shared_ptr<Meter> GetMeter(
+      nostd::string_view name,
+      nostd::string_view version,
+      nostd::string_view schema_url,
+      const common::KeyValueIterable *attributes) noexcept = 0;
+
+  /**
+   * Gets or creates a named Meter instance (API helper).
+   *
+   * @since ABI_VERSION 2
+   *
+   * @param[in] name Meter instrumentation scope
+   * @param[in] version Instrumentation scope version, optional
+   * @param[in] schema_url Instrumentation scope schema URL, optional
+   */
+  nostd::shared_ptr<Meter> GetMeter(nostd::string_view name,
+                                    nostd::string_view version    = "",
+                                    nostd::string_view schema_url = "")
+  {
+    return GetMeter(name, version, schema_url, nullptr);
+  }
+
+  /**
+   * Gets or creates a named Meter instance (API helper).
+   *
+   * @since ABI_VERSION 2
+   *
+   * @param[in] name Meter instrumentation scope
+   * @param[in] version Instrumentation scope version
+   * @param[in] schema_url Instrumentation scope schema URL
+   * @param[in] attributes Instrumentation scope attributes
+   */
+  nostd::shared_ptr<Meter> GetMeter(
+      nostd::string_view name,
+      nostd::string_view version,
+      nostd::string_view schema_url,
+      std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes)
+  {
+    /* Build a container from std::initializer_list. */
+    nostd::span<const std::pair<nostd::string_view, common::AttributeValue>> attributes_span{
+        attributes.begin(), attributes.end()};
+
+    /* Build a view on the container. */
+    common::KeyValueIterableView<
+        nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>>
+        iterable_attributes{attributes_span};
+
+    /* Add attributes using the view. */
+    return GetMeter(name, version, schema_url, &iterable_attributes);
+  }
+
+  /**
+   * Gets or creates a named Meter instance (API helper).
+   *
+   * @since ABI_VERSION 2
+   *
+   * @param[in] name Meter instrumentation scope
+   * @param[in] version Instrumentation scope version
+   * @param[in] schema_url Instrumentation scope schema URL
+   * @param[in] attributes Instrumentation scope attributes container
+   */
+  template <class T,
+            nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr>
+  nostd::shared_ptr<Meter> GetMeter(nostd::string_view name,
+                                    nostd::string_view version,
+                                    nostd::string_view schema_url,
+                                    const T &attributes)
+  {
+    /* Build a view on the container. */
+    common::KeyValueIterableView<T> iterable_attributes(attributes);
+
+    /* Add attributes using the view. */
+    return GetMeter(name, version, schema_url, &iterable_attributes);
+  }
+
+#else
+  /**
+   * Gets or creates a named Meter instance (ABI)
+   *
+   * @since ABI_VERSION 1
+   *
+   * @param[in] name Meter instrumentation scope
+   * @param[in] version Instrumentation scope version, optional
+   * @param[in] schema_url Instrumentation scope schema URL, optional
+   */
+  virtual nostd::shared_ptr<Meter> GetMeter(nostd::string_view name,
+                                            nostd::string_view version    = "",
+                                            nostd::string_view schema_url = "") noexcept = 0;
+#endif
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+  /**
+   * Remove a named Meter instance (ABI).
+   *
+   * This API is experimental, see
+   * https://github.com/open-telemetry/opentelemetry-specification/issues/2232
+   *
+   * @since ABI_VERSION 2
+   *
+   * @param[in] name Meter instrumentation scope
+   * @param[in] version Instrumentation scope version, optional
+   * @param[in] schema_url Instrumentation scope schema URL, optional
+   */
+  virtual void RemoveMeter(nostd::string_view name,
+                           nostd::string_view version    = "",
+                           nostd::string_view schema_url = "") noexcept = 0;
+#endif
+};
+}  // namespace metrics
+OPENTELEMETRY_END_NAMESPACE

+ 271 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/metrics/noop.h

@@ -0,0 +1,271 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/metrics/async_instruments.h"
+#include "opentelemetry/metrics/meter.h"
+#include "opentelemetry/metrics/meter_provider.h"
+#include "opentelemetry/metrics/observer_result.h"
+#include "opentelemetry/metrics/sync_instruments.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace metrics
+{
+
+template <class T>
+class NoopCounter : public Counter<T>
+{
+public:
+  NoopCounter(nostd::string_view /* name */,
+              nostd::string_view /* description */,
+              nostd::string_view /* unit */) noexcept
+  {}
+  void Add(T /* value */) noexcept override {}
+  void Add(T /* value */, const context::Context & /* context */) noexcept override {}
+  void Add(T /* value */, const common::KeyValueIterable & /* attributes */) noexcept override {}
+  void Add(T /* value */,
+           const common::KeyValueIterable & /* attributes */,
+           const context::Context & /* context */) noexcept override
+  {}
+};
+
+template <class T>
+class NoopHistogram : public Histogram<T>
+{
+public:
+  NoopHistogram(nostd::string_view /* name */,
+                nostd::string_view /* description */,
+                nostd::string_view /* unit */) noexcept
+  {}
+  void Record(T /* value */, const context::Context & /* context */) noexcept override {}
+  void Record(T /* value */,
+              const common::KeyValueIterable & /* attributes */,
+              const context::Context & /* context */) noexcept override
+  {}
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+  void Record(T /*value*/,
+              const opentelemetry::common::KeyValueIterable & /*attributes*/) noexcept override
+  {}
+
+  void Record(T /*value*/) noexcept override {}
+#endif
+};
+
+template <class T>
+class NoopUpDownCounter : public UpDownCounter<T>
+{
+public:
+  NoopUpDownCounter(nostd::string_view /* name */,
+                    nostd::string_view /* description */,
+                    nostd::string_view /* unit */) noexcept
+  {}
+  ~NoopUpDownCounter() override = default;
+  void Add(T /* value */) noexcept override {}
+  void Add(T /* value */, const context::Context & /* context */) noexcept override {}
+  void Add(T /* value */, const common::KeyValueIterable & /* attributes */) noexcept override {}
+  void Add(T /* value */,
+           const common::KeyValueIterable & /* attributes */,
+           const context::Context & /* context */) noexcept override
+  {}
+};
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+template <class T>
+class NoopGauge : public Gauge<T>
+{
+public:
+  NoopGauge(nostd::string_view /* name */,
+            nostd::string_view /* description */,
+            nostd::string_view /* unit */) noexcept
+  {}
+  ~NoopGauge() override = default;
+  void Record(T /* value */) noexcept override {}
+  void Record(T /* value */, const context::Context & /* context */) noexcept override {}
+  void Record(T /* value */, const common::KeyValueIterable & /* attributes */) noexcept override {}
+  void Record(T /* value */,
+              const common::KeyValueIterable & /* attributes */,
+              const context::Context & /* context */) noexcept override
+  {}
+};
+#endif
+
+class NoopObservableInstrument : public ObservableInstrument
+{
+public:
+  NoopObservableInstrument(nostd::string_view /* name */,
+                           nostd::string_view /* description */,
+                           nostd::string_view /* unit */) noexcept
+  {}
+
+  void AddCallback(ObservableCallbackPtr, void * /* state */) noexcept override {}
+  void RemoveCallback(ObservableCallbackPtr, void * /* state */) noexcept override {}
+};
+
+/**
+ * No-op implementation of Meter.
+ */
+class NoopMeter final : public Meter
+{
+public:
+  nostd::unique_ptr<Counter<uint64_t>> CreateUInt64Counter(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept override
+  {
+    return nostd::unique_ptr<Counter<uint64_t>>{new NoopCounter<uint64_t>(name, description, unit)};
+  }
+
+  nostd::unique_ptr<Counter<double>> CreateDoubleCounter(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept override
+  {
+    return nostd::unique_ptr<Counter<double>>{new NoopCounter<double>(name, description, unit)};
+  }
+
+  nostd::shared_ptr<ObservableInstrument> CreateInt64ObservableCounter(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept override
+  {
+    return nostd::shared_ptr<ObservableInstrument>(
+        new NoopObservableInstrument(name, description, unit));
+  }
+
+  nostd::shared_ptr<ObservableInstrument> CreateDoubleObservableCounter(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept override
+  {
+    return nostd::shared_ptr<ObservableInstrument>(
+        new NoopObservableInstrument(name, description, unit));
+  }
+
+  nostd::unique_ptr<Histogram<uint64_t>> CreateUInt64Histogram(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept override
+  {
+    return nostd::unique_ptr<Histogram<uint64_t>>{
+        new NoopHistogram<uint64_t>(name, description, unit)};
+  }
+
+  nostd::unique_ptr<Histogram<double>> CreateDoubleHistogram(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept override
+  {
+    return nostd::unique_ptr<Histogram<double>>{new NoopHistogram<double>(name, description, unit)};
+  }
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+  nostd::unique_ptr<Gauge<int64_t>> CreateInt64Gauge(nostd::string_view name,
+                                                     nostd::string_view description = "",
+                                                     nostd::string_view unit = "") noexcept override
+  {
+    return nostd::unique_ptr<Gauge<int64_t>>{new NoopGauge<int64_t>(name, description, unit)};
+  }
+
+  nostd::unique_ptr<Gauge<double>> CreateDoubleGauge(nostd::string_view name,
+                                                     nostd::string_view description = "",
+                                                     nostd::string_view unit = "") noexcept override
+  {
+    return nostd::unique_ptr<Gauge<double>>{new NoopGauge<double>(name, description, unit)};
+  }
+#endif
+
+  nostd::shared_ptr<ObservableInstrument> CreateInt64ObservableGauge(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept override
+  {
+    return nostd::shared_ptr<ObservableInstrument>(
+        new NoopObservableInstrument(name, description, unit));
+  }
+
+  nostd::shared_ptr<ObservableInstrument> CreateDoubleObservableGauge(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept override
+  {
+    return nostd::shared_ptr<ObservableInstrument>(
+        new NoopObservableInstrument(name, description, unit));
+  }
+
+  nostd::unique_ptr<UpDownCounter<int64_t>> CreateInt64UpDownCounter(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept override
+  {
+    return nostd::unique_ptr<UpDownCounter<int64_t>>{
+        new NoopUpDownCounter<int64_t>(name, description, unit)};
+  }
+
+  nostd::unique_ptr<UpDownCounter<double>> CreateDoubleUpDownCounter(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept override
+  {
+    return nostd::unique_ptr<UpDownCounter<double>>{
+        new NoopUpDownCounter<double>(name, description, unit)};
+  }
+
+  nostd::shared_ptr<ObservableInstrument> CreateInt64ObservableUpDownCounter(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept override
+  {
+    return nostd::shared_ptr<ObservableInstrument>(
+        new NoopObservableInstrument(name, description, unit));
+  }
+
+  nostd::shared_ptr<ObservableInstrument> CreateDoubleObservableUpDownCounter(
+      nostd::string_view name,
+      nostd::string_view description = "",
+      nostd::string_view unit        = "") noexcept override
+  {
+    return nostd::shared_ptr<ObservableInstrument>(
+        new NoopObservableInstrument(name, description, unit));
+  }
+};
+
+/**
+ * No-op implementation of a MeterProvider.
+ */
+class NoopMeterProvider final : public MeterProvider
+{
+public:
+  NoopMeterProvider() : meter_{nostd::shared_ptr<Meter>(new NoopMeter)} {}
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+  nostd::shared_ptr<Meter> GetMeter(
+      nostd::string_view /* name */,
+      nostd::string_view /* version */,
+      nostd::string_view /* schema_url */,
+      const common::KeyValueIterable * /* attributes */) noexcept override
+  {
+    return meter_;
+  }
+#else
+  nostd::shared_ptr<Meter> GetMeter(nostd::string_view /* name */,
+                                    nostd::string_view /* version */,
+                                    nostd::string_view /* schema_url */) noexcept override
+  {
+    return meter_;
+  }
+#endif
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+  void RemoveMeter(nostd::string_view /* name */,
+                   nostd::string_view /* version */,
+                   nostd::string_view /* schema_url */) noexcept override
+  {}
+#endif
+
+private:
+  nostd::shared_ptr<Meter> meter_;
+};
+}  // namespace metrics
+OPENTELEMETRY_END_NAMESPACE

+ 54 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/metrics/observer_result.h

@@ -0,0 +1,54 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/common/attribute_value.h"
+#include "opentelemetry/common/key_value_iterable_view.h"
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/nostd/span.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/nostd/type_traits.h"
+#include "opentelemetry/nostd/variant.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace metrics
+{
+
+/**
+ * ObserverResultT class is necessary for the callback recording asynchronous
+ * instrument use.
+ */
+template <class T>
+class ObserverResultT
+{
+
+public:
+  virtual ~ObserverResultT() = default;
+
+  virtual void Observe(T value) noexcept = 0;
+
+  virtual void Observe(T value, const common::KeyValueIterable &attributes) noexcept = 0;
+
+  template <class U,
+            nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
+  void Observe(T value, const U &attributes) noexcept
+  {
+    this->Observe(value, common::KeyValueIterableView<U>{attributes});
+  }
+
+  void Observe(T value,
+               std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
+                   attributes) noexcept
+  {
+    this->Observe(value, nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
+                             attributes.begin(), attributes.end()});
+  }
+};
+
+using ObserverResult = nostd::variant<nostd::shared_ptr<ObserverResultT<int64_t>>,
+                                      nostd::shared_ptr<ObserverResultT<double>>>;
+
+}  // namespace metrics
+OPENTELEMETRY_END_NAMESPACE

+ 60 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/metrics/provider.h

@@ -0,0 +1,60 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <mutex>
+
+#include "opentelemetry/common/spin_lock_mutex.h"
+#include "opentelemetry/metrics/meter_provider.h"
+#include "opentelemetry/metrics/noop.h"
+#include "opentelemetry/nostd/shared_ptr.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace metrics
+{
+
+/**
+ * Stores the singleton global MeterProvider.
+ */
+class Provider
+{
+public:
+  /**
+   * Returns the singleton MeterProvider.
+   *
+   * By default, a no-op MeterProvider is returned. This will never return a
+   * nullptr MeterProvider.
+   */
+  static nostd::shared_ptr<MeterProvider> GetMeterProvider() noexcept
+  {
+    std::lock_guard<common::SpinLockMutex> guard(GetLock());
+    return nostd::shared_ptr<MeterProvider>(GetProvider());
+  }
+
+  /**
+   * Changes the singleton MeterProvider.
+   */
+  static void SetMeterProvider(const nostd::shared_ptr<MeterProvider> &tp) noexcept
+  {
+    std::lock_guard<common::SpinLockMutex> guard(GetLock());
+    GetProvider() = tp;
+  }
+
+private:
+  OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr<MeterProvider> &GetProvider() noexcept
+  {
+    static nostd::shared_ptr<MeterProvider> provider(new NoopMeterProvider);
+    return provider;
+  }
+
+  OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept
+  {
+    static common::SpinLockMutex lock;
+    return lock;
+  }
+};
+
+}  // namespace metrics
+OPENTELEMETRY_END_NAMESPACE

+ 328 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/metrics/sync_instruments.h

@@ -0,0 +1,328 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/common/attribute_value.h"
+#include "opentelemetry/common/key_value_iterable_view.h"
+#include "opentelemetry/context/context.h"
+#include "opentelemetry/nostd/span.h"
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/nostd/type_traits.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace metrics
+{
+
+class SynchronousInstrument
+{
+public:
+  SynchronousInstrument()          = default;
+  virtual ~SynchronousInstrument() = default;
+};
+
+/* A Counter instrument that adds values. */
+template <class T>
+class Counter : public SynchronousInstrument
+{
+
+public:
+  /**
+   * Record a value
+   *
+   * @param value The increment amount. MUST be non-negative.
+   */
+  virtual void Add(T value) noexcept = 0;
+
+  /**
+   * Record a value
+   *
+   * @param value The increment amount. MUST be non-negative.
+   * @param context The explicit context to associate with this measurement.
+   */
+  virtual void Add(T value, const context::Context &context) noexcept = 0;
+
+  /**
+   * Record a value with a set of attributes.
+   *
+   * @param value The increment amount. MUST be non-negative.
+   * @param attributes A set of attributes to associate with the value.
+   */
+
+  virtual void Add(T value, const common::KeyValueIterable &attributes) noexcept = 0;
+
+  /**
+   * Record a value with a set of attributes.
+   *
+   * @param value The increment amount. MUST be non-negative.
+   * @param attributes A set of attributes to associate with the value.
+   * @param context The explicit context to associate with this measurement.
+   */
+  virtual void Add(T value,
+                   const common::KeyValueIterable &attributes,
+                   const context::Context &context) noexcept = 0;
+
+  template <class U,
+            nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
+  void Add(T value, const U &attributes) noexcept
+  {
+    this->Add(value, common::KeyValueIterableView<U>{attributes});
+  }
+
+  template <class U,
+            nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
+  void Add(T value, const U &attributes, const context::Context &context) noexcept
+  {
+    this->Add(value, common::KeyValueIterableView<U>{attributes}, context);
+  }
+
+  void Add(T value,
+           std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
+               attributes) noexcept
+  {
+    this->Add(value, nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
+                         attributes.begin(), attributes.end()});
+  }
+
+  void Add(T value,
+           std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes,
+           const context::Context &context) noexcept
+  {
+    this->Add(value,
+              nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
+                  attributes.begin(), attributes.end()},
+              context);
+  }
+};
+
+/** A histogram instrument that records values. */
+
+template <class T>
+class Histogram : public SynchronousInstrument
+{
+public:
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+  /**
+   * @since ABI_VERSION 2
+   * Records a value.
+   *
+   * @param value The measurement value. MUST be non-negative.
+   */
+  virtual void Record(T value) noexcept = 0;
+
+  /**
+   * @since ABI_VERSION 2
+   * Records a value with a set of attributes.
+   *
+   * @param value The measurement value. MUST be non-negative.
+   * @param attribute A set of attributes to associate with the value.
+   */
+  virtual void Record(T value, const common::KeyValueIterable &attribute) noexcept = 0;
+
+  template <class U,
+            nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
+  void Record(T value, const U &attributes) noexcept
+  {
+    this->Record(value, common::KeyValueIterableView<U>{attributes});
+  }
+
+  void Record(T value,
+              std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
+                  attributes) noexcept
+  {
+    this->Record(value, nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
+                            attributes.begin(), attributes.end()});
+  }
+#endif
+
+  /**
+   * Records a value.
+   *
+   * @param value The measurement value. MUST be non-negative.
+   * @param context The explicit context to associate with this measurement.
+   */
+  virtual void Record(T value, const context::Context &context) noexcept = 0;
+
+  /**
+   * Records a value with a set of attributes.
+   *
+   * @param value The measurement value. MUST be non-negative.
+   * @param attributes A set of attributes to associate with the value..
+   * @param context The explicit context to associate with this measurement.
+   */
+  virtual void Record(T value,
+                      const common::KeyValueIterable &attributes,
+                      const context::Context &context) noexcept = 0;
+
+  template <class U,
+            nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
+  void Record(T value, const U &attributes, const context::Context &context) noexcept
+  {
+    this->Record(value, common::KeyValueIterableView<U>{attributes}, context);
+  }
+
+  void Record(
+      T value,
+      std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes,
+      const context::Context &context) noexcept
+  {
+    this->Record(value,
+                 nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
+                     attributes.begin(), attributes.end()},
+                 context);
+  }
+};
+
+/** An up-down-counter instrument that adds or reduce values. */
+
+template <class T>
+class UpDownCounter : public SynchronousInstrument
+{
+public:
+  /**
+   * Record a value.
+   *
+   * @param value The increment amount. May be positive, negative or zero.
+   */
+  virtual void Add(T value) noexcept = 0;
+
+  /**
+   * Record a value.
+   *
+   * @param value The increment amount. May be positive, negative or zero.
+   * @param context The explicit context to associate with this measurement.
+   */
+  virtual void Add(T value, const context::Context &context) noexcept = 0;
+
+  /**
+   * Record a value with a set of attributes.
+   *
+   * @param value The increment amount. May be positive, negative or zero.
+   * @param attributes A set of attributes to associate with the count.
+   */
+  virtual void Add(T value, const common::KeyValueIterable &attributes) noexcept = 0;
+
+  /**
+   * Record a value with a set of attributes.
+   *
+   * @param value The increment amount. May be positive, negative or zero.
+   * @param attributes A set of attributes to associate with the count.
+   * @param context The explicit context to associate with this measurement.
+   */
+  virtual void Add(T value,
+                   const common::KeyValueIterable &attributes,
+                   const context::Context &context) noexcept = 0;
+
+  template <class U,
+            nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
+  void Add(T value, const U &attributes) noexcept
+  {
+    this->Add(value, common::KeyValueIterableView<U>{attributes});
+  }
+
+  template <class U,
+            nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
+  void Add(T value, const U &attributes, const context::Context &context) noexcept
+  {
+    this->Add(value, common::KeyValueIterableView<U>{attributes}, context);
+  }
+
+  void Add(T value,
+           std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
+               attributes) noexcept
+  {
+    this->Add(value, nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
+                         attributes.begin(), attributes.end()});
+  }
+
+  void Add(T value,
+           std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes,
+           const context::Context &context) noexcept
+  {
+    this->Add(value,
+              nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
+                  attributes.begin(), attributes.end()},
+              context);
+  }
+};
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+/* A Gauge instrument that records values. */
+template <class T>
+class Gauge : public SynchronousInstrument
+{
+
+public:
+  /**
+   * Record a value
+   *
+   * @param value The measurement value. May be positive, negative or zero.
+   */
+  virtual void Record(T value) noexcept = 0;
+
+  /**
+   * Record a value
+   *
+   * @param value The measurement value. May be positive, negative or zero.
+   * @param context The explicit context to associate with this measurement.
+   */
+  virtual void Record(T value, const context::Context &context) noexcept = 0;
+
+  /**
+   * Record a value with a set of attributes.
+   *
+   * @param value The measurement value. May be positive, negative or zero.
+   * @param attributes A set of attributes to associate with the value.
+   */
+
+  virtual void Record(T value, const common::KeyValueIterable &attributes) noexcept = 0;
+
+  /**
+   * Record a value with a set of attributes.
+   *
+   * @param value The measurement value. May be positive, negative or zero.
+   * @param attributes A set of attributes to associate with the value.
+   * @param context The explicit context to associate with this measurement.
+   */
+  virtual void Record(T value,
+                      const common::KeyValueIterable &attributes,
+                      const context::Context &context) noexcept = 0;
+
+  template <class U,
+            nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
+  void Record(T value, const U &attributes) noexcept
+  {
+    this->Record(value, common::KeyValueIterableView<U>{attributes});
+  }
+
+  template <class U,
+            nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
+  void Record(T value, const U &attributes, const context::Context &context) noexcept
+  {
+    this->Record(value, common::KeyValueIterableView<U>{attributes}, context);
+  }
+
+  void Record(T value,
+              std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
+                  attributes) noexcept
+  {
+    this->Record(value, nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
+                            attributes.begin(), attributes.end()});
+  }
+
+  void Record(
+      T value,
+      std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes,
+      const context::Context &context) noexcept
+  {
+    this->Record(value,
+                 nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
+                     attributes.begin(), attributes.end()},
+                 context);
+  }
+};
+#endif
+
+}  // namespace metrics
+OPENTELEMETRY_END_NAMESPACE

+ 21 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/all.h

@@ -0,0 +1,21 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <type_traits>
+
+#include "opentelemetry/nostd/utility.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+namespace detail
+{
+template <bool... Bs>
+using all = std::is_same<integer_sequence<bool, true, Bs...>, integer_sequence<bool, Bs..., true>>;
+
+}  // namespace detail
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE

+ 16 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/decay.h

@@ -0,0 +1,16 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <type_traits>
+
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+template <class T>
+using decay_t = typename std::decay<T>::type;
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE

+ 20 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/dependent_type.h

@@ -0,0 +1,20 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <type_traits>
+
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+namespace detail
+{
+template <typename T, bool>
+struct dependent_type : T
+{};
+}  // namespace detail
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE

+ 66 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/functional.h

@@ -0,0 +1,66 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <utility>
+
+#include "opentelemetry/version.h"
+
+#define OPENTELEMETRY_RETURN(...)                        \
+  noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) \
+  {                                                      \
+    return __VA_ARGS__;                                  \
+  }
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+namespace detail
+{
+struct equal_to
+{
+  template <typename Lhs, typename Rhs>
+  inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
+      OPENTELEMETRY_RETURN(std::forward<Lhs>(lhs) == std::forward<Rhs>(rhs))
+};
+
+struct not_equal_to
+{
+  template <typename Lhs, typename Rhs>
+  inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
+      OPENTELEMETRY_RETURN(std::forward<Lhs>(lhs) != std::forward<Rhs>(rhs))
+};
+
+struct less
+{
+  template <typename Lhs, typename Rhs>
+  inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
+      OPENTELEMETRY_RETURN(std::forward<Lhs>(lhs) < std::forward<Rhs>(rhs))
+};
+
+struct greater
+{
+  template <typename Lhs, typename Rhs>
+  inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
+      OPENTELEMETRY_RETURN(std::forward<Lhs>(lhs) > std::forward<Rhs>(rhs))
+};
+
+struct less_equal
+{
+  template <typename Lhs, typename Rhs>
+  inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
+      OPENTELEMETRY_RETURN(std::forward<Lhs>(lhs) <= std::forward<Rhs>(rhs))
+};
+
+struct greater_equal
+{
+  template <typename Lhs, typename Rhs>
+  inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
+      OPENTELEMETRY_RETURN(std::forward<Lhs>(lhs) >= std::forward<Rhs>(rhs))
+};
+}  // namespace detail
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE
+
+#undef OPENTELEMETRY_RETURN

+ 163 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/invoke.h

@@ -0,0 +1,163 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <type_traits>
+#include <utility>
+
+#include "opentelemetry/nostd/detail/decay.h"
+#include "opentelemetry/nostd/detail/void.h"
+#include "opentelemetry/version.h"
+
+#define OPENTELEMETRY_RETURN(...)                        \
+  noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) \
+  {                                                      \
+    return __VA_ARGS__;                                  \
+  }
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+namespace detail
+{
+
+template <typename T>
+struct is_reference_wrapper : std::false_type
+{};
+
+template <typename T>
+struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type
+{};
+
+template <bool, int>
+struct Invoke;
+
+template <>
+struct Invoke<true /* pmf */, 0 /* is_base_of */>
+{
+  template <typename R, typename T, typename Arg, typename... Args>
+  inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&...args)
+      OPENTELEMETRY_RETURN((std::forward<Arg>(arg).*pmf)(std::forward<Args>(args)...))
+};
+
+template <>
+struct Invoke<true /* pmf */, 1 /* is_reference_wrapper */>
+{
+  template <typename R, typename T, typename Arg, typename... Args>
+  inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&...args)
+      OPENTELEMETRY_RETURN((std::forward<Arg>(arg).get().*pmf)(std::forward<Args>(args)...))
+};
+
+template <>
+struct Invoke<true /* pmf */, 2 /* otherwise */>
+{
+  template <typename R, typename T, typename Arg, typename... Args>
+  inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&...args)
+      OPENTELEMETRY_RETURN(((*std::forward<Arg>(arg)).*pmf)(std::forward<Args>(args)...))
+};
+
+template <>
+struct Invoke<false /* pmo */, 0 /* is_base_of */>
+{
+  template <typename R, typename T, typename Arg>
+  inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
+      OPENTELEMETRY_RETURN(std::forward<Arg>(arg).*pmo)
+};
+
+template <>
+struct Invoke<false /* pmo */, 1 /* is_reference_wrapper */>
+{
+  template <typename R, typename T, typename Arg>
+  inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
+      OPENTELEMETRY_RETURN(std::forward<Arg>(arg).get().*pmo)
+};
+
+template <>
+struct Invoke<false /* pmo */, 2 /* otherwise */>
+{
+  template <typename R, typename T, typename Arg>
+  inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
+      OPENTELEMETRY_RETURN((*std::forward<Arg>(arg)).*pmo)
+};
+
+template <typename R, typename T, typename Arg, typename... Args>
+inline constexpr auto invoke_impl(R T::*f, Arg &&arg, Args &&...args) OPENTELEMETRY_RETURN(
+    Invoke<std::is_function<R>::value,
+           (std::is_base_of<T, decay_t<Arg>>::value     ? 0
+            : is_reference_wrapper<decay_t<Arg>>::value ? 1
+                                                        : 2)>::invoke(f,
+                                                                      std::forward<Arg>(arg),
+                                                                      std::forward<Args>(args)...))
+
+#ifdef _MSC_VER
+#  pragma warning(push)
+#  pragma warning(disable : 4100)
+#endif
+    template <typename F, typename... Args>
+    inline constexpr auto invoke_impl(F &&f, Args &&...args)
+        OPENTELEMETRY_RETURN(std::forward<F>(f)(std::forward<Args>(args)...))
+#ifdef _MSC_VER
+#  pragma warning(pop)
+#endif
+}  // namespace detail
+
+/* clang-format off */
+template <typename F, typename... Args>
+inline constexpr auto invoke(F &&f, Args &&... args)
+    OPENTELEMETRY_RETURN(detail::invoke_impl(std::forward<F>(f), std::forward<Args>(args)...))
+
+namespace detail
+/* clang-format on */
+{
+
+  template <typename Void, typename, typename...>
+  struct invoke_result
+  {};
+
+  template <typename F, typename... Args>
+  struct invoke_result<void_t<decltype(nostd::invoke(std::declval<F>(), std::declval<Args>()...))>,
+                       F, Args...>
+  {
+    using type = decltype(nostd::invoke(std::declval<F>(), std::declval<Args>()...));
+  };
+
+}  // namespace detail
+
+template <typename F, typename... Args>
+using invoke_result = detail::invoke_result<void, F, Args...>;
+
+template <typename F, typename... Args>
+using invoke_result_t = typename invoke_result<F, Args...>::type;
+
+namespace detail
+{
+
+template <typename Void, typename, typename...>
+struct is_invocable : std::false_type
+{};
+
+template <typename F, typename... Args>
+struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...> : std::true_type
+{};
+
+template <typename Void, typename, typename, typename...>
+struct is_invocable_r : std::false_type
+{};
+
+template <typename R, typename F, typename... Args>
+struct is_invocable_r<void_t<invoke_result_t<F, Args...>>, R, F, Args...>
+    : std::is_convertible<invoke_result_t<F, Args...>, R>
+{};
+
+}  // namespace detail
+
+template <typename F, typename... Args>
+using is_invocable = detail::is_invocable<void, F, Args...>;
+
+template <typename R, typename F, typename... Args>
+using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>;
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE
+
+#undef OPENTELEMETRY_RETURN

+ 75 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/trait.h

@@ -0,0 +1,75 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <type_traits>
+
+#include "opentelemetry/nostd/type_traits.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+namespace detail
+{
+enum class Trait
+{
+  TriviallyAvailable,
+  Available,
+  Unavailable
+};
+
+template <typename T,
+          template <typename>
+          class IsTriviallyAvailable,
+          template <typename>
+          class IsAvailable>
+inline constexpr Trait trait()
+{
+  return IsTriviallyAvailable<T>::value ? Trait::TriviallyAvailable
+         : IsAvailable<T>::value        ? Trait::Available
+                                        : Trait::Unavailable;
+}
+
+inline constexpr Trait common_trait_impl(Trait result)
+{
+  return result;
+}
+
+template <typename... Traits>
+inline constexpr Trait common_trait_impl(Trait result, Trait t, Traits... ts)
+{
+  return static_cast<int>(t) > static_cast<int>(result) ? common_trait_impl(t, ts...)
+                                                        : common_trait_impl(result, ts...);
+}
+
+template <typename... Traits>
+inline constexpr Trait common_trait(Traits... ts)
+{
+  return common_trait_impl(Trait::TriviallyAvailable, ts...);
+}
+
+template <typename... Ts>
+struct traits
+{
+  static constexpr Trait copy_constructible_trait =
+      common_trait(trait<Ts, is_trivially_copy_constructible, std::is_copy_constructible>()...);
+
+  static constexpr Trait move_constructible_trait =
+      common_trait(trait<Ts, is_trivially_move_constructible, std::is_move_constructible>()...);
+
+  static constexpr Trait copy_assignable_trait =
+      common_trait(copy_constructible_trait,
+                   trait<Ts, is_trivially_copy_assignable, std::is_copy_assignable>()...);
+
+  static constexpr Trait move_assignable_trait =
+      common_trait(move_constructible_trait,
+                   trait<Ts, is_trivially_move_assignable, std::is_move_assignable>()...);
+
+  static constexpr Trait destructible_trait =
+      common_trait(trait<Ts, std::is_trivially_destructible, std::is_destructible>()...);
+};
+}  // namespace detail
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE

+ 53 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/type_pack_element.h

@@ -0,0 +1,53 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <cstddef>
+#include <type_traits>
+
+#include "opentelemetry/nostd/utility.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+namespace detail
+{
+template <std::size_t N>
+using size_constant = std::integral_constant<std::size_t, N>;
+
+template <std::size_t I, typename T>
+struct indexed_type : size_constant<I>
+{
+  using type = T;
+};
+
+template <std::size_t I, typename... Ts>
+struct type_pack_element_impl
+{
+private:
+  template <typename>
+  struct set;
+
+  template <std::size_t... Is>
+  struct set<index_sequence<Is...>> : indexed_type<Is, Ts>...
+  {};
+
+  template <typename T>
+  inline static std::enable_if<true, T> impl(indexed_type<I, T>);
+
+  inline static std::enable_if<false> impl(...);
+
+public:
+  using type = decltype(impl(set<index_sequence_for<Ts...>>{}));
+};
+
+template <std::size_t I, typename... Ts>
+using type_pack_element = typename type_pack_element_impl<I, Ts...>::type;
+
+template <std::size_t I, typename... Ts>
+using type_pack_element_t = typename type_pack_element<I, Ts...>::type;
+}  // namespace detail
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE

+ 14 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/valueless.h

@@ -0,0 +1,14 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+struct valueless_t
+{};
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE

+ 40 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/variant_alternative.h

@@ -0,0 +1,40 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <type_traits>
+
+#include "opentelemetry/nostd/detail/type_pack_element.h"
+#include "opentelemetry/nostd/detail/variant_fwd.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+template <std::size_t I, typename T>
+struct variant_alternative;
+
+template <std::size_t I, typename T>
+using variant_alternative_t = typename variant_alternative<I, T>::type;
+
+template <std::size_t I, typename T>
+struct variant_alternative<I, const T> : std::add_const<variant_alternative_t<I, T>>
+{};
+
+template <std::size_t I, typename T>
+struct variant_alternative<I, volatile T> : std::add_volatile<variant_alternative_t<I, T>>
+{};
+
+template <std::size_t I, typename T>
+struct variant_alternative<I, const volatile T> : std::add_cv<variant_alternative_t<I, T>>
+{};
+
+template <std::size_t I, typename... Ts>
+struct variant_alternative<I, variant<Ts...>>
+{
+  static_assert(I < sizeof...(Ts), "index out of bounds in `std::variant_alternative<>`");
+  using type = detail::type_pack_element_t<I, Ts...>;
+};
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE

+ 14 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/variant_fwd.h

@@ -0,0 +1,14 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+template <typename... Ts>
+class variant;
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE

+ 33 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/variant_size.h

@@ -0,0 +1,33 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <type_traits>
+
+#include "opentelemetry/nostd/detail/variant_fwd.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+template <typename T>
+struct variant_size;
+
+template <typename T>
+struct variant_size<const T> : variant_size<T>
+{};
+
+template <typename T>
+struct variant_size<volatile T> : variant_size<T>
+{};
+
+template <typename T>
+struct variant_size<const volatile T> : variant_size<T>
+{};
+
+template <typename... Ts>
+struct variant_size<variant<Ts...>> : std::integral_constant<size_t, sizeof...(Ts)>
+{};
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE

+ 28 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/detail/void.h

@@ -0,0 +1,28 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+namespace detail
+{
+template <class...>
+struct voider
+{
+  using type = void;
+};
+}  // namespace detail
+
+/**
+ * Back port of std::void_t
+ *
+ * Note: voider workaround is required for gcc-4.8 to make SFINAE work
+ */
+template <class... Tx>
+using void_t = typename detail::voider<Tx...>::type;
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE

+ 94 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/function_ref.h

@@ -0,0 +1,94 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <iosfwd>
+#include <memory>  // IWYU pragma: keep
+#include <type_traits>
+#include <utility>
+
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+template <class Sig>
+class function_ref;  // IWYU pragma: keep
+
+/**
+ * Non-owning function reference that can be used as a more performant
+ * replacement for std::function when ownership sematics aren't needed.
+ *
+ * See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0792r0.html
+ *
+ * Based off of https://stackoverflow.com/a/39087660/4447365
+ */
+template <class R, class... Args>
+class function_ref<R(Args...)>
+{
+  void *callable_                = nullptr;
+  R (*invoker_)(void *, Args...) = nullptr;
+
+  template <class F>
+  using FunctionPointer = decltype(std::addressof(std::declval<F &>()));
+
+  template <class F>
+  void BindTo(F &f) noexcept
+  {
+    callable_ = static_cast<void *>(std::addressof(f));
+    invoker_  = [](void *callable, Args... args) -> R {
+      return (*static_cast<FunctionPointer<F>>(callable))(std::forward<Args>(args)...);
+    };
+  }
+
+  template <class R_in, class... Args_in>
+  void BindTo(R_in (*f)(Args_in...)) noexcept
+  {
+    using F = decltype(f);
+    if (f == nullptr)
+    {
+      return BindTo(nullptr);
+    }
+    callable_ = reinterpret_cast<void *>(f);
+    invoker_  = [](void *callable, Args... args) -> R {
+      return (F(callable))(std::forward<Args>(args)...);
+    };
+  }
+
+  void BindTo(std::nullptr_t) noexcept
+  {
+    callable_ = nullptr;
+    invoker_  = nullptr;
+  }
+
+public:
+  template <
+      class F,
+      typename std::enable_if<!std::is_same<function_ref, typename std::decay<F>::type>::value,
+                              int>::type = 0,
+      typename std::enable_if<
+#if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && (_MSVC_LANG > 201402))
+          // std::result_of deprecated in C++17, removed in C++20
+          std::is_convertible<typename std::invoke_result<F, Args...>::type, R>::value,
+#else
+          // std::result_of since C++11
+          std::is_convertible<typename std::result_of<F &(Args...)>::type, R>::value,
+#endif
+          int>::type = 0>
+  function_ref(F &&f)
+  {
+    BindTo(f);  // not forward
+  }
+
+  function_ref(std::nullptr_t) {}
+
+  function_ref(const function_ref &) noexcept = default;
+  function_ref(function_ref &&) noexcept      = default;
+
+  R operator()(Args... args) const { return invoker_(callable_, std::forward<Args>(args)...); }
+
+  explicit operator bool() const { return invoker_; }
+};
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE

+ 621 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/attributes.h

@@ -0,0 +1,621 @@
+// Copyright 2017 The Abseil 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
+//
+//      https://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.
+//
+// This header file defines macros for declaring attributes for functions,
+// types, and variables.
+//
+// These macros are used within Abseil and allow the compiler to optimize, where
+// applicable, certain function calls.
+//
+// This file is used for both C and C++!
+//
+// Most macros here are exposing GCC or Clang features, and are stubbed out for
+// other compilers.
+//
+// GCC attributes documentation:
+//   https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html
+//   https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Variable-Attributes.html
+//   https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Type-Attributes.html
+//
+// Most attributes in this file are already supported by GCC 4.7. However, some
+// of them are not supported in older version of Clang. Thus, we check
+// `__has_attribute()` first. If the check fails, we check if we are on GCC and
+// assume the attribute exists on GCC (which is verified on GCC 4.7).
+//
+// -----------------------------------------------------------------------------
+// Sanitizer Attributes
+// -----------------------------------------------------------------------------
+//
+// Sanitizer-related attributes are not "defined" in this file (and indeed
+// are not defined as such in any file). To utilize the following
+// sanitizer-related attributes within your builds, define the following macros
+// within your build using a `-D` flag, along with the given value for
+// `-fsanitize`:
+//
+//   * `ADDRESS_SANITIZER` + `-fsanitize=address` (Clang, GCC 4.8)
+//   * `MEMORY_SANITIZER` + `-fsanitize=memory` (Clang-only)
+//   * `THREAD_SANITIZER + `-fsanitize=thread` (Clang, GCC 4.8+)
+//   * `UNDEFINED_BEHAVIOR_SANITIZER` + `-fsanitize=undefined` (Clang, GCC 4.9+)
+//   * `CONTROL_FLOW_INTEGRITY` + -fsanitize=cfi (Clang-only)
+//
+// Example:
+//
+//   // Enable branches in the Abseil code that are tagged for ASan:
+//   $ bazel build --copt=-DADDRESS_SANITIZER --copt=-fsanitize=address
+//     --linkopt=-fsanitize=address *target*
+//
+// Since these macro names are only supported by GCC and Clang, we only check
+// for `__GNUC__` (GCC or Clang) and the above macros.
+#ifndef OTABSL_BASE_ATTRIBUTES_H_
+#define OTABSL_BASE_ATTRIBUTES_H_
+
+// OTABSL_HAVE_ATTRIBUTE
+//
+// A function-like feature checking macro that is a wrapper around
+// `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a
+// nonzero constant integer if the attribute is supported or 0 if not.
+//
+// It evaluates to zero if `__has_attribute` is not defined by the compiler.
+//
+// GCC: https://gcc.gnu.org/gcc-5/changes.html
+// Clang: https://clang.llvm.org/docs/LanguageExtensions.html
+#ifdef __has_attribute
+#define OTABSL_HAVE_ATTRIBUTE(x) __has_attribute(x)
+#else
+#define OTABSL_HAVE_ATTRIBUTE(x) 0
+#endif
+
+// OTABSL_HAVE_CPP_ATTRIBUTE
+//
+// A function-like feature checking macro that accepts C++11 style attributes.
+// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6
+// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
+// find `__has_cpp_attribute`, will evaluate to 0.
+#if defined(__cplusplus) && defined(__has_cpp_attribute)
+// NOTE: requiring __cplusplus above should not be necessary, but
+// works around https://bugs.llvm.org/show_bug.cgi?id=23435.
+#define OTABSL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
+#else
+#define OTABSL_HAVE_CPP_ATTRIBUTE(x) 0
+#endif
+
+// -----------------------------------------------------------------------------
+// Function Attributes
+// -----------------------------------------------------------------------------
+//
+// GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
+// Clang: https://clang.llvm.org/docs/AttributeReference.html
+
+// OTABSL_PRINTF_ATTRIBUTE
+// OTABSL_SCANF_ATTRIBUTE
+//
+// Tells the compiler to perform `printf` format string checking if the
+// compiler supports it; see the 'format' attribute in
+// <https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html>.
+//
+// Note: As the GCC manual states, "[s]ince non-static C++ methods
+// have an implicit 'this' argument, the arguments of such methods
+// should be counted from two, not one."
+#if OTABSL_HAVE_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__))
+#define OTABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) \
+  __attribute__((__format__(__printf__, string_index, first_to_check)))
+#define OTABSL_SCANF_ATTRIBUTE(string_index, first_to_check) \
+  __attribute__((__format__(__scanf__, string_index, first_to_check)))
+#else
+#define OTABSL_PRINTF_ATTRIBUTE(string_index, first_to_check)
+#define OTABSL_SCANF_ATTRIBUTE(string_index, first_to_check)
+#endif
+
+// OTABSL_ATTRIBUTE_ALWAYS_INLINE
+// OTABSL_ATTRIBUTE_NOINLINE
+//
+// Forces functions to either inline or not inline. Introduced in gcc 3.1.
+#if OTABSL_HAVE_ATTRIBUTE(always_inline) || \
+    (defined(__GNUC__) && !defined(__clang__))
+#define OTABSL_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline))
+#define OTABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE 1
+#else
+#define OTABSL_ATTRIBUTE_ALWAYS_INLINE
+#endif
+
+#if OTABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__))
+#define OTABSL_ATTRIBUTE_NOINLINE __attribute__((noinline))
+#define OTABSL_HAVE_ATTRIBUTE_NOINLINE 1
+#else
+#define OTABSL_ATTRIBUTE_NOINLINE
+#endif
+
+// OTABSL_ATTRIBUTE_NO_TAIL_CALL
+//
+// Prevents the compiler from optimizing away stack frames for functions which
+// end in a call to another function.
+#if OTABSL_HAVE_ATTRIBUTE(disable_tail_calls)
+#define OTABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1
+#define OTABSL_ATTRIBUTE_NO_TAIL_CALL __attribute__((disable_tail_calls))
+#elif defined(__GNUC__) && !defined(__clang__)
+#define OTABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1
+#define OTABSL_ATTRIBUTE_NO_TAIL_CALL \
+  __attribute__((optimize("no-optimize-sibling-calls")))
+#else
+#define OTABSL_ATTRIBUTE_NO_TAIL_CALL
+#define OTABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 0
+#endif
+
+// OTABSL_ATTRIBUTE_WEAK
+//
+// Tags a function as weak for the purposes of compilation and linking.
+// Weak attributes currently do not work properly in LLVM's Windows backend,
+// so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598
+// for further information.
+// The MinGW compiler doesn't complain about the weak attribute until the link
+// step, presumably because Windows doesn't use ELF binaries.
+#if (OTABSL_HAVE_ATTRIBUTE(weak) ||                   \
+     (defined(__GNUC__) && !defined(__clang__))) && \
+    !(defined(__llvm__) && defined(_WIN32)) && !defined(__MINGW32__)
+#undef OTABSL_ATTRIBUTE_WEAK
+#define OTABSL_ATTRIBUTE_WEAK __attribute__((weak))
+#define OTABSL_HAVE_ATTRIBUTE_WEAK 1
+#else
+#define OTABSL_ATTRIBUTE_WEAK
+#define OTABSL_HAVE_ATTRIBUTE_WEAK 0
+#endif
+
+// OTABSL_ATTRIBUTE_NONNULL
+//
+// Tells the compiler either (a) that a particular function parameter
+// should be a non-null pointer, or (b) that all pointer arguments should
+// be non-null.
+//
+// Note: As the GCC manual states, "[s]ince non-static C++ methods
+// have an implicit 'this' argument, the arguments of such methods
+// should be counted from two, not one."
+//
+// Args are indexed starting at 1.
+//
+// For non-static class member functions, the implicit `this` argument
+// is arg 1, and the first explicit argument is arg 2. For static class member
+// functions, there is no implicit `this`, and the first explicit argument is
+// arg 1.
+//
+// Example:
+//
+//   /* arg_a cannot be null, but arg_b can */
+//   void Function(void* arg_a, void* arg_b) OTABSL_ATTRIBUTE_NONNULL(1);
+//
+//   class C {
+//     /* arg_a cannot be null, but arg_b can */
+//     void Method(void* arg_a, void* arg_b) OTABSL_ATTRIBUTE_NONNULL(2);
+//
+//     /* arg_a cannot be null, but arg_b can */
+//     static void StaticMethod(void* arg_a, void* arg_b)
+//     OTABSL_ATTRIBUTE_NONNULL(1);
+//   };
+//
+// If no arguments are provided, then all pointer arguments should be non-null.
+//
+//  /* No pointer arguments may be null. */
+//  void Function(void* arg_a, void* arg_b, int arg_c) OTABSL_ATTRIBUTE_NONNULL();
+//
+// NOTE: The GCC nonnull attribute actually accepts a list of arguments, but
+// OTABSL_ATTRIBUTE_NONNULL does not.
+#if OTABSL_HAVE_ATTRIBUTE(nonnull) || (defined(__GNUC__) && !defined(__clang__))
+#define OTABSL_ATTRIBUTE_NONNULL(arg_index) __attribute__((nonnull(arg_index)))
+#else
+#define OTABSL_ATTRIBUTE_NONNULL(...)
+#endif
+
+// OTABSL_ATTRIBUTE_NORETURN
+//
+// Tells the compiler that a given function never returns.
+#if OTABSL_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__))
+#define OTABSL_ATTRIBUTE_NORETURN __attribute__((noreturn))
+#elif defined(_MSC_VER)
+#define OTABSL_ATTRIBUTE_NORETURN __declspec(noreturn)
+#else
+#define OTABSL_ATTRIBUTE_NORETURN
+#endif
+
+// OTABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS
+//
+// Tells the AddressSanitizer (or other memory testing tools) to ignore a given
+// function. Useful for cases when a function reads random locations on stack,
+// calls _exit from a cloned subprocess, deliberately accesses buffer
+// out of bounds or does other scary things with memory.
+// NOTE: GCC supports AddressSanitizer(asan) since 4.8.
+// https://gcc.gnu.org/gcc-4.8/changes.html
+#if defined(__GNUC__)
+#define OTABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
+#else
+#define OTABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS
+#endif
+
+// OTABSL_ATTRIBUTE_NO_SANITIZE_MEMORY
+//
+// Tells the  MemorySanitizer to relax the handling of a given function. All
+// "Use of uninitialized value" warnings from such functions will be suppressed,
+// and all values loaded from memory will be considered fully initialized.
+// This attribute is similar to the ADDRESS_SANITIZER attribute above, but deals
+// with initialized-ness rather than addressability issues.
+// NOTE: MemorySanitizer(msan) is supported by Clang but not GCC.
+#if defined(__clang__)
+#define OTABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
+#else
+#define OTABSL_ATTRIBUTE_NO_SANITIZE_MEMORY
+#endif
+
+// OTABSL_ATTRIBUTE_NO_SANITIZE_THREAD
+//
+// Tells the ThreadSanitizer to not instrument a given function.
+// NOTE: GCC supports ThreadSanitizer(tsan) since 4.8.
+// https://gcc.gnu.org/gcc-4.8/changes.html
+#if defined(__GNUC__)
+#define OTABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
+#else
+#define OTABSL_ATTRIBUTE_NO_SANITIZE_THREAD
+#endif
+
+// OTABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED
+//
+// Tells the UndefinedSanitizer to ignore a given function. Useful for cases
+// where certain behavior (eg. division by zero) is being used intentionally.
+// NOTE: GCC supports UndefinedBehaviorSanitizer(ubsan) since 4.9.
+// https://gcc.gnu.org/gcc-4.9/changes.html
+#if defined(__GNUC__) && \
+    (defined(UNDEFINED_BEHAVIOR_SANITIZER) || defined(ADDRESS_SANITIZER))
+#define OTABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \
+  __attribute__((no_sanitize("undefined")))
+#else
+#define OTABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED
+#endif
+
+// OTABSL_ATTRIBUTE_NO_SANITIZE_CFI
+//
+// Tells the ControlFlowIntegrity sanitizer to not instrument a given function.
+// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details.
+#if defined(__GNUC__) && defined(CONTROL_FLOW_INTEGRITY)
+#define OTABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi")))
+#else
+#define OTABSL_ATTRIBUTE_NO_SANITIZE_CFI
+#endif
+
+// OTABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK
+//
+// Tells the SafeStack to not instrument a given function.
+// See https://clang.llvm.org/docs/SafeStack.html for details.
+#if defined(__GNUC__) && defined(SAFESTACK_SANITIZER)
+#define OTABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \
+  __attribute__((no_sanitize("safe-stack")))
+#else
+#define OTABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK
+#endif
+
+// OTABSL_ATTRIBUTE_RETURNS_NONNULL
+//
+// Tells the compiler that a particular function never returns a null pointer.
+#if OTABSL_HAVE_ATTRIBUTE(returns_nonnull) || \
+    (defined(__GNUC__) && \
+     (__GNUC__ > 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) && \
+     !defined(__clang__))
+#define OTABSL_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull))
+#else
+#define OTABSL_ATTRIBUTE_RETURNS_NONNULL
+#endif
+
+// OTABSL_HAVE_ATTRIBUTE_SECTION
+//
+// Indicates whether labeled sections are supported. Weak symbol support is
+// a prerequisite. Labeled sections are not supported on Darwin/iOS.
+#ifdef OTABSL_HAVE_ATTRIBUTE_SECTION
+#error OTABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set
+#elif (OTABSL_HAVE_ATTRIBUTE(section) ||                \
+       (defined(__GNUC__) && !defined(__clang__))) && \
+    !defined(__APPLE__) && OTABSL_HAVE_ATTRIBUTE_WEAK
+#define OTABSL_HAVE_ATTRIBUTE_SECTION 1
+
+// OTABSL_ATTRIBUTE_SECTION
+//
+// Tells the compiler/linker to put a given function into a section and define
+// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section.
+// This functionality is supported by GNU linker.  Any function annotated with
+// `OTABSL_ATTRIBUTE_SECTION` must not be inlined, or it will be placed into
+// whatever section its caller is placed into.
+//
+#ifndef OTABSL_ATTRIBUTE_SECTION
+#define OTABSL_ATTRIBUTE_SECTION(name) \
+  __attribute__((section(#name))) __attribute__((noinline))
+#endif
+
+
+// OTABSL_ATTRIBUTE_SECTION_VARIABLE
+//
+// Tells the compiler/linker to put a given variable into a section and define
+// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section.
+// This functionality is supported by GNU linker.
+#ifndef OTABSL_ATTRIBUTE_SECTION_VARIABLE
+#define OTABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name)))
+#endif
+
+// OTABSL_DECLARE_ATTRIBUTE_SECTION_VARS
+//
+// A weak section declaration to be used as a global declaration
+// for OTABSL_ATTRIBUTE_SECTION_START|STOP(name) to compile and link
+// even without functions with OTABSL_ATTRIBUTE_SECTION(name).
+// OTABSL_DEFINE_ATTRIBUTE_SECTION should be in the exactly one file; it's
+// a no-op on ELF but not on Mach-O.
+//
+#ifndef OTABSL_DECLARE_ATTRIBUTE_SECTION_VARS
+#define OTABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) \
+  extern char __start_##name[] OTABSL_ATTRIBUTE_WEAK;    \
+  extern char __stop_##name[] OTABSL_ATTRIBUTE_WEAK
+#endif
+#ifndef OTABSL_DEFINE_ATTRIBUTE_SECTION_VARS
+#define OTABSL_INIT_ATTRIBUTE_SECTION_VARS(name)
+#define OTABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name)
+#endif
+
+// OTABSL_ATTRIBUTE_SECTION_START
+//
+// Returns `void*` pointers to start/end of a section of code with
+// functions having OTABSL_ATTRIBUTE_SECTION(name).
+// Returns 0 if no such functions exist.
+// One must OTABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) for this to compile and
+// link.
+//
+#define OTABSL_ATTRIBUTE_SECTION_START(name) \
+  (reinterpret_cast<void *>(__start_##name))
+#define OTABSL_ATTRIBUTE_SECTION_STOP(name) \
+  (reinterpret_cast<void *>(__stop_##name))
+
+#else  // !OTABSL_HAVE_ATTRIBUTE_SECTION
+
+#define OTABSL_HAVE_ATTRIBUTE_SECTION 0
+
+// provide dummy definitions
+#define OTABSL_ATTRIBUTE_SECTION(name)
+#define OTABSL_ATTRIBUTE_SECTION_VARIABLE(name)
+#define OTABSL_INIT_ATTRIBUTE_SECTION_VARS(name)
+#define OTABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name)
+#define OTABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name)
+#define OTABSL_ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void *>(0))
+#define OTABSL_ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void *>(0))
+
+#endif  // OTABSL_ATTRIBUTE_SECTION
+
+// OTABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC
+//
+// Support for aligning the stack on 32-bit x86.
+#if OTABSL_HAVE_ATTRIBUTE(force_align_arg_pointer) || \
+    (defined(__GNUC__) && !defined(__clang__))
+#if defined(__i386__)
+#define OTABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC \
+  __attribute__((force_align_arg_pointer))
+#define OTABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0)
+#elif defined(__x86_64__)
+#define OTABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (1)
+#define OTABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC
+#else  // !__i386__ && !__x86_64
+#define OTABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0)
+#define OTABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC
+#endif  // __i386__
+#else
+#define OTABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC
+#define OTABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0)
+#endif
+
+// OTABSL_MUST_USE_RESULT
+//
+// Tells the compiler to warn about unused results.
+//
+// When annotating a function, it must appear as the first part of the
+// declaration or definition. The compiler will warn if the return value from
+// such a function is unused:
+//
+//   OTABSL_MUST_USE_RESULT Sprocket* AllocateSprocket();
+//   AllocateSprocket();  // Triggers a warning.
+//
+// When annotating a class, it is equivalent to annotating every function which
+// returns an instance.
+//
+//   class OTABSL_MUST_USE_RESULT Sprocket {};
+//   Sprocket();  // Triggers a warning.
+//
+//   Sprocket MakeSprocket();
+//   MakeSprocket();  // Triggers a warning.
+//
+// Note that references and pointers are not instances:
+//
+//   Sprocket* SprocketPointer();
+//   SprocketPointer();  // Does *not* trigger a warning.
+//
+// OTABSL_MUST_USE_RESULT allows using cast-to-void to suppress the unused result
+// warning. For that, warn_unused_result is used only for clang but not for gcc.
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425
+//
+// Note: past advice was to place the macro after the argument list.
+#if OTABSL_HAVE_ATTRIBUTE(nodiscard)
+#define OTABSL_MUST_USE_RESULT [[nodiscard]]
+#elif defined(__clang__) && OTABSL_HAVE_ATTRIBUTE(warn_unused_result)
+#define OTABSL_MUST_USE_RESULT __attribute__((warn_unused_result))
+#else
+#define OTABSL_MUST_USE_RESULT
+#endif
+
+// OTABSL_ATTRIBUTE_HOT, OTABSL_ATTRIBUTE_COLD
+//
+// Tells GCC that a function is hot or cold. GCC can use this information to
+// improve static analysis, i.e. a conditional branch to a cold function
+// is likely to be not-taken.
+// This annotation is used for function declarations.
+//
+// Example:
+//
+//   int foo() OTABSL_ATTRIBUTE_HOT;
+#if OTABSL_HAVE_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__))
+#define OTABSL_ATTRIBUTE_HOT __attribute__((hot))
+#else
+#define OTABSL_ATTRIBUTE_HOT
+#endif
+
+#if OTABSL_HAVE_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__))
+#define OTABSL_ATTRIBUTE_COLD __attribute__((cold))
+#else
+#define OTABSL_ATTRIBUTE_COLD
+#endif
+
+// OTABSL_XRAY_ALWAYS_INSTRUMENT, OTABSL_XRAY_NEVER_INSTRUMENT, OTABSL_XRAY_LOG_ARGS
+//
+// We define the OTABSL_XRAY_ALWAYS_INSTRUMENT and OTABSL_XRAY_NEVER_INSTRUMENT
+// macro used as an attribute to mark functions that must always or never be
+// instrumented by XRay. Currently, this is only supported in Clang/LLVM.
+//
+// For reference on the LLVM XRay instrumentation, see
+// http://llvm.org/docs/XRay.html.
+//
+// A function with the XRAY_ALWAYS_INSTRUMENT macro attribute in its declaration
+// will always get the XRay instrumentation sleds. These sleds may introduce
+// some binary size and runtime overhead and must be used sparingly.
+//
+// These attributes only take effect when the following conditions are met:
+//
+//   * The file/target is built in at least C++11 mode, with a Clang compiler
+//     that supports XRay attributes.
+//   * The file/target is built with the -fxray-instrument flag set for the
+//     Clang/LLVM compiler.
+//   * The function is defined in the translation unit (the compiler honors the
+//     attribute in either the definition or the declaration, and must match).
+//
+// There are cases when, even when building with XRay instrumentation, users
+// might want to control specifically which functions are instrumented for a
+// particular build using special-case lists provided to the compiler. These
+// special case lists are provided to Clang via the
+// -fxray-always-instrument=... and -fxray-never-instrument=... flags. The
+// attributes in source take precedence over these special-case lists.
+//
+// To disable the XRay attributes at build-time, users may define
+// OTABSL_NO_XRAY_ATTRIBUTES. Do NOT define OTABSL_NO_XRAY_ATTRIBUTES on specific
+// packages/targets, as this may lead to conflicting definitions of functions at
+// link-time.
+//
+#if OTABSL_HAVE_CPP_ATTRIBUTE(clang::xray_always_instrument) && \
+    !defined(OTABSL_NO_XRAY_ATTRIBUTES)
+#define OTABSL_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]]
+#define OTABSL_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]]
+#if OTABSL_HAVE_CPP_ATTRIBUTE(clang::xray_log_args)
+#define OTABSL_XRAY_LOG_ARGS(N) \
+    [[clang::xray_always_instrument, clang::xray_log_args(N)]]
+#else
+#define OTABSL_XRAY_LOG_ARGS(N) [[clang::xray_always_instrument]]
+#endif
+#else
+#define OTABSL_XRAY_ALWAYS_INSTRUMENT
+#define OTABSL_XRAY_NEVER_INSTRUMENT
+#define OTABSL_XRAY_LOG_ARGS(N)
+#endif
+
+// OTABSL_ATTRIBUTE_REINITIALIZES
+//
+// Indicates that a member function reinitializes the entire object to a known
+// state, independent of the previous state of the object.
+//
+// The clang-tidy check bugprone-use-after-move allows member functions marked
+// with this attribute to be called on objects that have been moved from;
+// without the attribute, this would result in a use-after-move warning.
+#if OTABSL_HAVE_CPP_ATTRIBUTE(clang::reinitializes)
+#define OTABSL_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]]
+#else
+#define OTABSL_ATTRIBUTE_REINITIALIZES
+#endif
+
+// -----------------------------------------------------------------------------
+// Variable Attributes
+// -----------------------------------------------------------------------------
+
+// OTABSL_ATTRIBUTE_UNUSED
+//
+// Prevents the compiler from complaining about variables that appear unused.
+#if OTABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__))
+#undef OTABSL_ATTRIBUTE_UNUSED
+#define OTABSL_ATTRIBUTE_UNUSED __attribute__((__unused__))
+#else
+#define OTABSL_ATTRIBUTE_UNUSED
+#endif
+
+// OTABSL_ATTRIBUTE_INITIAL_EXEC
+//
+// Tells the compiler to use "initial-exec" mode for a thread-local variable.
+// See http://people.redhat.com/drepper/tls.pdf for the gory details.
+#if OTABSL_HAVE_ATTRIBUTE(tls_model) || (defined(__GNUC__) && !defined(__clang__))
+#define OTABSL_ATTRIBUTE_INITIAL_EXEC __attribute__((tls_model("initial-exec")))
+#else
+#define OTABSL_ATTRIBUTE_INITIAL_EXEC
+#endif
+
+// OTABSL_ATTRIBUTE_PACKED
+//
+// Instructs the compiler not to use natural alignment for a tagged data
+// structure, but instead to reduce its alignment to 1. This attribute can
+// either be applied to members of a structure or to a structure in its
+// entirety. Applying this attribute (judiciously) to a structure in its
+// entirety to optimize the memory footprint of very commonly-used structs is
+// fine. Do not apply this attribute to a structure in its entirety if the
+// purpose is to control the offsets of the members in the structure. Instead,
+// apply this attribute only to structure members that need it.
+//
+// When applying OTABSL_ATTRIBUTE_PACKED only to specific structure members the
+// natural alignment of structure members not annotated is preserved. Aligned
+// member accesses are faster than non-aligned member accesses even if the
+// targeted microprocessor supports non-aligned accesses.
+#if OTABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__))
+#define OTABSL_ATTRIBUTE_PACKED __attribute__((__packed__))
+#else
+#define OTABSL_ATTRIBUTE_PACKED
+#endif
+
+// OTABSL_ATTRIBUTE_FUNC_ALIGN
+//
+// Tells the compiler to align the function start at least to certain
+// alignment boundary
+#if OTABSL_HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__))
+#define OTABSL_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__((aligned(bytes)))
+#else
+#define OTABSL_ATTRIBUTE_FUNC_ALIGN(bytes)
+#endif
+
+// OTABSL_CONST_INIT
+//
+// A variable declaration annotated with the `OTABSL_CONST_INIT` attribute will
+// not compile (on supported platforms) unless the variable has a constant
+// initializer. This is useful for variables with static and thread storage
+// duration, because it guarantees that they will not suffer from the so-called
+// "static init order fiasco".  Prefer to put this attribute on the most visible
+// declaration of the variable, if there's more than one, because code that
+// accesses the variable can then use the attribute for optimization.
+//
+// Example:
+//
+//   class MyClass {
+//    public:
+//     OTABSL_CONST_INIT static MyType my_var;
+//   };
+//
+//   MyType MyClass::my_var = MakeMyType(...);
+//
+// Note that this attribute is redundant if the variable is declared constexpr.
+#if OTABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
+#define OTABSL_CONST_INIT [[clang::require_constant_initialization]]
+#else
+#define OTABSL_CONST_INIT
+#endif  // OTABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
+
+#endif  // OTABSL_BASE_ATTRIBUTES_H_

+ 671 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/config.h

@@ -0,0 +1,671 @@
+//
+// Copyright 2017 The Abseil 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
+//
+//      https://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.
+//
+// -----------------------------------------------------------------------------
+// File: config.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines a set of macros for checking the presence of
+// important compiler and platform features. Such macros can be used to
+// produce portable code by parameterizing compilation based on the presence or
+// lack of a given feature.
+//
+// We define a "feature" as some interface we wish to program to: for example,
+// a library function or system call. A value of `1` indicates support for
+// that feature; any other value indicates the feature support is undefined.
+//
+// Example:
+//
+// Suppose a programmer wants to write a program that uses the 'mmap()' system
+// call. The Abseil macro for that feature (`OTABSL_HAVE_MMAP`) allows you to
+// selectively include the `mmap.h` header and bracket code using that feature
+// in the macro:
+//
+//   #include "absl/base/config.h"
+//
+//   #ifdef OTABSL_HAVE_MMAP
+//   #include "sys/mman.h"
+//   #endif  //OTABSL_HAVE_MMAP
+//
+//   ...
+//   #ifdef OTABSL_HAVE_MMAP
+//   void *ptr = mmap(...);
+//   ...
+//   #endif  // OTABSL_HAVE_MMAP
+
+#ifndef OTABSL_BASE_CONFIG_H_
+#define OTABSL_BASE_CONFIG_H_
+
+// Included for the __GLIBC__ macro (or similar macros on other systems).
+#include <limits.h>
+
+#ifdef __cplusplus
+// Included for __GLIBCXX__, _LIBCPP_VERSION
+#include <cstddef>
+#endif  // __cplusplus
+
+#if defined(__APPLE__)
+// Included for TARGET_OS_IPHONE, __IPHONE_OS_VERSION_MIN_REQUIRED,
+// __IPHONE_8_0.
+#include <Availability.h>
+#include <TargetConditionals.h>
+#endif
+
+#include "options.h"
+#include "policy_checks.h"
+
+// Helper macro to convert a CPP variable to a string literal.
+#define OTABSL_INTERNAL_DO_TOKEN_STR(x) #x
+#define OTABSL_INTERNAL_TOKEN_STR(x) OTABSL_INTERNAL_DO_TOKEN_STR(x)
+
+// -----------------------------------------------------------------------------
+// Abseil namespace annotations
+// -----------------------------------------------------------------------------
+
+// OTABSL_NAMESPACE_BEGIN/OTABSL_NAMESPACE_END
+//
+// An annotation placed at the beginning/end of each `namespace absl` scope.
+// This is used to inject an inline namespace.
+//
+// The proper way to write Abseil code in the `absl` namespace is:
+//
+// namespace absl {
+// OTABSL_NAMESPACE_BEGIN
+//
+// void Foo();  // absl::OTABSL_OPTION_NAMESPACE_NAME::Foo().
+//
+// OTABSL_NAMESPACE_END
+// }  // namespace absl
+//
+// Users of Abseil should not use these macros, because users of Abseil should
+// not write `namespace absl {` in their own code for any reason.  (Abseil does
+// not support forward declarations of its own types, nor does it support
+// user-provided specialization of Abseil templates.  Code that violates these
+// rules may be broken without warning.)
+#if !defined(OTABSL_OPTION_NAMESPACE_NAME)
+#error options.h is misconfigured.
+#endif
+
+// Check that OTABSL_OPTION_NAMESPACE_NAME is neither "head" nor ""
+#if defined(__cplusplus)
+
+#define OTABSL_INTERNAL_INLINE_NAMESPACE_STR \
+  OTABSL_INTERNAL_TOKEN_STR(OTABSL_OPTION_NAMESPACE_NAME)
+
+static_assert(OTABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != '\0',
+              "options.h misconfigured: OTABSL_OPTION_NAMESPACE_NAME must "
+              "not be empty.");
+static_assert(OTABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
+                  OTABSL_INTERNAL_INLINE_NAMESPACE_STR[1] != 'e' ||
+                  OTABSL_INTERNAL_INLINE_NAMESPACE_STR[2] != 'a' ||
+                  OTABSL_INTERNAL_INLINE_NAMESPACE_STR[3] != 'd' ||
+                  OTABSL_INTERNAL_INLINE_NAMESPACE_STR[4] != '\0',
+              "options.h misconfigured: OTABSL_OPTION_NAMESPACE_NAME must "
+              "be changed to a new, unique identifier name.");
+
+#endif
+
+
+#define OTABSL_NAMESPACE_BEGIN namespace OTABSL_OPTION_NAMESPACE_NAME {
+#define OTABSL_NAMESPACE_END }
+
+// -----------------------------------------------------------------------------
+// Compiler Feature Checks
+// -----------------------------------------------------------------------------
+
+// OTABSL_HAVE_BUILTIN()
+//
+// Checks whether the compiler supports a Clang Feature Checking Macro, and if
+// so, checks whether it supports the provided builtin function "x" where x
+// is one of the functions noted in
+// https://clang.llvm.org/docs/LanguageExtensions.html
+//
+// Note: Use this macro to avoid an extra level of #ifdef __has_builtin check.
+// http://releases.llvm.org/3.3/tools/clang/docs/LanguageExtensions.html
+#ifdef __has_builtin
+#define OTABSL_HAVE_BUILTIN(x) __has_builtin(x)
+#else
+#define OTABSL_HAVE_BUILTIN(x) 0
+#endif
+
+#if defined(__is_identifier)
+#define OTABSL_INTERNAL_HAS_KEYWORD(x) !(__is_identifier(x))
+#else
+#define OTABSL_INTERNAL_HAS_KEYWORD(x) 0
+#endif
+
+// OTABSL_HAVE_TLS is defined to 1 when __thread should be supported.
+// We assume __thread is supported on Linux when compiled with Clang or compiled
+// against libstdc++ with _GLIBCXX_HAVE_TLS defined.
+#ifdef OTABSL_HAVE_TLS
+#error OTABSL_HAVE_TLS cannot be directly set
+#elif defined(__linux__) && (defined(__clang__) || defined(_GLIBCXX_HAVE_TLS))
+#define OTABSL_HAVE_TLS 1
+#endif
+
+// OTABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
+//
+// Checks whether `std::is_trivially_destructible<T>` is supported.
+//
+// Notes: All supported compilers using libc++ support this feature, as does
+// gcc >= 4.8.1 using libstdc++, and Visual Studio.
+#ifdef OTABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
+#error OTABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE cannot be directly set
+#elif defined(_LIBCPP_VERSION) ||                                        \
+    (defined(__clang__) && __clang_major__ >= 15) ||                     \
+    (!defined(__clang__) && defined(__GNUC__) && defined(__GLIBCXX__) && \
+     (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) ||        \
+    defined(_MSC_VER)
+#define OTABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE 1
+#endif
+
+// OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
+//
+// Checks whether `std::is_trivially_default_constructible<T>` and
+// `std::is_trivially_copy_constructible<T>` are supported.
+
+// OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
+//
+// Checks whether `std::is_trivially_copy_assignable<T>` is supported.
+
+// Notes: Clang with libc++ supports these features, as does gcc >= 5.1 with
+// either libc++ or libstdc++, and Visual Studio (but not NVCC).
+#if defined(OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE)
+#error OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE cannot be directly set
+#elif defined(OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE)
+#error OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE cannot directly set
+#elif (defined(__clang__) && defined(_LIBCPP_VERSION)) ||        \
+    (defined(__clang__) && __clang_major__ >= 15) ||             \
+    (!defined(__clang__) && defined(__GNUC__) &&                 \
+     (__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ >= 4)) && \
+     (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__))) ||      \
+    (defined(_MSC_VER) && !defined(__NVCC__))
+#define OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1
+#define OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1
+#endif
+
+// OTABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE
+//
+// Checks whether `std::is_trivially_copyable<T>` is supported.
+//
+// Notes: Clang 15+ with libc++ supports these features, GCC hasn't been tested.
+#if defined(OTABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE)
+#error OTABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE cannot be directly set
+#elif defined(__clang__) && (__clang_major__ >= 15)
+#define OTABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE 1
+#endif
+
+// OTABSL_HAVE_SOURCE_LOCATION_CURRENT
+//
+// Indicates whether `absl::OTABSL_OPTION_NAMESPACE_NAME::SourceLocation::current()` will return useful
+// information in some contexts.
+#ifndef OTABSL_HAVE_SOURCE_LOCATION_CURRENT
+#if OTABSL_INTERNAL_HAS_KEYWORD(__builtin_LINE) && \
+    OTABSL_INTERNAL_HAS_KEYWORD(__builtin_FILE)
+#define OTABSL_HAVE_SOURCE_LOCATION_CURRENT 1
+#endif
+#endif
+
+// OTABSL_HAVE_THREAD_LOCAL
+//
+// Checks whether C++11's `thread_local` storage duration specifier is
+// supported.
+#ifdef OTABSL_HAVE_THREAD_LOCAL
+#error OTABSL_HAVE_THREAD_LOCAL cannot be directly set
+#elif defined(__APPLE__)
+// Notes:
+// * Xcode's clang did not support `thread_local` until version 8, and
+//   even then not for all iOS < 9.0.
+// * Xcode 9.3 started disallowing `thread_local` for 32-bit iOS simulator
+//   targeting iOS 9.x.
+// * Xcode 10 moves the deployment target check for iOS < 9.0 to link time
+//   making __has_feature unreliable there.
+//
+// Otherwise, `__has_feature` is only supported by Clang so it has be inside
+// `defined(__APPLE__)` check.
+#if __has_feature(cxx_thread_local) && \
+    !(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
+#define OTABSL_HAVE_THREAD_LOCAL 1
+#endif
+#else  // !defined(__APPLE__)
+#define OTABSL_HAVE_THREAD_LOCAL 1
+#endif
+
+// There are platforms for which TLS should not be used even though the compiler
+// makes it seem like it's supported (Android NDK < r12b for example).
+// This is primarily because of linker problems and toolchain misconfiguration:
+// Abseil does not intend to support this indefinitely. Currently, the newest
+// toolchain that we intend to support that requires this behavior is the
+// r11 NDK - allowing for a 5 year support window on that means this option
+// is likely to be removed around June of 2021.
+// TLS isn't supported until NDK r12b per
+// https://developer.android.com/ndk/downloads/revision_history.html
+// Since NDK r16, `__NDK_MAJOR__` and `__NDK_MINOR__` are defined in
+// <android/ndk-version.h>. For NDK < r16, users should define these macros,
+// e.g. `-D__NDK_MAJOR__=11 -D__NKD_MINOR__=0` for NDK r11.
+#if defined(__ANDROID__) && defined(__clang__)
+#if __has_include(<android/ndk-version.h>)
+#include <android/ndk-version.h>
+#endif  // __has_include(<android/ndk-version.h>)
+#if defined(__ANDROID__) && defined(__clang__) && defined(__NDK_MAJOR__) && \
+    defined(__NDK_MINOR__) &&                                               \
+    ((__NDK_MAJOR__ < 12) || ((__NDK_MAJOR__ == 12) && (__NDK_MINOR__ < 1)))
+#undef OTABSL_HAVE_TLS
+#undef OTABSL_HAVE_THREAD_LOCAL
+#endif
+#endif  // defined(__ANDROID__) && defined(__clang__)
+
+// Emscripten doesn't yet support `thread_local` or `__thread`.
+// https://github.com/emscripten-core/emscripten/issues/3502
+#if defined(__EMSCRIPTEN__)
+#undef OTABSL_HAVE_TLS
+#undef OTABSL_HAVE_THREAD_LOCAL
+#endif  // defined(__EMSCRIPTEN__)
+
+// OTABSL_HAVE_INTRINSIC_INT128
+//
+// Checks whether the __int128 compiler extension for a 128-bit integral type is
+// supported.
+//
+// Note: __SIZEOF_INT128__ is defined by Clang and GCC when __int128 is
+// supported, but we avoid using it in certain cases:
+// * On Clang:
+//   * Building using Clang for Windows, where the Clang runtime library has
+//     128-bit support only on LP64 architectures, but Windows is LLP64.
+// * On Nvidia's nvcc:
+//   * nvcc also defines __GNUC__ and __SIZEOF_INT128__, but not all versions
+//     actually support __int128.
+#ifdef OTABSL_HAVE_INTRINSIC_INT128
+#error OTABSL_HAVE_INTRINSIC_INT128 cannot be directly set
+#elif defined(__SIZEOF_INT128__)
+#if (defined(__clang__) && !defined(_WIN32)) || \
+    (defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) ||                \
+    (defined(__GNUC__) && !defined(__clang__) && !defined(__CUDACC__))
+#define OTABSL_HAVE_INTRINSIC_INT128 1
+#elif defined(__CUDACC__)
+// __CUDACC_VER__ is a full version number before CUDA 9, and is defined to a
+// string explaining that it has been removed starting with CUDA 9. We use
+// nested #ifs because there is no short-circuiting in the preprocessor.
+// NOTE: `__CUDACC__` could be undefined while `__CUDACC_VER__` is defined.
+#if __CUDACC_VER__ >= 70000
+#define OTABSL_HAVE_INTRINSIC_INT128 1
+#endif  // __CUDACC_VER__ >= 70000
+#endif  // defined(__CUDACC__)
+#endif  // OTABSL_HAVE_INTRINSIC_INT128
+
+// OTABSL_HAVE_EXCEPTIONS
+//
+// Checks whether the compiler both supports and enables exceptions. Many
+// compilers support a "no exceptions" mode that disables exceptions.
+//
+// Generally, when OTABSL_HAVE_EXCEPTIONS is not defined:
+//
+// * Code using `throw` and `try` may not compile.
+// * The `noexcept` specifier will still compile and behave as normal.
+// * The `noexcept` operator may still return `false`.
+//
+// For further details, consult the compiler's documentation.
+#ifdef OTABSL_HAVE_EXCEPTIONS
+#error OTABSL_HAVE_EXCEPTIONS cannot be directly set.
+
+#elif defined(__clang__)
+
+#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6)
+// Clang >= 3.6
+#if __has_feature(cxx_exceptions)
+#define OTABSL_HAVE_EXCEPTIONS 1
+#endif  // __has_feature(cxx_exceptions)
+#else
+// Clang < 3.6
+// http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro
+#if defined(__EXCEPTIONS) && __has_feature(cxx_exceptions)
+#define OTABSL_HAVE_EXCEPTIONS 1
+#endif  // defined(__EXCEPTIONS) && __has_feature(cxx_exceptions)
+#endif  // __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6)
+
+// Handle remaining special cases and default to exceptions being supported.
+#elif !(defined(__GNUC__) && (__GNUC__ < 5) && !defined(__EXCEPTIONS)) &&    \
+    !(defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__cpp_exceptions)) && \
+    !(defined(_MSC_VER) && !defined(_CPPUNWIND))
+#define OTABSL_HAVE_EXCEPTIONS 1
+#endif
+
+// -----------------------------------------------------------------------------
+// Platform Feature Checks
+// -----------------------------------------------------------------------------
+
+// Currently supported operating systems and associated preprocessor
+// symbols:
+//
+//   Linux and Linux-derived           __linux__
+//   Android                           __ANDROID__ (implies __linux__)
+//   Linux (non-Android)               __linux__ && !__ANDROID__
+//   Darwin (macOS and iOS)            __APPLE__
+//   Akaros (http://akaros.org)        __ros__
+//   Windows                           _WIN32
+//   NaCL                              __native_client__
+//   AsmJS                             __asmjs__
+//   WebAssembly                       __wasm__
+//   Fuchsia                           __Fuchsia__
+//
+// Note that since Android defines both __ANDROID__ and __linux__, one
+// may probe for either Linux or Android by simply testing for __linux__.
+
+// OTABSL_HAVE_MMAP
+//
+// Checks whether the platform has an mmap(2) implementation as defined in
+// POSIX.1-2001.
+#ifdef OTABSL_HAVE_MMAP
+#error OTABSL_HAVE_MMAP cannot be directly set
+#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) ||   \
+    defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \
+    defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \
+    defined(__ASYLO__)
+#define OTABSL_HAVE_MMAP 1
+#endif
+
+// OTABSL_HAVE_PTHREAD_GETSCHEDPARAM
+//
+// Checks whether the platform implements the pthread_(get|set)schedparam(3)
+// functions as defined in POSIX.1-2001.
+#ifdef OTABSL_HAVE_PTHREAD_GETSCHEDPARAM
+#error OTABSL_HAVE_PTHREAD_GETSCHEDPARAM cannot be directly set
+#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
+    defined(__ros__)
+#define OTABSL_HAVE_PTHREAD_GETSCHEDPARAM 1
+#endif
+
+// OTABSL_HAVE_SCHED_YIELD
+//
+// Checks whether the platform implements sched_yield(2) as defined in
+// POSIX.1-2001.
+#ifdef OTABSL_HAVE_SCHED_YIELD
+#error OTABSL_HAVE_SCHED_YIELD cannot be directly set
+#elif defined(__linux__) || defined(__ros__) || defined(__native_client__)
+#define OTABSL_HAVE_SCHED_YIELD 1
+#endif
+
+// OTABSL_HAVE_SEMAPHORE_H
+//
+// Checks whether the platform supports the <semaphore.h> header and sem_init(3)
+// family of functions as standardized in POSIX.1-2001.
+//
+// Note: While Apple provides <semaphore.h> for both iOS and macOS, it is
+// explicitly deprecated and will cause build failures if enabled for those
+// platforms.  We side-step the issue by not defining it here for Apple
+// platforms.
+#ifdef OTABSL_HAVE_SEMAPHORE_H
+#error OTABSL_HAVE_SEMAPHORE_H cannot be directly set
+#elif defined(__linux__) || defined(__ros__)
+#define OTABSL_HAVE_SEMAPHORE_H 1
+#endif
+
+// OTABSL_HAVE_ALARM
+//
+// Checks whether the platform supports the <signal.h> header and alarm(2)
+// function as standardized in POSIX.1-2001.
+#ifdef OTABSL_HAVE_ALARM
+#error OTABSL_HAVE_ALARM cannot be directly set
+#elif defined(__GOOGLE_GRTE_VERSION__)
+// feature tests for Google's GRTE
+#define OTABSL_HAVE_ALARM 1
+#elif defined(__GLIBC__)
+// feature test for glibc
+#define OTABSL_HAVE_ALARM 1
+#elif defined(_MSC_VER)
+// feature tests for Microsoft's library
+#elif defined(__MINGW32__)
+// mingw32 doesn't provide alarm(2):
+// https://osdn.net/projects/mingw/scm/git/mingw-org-wsl/blobs/5.2-trunk/mingwrt/include/unistd.h
+// mingw-w64 provides a no-op implementation:
+// https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-crt/misc/alarm.c
+#elif defined(__EMSCRIPTEN__)
+// emscripten doesn't support signals
+#elif defined(__Fuchsia__)
+// Signals don't exist on fuchsia.
+#elif defined(__native_client__)
+#else
+// other standard libraries
+#define OTABSL_HAVE_ALARM 1
+#endif
+
+// OTABSL_IS_LITTLE_ENDIAN
+// OTABSL_IS_BIG_ENDIAN
+//
+// Checks the endianness of the platform.
+//
+// Notes: uses the built in endian macros provided by GCC (since 4.6) and
+// Clang (since 3.2); see
+// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html.
+// Otherwise, if _WIN32, assume little endian. Otherwise, bail with an error.
+#if defined(OTABSL_IS_BIG_ENDIAN)
+#error "OTABSL_IS_BIG_ENDIAN cannot be directly set."
+#endif
+#if defined(OTABSL_IS_LITTLE_ENDIAN)
+#error "OTABSL_IS_LITTLE_ENDIAN cannot be directly set."
+#endif
+
+#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
+     __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#define OTABSL_IS_LITTLE_ENDIAN 1
+#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
+    __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define OTABSL_IS_BIG_ENDIAN 1
+#elif defined(_WIN32)
+#define OTABSL_IS_LITTLE_ENDIAN 1
+#else
+#error "absl endian detection needs to be set up for your compiler"
+#endif
+
+// macOS 10.13 and iOS 10.11 don't let you use <any>, <optional>, or <variant>
+// even though the headers exist and are publicly noted to work.  See
+// https://github.com/abseil/abseil-cpp/issues/207 and
+// https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes
+// libc++ spells out the availability requirements in the file
+// llvm-project/libcxx/include/__config via the #define
+// _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS.
+#if defined(__APPLE__) && defined(_LIBCPP_VERSION) && \
+  ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
+   __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101400) || \
+  (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \
+   __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \
+  (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \
+   __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 120000) || \
+  (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \
+   __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 50000))
+#define OTABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1
+#else
+#define OTABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0
+#endif
+
+// OTABSL_HAVE_STD_ANY
+//
+// Checks whether C++17 std::any is available by checking whether <any> exists.
+#ifdef OTABSL_HAVE_STD_ANY
+#error "OTABSL_HAVE_STD_ANY cannot be directly set."
+#endif
+
+#ifdef __has_include
+#if __has_include(<any>) && __cplusplus >= 201703L && \
+    !OTABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
+#define OTABSL_HAVE_STD_ANY 1
+#endif
+#endif
+
+// OTABSL_HAVE_STD_OPTIONAL
+//
+// Checks whether C++17 std::optional is available.
+#ifdef OTABSL_HAVE_STD_OPTIONAL
+#error "OTABSL_HAVE_STD_OPTIONAL cannot be directly set."
+#endif
+
+#ifdef __has_include
+#if __has_include(<optional>) && __cplusplus >= 201703L && \
+    !OTABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
+#define OTABSL_HAVE_STD_OPTIONAL 1
+#endif
+#endif
+
+// OTABSL_HAVE_STD_VARIANT
+//
+// Checks whether C++17 std::variant is available.
+#ifdef OTABSL_HAVE_STD_VARIANT
+#error "OTABSL_HAVE_STD_VARIANT cannot be directly set."
+#endif
+
+#ifdef __has_include
+#if __has_include(<variant>) && __cplusplus >= 201703L && \
+    !OTABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
+#define OTABSL_HAVE_STD_VARIANT 1
+#endif
+#endif
+
+// OTABSL_HAVE_STD_STRING_VIEW
+//
+// Checks whether C++17 std::string_view is available.
+#ifdef OTABSL_HAVE_STD_STRING_VIEW
+#error "OTABSL_HAVE_STD_STRING_VIEW cannot be directly set."
+#endif
+
+#ifdef __has_include
+#if __has_include(<string_view>) && __cplusplus >= 201703L
+#define OTABSL_HAVE_STD_STRING_VIEW 1
+#endif
+#endif
+
+// For MSVC, `__has_include` is supported in VS 2017 15.3, which is later than
+// the support for <optional>, <any>, <string_view>, <variant>. So we use
+// _MSC_VER to check whether we have VS 2017 RTM (when <optional>, <any>,
+// <string_view>, <variant> is implemented) or higher. Also, `__cplusplus` is
+// not correctly set by MSVC, so we use `_MSVC_LANG` to check the language
+// version.
+// TODO(zhangxy): fix tests before enabling aliasing for `std::any`.
+#if defined(_MSC_VER) && _MSC_VER >= 1910 && \
+    ((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || __cplusplus > 201402)
+// #define OTABSL_HAVE_STD_ANY 1
+#define OTABSL_HAVE_STD_OPTIONAL 1
+#define OTABSL_HAVE_STD_VARIANT 1
+#define OTABSL_HAVE_STD_STRING_VIEW 1
+#endif
+
+// OTABSL_USES_STD_ANY
+//
+// Indicates whether absl::OTABSL_OPTION_NAMESPACE_NAME::any is an alias for std::any.
+#if !defined(OTABSL_OPTION_USE_STD_ANY)
+#error options.h is misconfigured.
+#elif OTABSL_OPTION_USE_STD_ANY == 0 || \
+    (OTABSL_OPTION_USE_STD_ANY == 2 && !defined(OTABSL_HAVE_STD_ANY))
+#undef OTABSL_USES_STD_ANY
+#elif OTABSL_OPTION_USE_STD_ANY == 1 || \
+    (OTABSL_OPTION_USE_STD_ANY == 2 && defined(OTABSL_HAVE_STD_ANY))
+#define OTABSL_USES_STD_ANY 1
+#else
+#error options.h is misconfigured.
+#endif
+
+// OTABSL_USES_STD_OPTIONAL
+//
+// Indicates whether absl::OTABSL_OPTION_NAMESPACE_NAME::optional is an alias for std::optional.
+#if !defined(OTABSL_OPTION_USE_STD_OPTIONAL)
+#error options.h is misconfigured.
+#elif OTABSL_OPTION_USE_STD_OPTIONAL == 0 || \
+    (OTABSL_OPTION_USE_STD_OPTIONAL == 2 && !defined(OTABSL_HAVE_STD_OPTIONAL))
+#undef OTABSL_USES_STD_OPTIONAL
+#elif OTABSL_OPTION_USE_STD_OPTIONAL == 1 || \
+    (OTABSL_OPTION_USE_STD_OPTIONAL == 2 && defined(OTABSL_HAVE_STD_OPTIONAL))
+#define OTABSL_USES_STD_OPTIONAL 1
+#else
+#error options.h is misconfigured.
+#endif
+
+// OTABSL_USES_STD_VARIANT
+//
+// Indicates whether absl::OTABSL_OPTION_NAMESPACE_NAME::variant is an alias for std::variant.
+#if !defined(OTABSL_OPTION_USE_STD_VARIANT)
+#error options.h is misconfigured.
+#elif OTABSL_OPTION_USE_STD_VARIANT == 0 || \
+    (OTABSL_OPTION_USE_STD_VARIANT == 2 && !defined(OTABSL_HAVE_STD_VARIANT))
+#undef OTABSL_USES_STD_VARIANT
+#elif OTABSL_OPTION_USE_STD_VARIANT == 1 || \
+    (OTABSL_OPTION_USE_STD_VARIANT == 2 && defined(OTABSL_HAVE_STD_VARIANT))
+#define OTABSL_USES_STD_VARIANT 1
+#else
+#error options.h is misconfigured.
+#endif
+
+// OTABSL_USES_STD_STRING_VIEW
+//
+// Indicates whether absl::OTABSL_OPTION_NAMESPACE_NAME::string_view is an alias for std::string_view.
+#if !defined(OTABSL_OPTION_USE_STD_STRING_VIEW)
+#error options.h is misconfigured.
+#elif OTABSL_OPTION_USE_STD_STRING_VIEW == 0 || \
+    (OTABSL_OPTION_USE_STD_STRING_VIEW == 2 &&  \
+     !defined(OTABSL_HAVE_STD_STRING_VIEW))
+#undef OTABSL_USES_STD_STRING_VIEW
+#elif OTABSL_OPTION_USE_STD_STRING_VIEW == 1 || \
+    (OTABSL_OPTION_USE_STD_STRING_VIEW == 2 &&  \
+     defined(OTABSL_HAVE_STD_STRING_VIEW))
+#define OTABSL_USES_STD_STRING_VIEW 1
+#else
+#error options.h is misconfigured.
+#endif
+
+// In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION
+// SEH exception from emplace for variant<SomeStruct> when constructing the
+// struct can throw. This defeats some of variant_test and
+// variant_exception_safety_test.
+#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_DEBUG)
+#define OTABSL_INTERNAL_MSVC_2017_DBG_MODE
+#endif
+
+// OTABSL_INTERNAL_MANGLED_NS
+// OTABSL_INTERNAL_MANGLED_BACKREFERENCE
+//
+// Internal macros for building up mangled names in our internal fork of CCTZ.
+// This implementation detail is only needed and provided for the MSVC build.
+//
+// These macros both expand to string literals.  OTABSL_INTERNAL_MANGLED_NS is
+// the mangled spelling of the `absl` namespace, and
+// OTABSL_INTERNAL_MANGLED_BACKREFERENCE is a back-reference integer representing
+// the proper count to skip past the CCTZ fork namespace names.  (This number
+// is one larger when there is an inline namespace name to skip.)
+#if defined(_MSC_VER)
+#define OTABSL_INTERNAL_MANGLED_NS \
+  OTABSL_INTERNAL_TOKEN_STR(OTABSL_OPTION_NAMESPACE_NAME) "@absl"
+#define OTABSL_INTERNAL_MANGLED_BACKREFERENCE "6"
+#endif
+
+#undef OTABSL_INTERNAL_HAS_KEYWORD
+
+// OTABSL_DLL
+//
+// When building Abseil as a DLL, this macro expands to `__declspec(dllexport)`
+// so we can annotate symbols appropriately as being exported. When used in
+// headers consuming a DLL, this macro expands to `__declspec(dllimport)` so
+// that consumers know the symbol is defined inside the DLL. In all other cases,
+// the macro expands to nothing.
+#if defined(_MSC_VER)
+#if defined(OTABSL_BUILD_DLL)
+#define OTABSL_DLL __declspec(dllexport)
+#elif 1
+#define OTABSL_DLL __declspec(dllimport)
+#else
+#define OTABSL_DLL
+#endif
+#else
+#define OTABSL_DLL
+#endif  // defined(_MSC_VER)
+
+#endif  // OTABSL_BASE_CONFIG_H_

+ 37 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/internal/identity.h

@@ -0,0 +1,37 @@
+// Copyright 2017 The Abseil 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
+//
+//      https://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 OTABSL_BASE_INTERNAL_IDENTITY_H_
+#define OTABSL_BASE_INTERNAL_IDENTITY_H_
+
+#include "../config.h"
+
+namespace absl {
+OTABSL_NAMESPACE_BEGIN
+namespace internal {
+
+template <typename T>
+struct identity {
+  typedef T type;
+};
+
+template <typename T>
+using identity_t = typename identity<T>::type;
+
+}  // namespace internal
+OTABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // OTABSL_BASE_INTERNAL_IDENTITY_H_

+ 107 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/internal/inline_variable.h

@@ -0,0 +1,107 @@
+// Copyright 2017 The Abseil 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
+//
+//      https://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 OTABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_
+#define OTABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_
+
+#include <type_traits>
+
+#include "identity.h"
+
+// File:
+//   This file define a macro that allows the creation of or emulation of C++17
+//   inline variables based on whether or not the feature is supported.
+
+////////////////////////////////////////////////////////////////////////////////
+// Macro: OTABSL_INTERNAL_INLINE_CONSTEXPR(type, name, init)
+//
+// Description:
+//   Expands to the equivalent of an inline constexpr instance of the specified
+//   `type` and `name`, initialized to the value `init`. If the compiler being
+//   used is detected as supporting actual inline variables as a language
+//   feature, then the macro expands to an actual inline variable definition.
+//
+// Requires:
+//   `type` is a type that is usable in an extern variable declaration.
+//
+// Requires: `name` is a valid identifier
+//
+// Requires:
+//   `init` is an expression that can be used in the following definition:
+//     constexpr type name = init;
+//
+// Usage:
+//
+//   // Equivalent to: `inline constexpr size_t variant_npos = -1;`
+//   OTABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1);
+//
+// Differences in implementation:
+//   For a direct, language-level inline variable, decltype(name) will be the
+//   type that was specified along with const qualification, whereas for
+//   emulated inline variables, decltype(name) may be different (in practice
+//   it will likely be a reference type).
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cpp_inline_variables
+
+// Clang's -Wmissing-variable-declarations option erroneously warned that
+// inline constexpr objects need to be pre-declared. This has now been fixed,
+// but we will need to support this workaround for people building with older
+// versions of clang.
+//
+// Bug: https://bugs.llvm.org/show_bug.cgi?id=35862
+//
+// Note:
+//   identity_t is used here so that the const and name are in the
+//   appropriate place for pointer types, reference types, function pointer
+//   types, etc..
+#if defined(__clang__)
+#define OTABSL_INTERNAL_EXTERN_DECL(type, name) \
+  extern const ::absl::OTABSL_OPTION_NAMESPACE_NAME::internal::identity_t<type> name;
+#else  // Otherwise, just define the macro to do nothing.
+#define OTABSL_INTERNAL_EXTERN_DECL(type, name)
+#endif  // defined(__clang__)
+
+// See above comment at top of file for details.
+#define OTABSL_INTERNAL_INLINE_CONSTEXPR(type, name, init) \
+  OTABSL_INTERNAL_EXTERN_DECL(type, name)                  \
+  inline constexpr ::absl::OTABSL_OPTION_NAMESPACE_NAME::internal::identity_t<type> name = init
+
+#else
+
+// See above comment at top of file for details.
+//
+// Note:
+//   identity_t is used here so that the const and name are in the
+//   appropriate place for pointer types, reference types, function pointer
+//   types, etc..
+#define OTABSL_INTERNAL_INLINE_CONSTEXPR(var_type, name, init)                  \
+  template <class /*AbslInternalDummy*/ = void>                               \
+  struct AbslInternalInlineVariableHolder##name {                             \
+    static constexpr ::absl::OTABSL_OPTION_NAMESPACE_NAME::internal::identity_t<var_type> kInstance = init; \
+  };                                                                          \
+                                                                              \
+  template <class AbslInternalDummy>                                          \
+  constexpr ::absl::OTABSL_OPTION_NAMESPACE_NAME::internal::identity_t<var_type>                            \
+      AbslInternalInlineVariableHolder##name<AbslInternalDummy>::kInstance;   \
+                                                                              \
+  static constexpr const ::absl::OTABSL_OPTION_NAMESPACE_NAME::internal::identity_t<var_type>&              \
+      name = /* NOLINT */                                                     \
+      AbslInternalInlineVariableHolder##name<>::kInstance;                    \
+  static_assert(sizeof(void (*)(decltype(name))) != 0,                        \
+                "Silence unused variable warnings.")
+
+#endif  // __cpp_inline_variables
+
+#endif  // OTABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_

+ 188 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/internal/invoke.h

@@ -0,0 +1,188 @@
+// Copyright 2017 The Abseil 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
+//
+//      https://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.
+//
+// absl::OTABSL_OPTION_NAMESPACE_NAME::base_internal::Invoke(f, args...) is an implementation of
+// INVOKE(f, args...) from section [func.require] of the C++ standard.
+//
+// [func.require]
+// Define INVOKE (f, t1, t2, ..., tN) as follows:
+// 1. (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T
+//    and t1 is an object of type T or a reference to an object of type T or a
+//    reference to an object of a type derived from T;
+// 2. ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a
+//    class T and t1 is not one of the types described in the previous item;
+// 3. t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is
+//    an object of type T or a reference to an object of type T or a reference
+//    to an object of a type derived from T;
+// 4. (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1
+//    is not one of the types described in the previous item;
+// 5. f(t1, t2, ..., tN) in all other cases.
+//
+// The implementation is SFINAE-friendly: substitution failure within Invoke()
+// isn't an error.
+
+#ifndef OTABSL_BASE_INTERNAL_INVOKE_H_
+#define OTABSL_BASE_INTERNAL_INVOKE_H_
+
+#include <algorithm>
+#include <type_traits>
+#include <utility>
+
+#include "../../meta/type_traits.h"
+
+// The following code is internal implementation detail.  See the comment at the
+// top of this file for the API documentation.
+
+namespace absl {
+OTABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+// The five classes below each implement one of the clauses from the definition
+// of INVOKE. The inner class template Accept<F, Args...> checks whether the
+// clause is applicable; static function template Invoke(f, args...) does the
+// invocation.
+//
+// By separating the clause selection logic from invocation we make sure that
+// Invoke() does exactly what the standard says.
+
+template <typename Derived>
+struct StrippedAccept {
+  template <typename... Args>
+  struct Accept : Derived::template AcceptImpl<typename std::remove_cv<
+                      typename std::remove_reference<Args>::type>::type...> {};
+};
+
+// (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T
+// and t1 is an object of type T or a reference to an object of type T or a
+// reference to an object of a type derived from T.
+struct MemFunAndRef : StrippedAccept<MemFunAndRef> {
+  template <typename... Args>
+  struct AcceptImpl : std::false_type {};
+
+  template <typename MemFunType, typename C, typename Obj, typename... Args>
+  struct AcceptImpl<MemFunType C::*, Obj, Args...>
+      : std::integral_constant<bool, std::is_base_of<C, Obj>::value &&
+                                         absl::OTABSL_OPTION_NAMESPACE_NAME::is_function<MemFunType>::value> {
+  };
+
+  template <typename MemFun, typename Obj, typename... Args>
+  static decltype((std::declval<Obj>().*
+                   std::declval<MemFun>())(std::declval<Args>()...))
+  Invoke(MemFun&& mem_fun, Obj&& obj, Args&&... args) {
+    return (std::forward<Obj>(obj).*
+            std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...);
+  }
+};
+
+// ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a
+// class T and t1 is not one of the types described in the previous item.
+struct MemFunAndPtr : StrippedAccept<MemFunAndPtr> {
+  template <typename... Args>
+  struct AcceptImpl : std::false_type {};
+
+  template <typename MemFunType, typename C, typename Ptr, typename... Args>
+  struct AcceptImpl<MemFunType C::*, Ptr, Args...>
+      : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value &&
+                                         absl::OTABSL_OPTION_NAMESPACE_NAME::is_function<MemFunType>::value> {
+  };
+
+  template <typename MemFun, typename Ptr, typename... Args>
+  static decltype(((*std::declval<Ptr>()).*
+                   std::declval<MemFun>())(std::declval<Args>()...))
+  Invoke(MemFun&& mem_fun, Ptr&& ptr, Args&&... args) {
+    return ((*std::forward<Ptr>(ptr)).*
+            std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...);
+  }
+};
+
+// t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is
+// an object of type T or a reference to an object of type T or a reference
+// to an object of a type derived from T.
+struct DataMemAndRef : StrippedAccept<DataMemAndRef> {
+  template <typename... Args>
+  struct AcceptImpl : std::false_type {};
+
+  template <typename R, typename C, typename Obj>
+  struct AcceptImpl<R C::*, Obj>
+      : std::integral_constant<bool, std::is_base_of<C, Obj>::value &&
+                                         !absl::OTABSL_OPTION_NAMESPACE_NAME::is_function<R>::value> {};
+
+  template <typename DataMem, typename Ref>
+  static decltype(std::declval<Ref>().*std::declval<DataMem>()) Invoke(
+      DataMem&& data_mem, Ref&& ref) {
+    return std::forward<Ref>(ref).*std::forward<DataMem>(data_mem);
+  }
+};
+
+// (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1
+// is not one of the types described in the previous item.
+struct DataMemAndPtr : StrippedAccept<DataMemAndPtr> {
+  template <typename... Args>
+  struct AcceptImpl : std::false_type {};
+
+  template <typename R, typename C, typename Ptr>
+  struct AcceptImpl<R C::*, Ptr>
+      : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value &&
+                                         !absl::OTABSL_OPTION_NAMESPACE_NAME::is_function<R>::value> {};
+
+  template <typename DataMem, typename Ptr>
+  static decltype((*std::declval<Ptr>()).*std::declval<DataMem>()) Invoke(
+      DataMem&& data_mem, Ptr&& ptr) {
+    return (*std::forward<Ptr>(ptr)).*std::forward<DataMem>(data_mem);
+  }
+};
+
+// f(t1, t2, ..., tN) in all other cases.
+struct Callable {
+  // Callable doesn't have Accept because it's the last clause that gets picked
+  // when none of the previous clauses are applicable.
+  template <typename F, typename... Args>
+  static decltype(std::declval<F>()(std::declval<Args>()...)) Invoke(
+      F&& f, Args&&... args) {
+    return std::forward<F>(f)(std::forward<Args>(args)...);
+  }
+};
+
+// Resolves to the first matching clause.
+template <typename... Args>
+struct Invoker {
+  typedef typename std::conditional<
+      MemFunAndRef::Accept<Args...>::value, MemFunAndRef,
+      typename std::conditional<
+          MemFunAndPtr::Accept<Args...>::value, MemFunAndPtr,
+          typename std::conditional<
+              DataMemAndRef::Accept<Args...>::value, DataMemAndRef,
+              typename std::conditional<DataMemAndPtr::Accept<Args...>::value,
+                                        DataMemAndPtr, Callable>::type>::type>::
+          type>::type type;
+};
+
+// The result type of Invoke<F, Args...>.
+template <typename F, typename... Args>
+using InvokeT = decltype(Invoker<F, Args...>::type::Invoke(
+    std::declval<F>(), std::declval<Args>()...));
+
+// Invoke(f, args...) is an implementation of INVOKE(f, args...) from section
+// [func.require] of the C++ standard.
+template <typename F, typename... Args>
+InvokeT<F, Args...> Invoke(F&& f, Args&&... args) {
+  return Invoker<F, Args...>::type::Invoke(std::forward<F>(f),
+                                           std::forward<Args>(args)...);
+}
+
+}  // namespace base_internal
+OTABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // OTABSL_BASE_INTERNAL_INVOKE_H_

+ 220 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/macros.h

@@ -0,0 +1,220 @@
+//
+// Copyright 2017 The Abseil 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
+//
+//      https://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.
+//
+// -----------------------------------------------------------------------------
+// File: macros.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the set of language macros used within Abseil code.
+// For the set of macros used to determine supported compilers and platforms,
+// see absl/base/config.h instead.
+//
+// This code is compiled directly on many platforms, including client
+// platforms like Windows, Mac, and embedded systems.  Before making
+// any changes here, make sure that you're not breaking any platforms.
+
+#ifndef OTABSL_BASE_MACROS_H_
+#define OTABSL_BASE_MACROS_H_
+
+#include <cassert>
+#include <cstddef>
+
+#include "attributes.h"
+#include "optimization.h"
+#include "port.h"
+
+// OTABSL_ARRAYSIZE()
+//
+// Returns the number of elements in an array as a compile-time constant, which
+// can be used in defining new arrays. If you use this macro on a pointer by
+// mistake, you will get a compile-time error.
+#define OTABSL_ARRAYSIZE(array) \
+  (sizeof(::absl::OTABSL_OPTION_NAMESPACE_NAME::macros_internal::ArraySizeHelper(array)))
+
+namespace absl {
+OTABSL_NAMESPACE_BEGIN
+namespace macros_internal {
+// Note: this internal template function declaration is used by OTABSL_ARRAYSIZE.
+// The function doesn't need a definition, as we only use its type.
+template <typename T, size_t N>
+auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N];
+}  // namespace macros_internal
+OTABSL_NAMESPACE_END
+}  // namespace absl
+
+// kLinkerInitialized
+//
+// An enum used only as a constructor argument to indicate that a variable has
+// static storage duration, and that the constructor should do nothing to its
+// state. Use of this macro indicates to the reader that it is legal to
+// declare a static instance of the class, provided the constructor is given
+// the absl::OTABSL_OPTION_NAMESPACE_NAME::base_internal::kLinkerInitialized argument.
+//
+// Normally, it is unsafe to declare a static variable that has a constructor or
+// a destructor because invocation order is undefined. However, if the type can
+// be zero-initialized (which the loader does for static variables) into a valid
+// state and the type's destructor does not affect storage, then a constructor
+// for static initialization can be declared.
+//
+// Example:
+//       // Declaration
+//       explicit MyClass(absl::OTABSL_OPTION_NAMESPACE_NAME::base_internal:LinkerInitialized x) {}
+//
+//       // Invocation
+//       static MyClass my_global(absl::OTABSL_OPTION_NAMESPACE_NAME::base_internal::kLinkerInitialized);
+namespace absl {
+OTABSL_NAMESPACE_BEGIN
+namespace base_internal {
+enum LinkerInitialized {
+  kLinkerInitialized = 0,
+};
+}  // namespace base_internal
+OTABSL_NAMESPACE_END
+}  // namespace absl
+
+// OTABSL_FALLTHROUGH_INTENDED
+//
+// Annotates implicit fall-through between switch labels, allowing a case to
+// indicate intentional fallthrough and turn off warnings about any lack of a
+// `break` statement. The OTABSL_FALLTHROUGH_INTENDED macro should be followed by
+// a semicolon and can be used in most places where `break` can, provided that
+// no statements exist between it and the next switch label.
+//
+// Example:
+//
+//  switch (x) {
+//    case 40:
+//    case 41:
+//      if (truth_is_out_there) {
+//        ++x;
+//        OTABSL_FALLTHROUGH_INTENDED;  // Use instead of/along with annotations
+//                                    // in comments
+//      } else {
+//        return x;
+//      }
+//    case 42:
+//      ...
+//
+// Notes: when compiled with clang in C++11 mode, the OTABSL_FALLTHROUGH_INTENDED
+// macro is expanded to the [[clang::fallthrough]] attribute, which is analysed
+// when  performing switch labels fall-through diagnostic
+// (`-Wimplicit-fallthrough`). See clang documentation on language extensions
+// for details:
+// https://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough
+//
+// When used with unsupported compilers, the OTABSL_FALLTHROUGH_INTENDED macro
+// has no effect on diagnostics. In any case this macro has no effect on runtime
+// behavior and performance of code.
+#ifdef OTABSL_FALLTHROUGH_INTENDED
+#error "OTABSL_FALLTHROUGH_INTENDED should not be defined."
+#endif
+
+// TODO(zhangxy): Use c++17 standard [[fallthrough]] macro, when supported.
+#if defined(__clang__) && defined(__has_warning)
+#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
+#define OTABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]]
+#endif
+#elif defined(__GNUC__) && __GNUC__ >= 7
+#define OTABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]]
+#endif
+
+#ifndef OTABSL_FALLTHROUGH_INTENDED
+#define OTABSL_FALLTHROUGH_INTENDED \
+  do {                            \
+  } while (0)
+#endif
+
+// OTABSL_DEPRECATED()
+//
+// Marks a deprecated class, struct, enum, function, method and variable
+// declarations. The macro argument is used as a custom diagnostic message (e.g.
+// suggestion of a better alternative).
+//
+// Examples:
+//
+//   class OTABSL_DEPRECATED("Use Bar instead") Foo {...};
+//
+//   OTABSL_DEPRECATED("Use Baz() instead") void Bar() {...}
+//
+//   template <typename T>
+//   OTABSL_DEPRECATED("Use DoThat() instead")
+//   void DoThis();
+//
+// Every usage of a deprecated entity will trigger a warning when compiled with
+// clang's `-Wdeprecated-declarations` option. This option is turned off by
+// default, but the warnings will be reported by clang-tidy.
+#if defined(__clang__) && __cplusplus >= 201103L
+#define OTABSL_DEPRECATED(message) __attribute__((deprecated(message)))
+#endif
+
+#ifndef OTABSL_DEPRECATED
+#define OTABSL_DEPRECATED(message)
+#endif
+
+// OTABSL_BAD_CALL_IF()
+//
+// Used on a function overload to trap bad calls: any call that matches the
+// overload will cause a compile-time error. This macro uses a clang-specific
+// "enable_if" attribute, as described at
+// https://clang.llvm.org/docs/AttributeReference.html#enable-if
+//
+// Overloads which use this macro should be bracketed by
+// `#ifdef OTABSL_BAD_CALL_IF`.
+//
+// Example:
+//
+//   int isdigit(int c);
+//   #ifdef OTABSL_BAD_CALL_IF
+//   int isdigit(int c)
+//     OTABSL_BAD_CALL_IF(c <= -1 || c > 255,
+//                       "'c' must have the value of an unsigned char or EOF");
+//   #endif // OTABSL_BAD_CALL_IF
+#if OTABSL_HAVE_ATTRIBUTE(enable_if)
+#define OTABSL_BAD_CALL_IF(expr, msg) \
+  __attribute__((enable_if(expr, "Bad call trap"), unavailable(msg)))
+#endif
+
+// OTABSL_ASSERT()
+//
+// In C++11, `assert` can't be used portably within constexpr functions.
+// OTABSL_ASSERT functions as a runtime assert but works in C++11 constexpr
+// functions.  Example:
+//
+// constexpr double Divide(double a, double b) {
+//   return OTABSL_ASSERT(b != 0), a / b;
+// }
+//
+// This macro is inspired by
+// https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/
+#if defined(NDEBUG)
+#define OTABSL_ASSERT(expr) \
+  (false ? static_cast<void>(expr) : static_cast<void>(0))
+#else
+#define OTABSL_ASSERT(expr)                           \
+  (OTABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
+                             : [] { assert(false && #expr); }())  // NOLINT
+#endif
+
+#ifdef OTABSL_HAVE_EXCEPTIONS
+#define OTABSL_INTERNAL_TRY try
+#define OTABSL_INTERNAL_CATCH_ANY catch (...)
+#define OTABSL_INTERNAL_RETHROW do { throw; } while (false)
+#else  // OTABSL_HAVE_EXCEPTIONS
+#define OTABSL_INTERNAL_TRY if (true)
+#define OTABSL_INTERNAL_CATCH_ANY else if (false)
+#define OTABSL_INTERNAL_RETHROW do {} while (false)
+#endif  // OTABSL_HAVE_EXCEPTIONS
+
+#endif  // OTABSL_BASE_MACROS_H_

+ 181 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/optimization.h

@@ -0,0 +1,181 @@
+//
+// Copyright 2017 The Abseil 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
+//
+//      https://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.
+//
+// -----------------------------------------------------------------------------
+// File: optimization.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines portable macros for performance optimization.
+
+#ifndef OTABSL_BASE_OPTIMIZATION_H_
+#define OTABSL_BASE_OPTIMIZATION_H_
+
+#include "config.h"
+
+// OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION
+//
+// Instructs the compiler to avoid optimizing tail-call recursion. Use of this
+// macro is useful when you wish to preserve the existing function order within
+// a stack trace for logging, debugging, or profiling purposes.
+//
+// Example:
+//
+//   int f() {
+//     int result = g();
+//     OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
+//     return result;
+//   }
+#if defined(__pnacl__)
+#define OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; }
+#elif defined(__clang__)
+// Clang will not tail call given inline volatile assembly.
+#define OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("")
+#elif defined(__GNUC__)
+// GCC will not tail call given inline volatile assembly.
+#define OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("")
+#elif defined(_MSC_VER)
+#include <intrin.h>
+// The __nop() intrinsic blocks the optimisation.
+#define OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __nop()
+#else
+#define OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; }
+#endif
+
+// OTABSL_CACHELINE_SIZE
+//
+// Explicitly defines the size of the L1 cache for purposes of alignment.
+// Setting the cacheline size allows you to specify that certain objects be
+// aligned on a cacheline boundary with `OTABSL_CACHELINE_ALIGNED` declarations.
+// (See below.)
+//
+// NOTE: this macro should be replaced with the following C++17 features, when
+// those are generally available:
+//
+//   * `std::hardware_constructive_interference_size`
+//   * `std::hardware_destructive_interference_size`
+//
+// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html
+// for more information.
+#if defined(__GNUC__)
+// Cache line alignment
+#if defined(__i386__) || defined(__x86_64__)
+#define OTABSL_CACHELINE_SIZE 64
+#elif defined(__powerpc64__)
+#define OTABSL_CACHELINE_SIZE 128
+#elif defined(__aarch64__)
+// We would need to read special register ctr_el0 to find out L1 dcache size.
+// This value is a good estimate based on a real aarch64 machine.
+#define OTABSL_CACHELINE_SIZE 64
+#elif defined(__arm__)
+// Cache line sizes for ARM: These values are not strictly correct since
+// cache line sizes depend on implementations, not architectures.  There
+// are even implementations with cache line sizes configurable at boot
+// time.
+#if defined(__ARM_ARCH_5T__)
+#define OTABSL_CACHELINE_SIZE 32
+#elif defined(__ARM_ARCH_7A__)
+#define OTABSL_CACHELINE_SIZE 64
+#endif
+#endif
+
+#ifndef OTABSL_CACHELINE_SIZE
+// A reasonable default guess.  Note that overestimates tend to waste more
+// space, while underestimates tend to waste more time.
+#define OTABSL_CACHELINE_SIZE 64
+#endif
+
+// OTABSL_CACHELINE_ALIGNED
+//
+// Indicates that the declared object be cache aligned using
+// `OTABSL_CACHELINE_SIZE` (see above). Cacheline aligning objects allows you to
+// load a set of related objects in the L1 cache for performance improvements.
+// Cacheline aligning objects properly allows constructive memory sharing and
+// prevents destructive (or "false") memory sharing.
+//
+// NOTE: this macro should be replaced with usage of `alignas()` using
+// `std::hardware_constructive_interference_size` and/or
+// `std::hardware_destructive_interference_size` when available within C++17.
+//
+// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html
+// for more information.
+//
+// On some compilers, `OTABSL_CACHELINE_ALIGNED` expands to an `__attribute__`
+// or `__declspec` attribute. For compilers where this is not known to work,
+// the macro expands to nothing.
+//
+// No further guarantees are made here. The result of applying the macro
+// to variables and types is always implementation-defined.
+//
+// WARNING: It is easy to use this attribute incorrectly, even to the point
+// of causing bugs that are difficult to diagnose, crash, etc. It does not
+// of itself guarantee that objects are aligned to a cache line.
+//
+// NOTE: Some compilers are picky about the locations of annotations such as
+// this attribute, so prefer to put it at the beginning of your declaration.
+// For example,
+//
+//   OTABSL_CACHELINE_ALIGNED static Foo* foo = ...
+//
+//   class OTABSL_CACHELINE_ALIGNED Bar { ...
+//
+// Recommendations:
+//
+// 1) Consult compiler documentation; this comment is not kept in sync as
+//    toolchains evolve.
+// 2) Verify your use has the intended effect. This often requires inspecting
+//    the generated machine code.
+// 3) Prefer applying this attribute to individual variables. Avoid
+//    applying it to types. This tends to localize the effect.
+#define OTABSL_CACHELINE_ALIGNED __attribute__((aligned(OTABSL_CACHELINE_SIZE)))
+#elif defined(_MSC_VER)
+#define OTABSL_CACHELINE_SIZE 64
+#define OTABSL_CACHELINE_ALIGNED __declspec(align(OTABSL_CACHELINE_SIZE))
+#else
+#define OTABSL_CACHELINE_SIZE 64
+#define OTABSL_CACHELINE_ALIGNED
+#endif
+
+// OTABSL_PREDICT_TRUE, OTABSL_PREDICT_FALSE
+//
+// Enables the compiler to prioritize compilation using static analysis for
+// likely paths within a boolean branch.
+//
+// Example:
+//
+//   if (OTABSL_PREDICT_TRUE(expression)) {
+//     return result;                        // Faster if more likely
+//   } else {
+//     return 0;
+//   }
+//
+// Compilers can use the information that a certain branch is not likely to be
+// taken (for instance, a CHECK failure) to optimize for the common case in
+// the absence of better information (ie. compiling gcc with `-fprofile-arcs`).
+//
+// Recommendation: Modern CPUs dynamically predict branch execution paths,
+// typically with accuracy greater than 97%. As a result, annotating every
+// branch in a codebase is likely counterproductive; however, annotating
+// specific branches that are both hot and consistently mispredicted is likely
+// to yield performance improvements.
+#if OTABSL_HAVE_BUILTIN(__builtin_expect) || \
+    (defined(__GNUC__) && !defined(__clang__))
+#define OTABSL_PREDICT_FALSE(x) (__builtin_expect(x, 0))
+#define OTABSL_PREDICT_TRUE(x) (__builtin_expect(false || (x), true))
+#else
+#define OTABSL_PREDICT_FALSE(x) (x)
+#define OTABSL_PREDICT_TRUE(x) (x)
+#endif
+
+#endif  // OTABSL_BASE_OPTIMIZATION_H_

+ 216 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/options.h

@@ -0,0 +1,216 @@
+#ifndef OTABSL_BASE_OPTIONS_H_
+#define OTABSL_BASE_OPTIONS_H_
+
+// Copyright 2019 The Abseil 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
+//
+//      https://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.
+//
+// -----------------------------------------------------------------------------
+// File: options.h
+// -----------------------------------------------------------------------------
+//
+// This file contains Abseil configuration options for setting specific
+// implementations instead of letting Abseil determine which implementation to
+// use at compile-time. Setting these options may be useful for package or build
+// managers who wish to guarantee ABI stability within binary builds (which are
+// otherwise difficult to enforce).
+//
+// *** IMPORTANT NOTICE FOR PACKAGE MANAGERS:  It is important that
+// maintainers of package managers who wish to package Abseil read and
+// understand this file! ***
+//
+// Abseil contains a number of possible configuration endpoints, based on
+// parameters such as the detected platform, language version, or command-line
+// flags used to invoke the underlying binary. As is the case with all
+// libraries, binaries which contain Abseil code must ensure that separate
+// packages use the same compiled copy of Abseil to avoid a diamond dependency
+// problem, which can occur if two packages built with different Abseil
+// configuration settings are linked together. Diamond dependency problems in
+// C++ may manifest as violations to the One Definition Rule (ODR) (resulting in
+// linker errors), or undefined behavior (resulting in crashes).
+//
+// Diamond dependency problems can be avoided if all packages utilize the same
+// exact version of Abseil. Building from source code with the same compilation
+// parameters is the easiest way to avoid such dependency problems. However, for
+// package managers who cannot control such compilation parameters, we are
+// providing the file to allow you to inject ABI (Application Binary Interface)
+// stability across builds. Settings options in this file will neither change
+// API nor ABI, providing a stable copy of Abseil between packages.
+//
+// Care must be taken to keep options within these configurations isolated
+// from any other dynamic settings, such as command-line flags which could alter
+// these options. This file is provided specifically to help build and package
+// managers provide a stable copy of Abseil within their libraries and binaries;
+// other developers should not have need to alter the contents of this file.
+//
+// -----------------------------------------------------------------------------
+// Usage
+// -----------------------------------------------------------------------------
+//
+// For any particular package release, set the appropriate definitions within
+// this file to whatever value makes the most sense for your package(s). Note
+// that, by default, most of these options, at the moment, affect the
+// implementation of types; future options may affect other implementation
+// details.
+//
+// NOTE: the defaults within this file all assume that Abseil can select the
+// proper Abseil implementation at compile-time, which will not be sufficient
+// to guarantee ABI stability to package managers.
+
+// Include a standard library header to allow configuration based on the
+// standard library in use.
+// Using C++20 feature-test macros when possible, otherwise fall back to
+// ciso646/iso646.h.There are warnings when including ciso646 in C++17 mode
+#ifdef __has_include
+#  if __has_include(<version>)
+#    include <version>
+#  endif
+#elif defined(_MSC_VER) && \
+    ((defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L))
+#  if _MSC_VER >= 1922
+#    include <version>
+#  endif
+#else
+#  if defined(__GNUC__) && !defined(__clang__) && !defined(__apple_build_version__)
+#    pragma GCC diagnostic push
+#    pragma GCC diagnostic ignored "-Wcpp"
+#  elif defined(__clang__) || defined(__apple_build_version__)
+#    pragma clang diagnostic push
+#    pragma clang diagnostic ignored "-Wcpp"
+#  endif
+#  include <ciso646>
+#  if defined(__GNUC__) && !defined(__clang__) && !defined(__apple_build_version__)
+#      pragma GCC diagnostic pop
+#  elif defined(__clang__) || defined(__apple_build_version__)
+#    pragma clang diagnostic pop
+#  endif
+#endif
+
+// -----------------------------------------------------------------------------
+// Type Compatibility Options
+// -----------------------------------------------------------------------------
+//
+// OTABSL_OPTION_USE_STD_ANY
+//
+// This option controls whether absl::OTABSL_OPTION_NAMESPACE_NAME::any is implemented as an alias to
+// std::any, or as an independent implementation.
+//
+// A value of 0 means to use Abseil's implementation.  This requires only C++11
+// support, and is expected to work on every toolchain we support.
+//
+// A value of 1 means to use an alias to std::any.  This requires that all code
+// using Abseil is built in C++17 mode or later.
+//
+// A value of 2 means to detect the C++ version being used to compile Abseil,
+// and use an alias only if a working std::any is available.  This option is
+// useful when you are building your entire program, including all of its
+// dependencies, from source.  It should not be used otherwise -- for example,
+// if you are distributing Abseil in a binary package manager -- since in
+// mode 2, absl::OTABSL_OPTION_NAMESPACE_NAME::any will name a different type, with a different mangled name
+// and binary layout, depending on the compiler flags passed by the end user.
+// For more info, see https://abseil.io/about/design/dropin-types.
+//
+// User code should not inspect this macro.  To check in the preprocessor if
+// absl::OTABSL_OPTION_NAMESPACE_NAME::any is a typedef of std::any, use the feature macro OTABSL_USES_STD_ANY.
+
+#define OTABSL_OPTION_USE_STD_ANY 0
+
+
+// OTABSL_OPTION_USE_STD_OPTIONAL
+//
+// This option controls whether absl::OTABSL_OPTION_NAMESPACE_NAME::optional is implemented as an alias to
+// std::optional, or as an independent implementation.
+//
+// A value of 0 means to use Abseil's implementation.  This requires only C++11
+// support, and is expected to work on every toolchain we support.
+//
+// A value of 1 means to use an alias to std::optional.  This requires that all
+// code using Abseil is built in C++17 mode or later.
+//
+// A value of 2 means to detect the C++ version being used to compile Abseil,
+// and use an alias only if a working std::optional is available.  This option
+// is useful when you are building your program from source.  It should not be
+// used otherwise -- for example, if you are distributing Abseil in a binary
+// package manager -- since in mode 2, absl::OTABSL_OPTION_NAMESPACE_NAME::optional will name a different
+// type, with a different mangled name and binary layout, depending on the
+// compiler flags passed by the end user.  For more info, see
+// https://abseil.io/about/design/dropin-types.
+
+// User code should not inspect this macro.  To check in the preprocessor if
+// absl::OTABSL_OPTION_NAMESPACE_NAME::optional is a typedef of std::optional, use the feature macro
+// OTABSL_USES_STD_OPTIONAL.
+
+#define OTABSL_OPTION_USE_STD_OPTIONAL 0
+
+
+// OTABSL_OPTION_USE_STD_STRING_VIEW
+//
+// This option controls whether absl::OTABSL_OPTION_NAMESPACE_NAME::string_view is implemented as an alias to
+// std::string_view, or as an independent implementation.
+//
+// A value of 0 means to use Abseil's implementation.  This requires only C++11
+// support, and is expected to work on every toolchain we support.
+//
+// A value of 1 means to use an alias to std::string_view.  This requires that
+// all code using Abseil is built in C++17 mode or later.
+//
+// A value of 2 means to detect the C++ version being used to compile Abseil,
+// and use an alias only if a working std::string_view is available.  This
+// option is useful when you are building your program from source.  It should
+// not be used otherwise -- for example, if you are distributing Abseil in a
+// binary package manager -- since in mode 2, absl::OTABSL_OPTION_NAMESPACE_NAME::string_view will name a
+// different type, with a different mangled name and binary layout, depending on
+// the compiler flags passed by the end user.  For more info, see
+// https://abseil.io/about/design/dropin-types.
+//
+// User code should not inspect this macro.  To check in the preprocessor if
+// absl::OTABSL_OPTION_NAMESPACE_NAME::string_view is a typedef of std::string_view, use the feature macro
+// OTABSL_USES_STD_STRING_VIEW.
+
+#define OTABSL_OPTION_USE_STD_STRING_VIEW 0
+
+// OTABSL_OPTION_USE_STD_VARIANT
+//
+// This option controls whether absl::OTABSL_OPTION_NAMESPACE_NAME::variant is implemented as an alias to
+// std::variant, or as an independent implementation.
+//
+// A value of 0 means to use Abseil's implementation.  This requires only C++11
+// support, and is expected to work on every toolchain we support.
+//
+// A value of 1 means to use an alias to std::variant.  This requires that all
+// code using Abseil is built in C++17 mode or later.
+//
+// A value of 2 means to detect the C++ version being used to compile Abseil,
+// and use an alias only if a working std::variant is available.  This option
+// is useful when you are building your program from source.  It should not be
+// used otherwise -- for example, if you are distributing Abseil in a binary
+// package manager -- since in mode 2, absl::OTABSL_OPTION_NAMESPACE_NAME::variant will name a different
+// type, with a different mangled name and binary layout, depending on the
+// compiler flags passed by the end user.  For more info, see
+// https://abseil.io/about/design/dropin-types.
+//
+// User code should not inspect this macro.  To check in the preprocessor if
+// absl::OTABSL_OPTION_NAMESPACE_NAME::variant is a typedef of std::variant, use the feature macro
+// OTABSL_USES_STD_VARIANT.
+
+#define OTABSL_OPTION_USE_STD_VARIANT 0
+
+
+// OTABSL_OPTION_NAMESPACE_NAME
+//
+// All codes in otabsl are under OTABSL_OPTION_NAMESPACE_NAME, we do not use inline namespace to avoid
+// conlict with external Abseil.
+
+#define OTABSL_OPTION_NAMESPACE_NAME otel_v1
+
+#endif  // OTABSL_BASE_OPTIONS_H_

+ 115 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/policy_checks.h

@@ -0,0 +1,115 @@
+// Copyright 2017 The Abseil 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
+//
+//      https://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.
+//
+// -----------------------------------------------------------------------------
+// File: policy_checks.h
+// -----------------------------------------------------------------------------
+//
+// This header enforces a minimum set of policies at build time, such as the
+// supported compiler and library versions. Unsupported configurations are
+// reported with `#error`. This enforcement is best effort, so successfully
+// compiling this header does not guarantee a supported configuration.
+
+#ifndef OTABSL_BASE_POLICY_CHECKS_H_
+#define OTABSL_BASE_POLICY_CHECKS_H_
+
+// Included for the __GLIBC_PREREQ macro used below.
+#include <limits.h>
+
+// Included for the _STLPORT_VERSION macro used below.
+#if defined(__cplusplus)
+#include <cstddef>
+#endif
+
+// -----------------------------------------------------------------------------
+// Operating System Check
+// -----------------------------------------------------------------------------
+
+#if defined(__CYGWIN__)
+#error "Cygwin is not supported."
+#endif
+
+// -----------------------------------------------------------------------------
+// Compiler Check
+// -----------------------------------------------------------------------------
+
+#if 0 /* FIXME: MG */
+// We support MSVC++ 14.0 update 2 and later.
+// This minimum will go up.
+#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023918 && !defined(__clang__)
+#error "This package requires Visual Studio 2015 Update 2 or higher."
+#endif
+#endif
+
+// We support gcc 4.7 and later.
+// This minimum will go up.
+#if defined(__GNUC__) && !defined(__clang__)
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7)
+#error "This package requires gcc 4.7 or higher."
+#endif
+#endif
+
+// We support Apple Xcode clang 4.2.1 (version 421.11.65) and later.
+// This corresponds to Apple Xcode version 4.5.
+// This minimum will go up.
+#if defined(__apple_build_version__) && __apple_build_version__ < 4211165
+#error "This package requires __apple_build_version__ of 4211165 or higher."
+#endif
+
+// -----------------------------------------------------------------------------
+// C++ Version Check
+// -----------------------------------------------------------------------------
+
+// Enforce C++11 as the minimum.
+#if defined(_MSVC_LANG)
+#if _MSVC_LANG < 201103L
+#error "C++ versions less than C++11 are not supported."
+#endif  // _MSVC_LANG < 201103L
+#elif defined(__cplusplus)
+#if __cplusplus < 201103L
+#error "C++ versions less than C++11 are not supported."
+#endif  // __cplusplus < 201103L
+#endif
+
+// -----------------------------------------------------------------------------
+// Standard Library Check
+// -----------------------------------------------------------------------------
+
+#if defined(_STLPORT_VERSION)
+#error "STLPort is not supported."
+#endif
+
+// -----------------------------------------------------------------------------
+// `char` Size Check
+// -----------------------------------------------------------------------------
+
+// Abseil currently assumes CHAR_BIT == 8. If you would like to use Abseil on a
+// platform where this is not the case, please provide us with the details about
+// your platform so we can consider relaxing this requirement.
+#if CHAR_BIT != 8
+#error "Abseil assumes CHAR_BIT == 8."
+#endif
+
+// -----------------------------------------------------------------------------
+// `int` Size Check
+// -----------------------------------------------------------------------------
+
+// Abseil currently assumes that an int is 4 bytes. If you would like to use
+// Abseil on a platform where this is not the case, please provide us with the
+// details about your platform so we can consider relaxing this requirement.
+#if INT_MAX < 2147483647
+#error "Abseil assumes that int is at least 4 bytes. "
+#endif
+
+#endif  // OTABSL_BASE_POLICY_CHECKS_H_

+ 26 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/base/port.h

@@ -0,0 +1,26 @@
+// Copyright 2017 The Abseil 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
+//
+//      https://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.
+//
+// This files is a forwarding header for other headers containing various
+// portability macros and functions.
+// This file is used for both C and C++!
+
+#ifndef OTABSL_BASE_PORT_H_
+#define OTABSL_BASE_PORT_H_
+
+#include "attributes.h"
+#include "config.h"
+#include "optimization.h"
+
+#endif  // OTABSL_BASE_PORT_H_

+ 779 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/meta/type_traits.h

@@ -0,0 +1,779 @@
+//
+// Copyright 2017 The Abseil 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
+//
+//      https://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.
+//
+// -----------------------------------------------------------------------------
+// type_traits.h
+// -----------------------------------------------------------------------------
+//
+// This file contains C++11-compatible versions of standard <type_traits> API
+// functions for determining the characteristics of types. Such traits can
+// support type inference, classification, and transformation, as well as
+// make it easier to write templates based on generic type behavior.
+//
+// See https://en.cppreference.com/w/cpp/header/type_traits
+//
+// WARNING: use of many of the constructs in this header will count as "complex
+// template metaprogramming", so before proceeding, please carefully consider
+// https://google.github.io/styleguide/cppguide.html#Template_metaprogramming
+//
+// WARNING: using template metaprogramming to detect or depend on API
+// features is brittle and not guaranteed. Neither the standard library nor
+// Abseil provides any guarantee that APIs are stable in the face of template
+// metaprogramming. Use with caution.
+#ifndef OTABSL_META_TYPE_TRAITS_H_
+#define OTABSL_META_TYPE_TRAITS_H_
+
+#include <stddef.h>
+#include <functional>
+#include <type_traits>
+
+#include "../base/config.h"
+
+// MSVC constructibility traits do not detect destructor properties and so our
+// implementations should not use them as a source-of-truth.
+#if defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__)
+#define OTABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION 1
+#endif
+
+namespace absl {
+OTABSL_NAMESPACE_BEGIN
+
+// Defined and documented later on in this file.
+template <typename T>
+struct is_trivially_destructible;
+
+// Defined and documented later on in this file.
+template <typename T>
+struct is_trivially_move_assignable;
+
+namespace type_traits_internal {
+
+// Silence MSVC warnings about the destructor being defined as deleted.
+#if defined(_MSC_VER) && !defined(__GNUC__)
+#pragma warning(push)
+#pragma warning(disable : 4624)
+#endif  // defined(_MSC_VER) && !defined(__GNUC__)
+
+template <class T>
+union SingleMemberUnion {
+  T t;
+};
+
+// Restore the state of the destructor warning that was silenced above.
+#if defined(_MSC_VER) && !defined(__GNUC__)
+#pragma warning(pop)
+#endif  // defined(_MSC_VER) && !defined(__GNUC__)
+
+template <class T>
+struct IsTriviallyMoveConstructibleObject
+    : std::integral_constant<
+          bool, std::is_move_constructible<
+                    type_traits_internal::SingleMemberUnion<T>>::value &&
+                    absl::OTABSL_OPTION_NAMESPACE_NAME::is_trivially_destructible<T>::value> {};
+
+template <class T>
+struct IsTriviallyCopyConstructibleObject
+    : std::integral_constant<
+          bool, std::is_copy_constructible<
+                    type_traits_internal::SingleMemberUnion<T>>::value &&
+                    absl::OTABSL_OPTION_NAMESPACE_NAME::is_trivially_destructible<T>::value> {};
+
+template <class T>
+struct IsTriviallyMoveAssignableReference : std::false_type {};
+
+template <class T>
+struct IsTriviallyMoveAssignableReference<T&>
+    : absl::OTABSL_OPTION_NAMESPACE_NAME::is_trivially_move_assignable<T>::type {};
+
+template <class T>
+struct IsTriviallyMoveAssignableReference<T&&>
+    : absl::OTABSL_OPTION_NAMESPACE_NAME::is_trivially_move_assignable<T>::type {};
+
+template <typename... Ts>
+struct VoidTImpl {
+  using type = void;
+};
+
+////////////////////////////////
+// Library Fundamentals V2 TS //
+////////////////////////////////
+
+// NOTE: The `is_detected` family of templates here differ from the library
+// fundamentals specification in that for library fundamentals, `Op<Args...>` is
+// evaluated as soon as the type `is_detected<Op, Args...>` undergoes
+// substitution, regardless of whether or not the `::value` is accessed. That
+// is inconsistent with all other standard traits and prevents lazy evaluation
+// in larger contexts (such as if the `is_detected` check is a trailing argument
+// of a `conjunction`. This implementation opts to instead be lazy in the same
+// way that the standard traits are (this "defect" of the detection idiom
+// specifications has been reported).
+
+template <class Enabler, template <class...> class Op, class... Args>
+struct is_detected_impl {
+  using type = std::false_type;
+};
+
+template <template <class...> class Op, class... Args>
+struct is_detected_impl<typename VoidTImpl<Op<Args...>>::type, Op, Args...> {
+  using type = std::true_type;
+};
+
+template <template <class...> class Op, class... Args>
+struct is_detected : is_detected_impl<void, Op, Args...>::type {};
+
+template <class Enabler, class To, template <class...> class Op, class... Args>
+struct is_detected_convertible_impl {
+  using type = std::false_type;
+};
+
+template <class To, template <class...> class Op, class... Args>
+struct is_detected_convertible_impl<
+    typename std::enable_if<std::is_convertible<Op<Args...>, To>::value>::type,
+    To, Op, Args...> {
+  using type = std::true_type;
+};
+
+template <class To, template <class...> class Op, class... Args>
+struct is_detected_convertible
+    : is_detected_convertible_impl<void, To, Op, Args...>::type {};
+
+template <typename T>
+using IsCopyAssignableImpl =
+    decltype(std::declval<T&>() = std::declval<const T&>());
+
+template <typename T>
+using IsMoveAssignableImpl = decltype(std::declval<T&>() = std::declval<T&&>());
+
+}  // namespace type_traits_internal
+
+// MSVC 19.10 and higher have a regression that causes our workarounds to fail, but their
+// std forms now appear to be compliant.
+#if defined(_MSC_VER) && !defined(__clang__) && (_MSC_VER >= 1910)
+
+template <typename T>
+using is_copy_assignable = std::is_copy_assignable<T>;
+
+template <typename T>
+using is_move_assignable = std::is_move_assignable<T>;
+
+#else
+
+template <typename T>
+struct is_copy_assignable : type_traits_internal::is_detected<
+                                type_traits_internal::IsCopyAssignableImpl, T> {
+};
+
+template <typename T>
+struct is_move_assignable : type_traits_internal::is_detected<
+                                type_traits_internal::IsMoveAssignableImpl, T> {
+};
+
+#endif
+
+// void_t()
+//
+// Ignores the type of any its arguments and returns `void`. In general, this
+// metafunction allows you to create a general case that maps to `void` while
+// allowing specializations that map to specific types.
+//
+// This metafunction is designed to be a drop-in replacement for the C++17
+// `std::void_t` metafunction.
+//
+// NOTE: `absl::OTABSL_OPTION_NAMESPACE_NAME::void_t` does not use the standard-specified implementation so
+// that it can remain compatible with gcc < 5.1. This can introduce slightly
+// different behavior, such as when ordering partial specializations.
+template <typename... Ts>
+using void_t = typename type_traits_internal::VoidTImpl<Ts...>::type;
+
+// conjunction
+//
+// Performs a compile-time logical AND operation on the passed types (which
+// must have  `::value` members convertible to `bool`. Short-circuits if it
+// encounters any `false` members (and does not compare the `::value` members
+// of any remaining arguments).
+//
+// This metafunction is designed to be a drop-in replacement for the C++17
+// `std::conjunction` metafunction.
+template <typename... Ts>
+struct conjunction;
+
+template <typename T, typename... Ts>
+struct conjunction<T, Ts...>
+    : std::conditional<T::value, conjunction<Ts...>, T>::type {};
+
+template <typename T>
+struct conjunction<T> : T {};
+
+template <>
+struct conjunction<> : std::true_type {};
+
+// disjunction
+//
+// Performs a compile-time logical OR operation on the passed types (which
+// must have  `::value` members convertible to `bool`. Short-circuits if it
+// encounters any `true` members (and does not compare the `::value` members
+// of any remaining arguments).
+//
+// This metafunction is designed to be a drop-in replacement for the C++17
+// `std::disjunction` metafunction.
+template <typename... Ts>
+struct disjunction;
+
+template <typename T, typename... Ts>
+struct disjunction<T, Ts...> :
+      std::conditional<T::value, T, disjunction<Ts...>>::type {};
+
+template <typename T>
+struct disjunction<T> : T {};
+
+template <>
+struct disjunction<> : std::false_type {};
+
+// negation
+//
+// Performs a compile-time logical NOT operation on the passed type (which
+// must have  `::value` members convertible to `bool`.
+//
+// This metafunction is designed to be a drop-in replacement for the C++17
+// `std::negation` metafunction.
+template <typename T>
+struct negation : std::integral_constant<bool, !T::value> {};
+
+// is_function()
+//
+// Determines whether the passed type `T` is a function type.
+//
+// This metafunction is designed to be a drop-in replacement for the C++11
+// `std::is_function()` metafunction for platforms that have incomplete C++11
+// support (such as libstdc++ 4.x).
+//
+// This metafunction works because appending `const` to a type does nothing to
+// function types and reference types (and forms a const-qualified type
+// otherwise).
+template <typename T>
+struct is_function
+    : std::integral_constant<
+          bool, !(std::is_reference<T>::value ||
+                  std::is_const<typename std::add_const<T>::type>::value)> {};
+
+// is_trivially_destructible()
+//
+// Determines whether the passed type `T` is trivially destructible.
+//
+// This metafunction is designed to be a drop-in replacement for the C++11
+// `std::is_trivially_destructible()` metafunction for platforms that have
+// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
+// fully support C++11, we check whether this yields the same result as the std
+// implementation.
+//
+// NOTE: the extensions (__has_trivial_xxx) are implemented in gcc (version >=
+// 4.3) and clang. Since we are supporting libstdc++ > 4.7, they should always
+// be present. These  extensions are documented at
+// https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html#Type-Traits.
+template <typename T>
+struct is_trivially_destructible
+#ifdef OTABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
+    : std::is_trivially_destructible<T> {
+#else
+    : std::integral_constant<bool, __has_trivial_destructor(T) &&
+                                   std::is_destructible<T>::value> {
+#endif
+#ifdef OTABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
+ private:
+  static constexpr bool compliant = std::is_trivially_destructible<T>::value ==
+                                    is_trivially_destructible::value;
+  static_assert(compliant || std::is_trivially_destructible<T>::value,
+                "Not compliant with std::is_trivially_destructible; "
+                "Standard: false, Implementation: true");
+  static_assert(compliant || !std::is_trivially_destructible<T>::value,
+                "Not compliant with std::is_trivially_destructible; "
+                "Standard: true, Implementation: false");
+#endif  // OTABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
+};
+
+// is_trivially_default_constructible()
+//
+// Determines whether the passed type `T` is trivially default constructible.
+//
+// This metafunction is designed to be a drop-in replacement for the C++11
+// `std::is_trivially_default_constructible()` metafunction for platforms that
+// have incomplete C++11 support (such as libstdc++ 4.x). On any platforms that
+// do fully support C++11, we check whether this yields the same result as the
+// std implementation.
+//
+// NOTE: according to the C++ standard, Section: 20.15.4.3 [meta.unary.prop]
+// "The predicate condition for a template specialization is_constructible<T,
+// Args...> shall be satisfied if and only if the following variable
+// definition would be well-formed for some invented variable t:
+//
+// T t(declval<Args>()...);
+//
+// is_trivially_constructible<T, Args...> additionally requires that the
+// variable definition does not call any operation that is not trivial.
+// For the purposes of this check, the call to std::declval is considered
+// trivial."
+//
+// Notes from https://en.cppreference.com/w/cpp/types/is_constructible:
+// In many implementations, is_nothrow_constructible also checks if the
+// destructor throws because it is effectively noexcept(T(arg)). Same
+// applies to is_trivially_constructible, which, in these implementations, also
+// requires that the destructor is trivial.
+// GCC bug 51452: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452
+// LWG issue 2116: http://cplusplus.github.io/LWG/lwg-active.html#2116.
+//
+// "T obj();" need to be well-formed and not call any nontrivial operation.
+// Nontrivially destructible types will cause the expression to be nontrivial.
+template <typename T>
+struct is_trivially_default_constructible
+#if defined(OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE)
+    : std::is_trivially_default_constructible<T> {
+#else
+    : std::integral_constant<bool, __has_trivial_constructor(T) &&
+                                   std::is_default_constructible<T>::value &&
+                                   is_trivially_destructible<T>::value> {
+#endif
+#if defined(OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
+    !defined(                                            \
+        OTABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
+ private:
+  static constexpr bool compliant =
+      std::is_trivially_default_constructible<T>::value ==
+      is_trivially_default_constructible::value;
+  static_assert(compliant || std::is_trivially_default_constructible<T>::value,
+                "Not compliant with std::is_trivially_default_constructible; "
+                "Standard: false, Implementation: true");
+  static_assert(compliant || !std::is_trivially_default_constructible<T>::value,
+                "Not compliant with std::is_trivially_default_constructible; "
+                "Standard: true, Implementation: false");
+#endif  // OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
+};
+
+// is_trivially_move_constructible()
+//
+// Determines whether the passed type `T` is trivially move constructible.
+//
+// This metafunction is designed to be a drop-in replacement for the C++11
+// `std::is_trivially_move_constructible()` metafunction for platforms that have
+// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
+// fully support C++11, we check whether this yields the same result as the std
+// implementation.
+//
+// NOTE: `T obj(declval<T>());` needs to be well-formed and not call any
+// nontrivial operation.  Nontrivially destructible types will cause the
+// expression to be nontrivial.
+template <typename T>
+struct is_trivially_move_constructible
+#if defined(OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE)
+    : std::is_trivially_move_constructible<T> {
+#else
+    : std::conditional<
+          std::is_object<T>::value && !std::is_array<T>::value,
+          type_traits_internal::IsTriviallyMoveConstructibleObject<T>,
+          std::is_reference<T>>::type::type {
+#endif
+#if defined(OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
+    !defined(                                            \
+        OTABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
+ private:
+  static constexpr bool compliant =
+      std::is_trivially_move_constructible<T>::value ==
+      is_trivially_move_constructible::value;
+  static_assert(compliant || std::is_trivially_move_constructible<T>::value,
+                "Not compliant with std::is_trivially_move_constructible; "
+                "Standard: false, Implementation: true");
+  static_assert(compliant || !std::is_trivially_move_constructible<T>::value,
+                "Not compliant with std::is_trivially_move_constructible; "
+                "Standard: true, Implementation: false");
+#endif  // OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
+};
+
+// is_trivially_copy_constructible()
+//
+// Determines whether the passed type `T` is trivially copy constructible.
+//
+// This metafunction is designed to be a drop-in replacement for the C++11
+// `std::is_trivially_copy_constructible()` metafunction for platforms that have
+// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
+// fully support C++11, we check whether this yields the same result as the std
+// implementation.
+//
+// NOTE: `T obj(declval<const T&>());` needs to be well-formed and not call any
+// nontrivial operation.  Nontrivially destructible types will cause the
+// expression to be nontrivial.
+template <typename T>
+struct is_trivially_copy_constructible
+    : std::conditional<
+          std::is_object<T>::value && !std::is_array<T>::value,
+          type_traits_internal::IsTriviallyCopyConstructibleObject<T>,
+          std::is_lvalue_reference<T>>::type::type {
+#if defined(OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
+    !defined(                                            \
+        OTABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
+ private:
+  static constexpr bool compliant =
+      std::is_trivially_copy_constructible<T>::value ==
+      is_trivially_copy_constructible::value;
+  static_assert(compliant || std::is_trivially_copy_constructible<T>::value,
+                "Not compliant with std::is_trivially_copy_constructible; "
+                "Standard: false, Implementation: true");
+  static_assert(compliant || !std::is_trivially_copy_constructible<T>::value,
+                "Not compliant with std::is_trivially_copy_constructible; "
+                "Standard: true, Implementation: false");
+#endif  // OTABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
+};
+
+// is_trivially_move_assignable()
+//
+// Determines whether the passed type `T` is trivially move assignable.
+//
+// This metafunction is designed to be a drop-in replacement for the C++11
+// `std::is_trivially_move_assignable()` metafunction for platforms that have
+// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
+// fully support C++11, we check whether this yields the same result as the std
+// implementation.
+//
+// NOTE: `is_assignable<T, U>::value` is `true` if the expression
+// `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated
+// operand. `is_trivially_assignable<T, U>` requires the assignment to call no
+// operation that is not trivial. `is_trivially_copy_assignable<T>` is simply
+// `is_trivially_assignable<T&, T>`.
+template <typename T>
+struct is_trivially_move_assignable
+    : std::conditional<
+          std::is_object<T>::value && !std::is_array<T>::value &&
+              std::is_move_assignable<T>::value,
+          std::is_move_assignable<type_traits_internal::SingleMemberUnion<T>>,
+          type_traits_internal::IsTriviallyMoveAssignableReference<T>>::type::
+          type {
+#ifdef OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
+ private:
+  static constexpr bool compliant =
+      std::is_trivially_move_assignable<T>::value ==
+      is_trivially_move_assignable::value;
+  static_assert(compliant || std::is_trivially_move_assignable<T>::value,
+                "Not compliant with std::is_trivially_move_assignable; "
+                "Standard: false, Implementation: true");
+  static_assert(compliant || !std::is_trivially_move_assignable<T>::value,
+                "Not compliant with std::is_trivially_move_assignable; "
+                "Standard: true, Implementation: false");
+#endif  // OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
+};
+
+// is_trivially_copy_assignable()
+//
+// Determines whether the passed type `T` is trivially copy assignable.
+//
+// This metafunction is designed to be a drop-in replacement for the C++11
+// `std::is_trivially_copy_assignable()` metafunction for platforms that have
+// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
+// fully support C++11, we check whether this yields the same result as the std
+// implementation.
+//
+// NOTE: `is_assignable<T, U>::value` is `true` if the expression
+// `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated
+// operand. `is_trivially_assignable<T, U>` requires the assignment to call no
+// operation that is not trivial. `is_trivially_copy_assignable<T>` is simply
+// `is_trivially_assignable<T&, const T&>`.
+template <typename T>
+struct is_trivially_copy_assignable
+#ifdef OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
+    : std::is_trivially_copy_assignable<T> {
+#else
+    : std::integral_constant<
+          bool, __has_trivial_assign(typename std::remove_reference<T>::type) &&
+                    absl::OTABSL_OPTION_NAMESPACE_NAME::is_copy_assignable<T>::value> {
+#endif
+#ifdef OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
+ private:
+  static constexpr bool compliant =
+      std::is_trivially_copy_assignable<T>::value ==
+      is_trivially_copy_assignable::value;
+  static_assert(compliant || std::is_trivially_copy_assignable<T>::value,
+                "Not compliant with std::is_trivially_copy_assignable; "
+                "Standard: false, Implementation: true");
+  static_assert(compliant || !std::is_trivially_copy_assignable<T>::value,
+                "Not compliant with std::is_trivially_copy_assignable; "
+                "Standard: true, Implementation: false");
+#endif  // OTABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
+};
+
+namespace type_traits_internal {
+// is_trivially_copyable()
+//
+// Determines whether the passed type `T` is trivially copyable.
+//
+// This metafunction is designed to be a drop-in replacement for the C++11
+// `std::is_trivially_copyable()` metafunction for platforms that have
+// incomplete C++11 support (such as libstdc++ 4.x). We use the C++17 definition
+// of TriviallyCopyable.
+//
+// NOTE: `is_trivially_copyable<T>::value` is `true` if all of T's copy/move
+// constructors/assignment operators are trivial or deleted, T has at least
+// one non-deleted copy/move constructor/assignment operator, and T is trivially
+// destructible. Arrays of trivially copyable types are trivially copyable.
+//
+// We expose this metafunction only for internal use within absl.
+
+#if defined(OTABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE)
+template <typename T>
+struct is_trivially_copyable : std::is_trivially_copyable<T> {};
+#else
+template <typename T>
+class is_trivially_copyable_impl {
+  using ExtentsRemoved = typename std::remove_all_extents<T>::type;
+  static constexpr bool kIsCopyOrMoveConstructible =
+      std::is_copy_constructible<ExtentsRemoved>::value ||
+      std::is_move_constructible<ExtentsRemoved>::value;
+  static constexpr bool kIsCopyOrMoveAssignable =
+      absl::OTABSL_OPTION_NAMESPACE_NAME::is_copy_assignable<ExtentsRemoved>::value ||
+      absl::OTABSL_OPTION_NAMESPACE_NAME::is_move_assignable<ExtentsRemoved>::value;
+
+ public:
+  static constexpr bool kValue =
+      (__has_trivial_copy(ExtentsRemoved) || !kIsCopyOrMoveConstructible) &&
+      (__has_trivial_assign(ExtentsRemoved) || !kIsCopyOrMoveAssignable) &&
+      (kIsCopyOrMoveConstructible || kIsCopyOrMoveAssignable) &&
+      is_trivially_destructible<ExtentsRemoved>::value &&
+      // We need to check for this explicitly because otherwise we'll say
+      // references are trivial copyable when compiled by MSVC.
+      !std::is_reference<ExtentsRemoved>::value;
+};
+
+template <typename T>
+struct is_trivially_copyable
+    : std::integral_constant<
+          bool, type_traits_internal::is_trivially_copyable_impl<T>::kValue> {};
+#endif
+}  // namespace type_traits_internal
+
+// -----------------------------------------------------------------------------
+// C++14 "_t" trait aliases
+// -----------------------------------------------------------------------------
+
+template <typename T>
+using remove_cv_t = typename std::remove_cv<T>::type;
+
+template <typename T>
+using remove_const_t = typename std::remove_const<T>::type;
+
+template <typename T>
+using remove_volatile_t = typename std::remove_volatile<T>::type;
+
+template <typename T>
+using add_cv_t = typename std::add_cv<T>::type;
+
+template <typename T>
+using add_const_t = typename std::add_const<T>::type;
+
+template <typename T>
+using add_volatile_t = typename std::add_volatile<T>::type;
+
+template <typename T>
+using remove_reference_t = typename std::remove_reference<T>::type;
+
+template <typename T>
+using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type;
+
+template <typename T>
+using add_rvalue_reference_t = typename std::add_rvalue_reference<T>::type;
+
+template <typename T>
+using remove_pointer_t = typename std::remove_pointer<T>::type;
+
+template <typename T>
+using add_pointer_t = typename std::add_pointer<T>::type;
+
+template <typename T>
+using make_signed_t = typename std::make_signed<T>::type;
+
+template <typename T>
+using make_unsigned_t = typename std::make_unsigned<T>::type;
+
+template <typename T>
+using remove_extent_t = typename std::remove_extent<T>::type;
+
+template <typename T>
+using remove_all_extents_t = typename std::remove_all_extents<T>::type;
+
+template <typename T>
+using decay_t = typename std::decay<T>::type;
+
+template <bool B, typename T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+template <bool B, typename T, typename F>
+using conditional_t = typename std::conditional<B, T, F>::type;
+
+template <typename... T>
+using common_type_t = typename std::common_type<T...>::type;
+
+template <typename T>
+using underlying_type_t = typename std::underlying_type<T>::type;
+
+namespace type_traits_internal {
+
+#if (!defined(_MSVC_LANG) && (__cplusplus >= 201703L)) || \
+    (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))
+// std::result_of is deprecated (C++17) or removed (C++20)
+template<typename> struct result_of;
+template<typename F, typename... Args>
+struct result_of<F(Args...)> : std::invoke_result<F, Args...> {};
+#else
+template<typename F> using result_of = std::result_of<F>;
+#endif
+
+}  // namespace type_traits_internal
+
+template<typename F>
+using result_of_t = typename type_traits_internal::result_of<F>::type;
+
+namespace type_traits_internal {
+// In MSVC we can't probe std::hash or stdext::hash because it triggers a
+// static_assert instead of failing substitution. Libc++ prior to 4.0
+// also used a static_assert.
+//
+#if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
+                          _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
+#define OTABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0
+#else
+#define OTABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1
+#endif
+
+#if !OTABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+template <typename Key, typename = size_t>
+struct IsHashable : std::true_type {};
+#else   // OTABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+template <typename Key, typename = void>
+struct IsHashable : std::false_type {};
+
+template <typename Key>
+struct IsHashable<
+    Key,
+    absl::OTABSL_OPTION_NAMESPACE_NAME::enable_if_t<std::is_convertible<
+        decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())),
+        std::size_t>::value>> : std::true_type {};
+#endif  // !OTABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+
+struct AssertHashEnabledHelper {
+ private:
+  static void Sink(...) {}
+  struct NAT {};
+
+  template <class Key>
+  static auto GetReturnType(int)
+      -> decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>()));
+  template <class Key>
+  static NAT GetReturnType(...);
+
+  template <class Key>
+  static std::nullptr_t DoIt() {
+    static_assert(IsHashable<Key>::value,
+                  "std::hash<Key> does not provide a call operator");
+    static_assert(
+        std::is_default_constructible<std::hash<Key>>::value,
+        "std::hash<Key> must be default constructible when it is enabled");
+    static_assert(
+        std::is_copy_constructible<std::hash<Key>>::value,
+        "std::hash<Key> must be copy constructible when it is enabled");
+    static_assert(absl::OTABSL_OPTION_NAMESPACE_NAME::is_copy_assignable<std::hash<Key>>::value,
+                  "std::hash<Key> must be copy assignable when it is enabled");
+    // is_destructible is unchecked as it's implied by each of the
+    // is_constructible checks.
+    using ReturnType = decltype(GetReturnType<Key>(0));
+    static_assert(std::is_same<ReturnType, NAT>::value ||
+                      std::is_same<ReturnType, size_t>::value,
+                  "std::hash<Key> must return size_t");
+    return nullptr;
+  }
+
+  template <class... Ts>
+  friend void AssertHashEnabled();
+};
+
+template <class... Ts>
+inline void AssertHashEnabled() {
+  using Helper = AssertHashEnabledHelper;
+  Helper::Sink(Helper::DoIt<Ts>()...);
+}
+
+}  // namespace type_traits_internal
+
+// An internal namespace that is required to implement the C++17 swap traits.
+// It is not further nested in type_traits_internal to avoid long symbol names.
+namespace swap_internal {
+
+// Necessary for the traits.
+using std::swap;
+
+// This declaration prevents global `swap` and `absl::OTABSL_OPTION_NAMESPACE_NAME::swap` overloads from being
+// considered unless ADL picks them up.
+void swap();
+
+template <class T>
+using IsSwappableImpl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
+
+// NOTE: This dance with the default template parameter is for MSVC.
+template <class T,
+          class IsNoexcept = std::integral_constant<
+              bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))>>
+using IsNothrowSwappableImpl = typename std::enable_if<IsNoexcept::value>::type;
+
+// IsSwappable
+//
+// Determines whether the standard swap idiom is a valid expression for
+// arguments of type `T`.
+template <class T>
+struct IsSwappable
+    : absl::OTABSL_OPTION_NAMESPACE_NAME::type_traits_internal::is_detected<IsSwappableImpl, T> {};
+
+// IsNothrowSwappable
+//
+// Determines whether the standard swap idiom is a valid expression for
+// arguments of type `T` and is noexcept.
+template <class T>
+struct IsNothrowSwappable
+    : absl::OTABSL_OPTION_NAMESPACE_NAME::type_traits_internal::is_detected<IsNothrowSwappableImpl, T> {};
+
+// Swap()
+//
+// Performs the swap idiom from a namespace where valid candidates may only be
+// found in `std` or via ADL.
+template <class T, absl::OTABSL_OPTION_NAMESPACE_NAME::enable_if_t<IsSwappable<T>::value, int> = 0>
+void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable<T>::value) {
+  swap(lhs, rhs);
+}
+
+// StdSwapIsUnconstrained
+//
+// Some standard library implementations are broken in that they do not
+// constrain `std::swap`. This will effectively tell us if we are dealing with
+// one of those implementations.
+using StdSwapIsUnconstrained = IsSwappable<void()>;
+
+}  // namespace swap_internal
+
+namespace type_traits_internal {
+
+// Make the swap-related traits/function accessible from this namespace.
+using swap_internal::IsNothrowSwappable;
+using swap_internal::IsSwappable;
+using swap_internal::Swap;
+using swap_internal::StdSwapIsUnconstrained;
+
+}  // namespace type_traits_internal
+OTABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // OTABSL_META_TYPE_TRAITS_H_

+ 94 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/types/bad_variant_access.h

@@ -0,0 +1,94 @@
+// Copyright 2018 The Abseil 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
+//
+//      https://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.
+//
+// -----------------------------------------------------------------------------
+// bad_variant_access.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the `absl::OTABSL_OPTION_NAMESPACE_NAME::bad_variant_access` type.
+
+#ifndef OTABSL_TYPES_BAD_VARIANT_ACCESS_H_
+#define OTABSL_TYPES_BAD_VARIANT_ACCESS_H_
+
+#include <stdexcept>
+
+#include "../base/config.h"
+
+#ifdef OTABSL_USES_STD_VARIANT
+
+#include <variant>
+
+namespace absl {
+OTABSL_NAMESPACE_BEGIN
+using std::bad_variant_access;
+OTABSL_NAMESPACE_END
+}  // namespace absl
+
+#else  // OTABSL_USES_STD_VARIANT
+
+namespace absl {
+OTABSL_NAMESPACE_BEGIN
+
+// -----------------------------------------------------------------------------
+// bad_variant_access
+// -----------------------------------------------------------------------------
+//
+// An `absl::OTABSL_OPTION_NAMESPACE_NAME::bad_variant_access` type is an exception type that is thrown in
+// the following cases:
+//
+//   * Calling `absl::OTABSL_OPTION_NAMESPACE_NAME::get(absl::OTABSL_OPTION_NAMESPACE_NAME::variant) with an index or type that does not
+//     match the currently selected alternative type
+//   * Calling `absl::OTABSL_OPTION_NAMESPACE_NAME::visit on an `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` that is in the
+//     `variant::valueless_by_exception` state.
+//
+// Example:
+//
+//   absl::OTABSL_OPTION_NAMESPACE_NAME::variant<int, std::string> v;
+//   v = 1;
+//   try {
+//     absl::OTABSL_OPTION_NAMESPACE_NAME::get<std::string>(v);
+//   } catch(const absl::OTABSL_OPTION_NAMESPACE_NAME::bad_variant_access& e) {
+//     std::cout << "Bad variant access: " << e.what() << '\n';
+//   }
+class bad_variant_access : public std::exception {
+ public:
+  bad_variant_access() noexcept = default;
+  ~bad_variant_access() override;
+  const char* what() const noexcept override;
+};
+
+namespace variant_internal {
+#ifdef THROW_BAD_VARIANT_ACCESS
+// Header-only implementation with static throw implementation.
+// No need to link against Abseil library.
+[[noreturn]] static inline void ThrowBadVariantAccess()
+{
+  THROW_BAD_VARIANT_ACCESS;
+}
+//[[noreturn]] static inline void Rethrow()
+//{
+//  THROW_BAD_VARIANT_ACCESS; // Unused!
+//};
+#else
+// Original implementation requires linking Abseil library!
+[[noreturn]] void ThrowBadVariantAccess();
+[[noreturn]] void Rethrow();
+#endif
+}  // namespace variant_internal
+OTABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // OTABSL_USES_STD_VARIANT
+
+#endif  // OTABSL_TYPES_BAD_VARIANT_ACCESS_H_

+ 1649 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/types/internal/variant.h

@@ -0,0 +1,1649 @@
+// Copyright 2018 The Abseil 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
+//
+//      https://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.
+//
+// Implementation details of absl/types/variant.h, pulled into a
+// separate file to avoid cluttering the top of the API header with
+// implementation details.
+
+#ifndef OTABSL_TYPES_variant_internal_H_
+#define OTABSL_TYPES_variant_internal_H_
+
+#include <cassert>
+#include <cstddef>
+#include <cstdlib>
+#include <memory>
+#include <stdexcept>
+#include <tuple>
+#include <type_traits>
+
+#include "../../base/config.h"
+#include "../../base/internal/identity.h"
+#include "../../base/internal/inline_variable.h"
+#include "../../base/internal/invoke.h"
+#include "../../base/macros.h"
+#include "../../base/optimization.h"
+#include "../../meta/type_traits.h"
+#include "../../types/bad_variant_access.h"
+#include "../../utility/utility.h"
+
+#if !defined(OTABSL_USES_STD_VARIANT)
+
+namespace absl {
+OTABSL_NAMESPACE_BEGIN
+
+template <class... Types>
+class variant;
+
+OTABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1);
+
+template <class T>
+struct variant_size;
+
+template <std::size_t I, class T>
+struct variant_alternative;
+
+namespace variant_internal {
+
+// NOTE: See specializations below for details.
+template <std::size_t I, class T>
+struct VariantAlternativeSfinae {};
+
+// Requires: I < variant_size_v<T>.
+//
+// Value: The Ith type of Types...
+template <std::size_t I, class T0, class... Tn>
+struct VariantAlternativeSfinae<I, variant<T0, Tn...>>
+    : VariantAlternativeSfinae<I - 1, variant<Tn...>> {};
+
+// Value: T0
+template <class T0, class... Ts>
+struct VariantAlternativeSfinae<0, variant<T0, Ts...>> {
+  using type = T0;
+};
+
+template <std::size_t I, class T>
+using VariantAlternativeSfinaeT = typename VariantAlternativeSfinae<I, T>::type;
+
+// NOTE: Requires T to be a reference type.
+template <class T, class U>
+struct GiveQualsTo;
+
+template <class T, class U>
+struct GiveQualsTo<T&, U> {
+  using type = U&;
+};
+
+template <class T, class U>
+struct GiveQualsTo<T&&, U> {
+  using type = U&&;
+};
+
+template <class T, class U>
+struct GiveQualsTo<const T&, U> {
+  using type = const U&;
+};
+
+template <class T, class U>
+struct GiveQualsTo<const T&&, U> {
+  using type = const U&&;
+};
+
+template <class T, class U>
+struct GiveQualsTo<volatile T&, U> {
+  using type = volatile U&;
+};
+
+template <class T, class U>
+struct GiveQualsTo<volatile T&&, U> {
+  using type = volatile U&&;
+};
+
+template <class T, class U>
+struct GiveQualsTo<volatile const T&, U> {
+  using type = volatile const U&;
+};
+
+template <class T, class U>
+struct GiveQualsTo<volatile const T&&, U> {
+  using type = volatile const U&&;
+};
+
+template <class T, class U>
+using GiveQualsToT = typename GiveQualsTo<T, U>::type;
+
+// Convenience alias, since size_t integral_constant is used a lot in this file.
+template <std::size_t I>
+using SizeT = std::integral_constant<std::size_t, I>;
+
+using NPos = SizeT<variant_npos>;
+
+template <class Variant, class T, class = void>
+struct IndexOfConstructedType {};
+
+template <std::size_t I, class Variant>
+struct VariantAccessResultImpl;
+
+template <std::size_t I, template <class...> class Variantemplate, class... T>
+struct VariantAccessResultImpl<I, Variantemplate<T...>&> {
+  using type = typename absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative<I, variant<T...>>::type&;
+};
+
+template <std::size_t I, template <class...> class Variantemplate, class... T>
+struct VariantAccessResultImpl<I, const Variantemplate<T...>&> {
+  using type =
+      const typename absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative<I, variant<T...>>::type&;
+};
+
+template <std::size_t I, template <class...> class Variantemplate, class... T>
+struct VariantAccessResultImpl<I, Variantemplate<T...>&&> {
+  using type = typename absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative<I, variant<T...>>::type&&;
+};
+
+template <std::size_t I, template <class...> class Variantemplate, class... T>
+struct VariantAccessResultImpl<I, const Variantemplate<T...>&&> {
+  using type =
+      const typename absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative<I, variant<T...>>::type&&;
+};
+
+template <std::size_t I, class Variant>
+using VariantAccessResult =
+    typename VariantAccessResultImpl<I, Variant&&>::type;
+
+// NOTE: This is used instead of std::array to reduce instantiation overhead.
+template <class T, std::size_t Size>
+struct SimpleArray {
+  static_assert(Size != 0, "");
+  T value[Size];
+};
+
+template <class T>
+struct AccessedType {
+  using type = T;
+};
+
+template <class T>
+using AccessedTypeT = typename AccessedType<T>::type;
+
+template <class T, std::size_t Size>
+struct AccessedType<SimpleArray<T, Size>> {
+  using type = AccessedTypeT<T>;
+};
+
+template <class T>
+constexpr T AccessSimpleArray(const T& value) {
+  return value;
+}
+
+template <class T, std::size_t Size, class... SizeT>
+constexpr AccessedTypeT<T> AccessSimpleArray(const SimpleArray<T, Size>& table,
+                                             std::size_t head_index,
+                                             SizeT... tail_indices) {
+  return AccessSimpleArray(table.value[head_index], tail_indices...);
+}
+
+// Note: Intentionally is an alias.
+template <class T>
+using AlwaysZero = SizeT<0>;
+
+template <class Op, class... Vs>
+struct VisitIndicesResultImpl {
+  using type = absl::OTABSL_OPTION_NAMESPACE_NAME::result_of_t<Op(AlwaysZero<Vs>...)>;
+};
+
+template <class Op, class... Vs>
+using VisitIndicesResultT = typename VisitIndicesResultImpl<Op, Vs...>::type;
+
+template <class ReturnType, class FunctionObject, class EndIndices,
+          class BoundIndices>
+struct MakeVisitationMatrix;
+
+template <class ReturnType, class FunctionObject, std::size_t... Indices>
+constexpr ReturnType call_with_indices(FunctionObject&& function) {
+  static_assert(
+      std::is_same<ReturnType, decltype(std::declval<FunctionObject>()(
+                                   SizeT<Indices>()...))>::value,
+      "Not all visitation overloads have the same return type.");
+  return absl::OTABSL_OPTION_NAMESPACE_NAME::forward<FunctionObject>(function)(SizeT<Indices>()...);
+}
+
+template <class ReturnType, class FunctionObject, std::size_t... BoundIndices>
+struct MakeVisitationMatrix<ReturnType, FunctionObject, index_sequence<>,
+                            index_sequence<BoundIndices...>> {
+  using ResultType = ReturnType (*)(FunctionObject&&);
+  // cppcheck-suppress [duplInheritedMember]
+  static constexpr ResultType Run() {
+    return &call_with_indices<ReturnType, FunctionObject,
+                              (BoundIndices - 1)...>;
+  }
+};
+
+template <typename Is, std::size_t J>
+struct AppendToIndexSequence;
+
+template <typename Is, std::size_t J>
+using AppendToIndexSequenceT = typename AppendToIndexSequence<Is, J>::type;
+
+template <std::size_t... Is, std::size_t J>
+struct AppendToIndexSequence<index_sequence<Is...>, J> {
+  using type = index_sequence<Is..., J>;
+};
+
+template <class ReturnType, class FunctionObject, class EndIndices,
+          class CurrIndices, class BoundIndices>
+struct MakeVisitationMatrixImpl;
+
+template <class ReturnType, class FunctionObject, class EndIndices,
+          std::size_t... CurrIndices, class BoundIndices>
+struct MakeVisitationMatrixImpl<ReturnType, FunctionObject, EndIndices,
+                                index_sequence<CurrIndices...>, BoundIndices> {
+  using ResultType = SimpleArray<
+      typename MakeVisitationMatrix<ReturnType, FunctionObject, EndIndices,
+                                    index_sequence<>>::ResultType,
+      sizeof...(CurrIndices)>;
+
+  static constexpr ResultType Run() {
+    return {{MakeVisitationMatrix<
+        ReturnType, FunctionObject, EndIndices,
+        AppendToIndexSequenceT<BoundIndices, CurrIndices>>::Run()...}};
+  }
+};
+
+template <class ReturnType, class FunctionObject, std::size_t HeadEndIndex,
+          std::size_t... TailEndIndices, std::size_t... BoundIndices>
+struct MakeVisitationMatrix<ReturnType, FunctionObject,
+                            index_sequence<HeadEndIndex, TailEndIndices...>,
+                            index_sequence<BoundIndices...>>
+    : MakeVisitationMatrixImpl<ReturnType, FunctionObject,
+                               index_sequence<TailEndIndices...>,
+                               absl::OTABSL_OPTION_NAMESPACE_NAME::make_index_sequence<HeadEndIndex>,
+                               index_sequence<BoundIndices...>> {};
+
+struct UnreachableSwitchCase {
+  template <class Op>
+  [[noreturn]] static VisitIndicesResultT<Op, std::size_t> Run(
+      Op&& /*ignored*/) {
+#if OTABSL_HAVE_BUILTIN(__builtin_unreachable) || \
+    (defined(__GNUC__) && !defined(__clang__))
+    __builtin_unreachable();
+#elif defined(_MSC_VER)
+    __assume(false);
+#else
+    // Try to use assert of false being identified as an unreachable intrinsic.
+    // NOTE: We use assert directly to increase chances of exploiting an assume
+    //       intrinsic.
+    assert(false);  // NOLINT
+
+    // Hack to silence potential no return warning -- cause an infinite loop.
+    return Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+#endif  // Checks for __builtin_unreachable
+  }
+};
+
+template <class Op, std::size_t I>
+struct ReachableSwitchCase {
+  static VisitIndicesResultT<Op, std::size_t> Run(Op&& op) {
+    return absl::OTABSL_OPTION_NAMESPACE_NAME::base_internal::Invoke(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op), SizeT<I>());
+  }
+};
+
+// The number 33 is just a guess at a reasonable maximum to our switch. It is
+// not based on any analysis. The reason it is a power of 2 plus 1 instead of a
+// power of 2 is because the number was picked to correspond to a power of 2
+// amount of "normal" alternatives, plus one for the possibility of the user
+// providing "monostate" in addition to the more natural alternatives.
+OTABSL_INTERNAL_INLINE_CONSTEXPR(std::size_t, MaxUnrolledVisitCases, 33);
+
+// Note: The default-definition is for unreachable cases.
+template <bool IsReachable>
+struct PickCaseImpl {
+  template <class Op, std::size_t I>
+  using Apply = UnreachableSwitchCase;
+};
+
+template <>
+struct PickCaseImpl</*IsReachable =*/true> {
+  template <class Op, std::size_t I>
+  using Apply = ReachableSwitchCase<Op, I>;
+};
+
+// Note: This form of dance with template aliases is to make sure that we
+//       instantiate a number of templates proportional to the number of variant
+//       alternatives rather than a number of templates proportional to our
+//       maximum unrolled amount of visitation cases (aliases are effectively
+//       "free" whereas other template instantiations are costly).
+template <class Op, std::size_t I, std::size_t EndIndex>
+using PickCase = typename PickCaseImpl<(I < EndIndex)>::template Apply<Op, I>;
+
+template <class ReturnType>
+[[noreturn]] ReturnType TypedThrowBadVariantAccess() {
+  absl::OTABSL_OPTION_NAMESPACE_NAME::variant_internal::ThrowBadVariantAccess();
+}
+
+// Given N variant sizes, determine the number of cases there would need to be
+// in a single switch-statement that would cover every possibility in the
+// corresponding N-ary visit operation.
+template <std::size_t... NumAlternatives>
+struct NumCasesOfSwitch;
+
+template <std::size_t HeadNumAlternatives, std::size_t... TailNumAlternatives>
+struct NumCasesOfSwitch<HeadNumAlternatives, TailNumAlternatives...> {
+  static constexpr std::size_t value =
+      (HeadNumAlternatives + 1) *
+      NumCasesOfSwitch<TailNumAlternatives...>::value;
+};
+
+template <>
+struct NumCasesOfSwitch<> {
+  static constexpr std::size_t value = 1;
+};
+
+// A switch statement optimizes better than the table of function pointers.
+template <std::size_t EndIndex>
+struct VisitIndicesSwitch {
+  static_assert(EndIndex <= MaxUnrolledVisitCases,
+                "Maximum unrolled switch size exceeded.");
+
+  template <class Op>
+  static VisitIndicesResultT<Op, std::size_t> Run(Op&& op, std::size_t i) {
+    switch (i) {
+      case 0:
+        return PickCase<Op, 0, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 1:
+        return PickCase<Op, 1, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 2:
+        return PickCase<Op, 2, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 3:
+        return PickCase<Op, 3, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 4:
+        return PickCase<Op, 4, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 5:
+        return PickCase<Op, 5, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 6:
+        return PickCase<Op, 6, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 7:
+        return PickCase<Op, 7, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 8:
+        return PickCase<Op, 8, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 9:
+        return PickCase<Op, 9, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 10:
+        return PickCase<Op, 10, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 11:
+        return PickCase<Op, 11, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 12:
+        return PickCase<Op, 12, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 13:
+        return PickCase<Op, 13, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 14:
+        return PickCase<Op, 14, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 15:
+        return PickCase<Op, 15, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 16:
+        return PickCase<Op, 16, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 17:
+        return PickCase<Op, 17, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 18:
+        return PickCase<Op, 18, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 19:
+        return PickCase<Op, 19, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 20:
+        return PickCase<Op, 20, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 21:
+        return PickCase<Op, 21, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 22:
+        return PickCase<Op, 22, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 23:
+        return PickCase<Op, 23, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 24:
+        return PickCase<Op, 24, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 25:
+        return PickCase<Op, 25, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 26:
+        return PickCase<Op, 26, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 27:
+        return PickCase<Op, 27, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 28:
+        return PickCase<Op, 28, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 29:
+        return PickCase<Op, 29, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 30:
+        return PickCase<Op, 30, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 31:
+        return PickCase<Op, 31, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      case 32:
+        return PickCase<Op, 32, EndIndex>::Run(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+      default:
+        OTABSL_ASSERT(i == variant_npos);
+        return absl::OTABSL_OPTION_NAMESPACE_NAME::base_internal::Invoke(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op), NPos());
+    }
+  }
+};
+
+template <std::size_t... EndIndices>
+struct VisitIndicesFallback {
+  template <class Op, class... SizeT>
+  static VisitIndicesResultT<Op, SizeT...> Run(Op&& op, SizeT... indices) {
+    return AccessSimpleArray(
+        MakeVisitationMatrix<VisitIndicesResultT<Op, SizeT...>, Op,
+                             index_sequence<(EndIndices + 1)...>,
+                             index_sequence<>>::Run(),
+        (indices + 1)...)(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op));
+  }
+};
+
+// Take an N-dimensional series of indices and convert them into a single index
+// without loss of information. The purpose of this is to be able to convert an
+// N-ary visit operation into a single switch statement.
+template <std::size_t...>
+struct FlattenIndices;
+
+template <std::size_t HeadSize, std::size_t... TailSize>
+struct FlattenIndices<HeadSize, TailSize...> {
+  template<class... SizeType>
+  static constexpr std::size_t Run(std::size_t head, SizeType... tail) {
+    return head + HeadSize * FlattenIndices<TailSize...>::Run(tail...);
+  }
+};
+
+template <>
+struct FlattenIndices<> {
+  static constexpr std::size_t Run() { return 0; }
+};
+
+// Take a single "flattened" index (flattened by FlattenIndices) and determine
+// the value of the index of one of the logically represented dimensions.
+template <std::size_t I, std::size_t IndexToGet, std::size_t HeadSize,
+          std::size_t... TailSize>
+struct UnflattenIndex {
+  static constexpr std::size_t value =
+      UnflattenIndex<I / HeadSize, IndexToGet - 1, TailSize...>::value;
+};
+
+template <std::size_t I, std::size_t HeadSize, std::size_t... TailSize>
+struct UnflattenIndex<I, 0, HeadSize, TailSize...> {
+  static constexpr std::size_t value = (I % HeadSize);
+};
+
+// The backend for converting an N-ary visit operation into a unary visit.
+template <class IndexSequence, std::size_t... EndIndices>
+struct VisitIndicesVariadicImpl;
+
+template <std::size_t... N, std::size_t... EndIndices>
+struct VisitIndicesVariadicImpl<absl::OTABSL_OPTION_NAMESPACE_NAME::index_sequence<N...>, EndIndices...> {
+  // A type that can take an N-ary function object and converts it to a unary
+  // function object that takes a single, flattened index, and "unflattens" it
+  // into its individual dimensions when forwarding to the wrapped object.
+  template <class Op>
+  struct FlattenedOp {
+    template <std::size_t I>
+    VisitIndicesResultT<Op, decltype(EndIndices)...> operator()(
+        SizeT<I> /*index*/) && {
+      return absl::OTABSL_OPTION_NAMESPACE_NAME::base_internal::Invoke(
+          absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op),
+          SizeT<UnflattenIndex<I, N, (EndIndices + 1)...>::value -
+                std::size_t{1}>()...);
+    }
+
+    Op&& op;
+  };
+
+  template <class Op, class... SizeType>
+  static VisitIndicesResultT<Op, decltype(EndIndices)...> Run(
+      Op&& op, SizeType... i) {
+    return VisitIndicesSwitch<NumCasesOfSwitch<EndIndices...>::value>::Run(
+        FlattenedOp<Op>{absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op)},
+        FlattenIndices<(EndIndices + std::size_t{1})...>::Run(
+            (i + std::size_t{1})...));
+  }
+};
+
+template <std::size_t... EndIndices>
+struct VisitIndicesVariadic
+    : VisitIndicesVariadicImpl<absl::OTABSL_OPTION_NAMESPACE_NAME::make_index_sequence<sizeof...(EndIndices)>,
+                               EndIndices...> {};
+
+// This implementation will flatten N-ary visit operations into a single switch
+// statement when the number of cases would be less than our maximum specified
+// switch-statement size.
+// TODO(calabrese)
+//   Based on benchmarks, determine whether the function table approach actually
+//   does optimize better than a chain of switch statements and possibly update
+//   the implementation accordingly. Also consider increasing the maximum switch
+//   size.
+template <std::size_t... EndIndices>
+struct VisitIndices
+    : absl::OTABSL_OPTION_NAMESPACE_NAME::conditional_t<(NumCasesOfSwitch<EndIndices...>::value <=
+                           MaxUnrolledVisitCases),
+                          VisitIndicesVariadic<EndIndices...>,
+                          VisitIndicesFallback<EndIndices...>> {};
+
+template <std::size_t EndIndex>
+struct VisitIndices<EndIndex>
+    : absl::OTABSL_OPTION_NAMESPACE_NAME::conditional_t<(EndIndex <= MaxUnrolledVisitCases),
+                          VisitIndicesSwitch<EndIndex>,
+                          VisitIndicesFallback<EndIndex>> {};
+
+// Suppress bogus warning on MSVC: MSVC complains that the `reinterpret_cast`
+// below is returning the address of a temporary or local object.
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4172)
+#endif  // _MSC_VER
+
+// TODO(calabrese) std::launder
+// TODO(calabrese) constexpr
+// NOTE: DO NOT REMOVE the `inline` keyword as it is necessary to work around a
+// MSVC bug. See https://github.com/abseil/abseil-cpp/issues/129 for details.
+template <class Self, std::size_t I>
+inline VariantAccessResult<I, Self> AccessUnion(Self&& self, SizeT<I> /*i*/) {
+  return reinterpret_cast<VariantAccessResult<I, Self>>(self);
+}
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif  // _MSC_VER
+
+template <class T>
+void DeducedDestroy(T& self) {  // NOLINT
+  self.~T();
+}
+
+// NOTE: This type exists as a single entity for variant and its bases to
+// befriend. It contains helper functionality that manipulates the state of the
+// variant, such as the implementation of things like assignment and emplace
+// operations.
+struct VariantCoreAccess {
+  template <class VariantType>
+  static typename VariantType::Variant& Derived(VariantType& self) {  // NOLINT
+    return static_cast<typename VariantType::Variant&>(self);
+  }
+
+  template <class VariantType>
+  static const typename VariantType::Variant& Derived(
+      const VariantType& self) {  // NOLINT
+    return static_cast<const typename VariantType::Variant&>(self);
+  }
+
+  template <class VariantType>
+  static void Destroy(VariantType& self) {  // NOLINT
+    Derived(self).destroy();
+    self.index_ = absl::OTABSL_OPTION_NAMESPACE_NAME::variant_npos;
+  }
+
+  template <class Variant>
+  static void SetIndex(Variant& self, std::size_t i) {  // NOLINT
+    self.index_ = i;
+  }
+
+  template <class Variant>
+  static void InitFrom(Variant& self, Variant&& other) {  // NOLINT
+    VisitIndices<absl::OTABSL_OPTION_NAMESPACE_NAME::variant_size<Variant>::value>::Run(
+        InitFromVisitor<Variant, Variant&&>{&self,
+                                            std::forward<Variant>(other)},
+        other.index());
+    self.index_ = other.index();
+  }
+
+  // Access a variant alternative, assuming the index is correct.
+  template <std::size_t I, class Variant>
+  static VariantAccessResult<I, Variant> Access(Variant&& self) {
+    // This cast instead of invocation of AccessUnion with an rvalue is a
+    // workaround for msvc. Without this there is a runtime failure when dealing
+    // with rvalues.
+    // TODO(calabrese) Reduce test case and find a simpler workaround.
+    return static_cast<VariantAccessResult<I, Variant>>(
+        variant_internal::AccessUnion(self.state_, SizeT<I>()));
+  }
+
+  // Access a variant alternative, throwing if the index is incorrect.
+  template <std::size_t I, class Variant>
+  static VariantAccessResult<I, Variant> CheckedAccess(Variant&& self) {
+    if (OTABSL_PREDICT_FALSE(self.index_ != I)) {
+      TypedThrowBadVariantAccess<VariantAccessResult<I, Variant>>();
+    }
+
+    return Access<I>(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Variant>(self));
+  }
+
+  // The implementation of the move-assignment operation for a variant.
+  template <class VType>
+  struct MoveAssignVisitor {
+    using DerivedType = typename VType::Variant;
+    template <std::size_t NewIndex>
+    void operator()(SizeT<NewIndex> /*new_i*/) const {
+      if (left->index_ == NewIndex) {
+        Access<NewIndex>(*left) = std::move(Access<NewIndex>(*right));
+      } else {
+        Derived(*left).template emplace<NewIndex>(
+            std::move(Access<NewIndex>(*right)));
+      }
+    }
+
+    void operator()(SizeT<absl::OTABSL_OPTION_NAMESPACE_NAME::variant_npos> /*new_i*/) const {
+      Destroy(*left);
+    }
+
+    VType* left;
+    VType* right;
+  };
+
+  template <class VType>
+  static MoveAssignVisitor<VType> MakeMoveAssignVisitor(VType* left,
+                                                        VType* other) {
+    return {left, other};
+  }
+
+  // The implementation of the assignment operation for a variant.
+  template <class VType>
+  struct CopyAssignVisitor {
+    using DerivedType = typename VType::Variant;
+    template <std::size_t NewIndex>
+    void operator()(SizeT<NewIndex> /*new_i*/) const {
+      using New =
+          typename absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative<NewIndex, DerivedType>::type;
+
+      if (left->index_ == NewIndex) {
+        Access<NewIndex>(*left) = Access<NewIndex>(*right);
+      } else if (std::is_nothrow_copy_constructible<New>::value ||
+                 !std::is_nothrow_move_constructible<New>::value) {
+        Derived(*left).template emplace<NewIndex>(Access<NewIndex>(*right));
+      } else {
+        Derived(*left) = DerivedType(Derived(*right));
+      }
+    }
+
+    void operator()(SizeT<absl::OTABSL_OPTION_NAMESPACE_NAME::variant_npos> /*new_i*/) const {
+      Destroy(*left);
+    }
+
+    VType* left;
+    const VType* right;
+  };
+
+  template <class VType>
+  static CopyAssignVisitor<VType> MakeCopyAssignVisitor(VType* left,
+                                                        const VType& other) {
+    return {left, &other};
+  }
+
+  // The implementation of conversion-assignment operations for variant.
+  template <class Left, class QualifiedNew>
+  struct ConversionAssignVisitor {
+    using NewIndex =
+        variant_internal::IndexOfConstructedType<Left, QualifiedNew>;
+
+    void operator()(SizeT<NewIndex::value> /*old_i*/
+                    ) const {
+      Access<NewIndex::value>(*left) = absl::OTABSL_OPTION_NAMESPACE_NAME::forward<QualifiedNew>(other);
+    }
+
+    template <std::size_t OldIndex>
+    void operator()(SizeT<OldIndex> /*old_i*/
+                    ) const {
+      using New =
+          typename absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative<NewIndex::value, Left>::type;
+      if (std::is_nothrow_constructible<New, QualifiedNew>::value ||
+          !std::is_nothrow_move_constructible<New>::value) {
+        left->template emplace<NewIndex::value>(
+            absl::OTABSL_OPTION_NAMESPACE_NAME::forward<QualifiedNew>(other));
+      } else {
+        // the standard says "equivalent to
+        // operator=(variant(std::forward<T>(t)))", but we use `emplace` here
+        // because the variant's move assignment operator could be deleted.
+        left->template emplace<NewIndex::value>(
+            New(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<QualifiedNew>(other)));
+      }
+    }
+
+    Left* left;
+    QualifiedNew&& other;
+  };
+
+  template <class Left, class QualifiedNew>
+  static ConversionAssignVisitor<Left, QualifiedNew>
+  MakeConversionAssignVisitor(Left* left, QualifiedNew&& qual) {
+    return {left, absl::OTABSL_OPTION_NAMESPACE_NAME::forward<QualifiedNew>(qual)};
+  }
+
+  // Backend for operations for `emplace()` which destructs `*self` then
+  // construct a new alternative with `Args...`.
+  template <std::size_t NewIndex, class Self, class... Args>
+  static typename absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative<NewIndex, Self>::type& Replace(
+      Self* self, Args&&... args) {
+    Destroy(*self);
+    using New = typename absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative<NewIndex, Self>::type;
+    // cppcheck-suppress [legacyUninitvar]
+    New* const result = ::new (static_cast<void*>(&self->state_))
+        New(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Args>(args)...);
+    self->index_ = NewIndex;
+    return *result;
+  }
+
+  template <class LeftVariant, class QualifiedRightVariant>
+  struct InitFromVisitor {
+    template <std::size_t NewIndex>
+    void operator()(SizeT<NewIndex> /*new_i*/) const {
+      using Alternative =
+          typename variant_alternative<NewIndex, LeftVariant>::type;
+      ::new (static_cast<void*>(&left->state_)) Alternative(
+          Access<NewIndex>(std::forward<QualifiedRightVariant>(right)));
+    }
+
+    void operator()(SizeT<absl::OTABSL_OPTION_NAMESPACE_NAME::variant_npos> /*new_i*/) const {
+      // This space intentionally left blank.
+    }
+    LeftVariant* left;
+    QualifiedRightVariant&& right;
+  };
+};
+
+template <class Expected, class... T>
+struct IndexOfImpl;
+
+template <class Expected>
+struct IndexOfImpl<Expected> {
+  using IndexFromEnd = SizeT<0>;
+  using MatchedIndexFromEnd = IndexFromEnd;
+  using MultipleMatches = std::false_type;
+};
+
+template <class Expected, class Head, class... Tail>
+struct IndexOfImpl<Expected, Head, Tail...> : IndexOfImpl<Expected, Tail...> {
+  using IndexFromEnd =
+      SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>;
+};
+
+template <class Expected, class... Tail>
+struct IndexOfImpl<Expected, Expected, Tail...>
+    : IndexOfImpl<Expected, Tail...> {
+  using IndexFromEnd =
+      SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>;
+  using MatchedIndexFromEnd = IndexFromEnd;
+  using MultipleMatches = std::integral_constant<
+      bool, IndexOfImpl<Expected, Tail...>::MatchedIndexFromEnd::value != 0>;
+};
+
+template <class Expected, class... Types>
+struct IndexOfMeta {
+  using Results = IndexOfImpl<Expected, Types...>;
+  static_assert(!Results::MultipleMatches::value,
+                "Attempted to access a variant by specifying a type that "
+                "matches more than one alternative.");
+  static_assert(Results::MatchedIndexFromEnd::value != 0,
+                "Attempted to access a variant by specifying a type that does "
+                "not match any alternative.");
+  using type = SizeT<sizeof...(Types) - Results::MatchedIndexFromEnd::value>;
+};
+
+template <class Expected, class... Types>
+using IndexOf = typename IndexOfMeta<Expected, Types...>::type;
+
+template <class Variant, class T, std::size_t CurrIndex>
+struct UnambiguousIndexOfImpl;
+
+// Terminating case encountered once we've checked all of the alternatives
+template <class T, std::size_t CurrIndex>
+struct UnambiguousIndexOfImpl<variant<>, T, CurrIndex> : SizeT<CurrIndex> {};
+
+// Case where T is not Head
+template <class Head, class... Tail, class T, std::size_t CurrIndex>
+struct UnambiguousIndexOfImpl<variant<Head, Tail...>, T, CurrIndex>
+    : UnambiguousIndexOfImpl<variant<Tail...>, T, CurrIndex + 1>::type {};
+
+// Case where T is Head
+template <class Head, class... Tail, std::size_t CurrIndex>
+struct UnambiguousIndexOfImpl<variant<Head, Tail...>, Head, CurrIndex>
+    : SizeT<UnambiguousIndexOfImpl<variant<Tail...>, Head, 0>::value ==
+                    sizeof...(Tail)
+                ? CurrIndex
+                : CurrIndex + sizeof...(Tail) + 1> {};
+
+template <class Variant, class T>
+struct UnambiguousIndexOf;
+
+struct NoMatch {
+  struct type {};
+};
+
+template <class... Alts, class T>
+struct UnambiguousIndexOf<variant<Alts...>, T>
+    : std::conditional<UnambiguousIndexOfImpl<variant<Alts...>, T, 0>::value !=
+                           sizeof...(Alts),
+                       UnambiguousIndexOfImpl<variant<Alts...>, T, 0>,
+                       NoMatch>::type::type {};
+
+template <class T, std::size_t /*Dummy*/>
+using UnambiguousTypeOfImpl = T;
+
+template <class Variant, class T>
+using UnambiguousTypeOfT =
+    UnambiguousTypeOfImpl<T, UnambiguousIndexOf<Variant, T>::value>;
+
+template <class H, class... T>
+class VariantStateBase;
+
+// This is an implementation of the "imaginary function" that is described in
+// [variant.ctor]
+// It is used in order to determine which alternative to construct during
+// initialization from some type T.
+template <class Variant, std::size_t I = 0>
+struct ImaginaryFun;
+
+template <std::size_t I>
+struct ImaginaryFun<variant<>, I> {
+  static void Run() = delete;
+};
+
+template <class H, class... T, std::size_t I>
+struct ImaginaryFun<variant<H, T...>, I> : ImaginaryFun<variant<T...>, I + 1> {
+  using ImaginaryFun<variant<T...>, I + 1>::Run;
+
+  // NOTE: const& and && are used instead of by-value due to lack of guaranteed
+  // move elision of C++17. This may have other minor differences, but tests
+  // pass.
+  static SizeT<I> Run(const H&, SizeT<I>);
+  static SizeT<I> Run(H&&, SizeT<I>);
+};
+
+// The following metafunctions are used in constructor and assignment
+// constraints.
+template <class Self, class T>
+struct IsNeitherSelfNorInPlace : std::true_type {};
+
+template <class Self>
+struct IsNeitherSelfNorInPlace<Self, Self> : std::false_type {};
+
+template <class Self, class T>
+struct IsNeitherSelfNorInPlace<Self, in_place_type_t<T>> : std::false_type {};
+
+template <class Self, std::size_t I>
+struct IsNeitherSelfNorInPlace<Self, in_place_index_t<I>> : std::false_type {};
+
+template <class Variant, class T, class = void>
+struct ConversionIsPossibleImpl : std::false_type {};
+
+template <class Variant, class T>
+struct ConversionIsPossibleImpl<
+    Variant, T,
+    void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>>
+    : std::true_type {};
+
+template <class Variant, class T>
+struct ConversionIsPossible : ConversionIsPossibleImpl<Variant, T>::type {};
+
+template <class Variant, class T>
+struct IndexOfConstructedType<
+    Variant, T,
+    void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>>
+    : decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {})) {};
+
+template <std::size_t... Is>
+struct ContainsVariantNPos
+    : absl::OTABSL_OPTION_NAMESPACE_NAME::negation<std::is_same<  // NOLINT
+          absl::OTABSL_OPTION_NAMESPACE_NAME::integer_sequence<bool, 0 <= Is...>,
+          absl::OTABSL_OPTION_NAMESPACE_NAME::integer_sequence<bool, Is != absl::OTABSL_OPTION_NAMESPACE_NAME::variant_npos...>>> {};
+
+template <class Op, class... QualifiedVariants>
+using RawVisitResult =
+    absl::OTABSL_OPTION_NAMESPACE_NAME::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>;
+
+// NOTE: The spec requires that all return-paths yield the same type and is not
+// SFINAE-friendly, so we can deduce the return type by examining the first
+// result. If it's not callable, then we get an error, but are compliant and
+// fast to compile.
+// TODO(calabrese) Possibly rewrite in a way that yields better compile errors
+// at the cost of longer compile-times.
+template <class Op, class... QualifiedVariants>
+struct VisitResultImpl {
+  using type =
+      absl::OTABSL_OPTION_NAMESPACE_NAME::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>;
+};
+
+// Done in two steps intentionally so that we don't cause substitution to fail.
+template <class Op, class... QualifiedVariants>
+using VisitResult = typename VisitResultImpl<Op, QualifiedVariants...>::type;
+
+template <class Op, class... QualifiedVariants>
+struct PerformVisitation {
+  using ReturnType = VisitResult<Op, QualifiedVariants...>;
+
+  template <std::size_t... Is>
+  constexpr ReturnType operator()(SizeT<Is>... indices) const {
+    return Run(typename ContainsVariantNPos<Is...>::type{},
+               absl::OTABSL_OPTION_NAMESPACE_NAME::index_sequence_for<QualifiedVariants...>(), indices...);
+  }
+
+  template <std::size_t... TupIs, std::size_t... Is>
+  constexpr ReturnType Run(std::false_type /*has_valueless*/,
+                           index_sequence<TupIs...>, SizeT<Is>...) const {
+    static_assert(
+        std::is_same<ReturnType,
+                     absl::OTABSL_OPTION_NAMESPACE_NAME::result_of_t<Op(VariantAccessResult<
+                                          Is, QualifiedVariants>...)>>::value,
+        "All visitation overloads must have the same return type.");
+    return absl::OTABSL_OPTION_NAMESPACE_NAME::base_internal::Invoke(
+        absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Op>(op),
+        VariantCoreAccess::Access<Is>(
+            absl::OTABSL_OPTION_NAMESPACE_NAME::forward<QualifiedVariants>(std::get<TupIs>(variant_tup)))...);
+  }
+
+  template <std::size_t... TupIs, std::size_t... Is>
+  [[noreturn]] ReturnType Run(std::true_type /*has_valueless*/,
+                              index_sequence<TupIs...>, SizeT<Is>...) const {
+    absl::OTABSL_OPTION_NAMESPACE_NAME::variant_internal::ThrowBadVariantAccess();
+  }
+
+  // TODO(calabrese) Avoid using a tuple, which causes lots of instantiations
+  // Attempts using lambda variadic captures fail on current GCC.
+  std::tuple<QualifiedVariants&&...> variant_tup;
+  Op&& op;
+};
+
+template <class... T>
+union Union;
+
+// We want to allow for variant<> to be trivial. For that, we need the default
+// constructor to be trivial, which means we can't define it ourselves.
+// Instead, we use a non-default constructor that takes NoopConstructorTag
+// that doesn't affect the triviality of the types.
+struct NoopConstructorTag {};
+
+template <std::size_t I>
+struct EmplaceTag {};
+
+template <>
+union Union<> {
+  constexpr explicit Union(NoopConstructorTag) noexcept {}
+};
+
+// Suppress bogus warning on MSVC: MSVC complains that Union<T...> has a defined
+// deleted destructor from the `std::is_destructible` check below.
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4624)
+#endif  // _MSC_VER
+
+template <class Head, class... Tail>
+union Union<Head, Tail...> {
+  using TailUnion = Union<Tail...>;
+
+  explicit constexpr Union(NoopConstructorTag /*tag*/) noexcept
+      : tail(NoopConstructorTag()) {}
+
+  template <class... P>
+  explicit constexpr Union(EmplaceTag<0>, P&&... args)
+      : head(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<P>(args)...) {}
+
+  template <std::size_t I, class... P>
+  explicit constexpr Union(EmplaceTag<I>, P&&... args)
+      : tail(EmplaceTag<I - 1>{}, absl::OTABSL_OPTION_NAMESPACE_NAME::forward<P>(args)...) {}
+
+  Head head;
+  TailUnion tail;
+};
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif  // _MSC_VER
+
+// TODO(calabrese) Just contain a Union in this union (certain configs fail).
+template <class... T>
+union DestructibleUnionImpl;
+
+template <>
+union DestructibleUnionImpl<> {
+  constexpr explicit DestructibleUnionImpl(NoopConstructorTag) noexcept {}
+};
+
+template <class Head, class... Tail>
+union DestructibleUnionImpl<Head, Tail...> {
+  using TailUnion = DestructibleUnionImpl<Tail...>;
+
+  explicit constexpr DestructibleUnionImpl(NoopConstructorTag /*tag*/) noexcept
+      : tail(NoopConstructorTag()) {}
+
+  template <class... P>
+  explicit constexpr DestructibleUnionImpl(EmplaceTag<0>, P&&... args)
+      : head(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<P>(args)...) {}
+
+  template <std::size_t I, class... P>
+  explicit constexpr DestructibleUnionImpl(EmplaceTag<I>, P&&... args)
+      : tail(EmplaceTag<I - 1>{}, absl::OTABSL_OPTION_NAMESPACE_NAME::forward<P>(args)...) {}
+
+  ~DestructibleUnionImpl() {}
+
+  Head head;
+  TailUnion tail;
+};
+
+// This union type is destructible even if one or more T are not trivially
+// destructible. In the case that all T are trivially destructible, then so is
+// this resultant type.
+template <class... T>
+using DestructibleUnion =
+    absl::OTABSL_OPTION_NAMESPACE_NAME::conditional_t<std::is_destructible<Union<T...>>::value, Union<T...>,
+                        DestructibleUnionImpl<T...>>;
+
+// Deepest base, containing the actual union and the discriminator
+template <class H, class... T>
+class VariantStateBase {
+ protected:
+  using Variant = variant<H, T...>;
+
+  template <class LazyH = H,
+            class ConstructibleH = absl::OTABSL_OPTION_NAMESPACE_NAME::enable_if_t<
+                std::is_default_constructible<LazyH>::value, LazyH>>
+  constexpr VariantStateBase() noexcept(
+      std::is_nothrow_default_constructible<ConstructibleH>::value)
+      : state_(EmplaceTag<0>()), index_(0) {}
+
+  template <std::size_t I, class... P>
+  explicit constexpr VariantStateBase(EmplaceTag<I> tag, P&&... args)
+      : state_(tag, absl::OTABSL_OPTION_NAMESPACE_NAME::forward<P>(args)...), index_(I) {}
+
+  explicit constexpr VariantStateBase(NoopConstructorTag)
+      : state_(NoopConstructorTag()), index_(variant_npos) {}
+
+  void destroy() {}  // Does nothing (shadowed in child if non-trivial)
+
+  DestructibleUnion<H, T...> state_;
+  std::size_t index_;
+};
+
+using absl::OTABSL_OPTION_NAMESPACE_NAME::internal::identity;
+
+// OverloadSet::Overload() is a unary function which is overloaded to
+// take any of the element types of the variant, by reference-to-const.
+// The return type of the overload on T is identity<T>, so that you
+// can statically determine which overload was called.
+//
+// Overload() is not defined, so it can only be called in unevaluated
+// contexts.
+template <typename... Ts>
+struct OverloadSet;
+
+template <typename T, typename... Ts>
+struct OverloadSet<T, Ts...> : OverloadSet<Ts...> {
+  using Base = OverloadSet<Ts...>;
+  static identity<T> Overload(const T&);
+  using Base::Overload;
+};
+
+template <>
+struct OverloadSet<> {
+  // For any case not handled above.
+  static void Overload(...);
+};
+
+template <class T>
+using LessThanResult = decltype(std::declval<T>() < std::declval<T>());
+
+template <class T>
+using GreaterThanResult = decltype(std::declval<T>() > std::declval<T>());
+
+template <class T>
+using LessThanOrEqualResult = decltype(std::declval<T>() <= std::declval<T>());
+
+template <class T>
+using GreaterThanOrEqualResult =
+    decltype(std::declval<T>() >= std::declval<T>());
+
+template <class T>
+using EqualResult = decltype(std::declval<T>() == std::declval<T>());
+
+template <class T>
+using NotEqualResult = decltype(std::declval<T>() != std::declval<T>());
+
+using type_traits_internal::is_detected_convertible;
+
+template <class... T>
+using RequireAllHaveEqualT = absl::OTABSL_OPTION_NAMESPACE_NAME::enable_if_t<
+    absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<is_detected_convertible<bool, EqualResult, T>...>::value,
+    bool>;
+
+template <class... T>
+using RequireAllHaveNotEqualT =
+    absl::OTABSL_OPTION_NAMESPACE_NAME::enable_if_t<absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<is_detected_convertible<
+                          bool, NotEqualResult, T>...>::value,
+                      bool>;
+
+template <class... T>
+using RequireAllHaveLessThanT =
+    absl::OTABSL_OPTION_NAMESPACE_NAME::enable_if_t<absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<is_detected_convertible<
+                          bool, LessThanResult, T>...>::value,
+                      bool>;
+
+template <class... T>
+using RequireAllHaveLessThanOrEqualT =
+    absl::OTABSL_OPTION_NAMESPACE_NAME::enable_if_t<absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<is_detected_convertible<
+                          bool, LessThanOrEqualResult, T>...>::value,
+                      bool>;
+
+template <class... T>
+using RequireAllHaveGreaterThanOrEqualT =
+    absl::OTABSL_OPTION_NAMESPACE_NAME::enable_if_t<absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<is_detected_convertible<
+                          bool, GreaterThanOrEqualResult, T>...>::value,
+                      bool>;
+
+template <class... T>
+using RequireAllHaveGreaterThanT =
+    absl::OTABSL_OPTION_NAMESPACE_NAME::enable_if_t<absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<is_detected_convertible<
+                          bool, GreaterThanResult, T>...>::value,
+                      bool>;
+
+// Helper template containing implementations details of variant that can't go
+// in the private section. For convenience, this takes the variant type as a
+// single template parameter.
+template <typename T>
+struct VariantHelper;
+
+template <typename... Ts>
+struct VariantHelper<variant<Ts...>> {
+  // Type metafunction which returns the element type selected if
+  // OverloadSet::Overload() is well-formed when called with argument type U.
+  template <typename U>
+  using BestMatch = decltype(
+      variant_internal::OverloadSet<Ts...>::Overload(std::declval<U>()));
+
+  // Type metafunction which returns true if OverloadSet::Overload() is
+  // well-formed when called with argument type U.
+  // CanAccept can't be just an alias because there is a MSVC bug on parameter
+  // pack expansion involving decltype.
+  template <typename U>
+  struct CanAccept :
+      std::integral_constant<bool, !std::is_void<BestMatch<U>>::value> {};
+
+  // Type metafunction which returns true if Other is an instantiation of
+  // variant, and variants's converting constructor from Other will be
+  // well-formed. We will use this to remove constructors that would be
+  // ill-formed from the overload set.
+  template <typename Other>
+  struct CanConvertFrom;
+
+  template <typename... Us>
+  struct CanConvertFrom<variant<Us...>>
+      : public absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<CanAccept<Us>...> {};
+};
+
+// A type with nontrivial copy ctor and trivial move ctor.
+struct TrivialMoveOnly {
+  TrivialMoveOnly(TrivialMoveOnly&&) = default;
+};
+
+// Trait class to detect whether a type is trivially move constructible.
+// A union's defaulted copy/move constructor is deleted if any variant member's
+// copy/move constructor is nontrivial.
+template <typename T>
+struct IsTriviallyMoveConstructible:
+  std::is_move_constructible<Union<T, TrivialMoveOnly>> {};
+
+// To guarantee triviality of all special-member functions that can be trivial,
+// we use a chain of conditional bases for each one.
+// The order of inheritance of bases from child to base are logically:
+//
+// variant
+// VariantCopyAssignBase
+// VariantMoveAssignBase
+// VariantCopyBase
+// VariantMoveBase
+// VariantStateBaseDestructor
+// VariantStateBase
+//
+// Note that there is a separate branch at each base that is dependent on
+// whether or not that corresponding special-member-function can be trivial in
+// the resultant variant type.
+
+template <class... T>
+class VariantStateBaseDestructorNontrivial;
+
+template <class... T>
+class VariantMoveBaseNontrivial;
+
+template <class... T>
+class VariantCopyBaseNontrivial;
+
+template <class... T>
+class VariantMoveAssignBaseNontrivial;
+
+template <class... T>
+class VariantCopyAssignBaseNontrivial;
+
+// Base that is dependent on whether or not the destructor can be trivial.
+template <class... T>
+using VariantStateBaseDestructor =
+    absl::OTABSL_OPTION_NAMESPACE_NAME::conditional_t<std::is_destructible<Union<T...>>::value,
+                        VariantStateBase<T...>,
+                        VariantStateBaseDestructorNontrivial<T...>>;
+
+// Base that is dependent on whether or not the move-constructor can be
+// implicitly generated by the compiler (trivial or deleted).
+// Previously we were using `std::is_move_constructible<Union<T...>>` to check
+// whether all Ts have trivial move constructor, but it ran into a GCC bug:
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84866
+// So we have to use a different approach (i.e. `HasTrivialMoveConstructor`) to
+// work around the bug.
+template <class... T>
+using VariantMoveBase = absl::OTABSL_OPTION_NAMESPACE_NAME::conditional_t<
+    absl::OTABSL_OPTION_NAMESPACE_NAME::disjunction<
+        absl::OTABSL_OPTION_NAMESPACE_NAME::negation<absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<std::is_move_constructible<T>...>>,
+        absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<IsTriviallyMoveConstructible<T>...>>::value,
+    VariantStateBaseDestructor<T...>, VariantMoveBaseNontrivial<T...>>;
+
+// Base that is dependent on whether or not the copy-constructor can be trivial.
+template <class... T>
+using VariantCopyBase = absl::OTABSL_OPTION_NAMESPACE_NAME::conditional_t<
+    absl::OTABSL_OPTION_NAMESPACE_NAME::disjunction<
+        absl::OTABSL_OPTION_NAMESPACE_NAME::negation<absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<std::is_copy_constructible<T>...>>,
+        std::is_copy_constructible<Union<T...>>>::value,
+    VariantMoveBase<T...>, VariantCopyBaseNontrivial<T...>>;
+
+// Base that is dependent on whether or not the move-assign can be trivial.
+template <class... T>
+using VariantMoveAssignBase = absl::OTABSL_OPTION_NAMESPACE_NAME::conditional_t<
+    absl::OTABSL_OPTION_NAMESPACE_NAME::disjunction<
+        absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<absl::OTABSL_OPTION_NAMESPACE_NAME::is_move_assignable<Union<T...>>,
+                          std::is_move_constructible<Union<T...>>,
+                          std::is_destructible<Union<T...>>>,
+        absl::OTABSL_OPTION_NAMESPACE_NAME::negation<absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<std::is_move_constructible<T>...,
+                                         // Note: We're not qualifying this with
+                                         // absl::OTABSL_OPTION_NAMESPACE_NAME:: because it doesn't compile
+                                         // under MSVC.
+                                         is_move_assignable<T>...>>>::value,
+    VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>;
+
+// Base that is dependent on whether or not the copy-assign can be trivial.
+template <class... T>
+using VariantCopyAssignBase = absl::OTABSL_OPTION_NAMESPACE_NAME::conditional_t<
+    absl::OTABSL_OPTION_NAMESPACE_NAME::disjunction<
+        absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<absl::OTABSL_OPTION_NAMESPACE_NAME::is_copy_assignable<Union<T...>>,
+                          std::is_copy_constructible<Union<T...>>,
+                          std::is_destructible<Union<T...>>>,
+        absl::OTABSL_OPTION_NAMESPACE_NAME::negation<absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<std::is_copy_constructible<T>...,
+                                         // Note: We're not qualifying this with
+                                         // absl::OTABSL_OPTION_NAMESPACE_NAME:: because it doesn't compile
+                                         // under MSVC.
+                                         is_copy_assignable<T>...>>>::value,
+    VariantMoveAssignBase<T...>, VariantCopyAssignBaseNontrivial<T...>>;
+
+template <class... T>
+using VariantBase = VariantCopyAssignBase<T...>;
+
+template <class... T>
+class VariantStateBaseDestructorNontrivial : protected VariantStateBase<T...> {
+ private:
+  using Base = VariantStateBase<T...>;
+
+ protected:
+  using Base::Base;
+
+  VariantStateBaseDestructorNontrivial() = default;
+  VariantStateBaseDestructorNontrivial(VariantStateBaseDestructorNontrivial&&) =
+      default;
+  VariantStateBaseDestructorNontrivial(
+      const VariantStateBaseDestructorNontrivial&) = default;
+  VariantStateBaseDestructorNontrivial& operator=(
+      VariantStateBaseDestructorNontrivial&&) = default;
+  VariantStateBaseDestructorNontrivial& operator=(
+      const VariantStateBaseDestructorNontrivial&) = default;
+
+  struct Destroyer {
+    template <std::size_t I>
+    void operator()(SizeT<I> i) const {
+      using Alternative =
+          typename absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative<I, variant<T...>>::type;
+      variant_internal::AccessUnion(self->state_, i).~Alternative();
+    }
+
+    void operator()(SizeT<absl::OTABSL_OPTION_NAMESPACE_NAME::variant_npos> /*i*/) const {
+      // This space intentionally left blank
+    }
+
+    VariantStateBaseDestructorNontrivial* self;
+  };
+
+  // cppcheck-suppress [duplInheritedMember]
+  void destroy() { VisitIndices<sizeof...(T)>::Run(Destroyer{this}, index_); }
+
+  ~VariantStateBaseDestructorNontrivial() { destroy(); }
+
+ protected:
+  using Base::index_;
+  using Base::state_;
+};
+
+template <class... T>
+class VariantMoveBaseNontrivial : protected VariantStateBaseDestructor<T...> {
+ private:
+  using Base = VariantStateBaseDestructor<T...>;
+
+ protected:
+  using Base::Base;
+
+  struct Construct {
+    template <std::size_t I>
+    void operator()(SizeT<I> i) const {
+      using Alternative =
+          typename absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative<I, variant<T...>>::type;
+      ::new (static_cast<void*>(&self->state_)) Alternative(
+          variant_internal::AccessUnion(absl::OTABSL_OPTION_NAMESPACE_NAME::move(other->state_), i));
+    }
+
+    void operator()(SizeT<absl::OTABSL_OPTION_NAMESPACE_NAME::variant_npos> /*i*/) const {}
+
+    VariantMoveBaseNontrivial* self;
+    VariantMoveBaseNontrivial* other;
+  };
+
+  VariantMoveBaseNontrivial() = default;
+  VariantMoveBaseNontrivial(VariantMoveBaseNontrivial&& other) noexcept(
+      absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<std::is_nothrow_move_constructible<T>...>::value)
+      : Base(NoopConstructorTag()) {
+    VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_);
+    index_ = other.index_;
+  }
+
+  VariantMoveBaseNontrivial(VariantMoveBaseNontrivial const&) = default;
+
+  VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial&&) = default;
+  VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial const&) =
+      default;
+
+ protected:
+  using Base::index_;
+  using Base::state_;
+};
+
+template <class... T>
+class VariantCopyBaseNontrivial : protected VariantMoveBase<T...> {
+ private:
+  using Base = VariantMoveBase<T...>;
+
+ protected:
+  using Base::Base;
+
+  VariantCopyBaseNontrivial() = default;
+  VariantCopyBaseNontrivial(VariantCopyBaseNontrivial&&) = default;
+
+  struct Construct {
+    template <std::size_t I>
+    void operator()(SizeT<I> i) const {
+      using Alternative =
+          typename absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative<I, variant<T...>>::type;
+      ::new (static_cast<void*>(&self->state_))
+          Alternative(variant_internal::AccessUnion(other->state_, i));
+    }
+
+    void operator()(SizeT<absl::OTABSL_OPTION_NAMESPACE_NAME::variant_npos> /*i*/) const {}
+
+    VariantCopyBaseNontrivial* self;
+    const VariantCopyBaseNontrivial* other;
+  };
+
+  VariantCopyBaseNontrivial(VariantCopyBaseNontrivial const& other)
+      : Base(NoopConstructorTag()) {
+    VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_);
+    index_ = other.index_;
+  }
+
+  VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial&&) = default;
+  VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial const&) =
+      default;
+
+ protected:
+  using Base::index_;
+  using Base::state_;
+};
+
+template <class... T>
+class VariantMoveAssignBaseNontrivial : protected VariantCopyBase<T...> {
+  friend struct VariantCoreAccess;
+
+ private:
+  using Base = VariantCopyBase<T...>;
+
+ protected:
+  using Base::Base;
+
+  VariantMoveAssignBaseNontrivial() = default;
+  VariantMoveAssignBaseNontrivial(VariantMoveAssignBaseNontrivial&&) = default;
+  VariantMoveAssignBaseNontrivial(const VariantMoveAssignBaseNontrivial&) =
+      default;
+  VariantMoveAssignBaseNontrivial& operator=(
+      VariantMoveAssignBaseNontrivial const&) = default;
+
+    VariantMoveAssignBaseNontrivial&
+    operator=(VariantMoveAssignBaseNontrivial&& other) noexcept(
+        absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<std::is_nothrow_move_constructible<T>...,
+                          std::is_nothrow_move_assignable<T>...>::value) {
+      VisitIndices<sizeof...(T)>::Run(
+          VariantCoreAccess::MakeMoveAssignVisitor(this, &other), other.index_);
+      return *this;
+    }
+
+ protected:
+  using Base::index_;
+  using Base::state_;
+};
+
+template <class... T>
+class VariantCopyAssignBaseNontrivial : protected VariantMoveAssignBase<T...> {
+  friend struct VariantCoreAccess;
+
+ private:
+  using Base = VariantMoveAssignBase<T...>;
+
+ protected:
+  using Base::Base;
+
+  VariantCopyAssignBaseNontrivial() = default;
+  VariantCopyAssignBaseNontrivial(VariantCopyAssignBaseNontrivial&&) = default;
+  VariantCopyAssignBaseNontrivial(const VariantCopyAssignBaseNontrivial&) =
+      default;
+  VariantCopyAssignBaseNontrivial& operator=(
+      VariantCopyAssignBaseNontrivial&&) = default;
+
+    VariantCopyAssignBaseNontrivial& operator=(
+        const VariantCopyAssignBaseNontrivial& other) {
+      VisitIndices<sizeof...(T)>::Run(
+          VariantCoreAccess::MakeCopyAssignVisitor(this, other), other.index_);
+      return *this;
+    }
+
+ protected:
+  using Base::index_;
+  using Base::state_;
+};
+
+////////////////////////////////////////
+// Visitors for Comparison Operations //
+////////////////////////////////////////
+
+template <class... Types>
+struct EqualsOp {
+  const variant<Types...>* v;
+  const variant<Types...>* w;
+
+  constexpr bool operator()(SizeT<absl::OTABSL_OPTION_NAMESPACE_NAME::variant_npos> /*v_i*/) const {
+    return true;
+  }
+
+  template <std::size_t I>
+  constexpr bool operator()(SizeT<I> /*v_i*/) const {
+    return VariantCoreAccess::Access<I>(*v) == VariantCoreAccess::Access<I>(*w);
+  }
+};
+
+template <class... Types>
+struct NotEqualsOp {
+  const variant<Types...>* v;
+  const variant<Types...>* w;
+
+  constexpr bool operator()(SizeT<absl::OTABSL_OPTION_NAMESPACE_NAME::variant_npos> /*v_i*/) const {
+    return false;
+  }
+
+  template <std::size_t I>
+  constexpr bool operator()(SizeT<I> /*v_i*/) const {
+    return VariantCoreAccess::Access<I>(*v) != VariantCoreAccess::Access<I>(*w);
+  }
+};
+
+template <class... Types>
+struct LessThanOp {
+  const variant<Types...>* v;
+  const variant<Types...>* w;
+
+  constexpr bool operator()(SizeT<absl::OTABSL_OPTION_NAMESPACE_NAME::variant_npos> /*v_i*/) const {
+    return false;
+  }
+
+  template <std::size_t I>
+  constexpr bool operator()(SizeT<I> /*v_i*/) const {
+    return VariantCoreAccess::Access<I>(*v) < VariantCoreAccess::Access<I>(*w);
+  }
+};
+
+template <class... Types>
+struct GreaterThanOp {
+  const variant<Types...>* v;
+  const variant<Types...>* w;
+
+  constexpr bool operator()(SizeT<absl::OTABSL_OPTION_NAMESPACE_NAME::variant_npos> /*v_i*/) const {
+    return false;
+  }
+
+  template <std::size_t I>
+  constexpr bool operator()(SizeT<I> /*v_i*/) const {
+    return VariantCoreAccess::Access<I>(*v) > VariantCoreAccess::Access<I>(*w);
+  }
+};
+
+template <class... Types>
+struct LessThanOrEqualsOp {
+  const variant<Types...>* v;
+  const variant<Types...>* w;
+
+  constexpr bool operator()(SizeT<absl::OTABSL_OPTION_NAMESPACE_NAME::variant_npos> /*v_i*/) const {
+    return true;
+  }
+
+  template <std::size_t I>
+  constexpr bool operator()(SizeT<I> /*v_i*/) const {
+    return VariantCoreAccess::Access<I>(*v) <= VariantCoreAccess::Access<I>(*w);
+  }
+};
+
+template <class... Types>
+struct GreaterThanOrEqualsOp {
+  const variant<Types...>* v;
+  const variant<Types...>* w;
+
+  constexpr bool operator()(SizeT<absl::OTABSL_OPTION_NAMESPACE_NAME::variant_npos> /*v_i*/) const {
+    return true;
+  }
+
+  template <std::size_t I>
+  constexpr bool operator()(SizeT<I> /*v_i*/) const {
+    return VariantCoreAccess::Access<I>(*v) >= VariantCoreAccess::Access<I>(*w);
+  }
+};
+
+// Precondition: v.index() == w.index();
+template <class... Types>
+struct SwapSameIndex {
+  variant<Types...>* v;
+  variant<Types...>* w;
+  template <std::size_t I>
+  void operator()(SizeT<I>) const {
+    type_traits_internal::Swap(VariantCoreAccess::Access<I>(*v),
+                               VariantCoreAccess::Access<I>(*w));
+  }
+
+  void operator()(SizeT<variant_npos>) const {}
+};
+
+// TODO(calabrese) do this from a different namespace for proper adl usage
+template <class... Types>
+struct Swap {
+  variant<Types...>* v;
+  variant<Types...>* w;
+
+  void generic_swap() const {
+    variant<Types...> tmp(std::move(*w));
+    VariantCoreAccess::Destroy(*w);
+    VariantCoreAccess::InitFrom(*w, std::move(*v));
+    VariantCoreAccess::Destroy(*v);
+    VariantCoreAccess::InitFrom(*v, std::move(tmp));
+  }
+
+  void operator()(SizeT<absl::OTABSL_OPTION_NAMESPACE_NAME::variant_npos> /*w_i*/) const {
+    if (!v->valueless_by_exception()) {
+      generic_swap();
+    }
+  }
+
+  template <std::size_t Wi>
+  void operator()(SizeT<Wi> /*w_i*/) {
+    if (v->index() == Wi) {
+      VisitIndices<sizeof...(Types)>::Run(SwapSameIndex<Types...>{v, w}, Wi);
+    } else {
+      generic_swap();
+    }
+  }
+};
+
+template <typename Variant, typename = void, typename... Ts>
+struct VariantHashBase {
+  VariantHashBase() = delete;
+  VariantHashBase(const VariantHashBase&) = delete;
+  VariantHashBase(VariantHashBase&&) = delete;
+  VariantHashBase& operator=(const VariantHashBase&) = delete;
+  VariantHashBase& operator=(VariantHashBase&&) = delete;
+};
+
+struct VariantHashVisitor {
+  template <typename T>
+  size_t operator()(const T& t) {
+    return std::hash<T>{}(t);
+  }
+};
+
+template <typename Variant, typename... Ts>
+struct VariantHashBase<Variant,
+                       absl::OTABSL_OPTION_NAMESPACE_NAME::enable_if_t<absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<
+                           type_traits_internal::IsHashable<Ts>...>::value>,
+                       Ts...> {
+  using argument_type = Variant;
+  using result_type = size_t;
+  size_t operator()(const Variant& var) const {
+    type_traits_internal::AssertHashEnabled<Ts...>();
+    if (var.valueless_by_exception()) {
+      return 239799884;
+    }
+    size_t result = VisitIndices<variant_size<Variant>::value>::Run(
+        PerformVisitation<VariantHashVisitor, const Variant&>{
+            std::forward_as_tuple(var), VariantHashVisitor{}},
+        var.index());
+    // Combine the index and the hash result in order to distinguish
+    // std::variant<int, int> holding the same value as different alternative.
+    return result ^ var.index();
+  }
+};
+
+}  // namespace variant_internal
+OTABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // !defined(OTABSL_USES_STD_VARIANT)
+#endif  // OTABSL_TYPES_variant_internal_H_

+ 866 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/types/variant.h

@@ -0,0 +1,866 @@
+// Copyright 2018 The Abseil 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
+//
+//      https://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.
+//
+// -----------------------------------------------------------------------------
+// variant.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines an `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` type for holding a type-safe
+// value of some prescribed set of types (noted as alternative types), and
+// associated functions for managing variants.
+//
+// The `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` type is a form of type-safe union. An `absl::OTABSL_OPTION_NAMESPACE_NAME::variant`
+// should always hold a value of one of its alternative types (except in the
+// "valueless by exception state" -- see below). A default-constructed
+// `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` will hold the value of its first alternative type, provided
+// it is default-constructible.
+//
+// In exceptional cases due to error, an `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` can hold no
+// value (known as a "valueless by exception" state), though this is not the
+// norm.
+//
+// As with `absl::OTABSL_OPTION_NAMESPACE_NAME::optional`, an `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` -- when it holds a value --
+// allocates a value of that type directly within the `variant` itself; it
+// cannot hold a reference, array, or the type `void`; it can, however, hold a
+// pointer to externally managed memory.
+//
+// `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` is a C++11 compatible version of the C++17 `std::variant`
+// abstraction and is designed to be a drop-in replacement for code compliant
+// with C++17.
+
+#ifndef OTABSL_TYPES_VARIANT_H_
+#define OTABSL_TYPES_VARIANT_H_
+
+#include "../base/config.h"
+#include "../utility/utility.h"
+
+#ifdef OTABSL_USES_STD_VARIANT
+
+#include <variant>  // IWYU pragma: export
+
+namespace absl {
+OTABSL_NAMESPACE_BEGIN
+using std::bad_variant_access;
+using std::get;
+using std::get_if;
+using std::holds_alternative;
+using std::monostate;
+using std::variant;
+using std::variant_alternative;
+using std::variant_alternative_t;
+using std::variant_npos;
+using std::variant_size;
+using std::variant_size_v;
+using std::visit;
+OTABSL_NAMESPACE_END
+}  // namespace absl
+
+#else  // OTABSL_USES_STD_VARIANT
+
+#include <functional>
+#include <new>
+#include <type_traits>
+#include <utility>
+
+#include "../base/macros.h"
+#include "../base/port.h"
+#include "../meta/type_traits.h"
+#include "../types/internal/variant.h"
+
+namespace absl {
+OTABSL_NAMESPACE_BEGIN
+
+// -----------------------------------------------------------------------------
+// absl::OTABSL_OPTION_NAMESPACE_NAME::variant
+// -----------------------------------------------------------------------------
+//
+// An `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` type is a form of type-safe union. An `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` --
+// except in exceptional cases -- always holds a value of one of its alternative
+// types.
+//
+// Example:
+//
+//   // Construct a variant that holds either an integer or a std::string and
+//   // assign it to a std::string.
+//   absl::OTABSL_OPTION_NAMESPACE_NAME::variant<int, std::string> v = std::string("abc");
+//
+//   // A default-constructed variant will hold a value-initialized value of
+//   // the first alternative type.
+//   auto a = absl::OTABSL_OPTION_NAMESPACE_NAME::variant<int, std::string>();   // Holds an int of value '0'.
+//
+//   // variants are assignable.
+//
+//   // copy assignment
+//   auto v1 = absl::OTABSL_OPTION_NAMESPACE_NAME::variant<int, std::string>("abc");
+//   auto v2 = absl::OTABSL_OPTION_NAMESPACE_NAME::variant<int, std::string>(10);
+//   v2 = v1;  // copy assign
+//
+//   // move assignment
+//   auto v1 = absl::OTABSL_OPTION_NAMESPACE_NAME::variant<int, std::string>("abc");
+//   v1 = absl::OTABSL_OPTION_NAMESPACE_NAME::variant<int, std::string>(10);
+//
+//   // assignment through type conversion
+//   a = 128;         // variant contains int
+//   a = "128";       // variant contains std::string
+//
+// An `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` holding a value of one of its alternative types `T` holds
+// an allocation of `T` directly within the variant itself. An `absl::OTABSL_OPTION_NAMESPACE_NAME::variant`
+// is not allowed to allocate additional storage, such as dynamic memory, to
+// allocate the contained value. The contained value shall be allocated in a
+// region of the variant storage suitably aligned for all alternative types.
+template <typename... Ts>
+class variant;
+
+// swap()
+//
+// Swaps two `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` values. This function is equivalent to `v.swap(w)`
+// where `v` and `w` are `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` types.
+//
+// Note that this function requires all alternative types to be both swappable
+// and move-constructible, because any two variants may refer to either the same
+// type (in which case, they will be swapped) or to two different types (in
+// which case the values will need to be moved).
+//
+template <
+    typename... Ts,
+    absl::OTABSL_OPTION_NAMESPACE_NAME::enable_if_t<
+        absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<std::is_move_constructible<Ts>...,
+                          type_traits_internal::IsSwappable<Ts>...>::value,
+        int> = 0>
+void swap(variant<Ts...>& v, variant<Ts...>& w) noexcept(noexcept(v.swap(w))) {
+  v.swap(w);
+}
+
+// variant_size
+//
+// Returns the number of alternative types available for a given `absl::OTABSL_OPTION_NAMESPACE_NAME::variant`
+// type as a compile-time constant expression. As this is a class template, it
+// is not generally useful for accessing the number of alternative types of
+// any given `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` instance.
+//
+// Example:
+//
+//   auto a = absl::OTABSL_OPTION_NAMESPACE_NAME::variant<int, std::string>;
+//   constexpr int num_types =
+//       absl::OTABSL_OPTION_NAMESPACE_NAME::variant_size<absl::OTABSL_OPTION_NAMESPACE_NAME::variant<int, std::string>>();
+//
+//   // You can also use the member constant `value`.
+//   constexpr int num_types =
+//       absl::OTABSL_OPTION_NAMESPACE_NAME::variant_size<absl::OTABSL_OPTION_NAMESPACE_NAME::variant<int, std::string>>::value;
+//
+//   // `absl::OTABSL_OPTION_NAMESPACE_NAME::variant_size` is more valuable for use in generic code:
+//   template <typename Variant>
+//   constexpr bool IsVariantMultivalue() {
+//       return absl::OTABSL_OPTION_NAMESPACE_NAME::variant_size<Variant>() > 1;
+//   }
+//
+// Note that the set of cv-qualified specializations of `variant_size` are
+// provided to ensure that those specializations compile (especially when passed
+// within template logic).
+template <class T>
+struct variant_size;
+
+template <class... Ts>
+struct variant_size<variant<Ts...>>
+    : std::integral_constant<std::size_t, sizeof...(Ts)> {};
+
+// Specialization of `variant_size` for const qualified variants.
+template <class T>
+struct variant_size<const T> : variant_size<T>::type {};
+
+// Specialization of `variant_size` for volatile qualified variants.
+template <class T>
+struct variant_size<volatile T> : variant_size<T>::type {};
+
+// Specialization of `variant_size` for const volatile qualified variants.
+template <class T>
+struct variant_size<const volatile T> : variant_size<T>::type {};
+
+// variant_alternative
+//
+// Returns the alternative type for a given `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` at the passed
+// index value as a compile-time constant expression. As this is a class
+// template resulting in a type, it is not useful for access of the run-time
+// value of any given `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` variable.
+//
+// Example:
+//
+//   // The type of the 0th alternative is "int".
+//   using alternative_type_0
+//     = absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative<0, absl::OTABSL_OPTION_NAMESPACE_NAME::variant<int, std::string>>::type;
+//
+//   static_assert(std::is_same<alternative_type_0, int>::value, "");
+//
+//   // `absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative` is more valuable for use in generic code:
+//   template <typename Variant>
+//   constexpr bool IsFirstElementTrivial() {
+//       return std::is_trivial_v<variant_alternative<0, Variant>::type>;
+//   }
+//
+// Note that the set of cv-qualified specializations of `variant_alternative`
+// are provided to ensure that those specializations compile (especially when
+// passed within template logic).
+template <std::size_t I, class T>
+struct variant_alternative;
+
+template <std::size_t I, class... Types>
+struct variant_alternative<I, variant<Types...>> {
+  using type =
+      variant_internal::VariantAlternativeSfinaeT<I, variant<Types...>>;
+};
+
+// Specialization of `variant_alternative` for const qualified variants.
+template <std::size_t I, class T>
+struct variant_alternative<I, const T> {
+  using type = const typename variant_alternative<I, T>::type;
+};
+
+// Specialization of `variant_alternative` for volatile qualified variants.
+template <std::size_t I, class T>
+struct variant_alternative<I, volatile T> {
+  using type = volatile typename variant_alternative<I, T>::type;
+};
+
+// Specialization of `variant_alternative` for const volatile qualified
+// variants.
+template <std::size_t I, class T>
+struct variant_alternative<I, const volatile T> {
+  using type = const volatile typename variant_alternative<I, T>::type;
+};
+
+// Template type alias for variant_alternative<I, T>::type.
+//
+// Example:
+//
+//   using alternative_type_0
+//     = absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative_t<0, absl::OTABSL_OPTION_NAMESPACE_NAME::variant<int, std::string>>;
+//   static_assert(std::is_same<alternative_type_0, int>::value, "");
+template <std::size_t I, class T>
+using variant_alternative_t = typename variant_alternative<I, T>::type;
+
+// holds_alternative()
+//
+// Checks whether the given variant currently holds a given alternative type,
+// returning `true` if so.
+//
+// Example:
+//
+//   absl::OTABSL_OPTION_NAMESPACE_NAME::variant<int, std::string> foo = 42;
+//   if (absl::OTABSL_OPTION_NAMESPACE_NAME::holds_alternative<int>(foo)) {
+//       std::cout << "The variant holds an integer";
+//   }
+template <class T, class... Types>
+constexpr bool holds_alternative(const variant<Types...>& v) noexcept {
+  static_assert(
+      variant_internal::UnambiguousIndexOfImpl<variant<Types...>, T,
+                                               0>::value != sizeof...(Types),
+      "The type T must occur exactly once in Types...");
+  return v.index() ==
+         variant_internal::UnambiguousIndexOf<variant<Types...>, T>::value;
+}
+
+// get()
+//
+// Returns a reference to the value currently within a given variant, using
+// either a unique alternative type amongst the variant's set of alternative
+// types, or the variant's index value. Attempting to get a variant's value
+// using a type that is not unique within the variant's set of alternative types
+// is a compile-time error. If the index of the alternative being specified is
+// different from the index of the alternative that is currently stored, throws
+// `absl::OTABSL_OPTION_NAMESPACE_NAME::bad_variant_access`.
+//
+// Example:
+//
+//   auto a = absl::OTABSL_OPTION_NAMESPACE_NAME::variant<int, std::string>;
+//
+//   // Get the value by type (if unique).
+//   int i = absl::OTABSL_OPTION_NAMESPACE_NAME::get<int>(a);
+//
+//   auto b = absl::OTABSL_OPTION_NAMESPACE_NAME::variant<int, int>;
+//
+//   // Getting the value by a type that is not unique is ill-formed.
+//   int j = absl::OTABSL_OPTION_NAMESPACE_NAME::get<int>(b);     // Compile Error!
+//
+//   // Getting value by index not ambiguous and allowed.
+//   int k = absl::OTABSL_OPTION_NAMESPACE_NAME::get<1>(b);
+
+// Overload for getting a variant's lvalue by type.
+template <class T, class... Types>
+constexpr T& get(variant<Types...>& v) {  // NOLINT
+  return variant_internal::VariantCoreAccess::CheckedAccess<
+      variant_internal::IndexOf<T, Types...>::value>(v);
+}
+
+// Overload for getting a variant's rvalue by type.
+// Note: `absl::OTABSL_OPTION_NAMESPACE_NAME::move()` is required to allow use of constexpr in C++11.
+template <class T, class... Types>
+constexpr T&& get(variant<Types...>&& v) {
+  return variant_internal::VariantCoreAccess::CheckedAccess<
+      variant_internal::IndexOf<T, Types...>::value>(absl::OTABSL_OPTION_NAMESPACE_NAME::move(v));
+}
+
+// Overload for getting a variant's const lvalue by type.
+template <class T, class... Types>
+constexpr const T& get(const variant<Types...>& v) {
+  return variant_internal::VariantCoreAccess::CheckedAccess<
+      variant_internal::IndexOf<T, Types...>::value>(v);
+}
+
+// Overload for getting a variant's const rvalue by type.
+// Note: `absl::OTABSL_OPTION_NAMESPACE_NAME::move()` is required to allow use of constexpr in C++11.
+template <class T, class... Types>
+constexpr const T&& get(const variant<Types...>&& v) {
+  return variant_internal::VariantCoreAccess::CheckedAccess<
+      variant_internal::IndexOf<T, Types...>::value>(absl::OTABSL_OPTION_NAMESPACE_NAME::move(v));
+}
+
+// Overload for getting a variant's lvalue by index.
+template <std::size_t I, class... Types>
+constexpr variant_alternative_t<I, variant<Types...>>& get(
+    variant<Types...>& v) {  // NOLINT
+  return variant_internal::VariantCoreAccess::CheckedAccess<I>(v);
+}
+
+// Overload for getting a variant's rvalue by index.
+// Note: `absl::OTABSL_OPTION_NAMESPACE_NAME::move()` is required to allow use of constexpr in C++11.
+template <std::size_t I, class... Types>
+constexpr variant_alternative_t<I, variant<Types...>>&& get(
+    variant<Types...>&& v) {
+  return variant_internal::VariantCoreAccess::CheckedAccess<I>(absl::OTABSL_OPTION_NAMESPACE_NAME::move(v));
+}
+
+// Overload for getting a variant's const lvalue by index.
+template <std::size_t I, class... Types>
+constexpr const variant_alternative_t<I, variant<Types...>>& get(
+    const variant<Types...>& v) {
+  return variant_internal::VariantCoreAccess::CheckedAccess<I>(v);
+}
+
+// Overload for getting a variant's const rvalue by index.
+// Note: `absl::OTABSL_OPTION_NAMESPACE_NAME::move()` is required to allow use of constexpr in C++11.
+template <std::size_t I, class... Types>
+constexpr const variant_alternative_t<I, variant<Types...>>&& get(
+    const variant<Types...>&& v) {
+  return variant_internal::VariantCoreAccess::CheckedAccess<I>(absl::OTABSL_OPTION_NAMESPACE_NAME::move(v));
+}
+
+// get_if()
+//
+// Returns a pointer to the value currently stored within a given variant, if
+// present, using either a unique alternative type amongst the variant's set of
+// alternative types, or the variant's index value. If such a value does not
+// exist, returns `nullptr`.
+//
+// As with `get`, attempting to get a variant's value using a type that is not
+// unique within the variant's set of alternative types is a compile-time error.
+
+// Overload for getting a pointer to the value stored in the given variant by
+// index.
+template <std::size_t I, class... Types>
+constexpr absl::OTABSL_OPTION_NAMESPACE_NAME::add_pointer_t<variant_alternative_t<I, variant<Types...>>>
+get_if(variant<Types...>* v) noexcept {
+  return (v != nullptr && v->index() == I)
+             ? std::addressof(
+                   variant_internal::VariantCoreAccess::Access<I>(*v))
+             : nullptr;
+}
+
+// Overload for getting a pointer to the const value stored in the given
+// variant by index.
+template <std::size_t I, class... Types>
+constexpr absl::OTABSL_OPTION_NAMESPACE_NAME::add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
+get_if(const variant<Types...>* v) noexcept {
+  return (v != nullptr && v->index() == I)
+             ? std::addressof(
+                   variant_internal::VariantCoreAccess::Access<I>(*v))
+             : nullptr;
+}
+
+// Overload for getting a pointer to the value stored in the given variant by
+// type.
+template <class T, class... Types>
+constexpr absl::OTABSL_OPTION_NAMESPACE_NAME::add_pointer_t<T> get_if(variant<Types...>* v) noexcept {
+  return absl::OTABSL_OPTION_NAMESPACE_NAME::get_if<variant_internal::IndexOf<T, Types...>::value>(v);
+}
+
+// Overload for getting a pointer to the const value stored in the given variant
+// by type.
+template <class T, class... Types>
+constexpr absl::OTABSL_OPTION_NAMESPACE_NAME::add_pointer_t<const T> get_if(
+    const variant<Types...>* v) noexcept {
+  return absl::OTABSL_OPTION_NAMESPACE_NAME::get_if<variant_internal::IndexOf<T, Types...>::value>(v);
+}
+
+// visit()
+//
+// Calls a provided functor on a given set of variants. `absl::OTABSL_OPTION_NAMESPACE_NAME::visit()` is
+// commonly used to conditionally inspect the state of a given variant (or set
+// of variants).
+//
+// The functor must return the same type when called with any of the variants'
+// alternatives.
+//
+// Example:
+//
+//   // Define a visitor functor
+//   struct GetVariant {
+//       template<typename T>
+//       void operator()(const T& i) const {
+//         std::cout << "The variant's value is: " << i;
+//       }
+//   };
+//
+//   // Declare our variant, and call `absl::OTABSL_OPTION_NAMESPACE_NAME::visit()` on it.
+//   // Note that `GetVariant()` returns void in either case.
+//   absl::OTABSL_OPTION_NAMESPACE_NAME::variant<int, std::string> foo = std::string("foo");
+//   GetVariant visitor;
+//   absl::OTABSL_OPTION_NAMESPACE_NAME::visit(visitor, foo);  // Prints `The variant's value is: foo'
+template <typename Visitor, typename... Variants>
+variant_internal::VisitResult<Visitor, Variants...> visit(Visitor&& vis,
+                                                          Variants&&... vars) {
+  return variant_internal::
+      VisitIndices<variant_size<absl::OTABSL_OPTION_NAMESPACE_NAME::decay_t<Variants> >::value...>::Run(
+          variant_internal::PerformVisitation<Visitor, Variants...>{
+              std::forward_as_tuple(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Variants>(vars)...),
+              absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Visitor>(vis)},
+          vars.index()...);
+}
+
+// monostate
+//
+// The monostate class serves as a first alternative type for a variant for
+// which the first variant type is otherwise not default-constructible.
+struct monostate {};
+
+// `absl::OTABSL_OPTION_NAMESPACE_NAME::monostate` Relational Operators
+
+constexpr bool operator<(monostate, monostate) noexcept { return false; }
+constexpr bool operator>(monostate, monostate) noexcept { return false; }
+constexpr bool operator<=(monostate, monostate) noexcept { return true; }
+constexpr bool operator>=(monostate, monostate) noexcept { return true; }
+constexpr bool operator==(monostate, monostate) noexcept { return true; }
+constexpr bool operator!=(monostate, monostate) noexcept { return false; }
+
+
+//------------------------------------------------------------------------------
+// `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` Template Definition
+//------------------------------------------------------------------------------
+template <typename T0, typename... Tn>
+class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
+  static_assert(absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<std::is_object<T0>,
+                                  std::is_object<Tn>...>::value,
+                "Attempted to instantiate a variant containing a non-object "
+                "type.");
+  // Intentionally not qualifying `negation` with `absl::OTABSL_OPTION_NAMESPACE_NAME::` to work around a bug
+  // in MSVC 2015 with inline namespace and variadic template.
+  static_assert(absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<negation<std::is_array<T0> >,
+                                  negation<std::is_array<Tn> >...>::value,
+                "Attempted to instantiate a variant containing an array type.");
+  static_assert(absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<std::is_nothrow_destructible<T0>,
+                                  std::is_nothrow_destructible<Tn>...>::value,
+                "Attempted to instantiate a variant containing a non-nothrow "
+                "destructible type.");
+
+  friend struct variant_internal::VariantCoreAccess;
+
+ private:
+  using Base = variant_internal::VariantBase<T0, Tn...>;
+
+ public:
+  // Constructors
+
+  // Constructs a variant holding a default-initialized value of the first
+  // alternative type.
+  constexpr variant() /*noexcept(see 111above)*/ = default;
+
+  // Copy constructor, standard semantics
+  variant(const variant& other) = default;
+
+  // Move constructor, standard semantics
+  variant(variant&& other) /*noexcept(see above)*/ = default;
+
+  // Constructs a variant of an alternative type specified by overload
+  // resolution of the provided forwarding arguments through
+  // direct-initialization.
+  //
+  // Note: If the selected constructor is a constexpr constructor, this
+  // constructor shall be a constexpr constructor.
+  //
+  // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r1.html
+  // has been voted passed the design phase in the C++ standard meeting in Mar
+  // 2018. It will be implemented and integrated into `absl::OTABSL_OPTION_NAMESPACE_NAME::variant`.
+  template <
+      class T,
+      std::size_t I = std::enable_if<
+          variant_internal::IsNeitherSelfNorInPlace<variant,
+                                                    absl::OTABSL_OPTION_NAMESPACE_NAME::decay_t<T>>::value,
+          variant_internal::IndexOfConstructedType<variant, T>>::type::value,
+      class Tj = absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative_t<I, variant>,
+      absl::OTABSL_OPTION_NAMESPACE_NAME::enable_if_t<std::is_constructible<Tj, T>::value>* =
+          nullptr>
+  constexpr variant(T&& t) noexcept(std::is_nothrow_constructible<Tj, T>::value)
+      : Base(variant_internal::EmplaceTag<I>(), absl::OTABSL_OPTION_NAMESPACE_NAME::forward<T>(t)) {}
+
+  // Constructs a variant of an alternative type from the arguments through
+  // direct-initialization.
+  //
+  // Note: If the selected constructor is a constexpr constructor, this
+  // constructor shall be a constexpr constructor.
+  template <class T, class... Args,
+            typename std::enable_if<std::is_constructible<
+                variant_internal::UnambiguousTypeOfT<variant, T>,
+                Args...>::value>::type* = nullptr>
+  constexpr explicit variant(in_place_type_t<T>, Args&&... args)
+      : Base(variant_internal::EmplaceTag<
+                 variant_internal::UnambiguousIndexOf<variant, T>::value>(),
+             absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Args>(args)...) {}
+
+  // Constructs a variant of an alternative type from an initializer list
+  // and other arguments through direct-initialization.
+  //
+  // Note: If the selected constructor is a constexpr constructor, this
+  // constructor shall be a constexpr constructor.
+  template <class T, class U, class... Args,
+            typename std::enable_if<std::is_constructible<
+                variant_internal::UnambiguousTypeOfT<variant, T>,
+                std::initializer_list<U>&, Args...>::value>::type* = nullptr>
+  constexpr explicit variant(in_place_type_t<T>, std::initializer_list<U> il,
+                             Args&&... args)
+      : Base(variant_internal::EmplaceTag<
+                 variant_internal::UnambiguousIndexOf<variant, T>::value>(),
+             il, absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Args>(args)...) {}
+
+  // Constructs a variant of an alternative type from a provided index,
+  // through value-initialization using the provided forwarded arguments.
+  template <std::size_t I, class... Args,
+            typename std::enable_if<std::is_constructible<
+                variant_internal::VariantAlternativeSfinaeT<I, variant>,
+                Args...>::value>::type* = nullptr>
+  constexpr explicit variant(in_place_index_t<I>, Args&&... args)
+      : Base(variant_internal::EmplaceTag<I>(), absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Args>(args)...) {}
+
+  // Constructs a variant of an alternative type from a provided index,
+  // through value-initialization of an initializer list and the provided
+  // forwarded arguments.
+  template <std::size_t I, class U, class... Args,
+            typename std::enable_if<std::is_constructible<
+                variant_internal::VariantAlternativeSfinaeT<I, variant>,
+                std::initializer_list<U>&, Args...>::value>::type* = nullptr>
+  constexpr explicit variant(in_place_index_t<I>, std::initializer_list<U> il,
+                             Args&&... args)
+      : Base(variant_internal::EmplaceTag<I>(), il,
+             absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Args>(args)...) {}
+
+  // Destructors
+
+  // Destroys the variant's currently contained value, provided that
+  // `absl::OTABSL_OPTION_NAMESPACE_NAME::valueless_by_exception()` is false.
+  ~variant() = default;
+
+  // Assignment Operators
+
+  // Copy assignment operator
+  variant& operator=(const variant& other) = default;
+
+  // Move assignment operator
+  variant& operator=(variant&& other) /*noexcept(see above)*/ = default;
+
+  // Converting assignment operator
+  //
+  // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r1.html
+  // has been voted passed the design phase in the C++ standard meeting in Mar
+  // 2018. It will be implemented and integrated into `absl::OTABSL_OPTION_NAMESPACE_NAME::variant`.
+  template <
+      class T,
+      std::size_t I = std::enable_if<
+          !std::is_same<absl::OTABSL_OPTION_NAMESPACE_NAME::decay_t<T>, variant>::value,
+          variant_internal::IndexOfConstructedType<variant, T>>::type::value,
+      class Tj = absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative_t<I, variant>,
+      typename std::enable_if<std::is_assignable<Tj&, T>::value &&
+                              std::is_constructible<Tj, T>::value>::type* =
+          nullptr>
+  variant& operator=(T&& t) noexcept(
+      std::is_nothrow_assignable<Tj&, T>::value&&
+          std::is_nothrow_constructible<Tj, T>::value) {
+    variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run(
+        variant_internal::VariantCoreAccess::MakeConversionAssignVisitor(
+            this, absl::OTABSL_OPTION_NAMESPACE_NAME::forward<T>(t)),
+        index());
+
+    return *this;
+  }
+
+
+  // emplace() Functions
+
+  // Constructs a value of the given alternative type T within the variant. The
+  // existing value of the variant is destroyed first (provided that
+  // `absl::OTABSL_OPTION_NAMESPACE_NAME::valueless_by_exception()` is false). Requires that T is unambiguous
+  // in the variant.
+  //
+  // Example:
+  //
+  //   absl::OTABSL_OPTION_NAMESPACE_NAME::variant<std::vector<int>, int, std::string> v;
+  //   v.emplace<int>(99);
+  //   v.emplace<std::string>("abc");
+  template <
+      class T, class... Args,
+      typename std::enable_if<std::is_constructible<
+          absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative_t<
+              variant_internal::UnambiguousIndexOf<variant, T>::value, variant>,
+          Args...>::value>::type* = nullptr>
+  T& emplace(Args&&... args) {
+    return variant_internal::VariantCoreAccess::Replace<
+        variant_internal::UnambiguousIndexOf<variant, T>::value>(
+        this, absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Args>(args)...);
+  }
+
+  // Constructs a value of the given alternative type T within the variant using
+  // an initializer list. The existing value of the variant is destroyed first
+  // (provided that `absl::OTABSL_OPTION_NAMESPACE_NAME::valueless_by_exception()` is false). Requires that T
+  // is unambiguous in the variant.
+  //
+  // Example:
+  //
+  //   absl::OTABSL_OPTION_NAMESPACE_NAME::variant<std::vector<int>, int, std::string> v;
+  //   v.emplace<std::vector<int>>({0, 1, 2});
+  template <
+      class T, class U, class... Args,
+      typename std::enable_if<std::is_constructible<
+          absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative_t<
+              variant_internal::UnambiguousIndexOf<variant, T>::value, variant>,
+          std::initializer_list<U>&, Args...>::value>::type* = nullptr>
+  T& emplace(std::initializer_list<U> il, Args&&... args) {
+    return variant_internal::VariantCoreAccess::Replace<
+        variant_internal::UnambiguousIndexOf<variant, T>::value>(
+        this, il, absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Args>(args)...);
+  }
+
+  // Destroys the current value of the variant (provided that
+  // `absl::OTABSL_OPTION_NAMESPACE_NAME::valueless_by_exception()` is false) and constructs a new value at
+  // the given index.
+  //
+  // Example:
+  //
+  //   absl::OTABSL_OPTION_NAMESPACE_NAME::variant<std::vector<int>, int, int> v;
+  //   v.emplace<1>(99);
+  //   v.emplace<2>(98);
+  //   v.emplace<int>(99);  // Won't compile. 'int' isn't a unique type.
+  template <std::size_t I, class... Args,
+            typename std::enable_if<
+                std::is_constructible<absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative_t<I, variant>,
+                                      Args...>::value>::type* = nullptr>
+  absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative_t<I, variant>& emplace(Args&&... args) {
+    return variant_internal::VariantCoreAccess::Replace<I>(
+        this, absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Args>(args)...);
+  }
+
+  // Destroys the current value of the variant (provided that
+  // `absl::OTABSL_OPTION_NAMESPACE_NAME::valueless_by_exception()` is false) and constructs a new value at
+  // the given index using an initializer list and the provided arguments.
+  //
+  // Example:
+  //
+  //   absl::OTABSL_OPTION_NAMESPACE_NAME::variant<std::vector<int>, int, int> v;
+  //   v.emplace<0>({0, 1, 2});
+  template <std::size_t I, class U, class... Args,
+            typename std::enable_if<std::is_constructible<
+                absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative_t<I, variant>,
+                std::initializer_list<U>&, Args...>::value>::type* = nullptr>
+  absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative_t<I, variant>& emplace(std::initializer_list<U> il,
+                                                   Args&&... args) {
+    return variant_internal::VariantCoreAccess::Replace<I>(
+        this, il, absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Args>(args)...);
+  }
+
+  // variant::valueless_by_exception()
+  //
+  // Returns false if and only if the variant currently holds a valid value.
+  constexpr bool valueless_by_exception() const noexcept {
+    return this->index_ == absl::OTABSL_OPTION_NAMESPACE_NAME::variant_npos;
+  }
+
+  // variant::index()
+  //
+  // Returns the index value of the variant's currently selected alternative
+  // type.
+  constexpr std::size_t index() const noexcept { return this->index_; }
+
+  // variant::swap()
+  //
+  // Swaps the values of two variant objects.
+  //
+  void swap(variant& rhs) noexcept(
+      absl::OTABSL_OPTION_NAMESPACE_NAME::conjunction<
+          std::is_nothrow_move_constructible<T0>,
+          std::is_nothrow_move_constructible<Tn>...,
+          type_traits_internal::IsNothrowSwappable<T0>,
+          type_traits_internal::IsNothrowSwappable<Tn>...>::value) {
+    return variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run(
+        variant_internal::Swap<T0, Tn...>{this, &rhs}, rhs.index());
+  }
+};
+
+// We need a valid declaration of variant<> for SFINAE and overload resolution
+// to work properly above, but we don't need a full declaration since this type
+// will never be constructed. This declaration, though incomplete, suffices.
+template <>
+class variant<>;
+
+//------------------------------------------------------------------------------
+// Relational Operators
+//------------------------------------------------------------------------------
+//
+// If neither operand is in the `variant::valueless_by_exception` state:
+//
+//   * If the index of both variants is the same, the relational operator
+//     returns the result of the corresponding relational operator for the
+//     corresponding alternative type.
+//   * If the index of both variants is not the same, the relational operator
+//     returns the result of that operation applied to the value of the left
+//     operand's index and the value of the right operand's index.
+//   * If at least one operand is in the valueless_by_exception state:
+//     - A variant in the valueless_by_exception state is only considered equal
+//       to another variant in the valueless_by_exception state.
+//     - If exactly one operand is in the valueless_by_exception state, the
+//       variant in the valueless_by_exception state is less than the variant
+//       that is not in the valueless_by_exception state.
+//
+// Note: The value 1 is added to each index in the relational comparisons such
+// that the index corresponding to the valueless_by_exception state wraps around
+// to 0 (the lowest value for the index type), and the remaining indices stay in
+// the same relative order.
+
+// Equal-to operator
+template <typename... Types>
+constexpr variant_internal::RequireAllHaveEqualT<Types...> operator==(
+    const variant<Types...>& a, const variant<Types...>& b) {
+  return (a.index() == b.index()) &&
+         variant_internal::VisitIndices<sizeof...(Types)>::Run(
+             variant_internal::EqualsOp<Types...>{&a, &b}, a.index());
+}
+
+// Not equal operator
+template <typename... Types>
+constexpr variant_internal::RequireAllHaveNotEqualT<Types...> operator!=(
+    const variant<Types...>& a, const variant<Types...>& b) {
+  return (a.index() != b.index()) ||
+         variant_internal::VisitIndices<sizeof...(Types)>::Run(
+             variant_internal::NotEqualsOp<Types...>{&a, &b}, a.index());
+}
+
+// Less-than operator
+template <typename... Types>
+constexpr variant_internal::RequireAllHaveLessThanT<Types...> operator<(
+    const variant<Types...>& a, const variant<Types...>& b) {
+  return (a.index() != b.index())
+             ? (a.index() + 1) < (b.index() + 1)
+             : variant_internal::VisitIndices<sizeof...(Types)>::Run(
+                   variant_internal::LessThanOp<Types...>{&a, &b}, a.index());
+}
+
+// Greater-than operator
+template <typename... Types>
+constexpr variant_internal::RequireAllHaveGreaterThanT<Types...> operator>(
+    const variant<Types...>& a, const variant<Types...>& b) {
+  return (a.index() != b.index())
+             ? (a.index() + 1) > (b.index() + 1)
+             : variant_internal::VisitIndices<sizeof...(Types)>::Run(
+                   variant_internal::GreaterThanOp<Types...>{&a, &b},
+                   a.index());
+}
+
+// Less-than or equal-to operator
+template <typename... Types>
+constexpr variant_internal::RequireAllHaveLessThanOrEqualT<Types...> operator<=(
+    const variant<Types...>& a, const variant<Types...>& b) {
+  return (a.index() != b.index())
+             ? (a.index() + 1) < (b.index() + 1)
+             : variant_internal::VisitIndices<sizeof...(Types)>::Run(
+                   variant_internal::LessThanOrEqualsOp<Types...>{&a, &b},
+                   a.index());
+}
+
+// Greater-than or equal-to operator
+template <typename... Types>
+constexpr variant_internal::RequireAllHaveGreaterThanOrEqualT<Types...>
+operator>=(const variant<Types...>& a, const variant<Types...>& b) {
+  return (a.index() != b.index())
+             ? (a.index() + 1) > (b.index() + 1)
+             : variant_internal::VisitIndices<sizeof...(Types)>::Run(
+                   variant_internal::GreaterThanOrEqualsOp<Types...>{&a, &b},
+                   a.index());
+}
+
+OTABSL_NAMESPACE_END
+}  // namespace absl
+
+namespace std {
+
+// hash()
+template <>  // NOLINT
+struct hash<absl::OTABSL_OPTION_NAMESPACE_NAME::monostate> {
+  std::size_t operator()(absl::OTABSL_OPTION_NAMESPACE_NAME::monostate) const { return 0; }
+};
+
+template <class... T>  // NOLINT
+struct hash<absl::OTABSL_OPTION_NAMESPACE_NAME::variant<T...>>
+    : absl::OTABSL_OPTION_NAMESPACE_NAME::variant_internal::VariantHashBase<absl::OTABSL_OPTION_NAMESPACE_NAME::variant<T...>, void,
+                                              absl::OTABSL_OPTION_NAMESPACE_NAME::remove_const_t<T>...> {};
+
+}  // namespace std
+
+#endif  // OTABSL_USES_STD_VARIANT
+
+namespace absl {
+OTABSL_NAMESPACE_BEGIN
+namespace variant_internal {
+
+// Helper visitor for converting a variant<Ts...>` into another type (mostly
+// variant) that can be constructed from any type.
+template <typename To>
+struct ConversionVisitor {
+  template <typename T>
+  To operator()(T&& v) const {
+    return To(std::forward<T>(v));
+  }
+};
+
+}  // namespace variant_internal
+
+// ConvertVariantTo()
+//
+// Helper functions to convert an `absl::OTABSL_OPTION_NAMESPACE_NAME::variant` to a variant of another set of
+// types, provided that the alternative type of the new variant type can be
+// converted from any type in the source variant.
+//
+// Example:
+//
+//   absl::OTABSL_OPTION_NAMESPACE_NAME::variant<name1, name2, float> InternalReq(const Req&);
+//
+//   // name1 and name2 are convertible to name
+//   absl::OTABSL_OPTION_NAMESPACE_NAME::variant<name, float> ExternalReq(const Req& req) {
+//     return absl::OTABSL_OPTION_NAMESPACE_NAME::ConvertVariantTo<absl::OTABSL_OPTION_NAMESPACE_NAME::variant<name, float>>(
+//              InternalReq(req));
+//   }
+template <typename To, typename Variant>
+To ConvertVariantTo(Variant&& variant) {
+  return absl::OTABSL_OPTION_NAMESPACE_NAME::visit(variant_internal::ConversionVisitor<To>{},
+                     std::forward<Variant>(variant));
+}
+
+OTABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // OTABSL_TYPES_VARIANT_H_

+ 350 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/internal/absl/utility/utility.h

@@ -0,0 +1,350 @@
+// Copyright 2017 The Abseil 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
+//
+//      https://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.
+//
+// This header file contains C++11 versions of standard <utility> header
+// abstractions available within C++14 and C++17, and are designed to be drop-in
+// replacement for code compliant with C++14 and C++17.
+//
+// The following abstractions are defined:
+//
+//   * integer_sequence<T, Ints...>  == std::integer_sequence<T, Ints...>
+//   * index_sequence<Ints...>       == std::index_sequence<Ints...>
+//   * make_integer_sequence<T, N>   == std::make_integer_sequence<T, N>
+//   * make_index_sequence<N>        == std::make_index_sequence<N>
+//   * index_sequence_for<Ts...>     == std::index_sequence_for<Ts...>
+//   * apply<Functor, Tuple>         == std::apply<Functor, Tuple>
+//   * exchange<T>                   == std::exchange<T>
+//   * make_from_tuple<T>            == std::make_from_tuple<T>
+//
+// This header file also provides the tag types `in_place_t`, `in_place_type_t`,
+// and `in_place_index_t`, as well as the constant `in_place`, and
+// `constexpr` `std::move()` and `std::forward()` implementations in C++11.
+//
+// References:
+//
+//  https://en.cppreference.com/w/cpp/utility/integer_sequence
+//  https://en.cppreference.com/w/cpp/utility/apply
+//  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html
+
+#ifndef OTABSL_UTILITY_UTILITY_H_
+#define OTABSL_UTILITY_UTILITY_H_
+
+#include <cstddef>
+#include <cstdlib>
+#include <tuple>
+#include <utility>
+
+#include "../base/config.h"
+#include "../base/internal/inline_variable.h"
+#include "../base/internal/invoke.h"
+#include "../meta/type_traits.h"
+
+namespace absl {
+OTABSL_NAMESPACE_BEGIN
+
+// integer_sequence
+//
+// Class template representing a compile-time integer sequence. An instantiation
+// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
+// type through its template arguments (which is a common need when
+// working with C++11 variadic templates). `absl::OTABSL_OPTION_NAMESPACE_NAME::integer_sequence` is designed
+// to be a drop-in replacement for C++14's `std::integer_sequence`.
+//
+// Example:
+//
+//   template< class T, T... Ints >
+//   void user_function(integer_sequence<T, Ints...>);
+//
+//   int main()
+//   {
+//     // user_function's `T` will be deduced to `int` and `Ints...`
+//     // will be deduced to `0, 1, 2, 3, 4`.
+//     user_function(make_integer_sequence<int, 5>());
+//   }
+template <typename T, T... Ints>
+struct integer_sequence {
+  using value_type = T;
+  static constexpr size_t size() noexcept { return sizeof...(Ints); }
+};
+
+// index_sequence
+//
+// A helper template for an `integer_sequence` of `size_t`,
+// `absl::OTABSL_OPTION_NAMESPACE_NAME::index_sequence` is designed to be a drop-in replacement for C++14's
+// `std::index_sequence`.
+template <size_t... Ints>
+using index_sequence = integer_sequence<size_t, Ints...>;
+
+namespace utility_internal {
+
+template <typename Seq, size_t SeqSize, size_t Rem>
+struct Extend;
+
+// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
+template <typename T, T... Ints, size_t SeqSize>
+struct Extend<integer_sequence<T, Ints...>, SeqSize, 0> {
+  using type = integer_sequence<T, Ints..., (Ints + SeqSize)...>;
+};
+
+template <typename T, T... Ints, size_t SeqSize>
+struct Extend<integer_sequence<T, Ints...>, SeqSize, 1> {
+  using type = integer_sequence<T, Ints..., (Ints + SeqSize)..., 2 * SeqSize>;
+};
+
+// Recursion helper for 'make_integer_sequence<T, N>'.
+// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
+template <typename T, size_t N>
+struct Gen {
+  using type =
+      typename Extend<typename Gen<T, N / 2>::type, N / 2, N % 2>::type;
+};
+
+template <typename T>
+struct Gen<T, 0> {
+  using type = integer_sequence<T>;
+};
+
+template <typename T>
+struct InPlaceTypeTag {
+  explicit InPlaceTypeTag() = delete;
+  InPlaceTypeTag(const InPlaceTypeTag&) = delete;
+  InPlaceTypeTag& operator=(const InPlaceTypeTag&) = delete;
+};
+
+template <size_t I>
+struct InPlaceIndexTag {
+  explicit InPlaceIndexTag() = delete;
+  InPlaceIndexTag(const InPlaceIndexTag&) = delete;
+  InPlaceIndexTag& operator=(const InPlaceIndexTag&) = delete;
+};
+
+}  // namespace utility_internal
+
+// Compile-time sequences of integers
+
+// make_integer_sequence
+//
+// This template alias is equivalent to
+// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
+// replacement for C++14's `std::make_integer_sequence`.
+template <typename T, T N>
+using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
+
+// make_index_sequence
+//
+// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
+// and is designed to be a drop-in replacement for C++14's
+// `std::make_index_sequence`.
+template <size_t N>
+using make_index_sequence = make_integer_sequence<size_t, N>;
+
+// index_sequence_for
+//
+// Converts a typename pack into an index sequence of the same length, and
+// is designed to be a drop-in replacement for C++14's
+// `std::index_sequence_for()`
+template <typename... Ts>
+using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
+
+// Tag types
+
+#ifdef OTABSL_USES_STD_OPTIONAL
+
+using std::in_place_t;
+using std::in_place;
+
+#else  // OTABSL_USES_STD_OPTIONAL
+
+// in_place_t
+//
+// Tag type used to specify in-place construction, such as with
+// `absl::OTABSL_OPTION_NAMESPACE_NAME::optional`, designed to be a drop-in replacement for C++17's
+// `std::in_place_t`.
+struct in_place_t {};
+
+OTABSL_INTERNAL_INLINE_CONSTEXPR(in_place_t, in_place, {});
+
+#endif  // OTABSL_USES_STD_OPTIONAL
+
+#if defined(OTABSL_USES_STD_ANY) || defined(OTABSL_USES_STD_VARIANT)
+using std::in_place_type;
+using std::in_place_type_t;
+#else
+
+// in_place_type_t
+//
+// Tag type used for in-place construction when the type to construct needs to
+// be specified, such as with `absl::OTABSL_OPTION_NAMESPACE_NAME::any`, designed to be a drop-in replacement
+// for C++17's `std::in_place_type_t`.
+template <typename T>
+using in_place_type_t = void (*)(utility_internal::InPlaceTypeTag<T>);
+
+template <typename T>
+void in_place_type(utility_internal::InPlaceTypeTag<T>) {}
+#endif  // OTABSL_USES_STD_ANY || OTABSL_USES_STD_VARIANT
+
+#ifdef OTABSL_USES_STD_VARIANT
+using std::in_place_index;
+using std::in_place_index_t;
+#else
+
+// in_place_index_t
+//
+// Tag type used for in-place construction when the type to construct needs to
+// be specified, such as with `absl::OTABSL_OPTION_NAMESPACE_NAME::any`, designed to be a drop-in replacement
+// for C++17's `std::in_place_index_t`.
+template <size_t I>
+using in_place_index_t = void (*)(utility_internal::InPlaceIndexTag<I>);
+
+template <size_t I>
+void in_place_index(utility_internal::InPlaceIndexTag<I>) {}
+#endif  // OTABSL_USES_STD_VARIANT
+
+// Constexpr move and forward
+
+// move()
+//
+// A constexpr version of `std::move()`, designed to be a drop-in replacement
+// for C++14's `std::move()`.
+template <typename T>
+constexpr absl::OTABSL_OPTION_NAMESPACE_NAME::remove_reference_t<T>&& move(T&& t) noexcept {
+  return static_cast<absl::OTABSL_OPTION_NAMESPACE_NAME::remove_reference_t<T>&&>(t);
+}
+
+// forward()
+//
+// A constexpr version of `std::forward()`, designed to be a drop-in replacement
+// for C++14's `std::forward()`.
+template <typename T>
+constexpr T&& forward(
+    absl::OTABSL_OPTION_NAMESPACE_NAME::remove_reference_t<T>& t) noexcept {  // NOLINT(runtime/references)
+  return static_cast<T&&>(t);
+}
+
+namespace utility_internal {
+// Helper method for expanding tuple into a called method.
+template <typename Functor, typename Tuple, std::size_t... Indexes>
+auto apply_helper(Functor&& functor, Tuple&& t, index_sequence<Indexes...>)
+    -> decltype(absl::OTABSL_OPTION_NAMESPACE_NAME::base_internal::Invoke(
+        absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Functor>(functor),
+        std::get<Indexes>(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Tuple>(t))...)) {
+  return absl::OTABSL_OPTION_NAMESPACE_NAME::base_internal::Invoke(
+      absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Functor>(functor),
+      std::get<Indexes>(absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Tuple>(t))...);
+}
+
+}  // namespace utility_internal
+
+// apply
+//
+// Invokes a Callable using elements of a tuple as its arguments.
+// Each element of the tuple corresponds to an argument of the call (in order).
+// Both the Callable argument and the tuple argument are perfect-forwarded.
+// For member-function Callables, the first tuple element acts as the `this`
+// pointer. `absl::OTABSL_OPTION_NAMESPACE_NAME::apply` is designed to be a drop-in replacement for C++17's
+// `std::apply`. Unlike C++17's `std::apply`, this is not currently `constexpr`.
+//
+// Example:
+//
+//   class Foo {
+//    public:
+//     void Bar(int);
+//   };
+//   void user_function1(int, std::string);
+//   void user_function2(std::unique_ptr<Foo>);
+//   auto user_lambda = [](int, int) {};
+//
+//   int main()
+//   {
+//       std::tuple<int, std::string> tuple1(42, "bar");
+//       // Invokes the first user function on int, std::string.
+//       absl::OTABSL_OPTION_NAMESPACE_NAME::apply(&user_function1, tuple1);
+//
+//       std::tuple<std::unique_ptr<Foo>> tuple2(absl::OTABSL_OPTION_NAMESPACE_NAME::make_unique<Foo>());
+//       // Invokes the user function that takes ownership of the unique
+//       // pointer.
+//       absl::OTABSL_OPTION_NAMESPACE_NAME::apply(&user_function2, std::move(tuple2));
+//
+//       auto foo = absl::OTABSL_OPTION_NAMESPACE_NAME::make_unique<Foo>();
+//       std::tuple<Foo*, int> tuple3(foo.get(), 42);
+//       // Invokes the method Bar on foo with one argument, 42.
+//       absl::OTABSL_OPTION_NAMESPACE_NAME::apply(&Foo::Bar, tuple3);
+//
+//       std::tuple<int, int> tuple4(8, 9);
+//       // Invokes a lambda.
+//       absl::OTABSL_OPTION_NAMESPACE_NAME::apply(user_lambda, tuple4);
+//   }
+template <typename Functor, typename Tuple>
+auto apply(Functor&& functor, Tuple&& t)
+    -> decltype(utility_internal::apply_helper(
+        absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Functor>(functor), absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Tuple>(t),
+        absl::OTABSL_OPTION_NAMESPACE_NAME::make_index_sequence<std::tuple_size<
+            typename std::remove_reference<Tuple>::type>::value>{})) {
+  return utility_internal::apply_helper(
+      absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Functor>(functor), absl::OTABSL_OPTION_NAMESPACE_NAME::forward<Tuple>(t),
+      absl::OTABSL_OPTION_NAMESPACE_NAME::make_index_sequence<std::tuple_size<
+          typename std::remove_reference<Tuple>::type>::value>{});
+}
+
+// exchange
+//
+// Replaces the value of `obj` with `new_value` and returns the old value of
+// `obj`.  `absl::OTABSL_OPTION_NAMESPACE_NAME::exchange` is designed to be a drop-in replacement for C++14's
+// `std::exchange`.
+//
+// Example:
+//
+//   Foo& operator=(Foo&& other) {
+//     ptr1_ = absl::OTABSL_OPTION_NAMESPACE_NAME::exchange(other.ptr1_, nullptr);
+//     int1_ = absl::OTABSL_OPTION_NAMESPACE_NAME::exchange(other.int1_, -1);
+//     return *this;
+//   }
+template <typename T, typename U = T>
+T exchange(T& obj, U&& new_value) {
+  T old_value = absl::OTABSL_OPTION_NAMESPACE_NAME::move(obj);
+  obj = absl::OTABSL_OPTION_NAMESPACE_NAME::forward<U>(new_value);
+  return old_value;
+}
+
+namespace utility_internal {
+template <typename T, typename Tuple, size_t... I>
+T make_from_tuple_impl(Tuple&& tup, absl::OTABSL_OPTION_NAMESPACE_NAME::index_sequence<I...>) {
+  return T(std::get<I>(std::forward<Tuple>(tup))...);
+}
+}  // namespace utility_internal
+
+// make_from_tuple
+//
+// Given the template parameter type `T` and a tuple of arguments
+// `std::tuple(arg0, arg1, ..., argN)` constructs an object of type `T` as if by
+// calling `T(arg0, arg1, ..., argN)`.
+//
+// Example:
+//
+//   std::tuple<const char*, size_t> args("hello world", 5);
+//   auto s = absl::OTABSL_OPTION_NAMESPACE_NAME::make_from_tuple<std::string>(args);
+//   assert(s == "hello");
+//
+template <typename T, typename Tuple>
+constexpr T make_from_tuple(Tuple&& tup) {
+  return utility_internal::make_from_tuple_impl<T>(
+      std::forward<Tuple>(tup),
+      absl::OTABSL_OPTION_NAMESPACE_NAME::make_index_sequence<
+          std::tuple_size<absl::OTABSL_OPTION_NAMESPACE_NAME::decay_t<Tuple>>::value>{});
+}
+
+OTABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // OTABSL_UTILITY_UTILITY_H_

+ 210 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/shared_ptr.h

@@ -0,0 +1,210 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#if defined(OPENTELEMETRY_STL_VERSION)
+#  if OPENTELEMETRY_STL_VERSION >= 2011
+#    include "opentelemetry/std/shared_ptr.h"
+#    define OPENTELEMETRY_HAVE_STD_SHARED_PTR
+#  endif
+#endif
+
+#if !defined(OPENTELEMETRY_HAVE_STD_SHARED_PTR)
+#  include <cstdlib>
+#  include <memory>
+#  include <utility>
+
+#  include "opentelemetry/nostd/unique_ptr.h"
+#  include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+/**
+ * Provide a type-erased version of std::shared_ptr that has ABI stability.
+ */
+template <class T>
+class shared_ptr
+{
+public:
+  using element_type = T;
+  using pointer      = element_type *;
+
+private:
+  static constexpr size_t kMaxSize   = 32;
+  static constexpr size_t kAlignment = 8;
+
+  struct alignas(kAlignment) PlacementBuffer
+  {
+    char data[kMaxSize]{};
+  };
+
+  class shared_ptr_wrapper
+  {
+  public:
+    shared_ptr_wrapper() noexcept = default;
+
+    shared_ptr_wrapper(std::shared_ptr<T> &&ptr) noexcept : ptr_{std::move(ptr)} {}
+
+    virtual ~shared_ptr_wrapper() {}
+
+    virtual void CopyTo(PlacementBuffer &buffer) const noexcept
+    {
+      new (buffer.data) shared_ptr_wrapper{*this};
+    }
+
+    virtual void MoveTo(PlacementBuffer &buffer) noexcept
+    {
+      new (buffer.data) shared_ptr_wrapper{std::move(this->ptr_)};
+    }
+
+    template <class U,
+              typename std::enable_if<std::is_convertible<pointer, U *>::value>::type * = nullptr>
+    void MoveTo(typename shared_ptr<U>::PlacementBuffer &buffer) noexcept
+    {
+      using other_shared_ptr_wrapper = typename shared_ptr<U>::shared_ptr_wrapper;
+      new (buffer.data) other_shared_ptr_wrapper{std::move(this->ptr_)};
+    }
+
+    virtual pointer Get() const noexcept { return ptr_.get(); }
+
+    virtual void Reset() noexcept { ptr_.reset(); }
+
+  private:
+    std::shared_ptr<T> ptr_;
+  };
+
+  static_assert(sizeof(shared_ptr_wrapper) <= kMaxSize, "Placement buffer is too small");
+  static_assert(alignof(shared_ptr_wrapper) <= kAlignment, "Placement buffer not properly aligned");
+
+public:
+  shared_ptr() noexcept { new (buffer_.data) shared_ptr_wrapper{}; }
+
+  explicit shared_ptr(pointer ptr)
+  {
+    std::shared_ptr<T> ptr_(ptr);
+    new (buffer_.data) shared_ptr_wrapper{std::move(ptr_)};
+  }
+
+  shared_ptr(std::shared_ptr<T> ptr) noexcept
+  {
+    new (buffer_.data) shared_ptr_wrapper{std::move(ptr)};
+  }
+
+  shared_ptr(shared_ptr &&other) noexcept { other.wrapper().MoveTo(buffer_); }
+
+  template <class U,
+            typename std::enable_if<std::is_convertible<U *, pointer>::value>::type * = nullptr>
+  shared_ptr(shared_ptr<U> &&other) noexcept
+  {
+    other.wrapper().template MoveTo<T>(buffer_);
+  }
+
+  shared_ptr(const shared_ptr &other) noexcept { other.wrapper().CopyTo(buffer_); }
+
+  shared_ptr(unique_ptr<T> &&other) noexcept
+  {
+    std::shared_ptr<T> ptr_(other.release());
+    new (buffer_.data) shared_ptr_wrapper{std::move(ptr_)};
+  }
+
+  shared_ptr(std::unique_ptr<T> &&other) noexcept
+  {
+    std::shared_ptr<T> ptr_(other.release());
+    new (buffer_.data) shared_ptr_wrapper{std::move(ptr_)};
+  }
+
+  ~shared_ptr() { wrapper().~shared_ptr_wrapper(); }
+
+  shared_ptr &operator=(shared_ptr &&other) noexcept
+  {
+    wrapper().~shared_ptr_wrapper();
+    other.wrapper().MoveTo(buffer_);
+    return *this;
+  }
+
+  shared_ptr &operator=(std::nullptr_t) noexcept
+  {
+    wrapper().Reset();
+    return *this;
+  }
+
+  shared_ptr &operator=(const shared_ptr &other) noexcept
+  {
+    wrapper().~shared_ptr_wrapper();
+    other.wrapper().CopyTo(buffer_);
+    return *this;
+  }
+
+  element_type &operator*() const noexcept { return *wrapper().Get(); }
+
+  pointer operator->() const noexcept { return wrapper().Get(); }
+
+  operator bool() const noexcept { return wrapper().Get() != nullptr; }
+
+  pointer get() const noexcept { return wrapper().Get(); }
+
+  void swap(shared_ptr<T> &other) noexcept
+  {
+    shared_ptr<T> tmp{std::move(other)};
+
+    wrapper().MoveTo(other.buffer_);
+    tmp.wrapper().MoveTo(buffer_);
+  }
+
+  template <typename U>
+  friend class shared_ptr;
+
+private:
+  PlacementBuffer buffer_;
+
+  shared_ptr_wrapper &wrapper() noexcept
+  {
+    return *reinterpret_cast<shared_ptr_wrapper *>(buffer_.data);
+  }
+
+  const shared_ptr_wrapper &wrapper() const noexcept
+  {
+    return *reinterpret_cast<const shared_ptr_wrapper *>(buffer_.data);
+  }
+};
+
+template <class T1, class T2>
+bool operator!=(const shared_ptr<T1> &lhs, const shared_ptr<T2> &rhs) noexcept
+{
+  return lhs.get() != rhs.get();
+}
+
+template <class T1, class T2>
+bool operator==(const shared_ptr<T1> &lhs, const shared_ptr<T2> &rhs) noexcept
+{
+  return lhs.get() == rhs.get();
+}
+
+template <class T>
+inline bool operator==(const shared_ptr<T> &lhs, std::nullptr_t) noexcept
+{
+  return lhs.get() == nullptr;
+}
+
+template <class T>
+inline bool operator==(std::nullptr_t, const shared_ptr<T> &rhs) noexcept
+{
+  return nullptr == rhs.get();
+}
+
+template <class T>
+inline bool operator!=(const shared_ptr<T> &lhs, std::nullptr_t) noexcept
+{
+  return lhs.get() != nullptr;
+}
+
+template <class T>
+inline bool operator!=(std::nullptr_t, const shared_ptr<T> &rhs) noexcept
+{
+  return nullptr != rhs.get();
+}
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE
+#endif /* OPENTELEMETRY_HAVE_STD_SHARED_PTR */

+ 274 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/span.h

@@ -0,0 +1,274 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+// Try to use either `std::span` or `gsl::span`
+#if defined(OPENTELEMETRY_STL_VERSION)
+#  if OPENTELEMETRY_STL_VERSION >= 2020
+#    include <array>
+#    include <cstddef>
+#    include <iterator>
+#    include <type_traits>
+
+/**
+ * @brief Clang 14.0.0 with libc++ do not support implicitly construct a span
+ * for a range. We just use our fallback version.
+ *
+ */
+#    if !defined(OPENTELEMETRY_OPTION_USE_STD_SPAN) && defined(_LIBCPP_VERSION)
+#      if _LIBCPP_VERSION <= 14000
+#        define OPENTELEMETRY_OPTION_USE_STD_SPAN 0
+#      endif
+#    endif
+#    ifndef OPENTELEMETRY_OPTION_USE_STD_SPAN
+#      define OPENTELEMETRY_OPTION_USE_STD_SPAN 1
+#    endif
+#    if OPENTELEMETRY_OPTION_USE_STD_SPAN
+#      include "opentelemetry/std/span.h"
+#    endif
+#  endif /* OPENTELEMETRY_STL_VERSION >= 2020 */
+#endif   /* OPENTELEMETRY_STL_VERSION */
+
+// Fallback to `nostd::span` if necessary
+#if !defined(OPENTELEMETRY_HAVE_SPAN)
+#  include <array>
+#  include <cassert>
+#  include <cstddef>
+#  include <exception>
+#  include <iterator>
+#  include <type_traits>
+
+#  include "opentelemetry/nostd/utility.h"
+#  include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+constexpr size_t dynamic_extent = static_cast<size_t>(-1);
+
+template <class T, size_t Extent = dynamic_extent>
+class span;
+
+namespace detail
+{
+/**
+ * Helper class to resolve overloaded constructors
+ */
+template <class T>
+struct is_specialized_span_convertible : std::false_type
+{};
+
+template <class T, size_t N>
+struct is_specialized_span_convertible<std::array<T, N>> : std::true_type
+{};
+
+template <class T, size_t N>
+struct is_specialized_span_convertible<T[N]> : std::true_type
+{};
+
+template <class T, size_t Extent>
+struct is_specialized_span_convertible<span<T, Extent>> : std::true_type
+{};
+}  // namespace detail
+
+/**
+ * Back port of std::span.
+ *
+ * See https://en.cppreference.com/w/cpp/container/span for interface documentation.
+ *
+ * Note: This provides a subset of the methods available on std::span.
+ *
+ * Note: The std::span API specifies error cases to have undefined behavior, so this implementation
+ * chooses to terminate or assert rather than throw exceptions.
+ */
+template <class T, size_t Extent>
+class span
+{
+public:
+  static constexpr size_t extent = Extent;
+
+  // This arcane code is how we make default-construction result in an SFINAE error
+  // with C++11 when Extent != 0 as specified by the std::span API.
+  //
+  // See https://stackoverflow.com/a/10309720/4447365
+  template <bool B = Extent == 0, typename std::enable_if<B>::type * = nullptr>
+  span() noexcept : data_{nullptr}
+  {}
+
+  span(T *data, size_t count) noexcept : data_{data}
+  {
+    if (count != Extent)
+    {
+      std::terminate();
+    }
+  }
+
+  span(T *first, T *last) noexcept : data_{first}
+  {
+    if (std::distance(first, last) != Extent)
+    {
+      std::terminate();
+    }
+  }
+
+  template <size_t N, typename std::enable_if<Extent == N>::type * = nullptr>
+  span(T (&array)[N]) noexcept : data_{array}
+  {}
+
+  template <size_t N, typename std::enable_if<Extent == N>::type * = nullptr>
+  span(std::array<T, N> &array) noexcept : data_{array.data()}
+  {}
+
+  template <size_t N, typename std::enable_if<Extent == N>::type * = nullptr>
+  span(const std::array<T, N> &array) noexcept : data_{array.data()}
+  {}
+
+  template <
+      class C,
+      typename std::enable_if<!detail::is_specialized_span_convertible<C>::value &&
+                              std::is_convertible<typename std::remove_pointer<decltype(nostd::data(
+                                                      std::declval<C &>()))>::type (*)[],
+                                                  T (*)[]>::value &&
+                              std::is_convertible<decltype(nostd::size(std::declval<const C &>())),
+                                                  size_t>::value>::type * = nullptr>
+  span(C &c) noexcept(noexcept(nostd::data(c), nostd::size(c))) : data_{nostd::data(c)}
+  {
+    if (nostd::size(c) != Extent)
+    {
+      std::terminate();
+    }
+  }
+
+  template <
+      class C,
+      typename std::enable_if<!detail::is_specialized_span_convertible<C>::value &&
+                              std::is_convertible<typename std::remove_pointer<decltype(nostd::data(
+                                                      std::declval<const C &>()))>::type (*)[],
+                                                  T (*)[]>::value &&
+                              std::is_convertible<decltype(nostd::size(std::declval<const C &>())),
+                                                  size_t>::value>::type * = nullptr>
+  span(const C &c) noexcept(noexcept(nostd::data(c), nostd::size(c))) : data_{nostd::data(c)}
+  {
+    if (nostd::size(c) != Extent)
+    {
+      std::terminate();
+    }
+  }
+
+  template <class U,
+            size_t N,
+            typename std::enable_if<N == Extent &&
+                                    std::is_convertible<U (*)[], T (*)[]>::value>::type * = nullptr>
+  span(const span<U, N> &other) noexcept : data_{other.data()}
+  {}
+
+  span(const span &) noexcept = default;
+
+  span &operator=(const span &) noexcept = default;
+
+  bool empty() const noexcept { return Extent == 0; }
+
+  T *data() const noexcept { return data_; }
+
+  size_t size() const noexcept { return Extent; }
+
+  T &operator[](size_t index) const noexcept
+  {
+    assert(index < Extent);
+    return data_[index];
+  }
+
+  T *begin() const noexcept { return data_; }
+
+  T *end() const noexcept { return data_ + Extent; }
+
+private:
+  T *data_;
+};
+
+template <class T>
+class span<T, dynamic_extent>
+{
+public:
+  static constexpr size_t extent = dynamic_extent;
+
+  span() noexcept : extent_{0}, data_{nullptr} {}
+
+  span(T *data, size_t count) noexcept : extent_{count}, data_{data} {}
+
+  span(T *first, T *last) noexcept
+      : extent_{static_cast<size_t>(std::distance(first, last))}, data_{first}
+  {
+    assert(first <= last);
+  }
+
+  template <size_t N>
+  span(T (&array)[N]) noexcept : extent_{N}, data_{array}
+  {}
+
+  template <size_t N>
+  span(std::array<T, N> &array) noexcept : extent_{N}, data_{array.data()}
+  {}
+
+  template <size_t N>
+  span(const std::array<T, N> &array) noexcept : extent_{N}, data_{array.data()}
+  {}
+
+  template <
+      class C,
+      typename std::enable_if<!detail::is_specialized_span_convertible<C>::value &&
+                              std::is_convertible<typename std::remove_pointer<decltype(nostd::data(
+                                                      std::declval<C &>()))>::type (*)[],
+                                                  T (*)[]>::value &&
+                              std::is_convertible<decltype(nostd::size(std::declval<const C &>())),
+                                                  size_t>::value>::type * = nullptr>
+  span(C &c) noexcept(noexcept(nostd::data(c), nostd::size(c)))
+      : extent_{nostd::size(c)}, data_{nostd::data(c)}
+  {}
+
+  template <
+      class C,
+      typename std::enable_if<!detail::is_specialized_span_convertible<C>::value &&
+                              std::is_convertible<typename std::remove_pointer<decltype(nostd::data(
+                                                      std::declval<const C &>()))>::type (*)[],
+                                                  T (*)[]>::value &&
+                              std::is_convertible<decltype(nostd::size(std::declval<const C &>())),
+                                                  size_t>::value>::type * = nullptr>
+  span(const C &c) noexcept(noexcept(nostd::data(c), nostd::size(c)))
+      : extent_{nostd::size(c)}, data_{nostd::data(c)}
+  {}
+
+  template <class U,
+            size_t N,
+            typename std::enable_if<std::is_convertible<U (*)[], T (*)[]>::value>::type * = nullptr>
+  span(const span<U, N> &other) noexcept : extent_{other.size()}, data_{other.data()}
+  {}
+
+  span(const span &) noexcept = default;
+
+  span &operator=(const span &) noexcept = default;
+
+  bool empty() const noexcept { return extent_ == 0; }
+
+  T *data() const noexcept { return data_; }
+
+  size_t size() const noexcept { return extent_; }
+
+  T &operator[](size_t index) const noexcept
+  {
+    assert(index < extent_);
+    return data_[index];
+  }
+
+  T *begin() const noexcept { return data_; }
+
+  T *end() const noexcept { return data_ + extent_; }
+
+private:
+  size_t extent_;
+  T *data_;
+};
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE
+#endif

+ 226 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/string_view.h

@@ -0,0 +1,226 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#if defined(OPENTELEMETRY_STL_VERSION)
+#  if OPENTELEMETRY_STL_VERSION >= 2017
+#    include "opentelemetry/std/string_view.h"
+#    define OPENTELEMETRY_HAVE_STD_STRING_VIEW
+#  endif
+#endif
+
+#if !defined(OPENTELEMETRY_HAVE_STD_STRING_VIEW)
+#  include <algorithm>
+#  include <cstring>
+#  include <functional>
+#  include <ostream>
+#  include <stdexcept>
+#  include <string>
+#  include <type_traits>
+#  include <utility>
+
+#  include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+
+using Traits = std::char_traits<char>;
+
+/**
+ * Back port of std::string_view to work with pre-cpp-17 compilers.
+ *
+ * Note: This provides a subset of the methods available on std::string_view but
+ * tries to be as compatible as possible with the std::string_view interface.
+ */
+class string_view
+{
+public:
+  typedef std::size_t size_type;
+
+  static constexpr size_type npos = static_cast<size_type>(-1);
+
+  string_view() noexcept : length_(0), data_(nullptr) {}
+
+  string_view(const char *str) noexcept : length_(std::strlen(str)), data_(str) {}
+
+  string_view(const std::basic_string<char> &str OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND) noexcept
+      : length_(str.length()), data_(str.c_str())
+  {}
+
+  string_view(const char *str, size_type len) noexcept : length_(len), data_(str) {}
+
+  explicit operator std::string() const { return {data_, length_}; }
+
+  const char *data() const noexcept { return data_; }
+
+  bool empty() const noexcept { return length_ == 0; }
+
+  size_type length() const noexcept { return length_; }
+
+  size_type size() const noexcept { return length_; }
+
+  const char *begin() const noexcept { return data(); }
+
+  const char *end() const noexcept { return data() + length(); }
+
+  const char &operator[](size_type i) { return *(data() + i); }
+
+  string_view substr(size_type pos, size_type n = npos) const
+  {
+    if (pos > length_)
+    {
+#  if __EXCEPTIONS
+      throw std::out_of_range{"opentelemetry::nostd::string_view"};
+#  else
+      std::terminate();
+#  endif
+    }
+    n = (std::min)(n, length_ - pos);
+    return string_view(data_ + pos, n);
+  }
+
+  int compare(string_view v) const noexcept
+  {
+    size_type len = (std::min)(size(), v.size());
+    int result    = Traits::compare(data(), v.data(), len);
+    if (result == 0)
+      result = size() == v.size() ? 0 : (size() < v.size() ? -1 : 1);
+    return result;
+  }
+
+  int compare(size_type pos1, size_type count1, string_view v) const
+  {
+    return substr(pos1, count1).compare(v);
+  }
+
+  int compare(size_type pos1,
+              size_type count1,
+              string_view v,
+              size_type pos2,
+              size_type count2) const
+  {
+    return substr(pos1, count1).compare(v.substr(pos2, count2));
+  }
+
+  int compare(const char *s) const { return compare(string_view(s)); }
+
+  int compare(size_type pos1, size_type count1, const char *s) const
+  {
+    return substr(pos1, count1).compare(string_view(s));
+  }
+
+  int compare(size_type pos1, size_type count1, const char *s, size_type count2) const
+  {
+    return substr(pos1, count1).compare(string_view(s, count2));
+  }
+
+  size_type find(char ch, size_type pos = 0) const noexcept
+  {
+    size_type res = npos;
+    if (pos < length())
+    {
+      auto found = Traits::find(data() + pos, length() - pos, ch);
+      if (found)
+      {
+        res = found - data();
+      }
+    }
+    return res;
+  }
+
+  bool operator<(const string_view v) const noexcept { return compare(v) < 0; }
+
+  bool operator>(const string_view v) const noexcept { return compare(v) > 0; }
+
+private:
+  // Note: uses the same binary layout as libstdc++'s std::string_view
+  // See
+  // https://github.com/gcc-mirror/gcc/blob/e0c554e4da7310df83bb1dcc7b8e6c4c9c5a2a4f/libstdc%2B%2B-v3/include/std/string_view#L466-L467
+  size_type length_;
+  const char *data_;
+};
+
+inline bool operator==(string_view lhs, string_view rhs) noexcept
+{
+  return lhs.length() == rhs.length() &&
+#  if defined(_MSC_VER)
+#    if _MSC_VER >= 1900 && _MSC_VER <= 1911
+         // Avoid SCL error in Visual Studio 2015, VS2017 update 1 to update 4
+         (std::memcmp(lhs.data(), rhs.data(), lhs.length()) == 0);
+#    else
+         std::equal(lhs.data(), lhs.data() + lhs.length(), rhs.data());
+#    endif
+#  else
+         std::equal(lhs.data(), lhs.data() + lhs.length(), rhs.data());
+#  endif
+}
+
+inline bool operator==(string_view lhs, const std::string &rhs) noexcept
+{
+  return lhs == string_view(rhs);
+}
+
+inline bool operator==(const std::string &lhs, string_view rhs) noexcept
+{
+  return string_view(lhs) == rhs;
+}
+
+inline bool operator==(string_view lhs, const char *rhs) noexcept
+{
+  return lhs == string_view(rhs);
+}
+
+inline bool operator==(const char *lhs, string_view rhs) noexcept
+{
+  return string_view(lhs) == rhs;
+}
+
+inline bool operator!=(string_view lhs, string_view rhs) noexcept
+{
+  return !(lhs == rhs);
+}
+
+inline bool operator!=(string_view lhs, const std::string &rhs) noexcept
+{
+  return !(lhs == rhs);
+}
+
+inline bool operator!=(const std::string &lhs, string_view rhs) noexcept
+{
+  return !(lhs == rhs);
+}
+
+inline bool operator!=(string_view lhs, const char *rhs) noexcept
+{
+  return !(lhs == rhs);
+}
+
+inline bool operator!=(const char *lhs, string_view rhs) noexcept
+{
+  return !(lhs == rhs);
+}
+
+inline std::ostream &operator<<(std::ostream &os, string_view s)
+{
+  return os.write(s.data(), static_cast<std::streamsize>(s.length()));
+}
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE
+
+namespace std
+{
+template <>
+struct hash<OPENTELEMETRY_NAMESPACE::nostd::string_view>
+{
+  std::size_t operator()(const OPENTELEMETRY_NAMESPACE::nostd::string_view &k) const
+  {
+    // TODO: for C++17 that has native support for std::basic_string_view it would
+    // be more performance-efficient to provide a zero-copy hash.
+    auto s = std::string(k.data(), k.size());
+    return std::hash<std::string>{}(s);
+  }
+};
+}  // namespace std
+#endif /* OPENTELEMETRY_HAVE_STD_STRING_VIEW */

+ 172 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/type_traits.h

@@ -0,0 +1,172 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#if defined(OPENTELEMETRY_STL_VERSION)
+#  if OPENTELEMETRY_STL_VERSION >= 2011
+#    include "opentelemetry/std/type_traits.h"
+#    define OPENTELEMETRY_HAVE_STD_TYPE_TRAITS
+#  endif
+#endif
+
+#include <type_traits>
+
+#if !defined(OPENTELEMETRY_HAVE_STD_TYPE_TRAITS)
+#  include <array>
+
+#  include "opentelemetry/nostd/detail/void.h"  // IWYU pragma: export
+#  include "opentelemetry/version.h"
+#endif
+
+#if !defined(__GLIBCXX__) || (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 7) || \
+    (defined(__GLIBCXX__) && __GLIBCXX__ >= 20150422)  // >= libstdc++-5
+#  define OPENTELEMETRY_TRIVIALITY_TYPE_TRAITS
+#endif
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+/**
+ * Back port of std::add_pointer_t
+ */
+template <class T>
+using add_pointer_t = typename std::add_pointer<T>::type;
+
+/**
+ * Back port of std::enable_if_t
+ */
+template <bool B, class T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+/**
+ * Back port of std::remove_const_t
+ */
+template <typename T>
+using remove_const_t = typename std::remove_const<T>::type;
+
+/**
+ * Back port of std::remove_reference_t
+ */
+template <typename T>
+using remove_reference_t = typename std::remove_reference<T>::type;
+
+/**
+ * Back port of std::remove_cvref_t
+ */
+template <typename T>
+using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type;
+
+/**
+ * Back port of std::remove_all_extents
+ */
+template <typename T>
+struct remove_all_extents
+{
+  using type = T;
+};
+
+template <typename T, std::size_t N>
+struct remove_all_extents<std::array<T, N>> : remove_all_extents<T>
+{};
+
+/**
+ * Back port of std::remove_all_extents_t
+ */
+template <typename T>
+using remove_all_extents_t = typename remove_all_extents<T>::type;
+
+#if defined(OPENTELEMETRY_STL_VERSION) && OPENTELEMETRY_STL_VERSION >= 2017
+using std::is_nothrow_swappable;
+using std::is_swappable;
+#else
+/**
+ * Back port of std::is_swappable
+ */
+namespace detail
+{
+namespace swappable
+{
+
+using std::swap;
+
+template <typename T>
+struct is_swappable
+{
+private:
+  template <typename U, typename = decltype(swap(std::declval<U &>(), std::declval<U &>()))>
+  inline static std::true_type test(int);
+
+  template <typename U>
+  inline static std::false_type test(...);
+
+public:
+  static constexpr bool value = decltype(test<T>(0))::value;
+};
+
+}  // namespace swappable
+}  // namespace detail
+
+using detail::swappable::is_swappable;
+
+/**
+ * Back port of std::is_swappable
+ */
+namespace detail
+{
+namespace swappable
+{
+template <bool IsSwappable, typename T>
+struct is_nothrow_swappable
+{
+  static constexpr bool value = noexcept(swap(std::declval<T &>(), std::declval<T &>()));
+};
+
+template <typename T>
+struct is_nothrow_swappable<false, T> : std::false_type
+{};
+}  // namespace swappable
+}  // namespace detail
+template <typename T>
+using is_nothrow_swappable = detail::swappable::is_nothrow_swappable<is_swappable<T>::value, T>;
+#endif
+
+/**
+ * Back port of
+ *  std::is_trivialy_copy_constructible
+ *  std::is_trivialy_move_constructible
+ *  std::is_trivialy_copy_assignable
+ *  std::is_trivialy_move_assignable
+ */
+#ifdef OPENTELEMETRY_TRIVIALITY_TYPE_TRAITS
+using std::is_trivially_copy_assignable;
+using std::is_trivially_copy_constructible;
+using std::is_trivially_move_assignable;
+using std::is_trivially_move_constructible;
+#else
+template <typename T>
+struct is_trivially_copy_constructible
+{
+  static constexpr bool value = std::is_copy_constructible<T>::value && __has_trivial_copy(T);
+};
+
+template <typename T>
+struct is_trivially_move_constructible
+{
+  static constexpr bool value = __is_trivial(T);
+};
+
+template <typename T>
+struct is_trivially_copy_assignable
+{
+  static constexpr bool value = std::is_copy_assignable<T>::value && __has_trivial_assign(T);
+};
+
+template <typename T>
+struct is_trivially_move_assignable
+{
+  static constexpr bool value = __is_trivial(T);
+};
+#endif
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE

+ 180 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/unique_ptr.h

@@ -0,0 +1,180 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#if defined(OPENTELEMETRY_STL_VERSION)
+#  if OPENTELEMETRY_STL_VERSION >= 2011
+#    include "opentelemetry/std/unique_ptr.h"
+#    define OPENTELEMETRY_HAVE_STD_UNIQUE_PTR
+#  endif
+#endif
+
+#if !defined(OPENTELEMETRY_HAVE_STD_UNIQUE_PTR)
+#  include <cstddef>
+#  include <memory>
+#  include <type_traits>
+#  include <utility>
+
+#  include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+namespace detail
+{
+template <class T>
+struct unique_ptr_element_type
+{
+  using type = T;
+};
+
+template <class T>
+struct unique_ptr_element_type<T[]>
+{
+  using type = T;
+};
+}  // namespace detail
+
+/**
+ * Provide a simplified port of std::unique_ptr that has ABI stability.
+ *
+ * Note: This implementation doesn't allow for a custom deleter.
+ */
+template <class T>
+class unique_ptr
+{
+public:
+  using element_type = typename detail::unique_ptr_element_type<T>::type;
+  using pointer      = element_type *;
+
+  unique_ptr() noexcept : ptr_{nullptr} {}
+
+  unique_ptr(std::nullptr_t) noexcept : ptr_{nullptr} {}
+
+  explicit unique_ptr(pointer ptr) noexcept : ptr_{ptr} {}
+
+  unique_ptr(unique_ptr &&other) noexcept : ptr_{other.release()} {}
+
+  template <class U,
+            typename std::enable_if<std::is_convertible<U *, pointer>::value>::type * = nullptr>
+  unique_ptr(unique_ptr<U> &&other) noexcept : ptr_{other.release()}
+  {}
+
+  template <class U,
+            typename std::enable_if<std::is_convertible<U *, pointer>::value>::type * = nullptr>
+  unique_ptr(std::unique_ptr<U> &&other) noexcept : ptr_{other.release()}
+  {}
+
+  ~unique_ptr() { reset(); }
+
+  unique_ptr &operator=(unique_ptr &&other) noexcept
+  {
+    reset(other.release());
+    return *this;
+  }
+
+  unique_ptr &operator=(std::nullptr_t) noexcept
+  {
+    reset();
+    return *this;
+  }
+
+  template <class U,
+            typename std::enable_if<std::is_convertible<U *, pointer>::value>::type * = nullptr>
+  unique_ptr &operator=(unique_ptr<U> &&other) noexcept
+  {
+    reset(other.release());
+    return *this;
+  }
+
+  template <class U,
+            typename std::enable_if<std::is_convertible<U *, pointer>::value>::type * = nullptr>
+  unique_ptr &operator=(std::unique_ptr<U> &&other) noexcept
+  {
+    reset(other.release());
+    return *this;
+  }
+
+  operator std::unique_ptr<T>() && noexcept { return std::unique_ptr<T>{release()}; }
+
+  operator bool() const noexcept { return ptr_ != nullptr; }
+
+  element_type &operator*() const noexcept { return *ptr_; }
+
+  pointer operator->() const noexcept { return get(); }
+
+  pointer get() const noexcept { return ptr_; }
+
+  void reset(pointer ptr = nullptr) noexcept
+  {
+    if (ptr_ != nullptr)
+    {
+      this->delete_ptr();
+    }
+    ptr_ = ptr;
+  }
+
+  pointer release() noexcept
+  {
+    auto result = ptr_;
+    ptr_        = nullptr;
+    return result;
+  }
+
+  void swap(unique_ptr &other) noexcept { std::swap(ptr_, other.ptr_); }
+
+private:
+  pointer ptr_;
+
+  void delete_ptr() noexcept
+  {
+    if (std::is_array<T>::value)
+    {
+      delete[] ptr_;
+    }
+    else
+    {
+      delete ptr_;
+    }
+  }
+};
+
+template <class T1, class T2>
+bool operator==(const unique_ptr<T1> &lhs, const unique_ptr<T2> &rhs) noexcept
+{
+  return lhs.get() == rhs.get();
+}
+
+template <class T>
+bool operator==(const unique_ptr<T> &lhs, std::nullptr_t) noexcept
+{
+  return lhs.get() == nullptr;
+}
+
+template <class T>
+bool operator==(std::nullptr_t, const unique_ptr<T> &rhs) noexcept
+{
+  return nullptr == rhs.get();
+}
+
+template <class T1, class T2>
+bool operator!=(const unique_ptr<T1> &lhs, const unique_ptr<T2> &rhs) noexcept
+{
+  return lhs.get() != rhs.get();
+}
+
+template <class T>
+bool operator!=(const unique_ptr<T> &lhs, std::nullptr_t) noexcept
+{
+  return lhs.get() != nullptr;
+}
+
+template <class T>
+bool operator!=(std::nullptr_t, const unique_ptr<T> &rhs) noexcept
+{
+  return nullptr != rhs.get();
+}
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE
+#endif /* OPENTELEMETRY_HAVE_STD_UNIQUE_PTR */

+ 160 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/utility.h

@@ -0,0 +1,160 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#if defined(OPENTELEMETRY_STL_VERSION)
+#  if OPENTELEMETRY_STL_VERSION >= 2014
+#    include "opentelemetry/std/utility.h"
+#    define OPENTELEMETRY_HAVE_STD_UTILITY
+#  endif
+#endif
+
+#if !defined(OPENTELEMETRY_HAVE_STD_UTILITY)
+#  include <cstddef>
+#  include <initializer_list>
+#  include <type_traits>
+
+#  include "opentelemetry/nostd/detail/decay.h"   // IWYU pragma: export
+#  include "opentelemetry/nostd/detail/invoke.h"  // IWYU pragma: export
+#  include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+/**
+ * Back port of std::data
+ *
+ * See https://en.cppreference.com/w/cpp/iterator/data
+ */
+template <class C>
+auto data(C &c) noexcept(noexcept(c.data())) -> decltype(c.data())
+{
+  return c.data();
+}
+
+template <class C>
+auto data(const C &c) noexcept(noexcept(c.data())) -> decltype(c.data())
+{
+  return c.data();
+}
+
+template <class T, size_t N>
+T *data(T (&array)[N]) noexcept
+{
+  return array;
+}
+
+template <class E>
+const E *data(std::initializer_list<E> list) noexcept
+{
+  return list.begin();
+}
+
+/**
+ * Back port of std::size
+ *
+ * See https://en.cppreference.com/w/cpp/iterator/size
+ */
+template <class C>
+auto size(const C &c) noexcept(noexcept(c.size())) -> decltype(c.size())
+{
+  return c.size();
+}
+
+template <class T, size_t N>
+size_t size(T (& /* array */)[N]) noexcept
+{
+  return N;
+}
+
+/**
+ * Back port of std::bool_constant
+ */
+template <bool B>
+using bool_constant = std::integral_constant<bool, B>;
+
+/**
+ * Back port of std::integer_sequence
+ */
+template <typename T, T... Is>
+struct integer_sequence
+{
+  using value_type = T;
+  static constexpr std::size_t size() noexcept { return sizeof...(Is); }
+};
+
+/**
+ * Back port of std::index_sequence
+ */
+template <std::size_t... Is>
+using index_sequence = integer_sequence<std::size_t, Is...>;
+
+/**
+ * Back port of std::make_index_sequence
+ */
+namespace detail
+{
+template <class, size_t>
+struct index_sequence_push_back
+{};
+
+template <size_t... Indexes, size_t I>
+struct index_sequence_push_back<index_sequence<Indexes...>, I>
+{
+  using type = index_sequence<Indexes..., I>;
+};
+
+template <class T, size_t I>
+using index_sequence_push_back_t = typename index_sequence_push_back<T, I>::type;
+
+template <size_t N>
+struct make_index_sequence_impl
+{
+  using type = index_sequence_push_back_t<typename make_index_sequence_impl<N - 1>::type, N - 1>;
+};
+
+template <>
+struct make_index_sequence_impl<0>
+{
+  using type = index_sequence<>;
+};
+}  // namespace detail
+
+template <size_t N>
+using make_index_sequence = typename detail::make_index_sequence_impl<N>::type;
+
+/**
+ * Back port of std::index_sequence_for
+ */
+template <class... Ts>
+using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
+
+/**
+ * Back port of std::in_place_t
+ */
+struct in_place_t
+{
+  explicit in_place_t() = default;
+};
+
+/**
+ * Back port of std::in_place_index_t
+ */
+template <std::size_t I>
+struct in_place_index_t
+{
+  explicit in_place_index_t() = default;
+};
+
+/**
+ * Back port of std::in_place_type_t
+ */
+template <typename T>
+struct in_place_type_t
+{
+  explicit in_place_type_t() = default;
+};
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE
+#endif /* OPENTELEMETRY_HAVE_STD_UTILITY */

+ 85 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/nostd/variant.h

@@ -0,0 +1,85 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/version.h"
+
+#if defined(OPENTELEMETRY_STL_VERSION)
+#  if OPENTELEMETRY_STL_VERSION >= 2017
+#    include "opentelemetry/std/variant.h"
+#    define OPENTELEMETRY_HAVE_STD_VARIANT
+#  endif
+#endif
+
+#if !defined(OPENTELEMETRY_HAVE_STD_VARIANT)
+
+// We use a LOCAL snapshot of Abseil that is known to compile with Visual Studio 2015.
+// Header-only. Without compiling the actual Abseil binary. As Abseil moves on to new
+// toolchains, it may drop support for Visual Studio 2015 in future versions.
+
+#  if defined(__EXCEPTIONS)
+#    include <exception>
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+
+class bad_variant_access : public std::exception
+{
+public:
+  virtual const char *what() const noexcept override { return "bad_variant_access"; }
+};
+
+[[noreturn]] inline void throw_bad_variant_access()
+{
+  throw bad_variant_access{};
+}
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE
+#    define THROW_BAD_VARIANT_ACCESS opentelemetry::nostd::throw_bad_variant_access()
+#  else
+#    define THROW_BAD_VARIANT_ACCESS std::terminate()
+#  endif
+
+#  ifdef _MSC_VER
+// Abseil variant implementation contains some benign non-impacting warnings
+// that should be suppressed if compiling with Visual Studio 2017 and above.
+#    pragma warning(push)
+#    pragma warning(disable : 4245)  // conversion from int to const unsigned _int64
+#    pragma warning(disable : 4127)  // conditional expression is constant
+#  endif
+
+#  include "opentelemetry/nostd/internal/absl/base/options.h"
+
+namespace absl
+{
+namespace OTABSL_OPTION_NAMESPACE_NAME
+{
+template <class T>
+struct variant_size;
+template <typename... Ts>
+class variant;
+}  // namespace OTABSL_OPTION_NAMESPACE_NAME
+}  // namespace absl
+
+#  include "opentelemetry/nostd/internal/absl/types/variant.h"
+
+#  ifdef _MSC_VER
+#    pragma warning(pop)
+#  endif
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace nostd
+{
+using absl::OTABSL_OPTION_NAMESPACE_NAME::get;
+using absl::OTABSL_OPTION_NAMESPACE_NAME::get_if;
+using absl::OTABSL_OPTION_NAMESPACE_NAME::holds_alternative;
+using absl::OTABSL_OPTION_NAMESPACE_NAME::monostate;
+using absl::OTABSL_OPTION_NAMESPACE_NAME::variant;
+using absl::OTABSL_OPTION_NAMESPACE_NAME::variant_alternative_t;
+using absl::OTABSL_OPTION_NAMESPACE_NAME::variant_size;
+using absl::OTABSL_OPTION_NAMESPACE_NAME::visit;
+}  // namespace nostd
+OPENTELEMETRY_END_NAMESPACE
+
+#endif /* OPENTELEMETRY_HAVE_STD_VARIANT */

+ 20 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/detail/dynamic_library_handle.h

@@ -0,0 +1,20 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace plugin
+{
+/**
+ * Manage the ownership of a dynamically loaded library.
+ */
+class DynamicLibraryHandle
+{
+public:
+  virtual ~DynamicLibraryHandle() = default;
+};
+}  // namespace plugin
+OPENTELEMETRY_END_NAMESPACE

+ 73 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/detail/dynamic_load_unix.h

@@ -0,0 +1,73 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <dlfcn.h>
+#include <algorithm>
+#include <memory>
+
+#include "opentelemetry/plugin/detail/dynamic_library_handle.h"
+#include "opentelemetry/plugin/detail/loader_info.h"
+#include "opentelemetry/plugin/detail/utility.h"
+#include "opentelemetry/plugin/factory.h"
+#include "opentelemetry/plugin/hook.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace plugin
+{
+class DynamicLibraryHandleUnix final : public DynamicLibraryHandle
+{
+public:
+  explicit DynamicLibraryHandleUnix(void *handle) noexcept : handle_{handle} {}
+
+  ~DynamicLibraryHandleUnix() override { ::dlclose(handle_); }
+
+private:
+  void *handle_;
+};
+
+inline std::unique_ptr<Factory> LoadFactory(const char *plugin, std::string &error_message) noexcept
+{
+  dlerror();  // Clear any existing error.
+
+  auto handle = ::dlopen(plugin, RTLD_NOW | RTLD_LOCAL);
+  if (handle == nullptr)
+  {
+    detail::CopyErrorMessage(dlerror(), error_message);
+    return nullptr;
+  }
+
+  std::shared_ptr<DynamicLibraryHandle> library_handle{new (std::nothrow)
+                                                           DynamicLibraryHandleUnix{handle}};
+  if (library_handle == nullptr)
+  {
+    return nullptr;
+  }
+
+  auto make_factory_impl =
+      reinterpret_cast<OpenTelemetryHook *>(::dlsym(handle, "OpenTelemetryMakeFactoryImpl"));
+  if (make_factory_impl == nullptr)
+  {
+    detail::CopyErrorMessage(dlerror(), error_message);
+    return nullptr;
+  }
+  if (*make_factory_impl == nullptr)
+  {
+    detail::CopyErrorMessage("Invalid plugin hook", error_message);
+    return nullptr;
+  }
+  LoaderInfo loader_info;
+  nostd::unique_ptr<char[]> plugin_error_message;
+  auto factory_impl = (**make_factory_impl)(loader_info, plugin_error_message);
+  if (factory_impl == nullptr)
+  {
+    detail::CopyErrorMessage(plugin_error_message.get(), error_message);
+    return nullptr;
+  }
+  return std::unique_ptr<Factory>{new (std::nothrow)
+                                      Factory{std::move(library_handle), std::move(factory_impl)}};
+}
+}  // namespace plugin
+OPENTELEMETRY_END_NAMESPACE

+ 96 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/detail/dynamic_load_windows.h

@@ -0,0 +1,96 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <memory>
+
+#include "opentelemetry/plugin/detail/dynamic_library_handle.h"
+#include "opentelemetry/plugin/detail/loader_info.h"
+#include "opentelemetry/plugin/detail/utility.h"
+#include "opentelemetry/plugin/factory.h"
+#include "opentelemetry/plugin/hook.h"
+#include "opentelemetry/version.h"
+
+#include <Windows.h>
+
+#include <WinBase.h>
+#include <errhandlingapi.h>
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace plugin
+{
+namespace detail
+{
+inline void GetLastErrorMessage(std::string &error_message) noexcept
+{
+  auto error_code = ::GetLastError();
+  // See https://stackoverflow.com/a/455533/4447365
+  LPTSTR error_text = nullptr;
+  auto size         = ::FormatMessage(
+      FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
+      nullptr, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+      reinterpret_cast<LPTSTR>(&error_text), 0, nullptr);
+  if (size == 0)
+  {
+    return;
+  }
+  CopyErrorMessage(error_text, error_message);
+  ::LocalFree(error_text);
+}
+}  // namespace detail
+
+class DynamicLibraryHandleWindows final : public DynamicLibraryHandle
+{
+public:
+  explicit DynamicLibraryHandleWindows(HINSTANCE handle) : handle_{handle} {}
+
+  ~DynamicLibraryHandleWindows() override { ::FreeLibrary(handle_); }
+
+private:
+  HINSTANCE handle_;
+};
+
+inline std::unique_ptr<Factory> LoadFactory(const char *plugin, std::string &error_message) noexcept
+{
+  auto handle = ::LoadLibrary(plugin);
+  if (handle == nullptr)
+  {
+    detail::GetLastErrorMessage(error_message);
+    return nullptr;
+  }
+
+  std::shared_ptr<DynamicLibraryHandle> library_handle{new (std::nothrow)
+                                                           DynamicLibraryHandleWindows{handle}};
+  if (library_handle == nullptr)
+  {
+    detail::CopyErrorMessage("Allocation failure", error_message);
+    return nullptr;
+  }
+
+  auto make_factory_impl = reinterpret_cast<OpenTelemetryHook *>(
+      ::GetProcAddress(handle, "OpenTelemetryMakeFactoryImpl"));
+  if (make_factory_impl == nullptr)
+  {
+    detail::GetLastErrorMessage(error_message);
+    return nullptr;
+  }
+  if (*make_factory_impl == nullptr)
+  {
+    detail::CopyErrorMessage("Invalid plugin hook", error_message);
+    return nullptr;
+  }
+
+  LoaderInfo loader_info;
+  nostd::unique_ptr<char[]> plugin_error_message;
+  auto factory_impl = (**make_factory_impl)(loader_info, plugin_error_message);
+  if (factory_impl == nullptr)
+  {
+    detail::CopyErrorMessage(plugin_error_message.get(), error_message);
+    return nullptr;
+  }
+  return std::unique_ptr<Factory>{new (std::nothrow)
+                                      Factory{std::move(library_handle), std::move(factory_impl)}};
+}
+}  // namespace plugin
+OPENTELEMETRY_END_NAMESPACE

+ 24 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/detail/loader_info.h

@@ -0,0 +1,24 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/nostd/string_view.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace plugin
+{
+/**
+ * LoaderInfo describes the versioning of the loader.
+ *
+ * Plugins can check against this information and properly error out if they were built against an
+ * incompatible OpenTelemetry API.
+ */
+struct LoaderInfo
+{
+  nostd::string_view opentelemetry_version     = OPENTELEMETRY_VERSION;
+  nostd::string_view opentelemetry_abi_version = OPENTELEMETRY_ABI_VERSION;
+};
+}  // namespace plugin
+OPENTELEMETRY_END_NAMESPACE

+ 27 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/detail/tracer_handle.h

@@ -0,0 +1,27 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace trace
+{
+class Tracer;
+}  // namespace trace
+
+namespace plugin
+{
+/**
+ * Manage the ownership of a dynamically loaded tracer.
+ */
+class TracerHandle
+{
+public:
+  virtual ~TracerHandle() = default;
+
+  virtual trace::Tracer &tracer() const noexcept = 0;
+};
+}  // namespace plugin
+OPENTELEMETRY_END_NAMESPACE

+ 36 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/detail/utility.h

@@ -0,0 +1,36 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#if __EXCEPTIONS
+#  include <new>
+#endif  // __EXCEPTIONS
+
+#include <string>
+
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace plugin
+{
+namespace detail
+{
+inline void CopyErrorMessage(const char *source, std::string &destination) noexcept
+#if __EXCEPTIONS
+try
+#endif
+{
+  if (source == nullptr)
+  {
+    return;
+  }
+  destination.assign(source);
+}
+#if __EXCEPTIONS
+catch (const std::bad_alloc &)
+{}
+#endif
+}  // namespace detail
+}  // namespace plugin
+OPENTELEMETRY_END_NAMESPACE

+ 30 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/dynamic_load.h

@@ -0,0 +1,30 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "opentelemetry/plugin/factory.h"
+#include "opentelemetry/version.h"
+
+#ifdef _WIN32
+#  include "opentelemetry/plugin/detail/dynamic_load_windows.h"  // IWYU pragma: export
+#else
+#  include "opentelemetry/plugin/detail/dynamic_load_unix.h"  // IWYU pragma: export
+#endif
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace plugin
+{
+
+/**
+ * Load an OpenTelemetry implementation as a plugin.
+ * @param plugin the path to the plugin to load
+ * @param error_message on failure this is set to an error message
+ * @return a Factory that can be used to create OpenTelemetry objects or nullptr on failure.
+ */
+std::unique_ptr<Factory> LoadFactory(const char *plugin, std::string &error_message) noexcept;
+}  // namespace plugin
+OPENTELEMETRY_END_NAMESPACE

+ 65 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/factory.h

@@ -0,0 +1,65 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "opentelemetry/plugin/detail/utility.h"  // IWYU pragma: export
+#include "opentelemetry/plugin/tracer.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace plugin
+{
+/**
+ * Factory creates OpenTelemetry objects from configuration strings.
+ */
+class Factory final
+{
+public:
+  class FactoryImpl
+  {
+  public:
+    virtual ~FactoryImpl() {}
+
+    virtual nostd::unique_ptr<TracerHandle> MakeTracerHandle(
+        nostd::string_view tracer_config,
+        nostd::unique_ptr<char[]> &error_message) const noexcept = 0;
+  };
+
+  Factory(std::shared_ptr<DynamicLibraryHandle> library_handle,
+          std::unique_ptr<FactoryImpl> &&factory_impl) noexcept
+      : library_handle_{std::move(library_handle)}, factory_impl_{std::move(factory_impl)}
+  {}
+
+  /**
+   * Construct a tracer from a configuration string.
+   * @param tracer_config a representation of the tracer's config as a string.
+   * @param error_message on failure this will contain an error message.
+   * @return a Tracer on success or nullptr on failure.
+   */
+  std::shared_ptr<trace::Tracer> MakeTracer(nostd::string_view tracer_config,
+                                            std::string &error_message) const noexcept
+  {
+    nostd::unique_ptr<char[]> plugin_error_message;
+    auto tracer_handle = factory_impl_->MakeTracerHandle(tracer_config, plugin_error_message);
+    if (tracer_handle == nullptr)
+    {
+      detail::CopyErrorMessage(plugin_error_message.get(), error_message);
+      return nullptr;
+    }
+    return std::shared_ptr<trace::Tracer>{new (std::nothrow)
+                                              Tracer{library_handle_, std::move(tracer_handle)}};
+  }
+
+private:
+  // Note: The order is important here.
+  //
+  // It's undefined behavior to close the library while a loaded FactoryImpl is still active.
+  std::shared_ptr<DynamicLibraryHandle> library_handle_;
+  std::unique_ptr<FactoryImpl> factory_impl_;
+};
+}  // namespace plugin
+OPENTELEMETRY_END_NAMESPACE

+ 51 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/hook.h

@@ -0,0 +1,51 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "opentelemetry/nostd/unique_ptr.h"
+#include "opentelemetry/version.h"
+
+#ifdef _WIN32
+
+/**
+ * Cross-platform helper macro to declare the symbol used to load an OpenTelemetry implementation
+ * as a plugin.
+ *
+ * Note: The symbols use weak linkage so as to support using an OpenTelemetry both as a regular
+ * library and a dynamically loaded plugin. The weak linkage allows for multiple implementations to
+ * be linked in without getting multiple definition errors.
+ */
+#  define OPENTELEMETRY_DEFINE_PLUGIN_HOOK(X)                                   \
+    extern "C" {                                                                \
+    extern __declspec(dllexport) opentelemetry::plugin::OpenTelemetryHook const \
+        OpenTelemetryMakeFactoryImpl;                                           \
+                                                                                \
+    __declspec(selectany) opentelemetry::plugin::OpenTelemetryHook const        \
+        OpenTelemetryMakeFactoryImpl = X;                                       \
+    }  // extern "C"
+
+#else
+
+#  define OPENTELEMETRY_DEFINE_PLUGIN_HOOK(X)                                                      \
+    extern "C" {                                                                                   \
+    __attribute((                                                                                  \
+        weak)) extern opentelemetry::plugin::OpenTelemetryHook const OpenTelemetryMakeFactoryImpl; \
+                                                                                                   \
+    opentelemetry::plugin::OpenTelemetryHook const OpenTelemetryMakeFactoryImpl = X;               \
+    }  // extern "C"
+
+#endif
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace plugin
+{
+
+struct LoaderInfo;
+class FactoryImpl;
+
+using OpenTelemetryHook =
+    nostd::unique_ptr<Factory::FactoryImpl> (*)(const LoaderInfo &loader_info,
+                                                nostd::unique_ptr<char[]> &error_message);
+}  // namespace plugin
+OPENTELEMETRY_END_NAMESPACE

+ 133 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/plugin/tracer.h

@@ -0,0 +1,133 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <memory>
+
+#include "opentelemetry/common/key_value_iterable.h"
+#include "opentelemetry/plugin/detail/tracer_handle.h"  // IWYU pragma: export
+#include "opentelemetry/trace/span_context_kv_iterable.h"
+#include "opentelemetry/trace/tracer.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace plugin
+{
+
+class DynamicLibraryHandle;
+
+class Span final : public trace::Span
+{
+public:
+  Span(std::shared_ptr<trace::Tracer> &&tracer, const nostd::shared_ptr<trace::Span> &span) noexcept
+      : tracer_{std::move(tracer)}, span_{span}
+  {}
+
+  // trace::Span
+  void SetAttribute(nostd::string_view name, const common::AttributeValue &value) noexcept override
+  {
+    span_->SetAttribute(name, value);
+  }
+
+  void AddEvent(nostd::string_view name) noexcept override { span_->AddEvent(name); }
+
+  void AddEvent(nostd::string_view name, common::SystemTimestamp timestamp) noexcept override
+  {
+    span_->AddEvent(name, timestamp);
+  }
+
+  void AddEvent(nostd::string_view name,
+                const common::KeyValueIterable &attributes) noexcept override
+  {
+    span_->AddEvent(name, attributes);
+  }
+
+  void AddEvent(nostd::string_view name,
+                common::SystemTimestamp timestamp,
+                const common::KeyValueIterable &attributes) noexcept override
+  {
+    span_->AddEvent(name, timestamp, attributes);
+  }
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+  void AddLink(const trace::SpanContext &target,
+               const common::KeyValueIterable &attrs) noexcept override
+  {
+    span_->AddLink(target, attrs);
+  }
+
+  void AddLinks(const trace::SpanContextKeyValueIterable &links) noexcept override
+  {
+    span_->AddLinks(links);
+  }
+#endif
+
+  void SetStatus(trace::StatusCode code, nostd::string_view description) noexcept override
+  {
+    span_->SetStatus(code, description);
+  }
+
+  void UpdateName(nostd::string_view name) noexcept override { span_->UpdateName(name); }
+
+  void End(const trace::EndSpanOptions &options = {}) noexcept override { span_->End(options); }
+
+  bool IsRecording() const noexcept override { return span_->IsRecording(); }
+
+  trace::SpanContext GetContext() const noexcept override { return span_->GetContext(); }
+
+private:
+  std::shared_ptr<trace::Tracer> tracer_;
+  nostd::shared_ptr<trace::Span> span_;
+};
+
+class Tracer final : public trace::Tracer, public std::enable_shared_from_this<Tracer>
+{
+public:
+  Tracer(std::shared_ptr<DynamicLibraryHandle> library_handle,
+         std::unique_ptr<TracerHandle> &&tracer_handle) noexcept
+      : library_handle_{std::move(library_handle)}, tracer_handle_{std::move(tracer_handle)}
+  {
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+    UpdateEnabled(true);
+#endif
+  }
+
+  // trace::Tracer
+  nostd::shared_ptr<trace::Span> StartSpan(
+      nostd::string_view name,
+      const common::KeyValueIterable &attributes,
+      const trace::SpanContextKeyValueIterable &links,
+      const trace::StartSpanOptions &options = {}) noexcept override
+  {
+    auto span = tracer_handle_->tracer().StartSpan(name, attributes, links, options);
+    if (span == nullptr)
+    {
+      return nostd::shared_ptr<trace::Span>(nullptr);
+    }
+    return nostd::shared_ptr<trace::Span>{new (std::nothrow) Span{this->shared_from_this(), span}};
+  }
+
+#if OPENTELEMETRY_ABI_VERSION_NO == 1
+
+  void ForceFlushWithMicroseconds(uint64_t timeout) noexcept override
+  {
+    tracer_handle_->tracer().ForceFlushWithMicroseconds(timeout);
+  }
+
+  void CloseWithMicroseconds(uint64_t timeout) noexcept override
+  {
+    tracer_handle_->tracer().CloseWithMicroseconds(timeout);
+  }
+
+#endif /* OPENTELEMETRY_ABI_VERSION_NO */
+
+private:
+  // Note: The order is important here.
+  //
+  // It's undefined behavior to close the library while a loaded tracer is still active.
+  std::shared_ptr<DynamicLibraryHandle> library_handle_;
+  std::unique_ptr<TracerHandle> tracer_handle_;
+};
+}  // namespace plugin
+OPENTELEMETRY_END_NAMESPACE

+ 97 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/azure_metrics.h

@@ -0,0 +1,97 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_metrics-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/metrics/meter.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace azure
+{
+
+/**
+ * Number of active client instances
+ * <p>
+ * updowncounter
+ */
+static constexpr const char *kMetricAzureCosmosdbClientActiveInstanceCount =
+    "azure.cosmosdb.client.active_instance.count";
+static constexpr const char *descrMetricAzureCosmosdbClientActiveInstanceCount =
+    "Number of active client instances";
+static constexpr const char *unitMetricAzureCosmosdbClientActiveInstanceCount = "{instance}";
+
+static inline nostd::unique_ptr<metrics::UpDownCounter<int64_t>>
+CreateSyncInt64MetricAzureCosmosdbClientActiveInstanceCount(metrics::Meter *meter)
+{
+  return meter->CreateInt64UpDownCounter(kMetricAzureCosmosdbClientActiveInstanceCount,
+                                         descrMetricAzureCosmosdbClientActiveInstanceCount,
+                                         unitMetricAzureCosmosdbClientActiveInstanceCount);
+}
+
+static inline nostd::unique_ptr<metrics::UpDownCounter<double>>
+CreateSyncDoubleMetricAzureCosmosdbClientActiveInstanceCount(metrics::Meter *meter)
+{
+  return meter->CreateDoubleUpDownCounter(kMetricAzureCosmosdbClientActiveInstanceCount,
+                                          descrMetricAzureCosmosdbClientActiveInstanceCount,
+                                          unitMetricAzureCosmosdbClientActiveInstanceCount);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncInt64MetricAzureCosmosdbClientActiveInstanceCount(metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableUpDownCounter(
+      kMetricAzureCosmosdbClientActiveInstanceCount,
+      descrMetricAzureCosmosdbClientActiveInstanceCount,
+      unitMetricAzureCosmosdbClientActiveInstanceCount);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncDoubleMetricAzureCosmosdbClientActiveInstanceCount(metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableUpDownCounter(
+      kMetricAzureCosmosdbClientActiveInstanceCount,
+      descrMetricAzureCosmosdbClientActiveInstanceCount,
+      unitMetricAzureCosmosdbClientActiveInstanceCount);
+}
+
+/**
+ * <a href="https://learn.microsoft.com/azure/cosmos-db/request-units">Request units</a> consumed by
+ * the operation <p> histogram
+ */
+static constexpr const char *kMetricAzureCosmosdbClientOperationRequestCharge =
+    "azure.cosmosdb.client.operation.request_charge";
+static constexpr const char *descrMetricAzureCosmosdbClientOperationRequestCharge =
+    "[Request units](https://learn.microsoft.com/azure/cosmos-db/request-units) consumed by the "
+    "operation";
+static constexpr const char *unitMetricAzureCosmosdbClientOperationRequestCharge = "{request_unit}";
+
+static inline nostd::unique_ptr<metrics::Histogram<uint64_t>>
+CreateSyncInt64MetricAzureCosmosdbClientOperationRequestCharge(metrics::Meter *meter)
+{
+  return meter->CreateUInt64Histogram(kMetricAzureCosmosdbClientOperationRequestCharge,
+                                      descrMetricAzureCosmosdbClientOperationRequestCharge,
+                                      unitMetricAzureCosmosdbClientOperationRequestCharge);
+}
+
+static inline nostd::unique_ptr<metrics::Histogram<double>>
+CreateSyncDoubleMetricAzureCosmosdbClientOperationRequestCharge(metrics::Meter *meter)
+{
+  return meter->CreateDoubleHistogram(kMetricAzureCosmosdbClientOperationRequestCharge,
+                                      descrMetricAzureCosmosdbClientOperationRequestCharge,
+                                      unitMetricAzureCosmosdbClientOperationRequestCharge);
+}
+
+}  // namespace azure
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 213 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/cicd_metrics.h

@@ -0,0 +1,213 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_metrics-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/metrics/meter.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace cicd
+{
+
+/**
+ * The number of pipeline runs currently active in the system by state.
+ * <p>
+ * updowncounter
+ */
+static constexpr const char *kMetricCicdPipelineRunActive = "cicd.pipeline.run.active";
+static constexpr const char *descrMetricCicdPipelineRunActive =
+    "The number of pipeline runs currently active in the system by state.";
+static constexpr const char *unitMetricCicdPipelineRunActive = "{run}";
+
+static inline nostd::unique_ptr<metrics::UpDownCounter<int64_t>>
+CreateSyncInt64MetricCicdPipelineRunActive(metrics::Meter *meter)
+{
+  return meter->CreateInt64UpDownCounter(kMetricCicdPipelineRunActive,
+                                         descrMetricCicdPipelineRunActive,
+                                         unitMetricCicdPipelineRunActive);
+}
+
+static inline nostd::unique_ptr<metrics::UpDownCounter<double>>
+CreateSyncDoubleMetricCicdPipelineRunActive(metrics::Meter *meter)
+{
+  return meter->CreateDoubleUpDownCounter(kMetricCicdPipelineRunActive,
+                                          descrMetricCicdPipelineRunActive,
+                                          unitMetricCicdPipelineRunActive);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncInt64MetricCicdPipelineRunActive(metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableUpDownCounter(kMetricCicdPipelineRunActive,
+                                                   descrMetricCicdPipelineRunActive,
+                                                   unitMetricCicdPipelineRunActive);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncDoubleMetricCicdPipelineRunActive(metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableUpDownCounter(kMetricCicdPipelineRunActive,
+                                                    descrMetricCicdPipelineRunActive,
+                                                    unitMetricCicdPipelineRunActive);
+}
+
+/**
+ * Duration of a pipeline run grouped by pipeline, state and result.
+ * <p>
+ * histogram
+ */
+static constexpr const char *kMetricCicdPipelineRunDuration = "cicd.pipeline.run.duration";
+static constexpr const char *descrMetricCicdPipelineRunDuration =
+    "Duration of a pipeline run grouped by pipeline, state and result.";
+static constexpr const char *unitMetricCicdPipelineRunDuration = "s";
+
+static inline nostd::unique_ptr<metrics::Histogram<uint64_t>>
+CreateSyncInt64MetricCicdPipelineRunDuration(metrics::Meter *meter)
+{
+  return meter->CreateUInt64Histogram(kMetricCicdPipelineRunDuration,
+                                      descrMetricCicdPipelineRunDuration,
+                                      unitMetricCicdPipelineRunDuration);
+}
+
+static inline nostd::unique_ptr<metrics::Histogram<double>>
+CreateSyncDoubleMetricCicdPipelineRunDuration(metrics::Meter *meter)
+{
+  return meter->CreateDoubleHistogram(kMetricCicdPipelineRunDuration,
+                                      descrMetricCicdPipelineRunDuration,
+                                      unitMetricCicdPipelineRunDuration);
+}
+
+/**
+ * The number of errors encountered in pipeline runs (eg. compile, test failures).
+ * <p>
+ * There might be errors in a pipeline run that are non fatal (eg. they are suppressed) or in a
+ * parallel stage multiple stages could have a fatal error. This means that this error count might
+ * not be the same as the count of metric @code cicd.pipeline.run.duration @endcode with run result
+ * @code failure @endcode. <p> counter
+ */
+static constexpr const char *kMetricCicdPipelineRunErrors = "cicd.pipeline.run.errors";
+static constexpr const char *descrMetricCicdPipelineRunErrors =
+    "The number of errors encountered in pipeline runs (eg. compile, test failures).";
+static constexpr const char *unitMetricCicdPipelineRunErrors = "{error}";
+
+static inline nostd::unique_ptr<metrics::Counter<uint64_t>>
+CreateSyncInt64MetricCicdPipelineRunErrors(metrics::Meter *meter)
+{
+  return meter->CreateUInt64Counter(kMetricCicdPipelineRunErrors, descrMetricCicdPipelineRunErrors,
+                                    unitMetricCicdPipelineRunErrors);
+}
+
+static inline nostd::unique_ptr<metrics::Counter<double>>
+CreateSyncDoubleMetricCicdPipelineRunErrors(metrics::Meter *meter)
+{
+  return meter->CreateDoubleCounter(kMetricCicdPipelineRunErrors, descrMetricCicdPipelineRunErrors,
+                                    unitMetricCicdPipelineRunErrors);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncInt64MetricCicdPipelineRunErrors(metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableCounter(kMetricCicdPipelineRunErrors,
+                                             descrMetricCicdPipelineRunErrors,
+                                             unitMetricCicdPipelineRunErrors);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncDoubleMetricCicdPipelineRunErrors(metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableCounter(kMetricCicdPipelineRunErrors,
+                                              descrMetricCicdPipelineRunErrors,
+                                              unitMetricCicdPipelineRunErrors);
+}
+
+/**
+ * The number of errors in a component of the CICD system (eg. controller, scheduler, agent).
+ * <p>
+ * Errors in pipeline run execution are explicitly excluded. Ie a test failure is not counted in
+ * this metric. <p> counter
+ */
+static constexpr const char *kMetricCicdSystemErrors = "cicd.system.errors";
+static constexpr const char *descrMetricCicdSystemErrors =
+    "The number of errors in a component of the CICD system (eg. controller, scheduler, agent).";
+static constexpr const char *unitMetricCicdSystemErrors = "{error}";
+
+static inline nostd::unique_ptr<metrics::Counter<uint64_t>> CreateSyncInt64MetricCicdSystemErrors(
+    metrics::Meter *meter)
+{
+  return meter->CreateUInt64Counter(kMetricCicdSystemErrors, descrMetricCicdSystemErrors,
+                                    unitMetricCicdSystemErrors);
+}
+
+static inline nostd::unique_ptr<metrics::Counter<double>> CreateSyncDoubleMetricCicdSystemErrors(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleCounter(kMetricCicdSystemErrors, descrMetricCicdSystemErrors,
+                                    unitMetricCicdSystemErrors);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncInt64MetricCicdSystemErrors(metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableCounter(kMetricCicdSystemErrors, descrMetricCicdSystemErrors,
+                                             unitMetricCicdSystemErrors);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncDoubleMetricCicdSystemErrors(metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableCounter(kMetricCicdSystemErrors, descrMetricCicdSystemErrors,
+                                              unitMetricCicdSystemErrors);
+}
+
+/**
+ * The number of workers on the CICD system by state.
+ * <p>
+ * updowncounter
+ */
+static constexpr const char *kMetricCicdWorkerCount = "cicd.worker.count";
+static constexpr const char *descrMetricCicdWorkerCount =
+    "The number of workers on the CICD system by state.";
+static constexpr const char *unitMetricCicdWorkerCount = "{count}";
+
+static inline nostd::unique_ptr<metrics::UpDownCounter<int64_t>>
+CreateSyncInt64MetricCicdWorkerCount(metrics::Meter *meter)
+{
+  return meter->CreateInt64UpDownCounter(kMetricCicdWorkerCount, descrMetricCicdWorkerCount,
+                                         unitMetricCicdWorkerCount);
+}
+
+static inline nostd::unique_ptr<metrics::UpDownCounter<double>>
+CreateSyncDoubleMetricCicdWorkerCount(metrics::Meter *meter)
+{
+  return meter->CreateDoubleUpDownCounter(kMetricCicdWorkerCount, descrMetricCicdWorkerCount,
+                                          unitMetricCicdWorkerCount);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncInt64MetricCicdWorkerCount(metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableUpDownCounter(
+      kMetricCicdWorkerCount, descrMetricCicdWorkerCount, unitMetricCicdWorkerCount);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncDoubleMetricCicdWorkerCount(metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableUpDownCounter(
+      kMetricCicdWorkerCount, descrMetricCicdWorkerCount, unitMetricCicdWorkerCount);
+}
+
+}  // namespace cicd
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 41 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/client_attributes.h

@@ -0,0 +1,41 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_attributes-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace client
+{
+
+/**
+  Client address - domain name if available without reverse DNS lookup; otherwise, IP address or
+  Unix domain socket name. <p> When observed from the server side, and when communicating through an
+  intermediary, @code client.address @endcode SHOULD represent the client address behind any
+  intermediaries,  for example proxies, if it's available.
+ */
+static constexpr const char *kClientAddress = "client.address";
+
+/**
+  Client port number.
+  <p>
+  When observed from the server side, and when communicating through an intermediary, @code
+  client.port @endcode SHOULD represent the client port behind any intermediaries,  for example
+  proxies, if it's available.
+ */
+static constexpr const char *kClientPort = "client.port";
+
+}  // namespace client
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 81 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/code_attributes.h

@@ -0,0 +1,81 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_attributes-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace code
+{
+
+/**
+  The column number in @code code.file.path @endcode best representing the operation. It SHOULD
+  point within the code unit named in @code code.function.name @endcode. This attribute MUST NOT be
+  used on the Profile signal since the data is already captured in 'message Line'. This constraint
+  is imposed to prevent redundancy and maintain data integrity.
+ */
+static constexpr const char *kCodeColumnNumber = "code.column.number";
+
+/**
+  The source code file name that identifies the code unit as uniquely as possible (preferably an
+  absolute file path). This attribute MUST NOT be used on the Profile signal since the data is
+  already captured in 'message Function'. This constraint is imposed to prevent redundancy and
+  maintain data integrity.
+ */
+static constexpr const char *kCodeFilePath = "code.file.path";
+
+/**
+  The method or function fully-qualified name without arguments. The value should fit the natural
+  representation of the language runtime, which is also likely the same used within @code
+  code.stacktrace @endcode attribute value. This attribute MUST NOT be used on the Profile signal
+  since the data is already captured in 'message Function'. This constraint is imposed to prevent
+  redundancy and maintain data integrity. <p> Values and format depends on each language runtime,
+  thus it is impossible to provide an exhaustive list of examples. The values are usually the same
+  (or prefixes of) the ones found in native stack trace representation stored in
+  @code code.stacktrace @endcode without information on arguments.
+  <p>
+  Examples:
+  <ul>
+    <li>Java method: @code com.example.MyHttpService.serveRequest @endcode</li>
+    <li>Java anonymous class method: @code com.mycompany.Main$1.myMethod @endcode</li>
+    <li>Java lambda method: @code com.mycompany.Main$$Lambda/0x0000748ae4149c00.myMethod
+  @endcode</li> <li>PHP function: @code GuzzleHttp\Client::transfer @endcode</li> <li>Go function:
+  @code github.com/my/repo/pkg.foo.func5 @endcode</li> <li>Elixir: @code OpenTelemetry.Ctx.new
+  @endcode</li> <li>Erlang: @code opentelemetry_ctx:new @endcode</li> <li>Rust: @code
+  playground::my_module::my_cool_func @endcode</li> <li>C function: @code fopen @endcode</li>
+  </ul>
+ */
+static constexpr const char *kCodeFunctionName = "code.function.name";
+
+/**
+  The line number in @code code.file.path @endcode best representing the operation. It SHOULD point
+  within the code unit named in @code code.function.name @endcode. This attribute MUST NOT be used
+  on the Profile signal since the data is already captured in 'message Line'. This constraint is
+  imposed to prevent redundancy and maintain data integrity.
+ */
+static constexpr const char *kCodeLineNumber = "code.line.number";
+
+/**
+  A stacktrace as a string in the natural representation for the language runtime. The
+  representation is identical to <a
+  href="/docs/exceptions/exceptions-spans.md#stacktrace-representation">@code exception.stacktrace
+  @endcode</a>. This attribute MUST NOT be used on the Profile signal since the data is already
+  captured in 'message Location'. This constraint is imposed to prevent redundancy and maintain data
+  integrity.
+ */
+static constexpr const char *kCodeStacktrace = "code.stacktrace";
+
+}  // namespace code
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 266 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/container_metrics.h

@@ -0,0 +1,266 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_metrics-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/metrics/meter.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace container
+{
+
+/**
+ * Total CPU time consumed
+ * <p>
+ * Total CPU time consumed by the specific container on all available CPU cores
+ * <p>
+ * counter
+ */
+static constexpr const char *kMetricContainerCpuTime     = "container.cpu.time";
+static constexpr const char *descrMetricContainerCpuTime = "Total CPU time consumed";
+static constexpr const char *unitMetricContainerCpuTime  = "s";
+
+static inline nostd::unique_ptr<metrics::Counter<uint64_t>> CreateSyncInt64MetricContainerCpuTime(
+    metrics::Meter *meter)
+{
+  return meter->CreateUInt64Counter(kMetricContainerCpuTime, descrMetricContainerCpuTime,
+                                    unitMetricContainerCpuTime);
+}
+
+static inline nostd::unique_ptr<metrics::Counter<double>> CreateSyncDoubleMetricContainerCpuTime(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleCounter(kMetricContainerCpuTime, descrMetricContainerCpuTime,
+                                    unitMetricContainerCpuTime);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncInt64MetricContainerCpuTime(metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableCounter(kMetricContainerCpuTime, descrMetricContainerCpuTime,
+                                             unitMetricContainerCpuTime);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncDoubleMetricContainerCpuTime(metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableCounter(kMetricContainerCpuTime, descrMetricContainerCpuTime,
+                                              unitMetricContainerCpuTime);
+}
+
+/**
+ * Container's CPU usage, measured in cpus. Range from 0 to the number of allocatable CPUs
+ * <p>
+ * CPU usage of the specific container on all available CPU cores, averaged over the sample window
+ * <p>
+ * gauge
+ */
+static constexpr const char *kMetricContainerCpuUsage = "container.cpu.usage";
+static constexpr const char *descrMetricContainerCpuUsage =
+    "Container's CPU usage, measured in cpus. Range from 0 to the number of allocatable CPUs";
+static constexpr const char *unitMetricContainerCpuUsage = "{cpu}";
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+
+static inline nostd::unique_ptr<metrics::Gauge<int64_t>> CreateSyncInt64MetricContainerCpuUsage(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64Gauge(kMetricContainerCpuUsage, descrMetricContainerCpuUsage,
+                                 unitMetricContainerCpuUsage);
+}
+
+static inline nostd::unique_ptr<metrics::Gauge<double>> CreateSyncDoubleMetricContainerCpuUsage(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleGauge(kMetricContainerCpuUsage, descrMetricContainerCpuUsage,
+                                  unitMetricContainerCpuUsage);
+}
+#endif /* OPENTELEMETRY_ABI_VERSION_NO */
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncInt64MetricContainerCpuUsage(metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableGauge(kMetricContainerCpuUsage, descrMetricContainerCpuUsage,
+                                           unitMetricContainerCpuUsage);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncDoubleMetricContainerCpuUsage(metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableGauge(kMetricContainerCpuUsage, descrMetricContainerCpuUsage,
+                                            unitMetricContainerCpuUsage);
+}
+
+/**
+ * Disk bytes for the container.
+ * <p>
+ * The total number of bytes read/written successfully (aggregated from all disks).
+ * <p>
+ * counter
+ */
+static constexpr const char *kMetricContainerDiskIo     = "container.disk.io";
+static constexpr const char *descrMetricContainerDiskIo = "Disk bytes for the container.";
+static constexpr const char *unitMetricContainerDiskIo  = "By";
+
+static inline nostd::unique_ptr<metrics::Counter<uint64_t>> CreateSyncInt64MetricContainerDiskIo(
+    metrics::Meter *meter)
+{
+  return meter->CreateUInt64Counter(kMetricContainerDiskIo, descrMetricContainerDiskIo,
+                                    unitMetricContainerDiskIo);
+}
+
+static inline nostd::unique_ptr<metrics::Counter<double>> CreateSyncDoubleMetricContainerDiskIo(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleCounter(kMetricContainerDiskIo, descrMetricContainerDiskIo,
+                                    unitMetricContainerDiskIo);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncInt64MetricContainerDiskIo(metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableCounter(kMetricContainerDiskIo, descrMetricContainerDiskIo,
+                                             unitMetricContainerDiskIo);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncDoubleMetricContainerDiskIo(metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableCounter(kMetricContainerDiskIo, descrMetricContainerDiskIo,
+                                              unitMetricContainerDiskIo);
+}
+
+/**
+ * Memory usage of the container.
+ * <p>
+ * Memory usage of the container.
+ * <p>
+ * counter
+ */
+static constexpr const char *kMetricContainerMemoryUsage     = "container.memory.usage";
+static constexpr const char *descrMetricContainerMemoryUsage = "Memory usage of the container.";
+static constexpr const char *unitMetricContainerMemoryUsage  = "By";
+
+static inline nostd::unique_ptr<metrics::Counter<uint64_t>>
+CreateSyncInt64MetricContainerMemoryUsage(metrics::Meter *meter)
+{
+  return meter->CreateUInt64Counter(kMetricContainerMemoryUsage, descrMetricContainerMemoryUsage,
+                                    unitMetricContainerMemoryUsage);
+}
+
+static inline nostd::unique_ptr<metrics::Counter<double>>
+CreateSyncDoubleMetricContainerMemoryUsage(metrics::Meter *meter)
+{
+  return meter->CreateDoubleCounter(kMetricContainerMemoryUsage, descrMetricContainerMemoryUsage,
+                                    unitMetricContainerMemoryUsage);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncInt64MetricContainerMemoryUsage(metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableCounter(
+      kMetricContainerMemoryUsage, descrMetricContainerMemoryUsage, unitMetricContainerMemoryUsage);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncDoubleMetricContainerMemoryUsage(metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableCounter(
+      kMetricContainerMemoryUsage, descrMetricContainerMemoryUsage, unitMetricContainerMemoryUsage);
+}
+
+/**
+ * Network bytes for the container.
+ * <p>
+ * The number of bytes sent/received on all network interfaces by the container.
+ * <p>
+ * counter
+ */
+static constexpr const char *kMetricContainerNetworkIo     = "container.network.io";
+static constexpr const char *descrMetricContainerNetworkIo = "Network bytes for the container.";
+static constexpr const char *unitMetricContainerNetworkIo  = "By";
+
+static inline nostd::unique_ptr<metrics::Counter<uint64_t>> CreateSyncInt64MetricContainerNetworkIo(
+    metrics::Meter *meter)
+{
+  return meter->CreateUInt64Counter(kMetricContainerNetworkIo, descrMetricContainerNetworkIo,
+                                    unitMetricContainerNetworkIo);
+}
+
+static inline nostd::unique_ptr<metrics::Counter<double>> CreateSyncDoubleMetricContainerNetworkIo(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleCounter(kMetricContainerNetworkIo, descrMetricContainerNetworkIo,
+                                    unitMetricContainerNetworkIo);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncInt64MetricContainerNetworkIo(metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableCounter(
+      kMetricContainerNetworkIo, descrMetricContainerNetworkIo, unitMetricContainerNetworkIo);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncDoubleMetricContainerNetworkIo(metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableCounter(
+      kMetricContainerNetworkIo, descrMetricContainerNetworkIo, unitMetricContainerNetworkIo);
+}
+
+/**
+ * The time the container has been running
+ * <p>
+ * Instrumentations SHOULD use a gauge with type @code double @endcode and measure uptime in seconds
+ * as a floating point number with the highest precision available. The actual accuracy would depend
+ * on the instrumentation and operating system. <p> gauge
+ */
+static constexpr const char *kMetricContainerUptime     = "container.uptime";
+static constexpr const char *descrMetricContainerUptime = "The time the container has been running";
+static constexpr const char *unitMetricContainerUptime  = "s";
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+
+static inline nostd::unique_ptr<metrics::Gauge<int64_t>> CreateSyncInt64MetricContainerUptime(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64Gauge(kMetricContainerUptime, descrMetricContainerUptime,
+                                 unitMetricContainerUptime);
+}
+
+static inline nostd::unique_ptr<metrics::Gauge<double>> CreateSyncDoubleMetricContainerUptime(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleGauge(kMetricContainerUptime, descrMetricContainerUptime,
+                                  unitMetricContainerUptime);
+}
+#endif /* OPENTELEMETRY_ABI_VERSION_NO */
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncInt64MetricContainerUptime(metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableGauge(kMetricContainerUptime, descrMetricContainerUptime,
+                                           unitMetricContainerUptime);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncDoubleMetricContainerUptime(metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableGauge(kMetricContainerUptime, descrMetricContainerUptime,
+                                            unitMetricContainerUptime);
+}
+
+}  // namespace container
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 141 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/cpu_metrics.h

@@ -0,0 +1,141 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_metrics-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/metrics/meter.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace cpu
+{
+
+/**
+ * Operating frequency of the logical CPU in Hertz.
+ * <p>
+ * gauge
+ */
+static constexpr const char *kMetricCpuFrequency = "cpu.frequency";
+static constexpr const char *descrMetricCpuFrequency =
+    "Operating frequency of the logical CPU in Hertz.";
+static constexpr const char *unitMetricCpuFrequency = "Hz";
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+
+static inline nostd::unique_ptr<metrics::Gauge<int64_t>> CreateSyncInt64MetricCpuFrequency(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64Gauge(kMetricCpuFrequency, descrMetricCpuFrequency,
+                                 unitMetricCpuFrequency);
+}
+
+static inline nostd::unique_ptr<metrics::Gauge<double>> CreateSyncDoubleMetricCpuFrequency(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleGauge(kMetricCpuFrequency, descrMetricCpuFrequency,
+                                  unitMetricCpuFrequency);
+}
+#endif /* OPENTELEMETRY_ABI_VERSION_NO */
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncInt64MetricCpuFrequency(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableGauge(kMetricCpuFrequency, descrMetricCpuFrequency,
+                                           unitMetricCpuFrequency);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncDoubleMetricCpuFrequency(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableGauge(kMetricCpuFrequency, descrMetricCpuFrequency,
+                                            unitMetricCpuFrequency);
+}
+
+/**
+ * Seconds each logical CPU spent on each mode
+ * <p>
+ * counter
+ */
+static constexpr const char *kMetricCpuTime     = "cpu.time";
+static constexpr const char *descrMetricCpuTime = "Seconds each logical CPU spent on each mode";
+static constexpr const char *unitMetricCpuTime  = "s";
+
+static inline nostd::unique_ptr<metrics::Counter<uint64_t>> CreateSyncInt64MetricCpuTime(
+    metrics::Meter *meter)
+{
+  return meter->CreateUInt64Counter(kMetricCpuTime, descrMetricCpuTime, unitMetricCpuTime);
+}
+
+static inline nostd::unique_ptr<metrics::Counter<double>> CreateSyncDoubleMetricCpuTime(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleCounter(kMetricCpuTime, descrMetricCpuTime, unitMetricCpuTime);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncInt64MetricCpuTime(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableCounter(kMetricCpuTime, descrMetricCpuTime, unitMetricCpuTime);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncDoubleMetricCpuTime(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableCounter(kMetricCpuTime, descrMetricCpuTime,
+                                              unitMetricCpuTime);
+}
+
+/**
+ * For each logical CPU, the utilization is calculated as the change in cumulative CPU time
+ * (cpu.time) over a measurement interval, divided by the elapsed time. <p> gauge
+ */
+static constexpr const char *kMetricCpuUtilization = "cpu.utilization";
+static constexpr const char *descrMetricCpuUtilization =
+    "For each logical CPU, the utilization is calculated as the change in cumulative CPU time "
+    "(cpu.time) over a measurement interval, divided by the elapsed time.";
+static constexpr const char *unitMetricCpuUtilization = "1";
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+
+static inline nostd::unique_ptr<metrics::Gauge<int64_t>> CreateSyncInt64MetricCpuUtilization(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64Gauge(kMetricCpuUtilization, descrMetricCpuUtilization,
+                                 unitMetricCpuUtilization);
+}
+
+static inline nostd::unique_ptr<metrics::Gauge<double>> CreateSyncDoubleMetricCpuUtilization(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleGauge(kMetricCpuUtilization, descrMetricCpuUtilization,
+                                  unitMetricCpuUtilization);
+}
+#endif /* OPENTELEMETRY_ABI_VERSION_NO */
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncInt64MetricCpuUtilization(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableGauge(kMetricCpuUtilization, descrMetricCpuUtilization,
+                                           unitMetricCpuUtilization);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncDoubleMetricCpuUtilization(metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableGauge(kMetricCpuUtilization, descrMetricCpuUtilization,
+                                            unitMetricCpuUtilization);
+}
+
+}  // namespace cpu
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 349 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/db_attributes.h

@@ -0,0 +1,349 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_attributes-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace db
+{
+
+/**
+  The name of a collection (table, container) within the database.
+  <p>
+  It is RECOMMENDED to capture the value as provided by the application
+  without attempting to do any case normalization.
+  <p>
+  The collection name SHOULD NOT be extracted from @code db.query.text @endcode,
+  when the database system supports query text with multiple collections
+  in non-batch operations.
+  <p>
+  For batch operations, if the individual operations are known to have the same
+  collection name then that collection name SHOULD be used.
+ */
+static constexpr const char *kDbCollectionName = "db.collection.name";
+
+/**
+  The name of the database, fully qualified within the server address and port.
+  <p>
+  If a database system has multiple namespace components, they SHOULD be concatenated from the most
+  general to the most specific namespace component, using @code | @endcode as a separator between
+  the components. Any missing components (and their associated separators) SHOULD be omitted.
+  Semantic conventions for individual database systems SHOULD document what @code db.namespace
+  @endcode means in the context of that system. It is RECOMMENDED to capture the value as provided
+  by the application without attempting to do any case normalization.
+ */
+static constexpr const char *kDbNamespace = "db.namespace";
+
+/**
+  The number of queries included in a batch operation.
+  <p>
+  Operations are only considered batches when they contain two or more operations, and so @code
+  db.operation.batch.size @endcode SHOULD never be @code 1 @endcode.
+ */
+static constexpr const char *kDbOperationBatchSize = "db.operation.batch.size";
+
+/**
+  The name of the operation or command being executed.
+  <p>
+  It is RECOMMENDED to capture the value as provided by the application
+  without attempting to do any case normalization.
+  <p>
+  The operation name SHOULD NOT be extracted from @code db.query.text @endcode,
+  when the database system supports query text with multiple operations
+  in non-batch operations.
+  <p>
+  If spaces can occur in the operation name, multiple consecutive spaces
+  SHOULD be normalized to a single space.
+  <p>
+  For batch operations, if the individual operations are known to have the same operation name
+  then that operation name SHOULD be used prepended by @code BATCH  @endcode,
+  otherwise @code db.operation.name @endcode SHOULD be @code BATCH @endcode or some other database
+  system specific term if more applicable.
+ */
+static constexpr const char *kDbOperationName = "db.operation.name";
+
+/**
+  Low cardinality summary of a database query.
+  <p>
+  The query summary describes a class of database queries and is useful
+  as a grouping key, especially when analyzing telemetry for database
+  calls involving complex queries.
+  <p>
+  Summary may be available to the instrumentation through
+  instrumentation hooks or other means. If it is not available, instrumentations
+  that support query parsing SHOULD generate a summary following
+  <a href="/docs/database/database-spans.md#generating-a-summary-of-the-query">Generating query
+  summary</a> section.
+ */
+static constexpr const char *kDbQuerySummary = "db.query.summary";
+
+/**
+  The database query being executed.
+  <p>
+  For sanitization see <a
+  href="/docs/database/database-spans.md#sanitization-of-dbquerytext">Sanitization of @code
+  db.query.text @endcode</a>. For batch operations, if the individual operations are known to have
+  the same query text then that query text SHOULD be used, otherwise all of the individual query
+  texts SHOULD be concatenated with separator @code ;  @endcode or some other database system
+  specific separator if more applicable. Parameterized query text SHOULD NOT be sanitized. Even
+  though parameterized query text can potentially have sensitive data, by using a parameterized
+  query the user is giving a strong signal that any sensitive data will be passed as parameter
+  values, and the benefit to observability of capturing the static part of the query text by default
+  outweighs the risk.
+ */
+static constexpr const char *kDbQueryText = "db.query.text";
+
+/**
+  Database response status code.
+  <p>
+  The status code returned by the database. Usually it represents an error code, but may also
+  represent partial success, warning, or differentiate between various types of successful outcomes.
+  Semantic conventions for individual database systems SHOULD document what @code
+  db.response.status_code @endcode means in the context of that system.
+ */
+static constexpr const char *kDbResponseStatusCode = "db.response.status_code";
+
+/**
+  The name of a stored procedure within the database.
+  <p>
+  It is RECOMMENDED to capture the value as provided by the application
+  without attempting to do any case normalization.
+  <p>
+  For batch operations, if the individual operations are known to have the same
+  stored procedure name then that stored procedure name SHOULD be used.
+ */
+static constexpr const char *kDbStoredProcedureName = "db.stored_procedure.name";
+
+/**
+  The database management system (DBMS) product as identified by the client instrumentation.
+  <p>
+  The actual DBMS may differ from the one identified by the client. For example, when using
+  PostgreSQL client libraries to connect to a CockroachDB, the @code db.system.name @endcode is set
+  to @code postgresql @endcode based on the instrumentation's best knowledge.
+ */
+static constexpr const char *kDbSystemName = "db.system.name";
+
+namespace DbSystemNameValues
+{
+/**
+  Some other SQL database. Fallback only.
+ */
+static constexpr const char *kOtherSql = "other_sql";
+
+/**
+  <a href="https://documentation.softwareag.com/?pf=adabas">Adabas (Adaptable Database System)</a>
+ */
+static constexpr const char *kSoftwareagAdabas = "softwareag.adabas";
+
+/**
+  <a href="https://www.actian.com/databases/ingres/">Actian Ingres</a>
+ */
+static constexpr const char *kActianIngres = "actian.ingres";
+
+/**
+  <a href="https://aws.amazon.com/pm/dynamodb/">Amazon DynamoDB</a>
+ */
+static constexpr const char *kAwsDynamodb = "aws.dynamodb";
+
+/**
+  <a href="https://aws.amazon.com/redshift/">Amazon Redshift</a>
+ */
+static constexpr const char *kAwsRedshift = "aws.redshift";
+
+/**
+  <a href="https://learn.microsoft.com/azure/cosmos-db">Azure Cosmos DB</a>
+ */
+static constexpr const char *kAzureCosmosdb = "azure.cosmosdb";
+
+/**
+  <a href="https://www.intersystems.com/products/cache/">InterSystems Caché</a>
+ */
+static constexpr const char *kIntersystemsCache = "intersystems.cache";
+
+/**
+  <a href="https://cassandra.apache.org/">Apache Cassandra</a>
+ */
+static constexpr const char *kCassandra = "cassandra";
+
+/**
+  <a href="https://clickhouse.com/">ClickHouse</a>
+ */
+static constexpr const char *kClickhouse = "clickhouse";
+
+/**
+  <a href="https://www.cockroachlabs.com/">CockroachDB</a>
+ */
+static constexpr const char *kCockroachdb = "cockroachdb";
+
+/**
+  <a href="https://www.couchbase.com/">Couchbase</a>
+ */
+static constexpr const char *kCouchbase = "couchbase";
+
+/**
+  <a href="https://couchdb.apache.org/">Apache CouchDB</a>
+ */
+static constexpr const char *kCouchdb = "couchdb";
+
+/**
+  <a href="https://db.apache.org/derby/">Apache Derby</a>
+ */
+static constexpr const char *kDerby = "derby";
+
+/**
+  <a href="https://www.elastic.co/elasticsearch">Elasticsearch</a>
+ */
+static constexpr const char *kElasticsearch = "elasticsearch";
+
+/**
+  <a href="https://www.firebirdsql.org/">Firebird</a>
+ */
+static constexpr const char *kFirebirdsql = "firebirdsql";
+
+/**
+  <a href="https://cloud.google.com/spanner">Google Cloud Spanner</a>
+ */
+static constexpr const char *kGcpSpanner = "gcp.spanner";
+
+/**
+  <a href="https://geode.apache.org/">Apache Geode</a>
+ */
+static constexpr const char *kGeode = "geode";
+
+/**
+  <a href="https://h2database.com/">H2 Database</a>
+ */
+static constexpr const char *kH2database = "h2database";
+
+/**
+  <a href="https://hbase.apache.org/">Apache HBase</a>
+ */
+static constexpr const char *kHbase = "hbase";
+
+/**
+  <a href="https://hive.apache.org/">Apache Hive</a>
+ */
+static constexpr const char *kHive = "hive";
+
+/**
+  <a href="https://hsqldb.org/">HyperSQL Database</a>
+ */
+static constexpr const char *kHsqldb = "hsqldb";
+
+/**
+  <a href="https://www.ibm.com/db2">IBM Db2</a>
+ */
+static constexpr const char *kIbmDb2 = "ibm.db2";
+
+/**
+  <a href="https://www.ibm.com/products/informix">IBM Informix</a>
+ */
+static constexpr const char *kIbmInformix = "ibm.informix";
+
+/**
+  <a href="https://www.ibm.com/products/netezza">IBM Netezza</a>
+ */
+static constexpr const char *kIbmNetezza = "ibm.netezza";
+
+/**
+  <a href="https://www.influxdata.com/">InfluxDB</a>
+ */
+static constexpr const char *kInfluxdb = "influxdb";
+
+/**
+  <a href="https://www.instantdb.com/">Instant</a>
+ */
+static constexpr const char *kInstantdb = "instantdb";
+
+/**
+  <a href="https://mariadb.org/">MariaDB</a>
+ */
+static constexpr const char *kMariadb = "mariadb";
+
+/**
+  <a href="https://memcached.org/">Memcached</a>
+ */
+static constexpr const char *kMemcached = "memcached";
+
+/**
+  <a href="https://www.mongodb.com/">MongoDB</a>
+ */
+static constexpr const char *kMongodb = "mongodb";
+
+/**
+  <a href="https://www.microsoft.com/sql-server">Microsoft SQL Server</a>
+ */
+static constexpr const char *kMicrosoftSqlServer = "microsoft.sql_server";
+
+/**
+  <a href="https://www.mysql.com/">MySQL</a>
+ */
+static constexpr const char *kMysql = "mysql";
+
+/**
+  <a href="https://neo4j.com/">Neo4j</a>
+ */
+static constexpr const char *kNeo4j = "neo4j";
+
+/**
+  <a href="https://opensearch.org/">OpenSearch</a>
+ */
+static constexpr const char *kOpensearch = "opensearch";
+
+/**
+  <a href="https://www.oracle.com/database/">Oracle Database</a>
+ */
+static constexpr const char *kOracleDb = "oracle.db";
+
+/**
+  <a href="https://www.postgresql.org/">PostgreSQL</a>
+ */
+static constexpr const char *kPostgresql = "postgresql";
+
+/**
+  <a href="https://redis.io/">Redis</a>
+ */
+static constexpr const char *kRedis = "redis";
+
+/**
+  <a href="https://www.sap.com/products/technology-platform/hana/what-is-sap-hana.html">SAP HANA</a>
+ */
+static constexpr const char *kSapHana = "sap.hana";
+
+/**
+  <a href="https://maxdb.sap.com/">SAP MaxDB</a>
+ */
+static constexpr const char *kSapMaxdb = "sap.maxdb";
+
+/**
+  <a href="https://www.sqlite.org/">SQLite</a>
+ */
+static constexpr const char *kSqlite = "sqlite";
+
+/**
+  <a href="https://www.teradata.com/">Teradata</a>
+ */
+static constexpr const char *kTeradata = "teradata";
+
+/**
+  <a href="https://trino.io/">Trino</a>
+ */
+static constexpr const char *kTrino = "trino";
+
+}  // namespace DbSystemNameValues
+
+}  // namespace db
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 53 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/db_metrics.h

@@ -0,0 +1,53 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_metrics-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/metrics/meter.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace db
+{
+
+/**
+  Duration of database client operations.
+  <p>
+  Batch operations SHOULD be recorded as a single operation.
+  <p>
+  histogram
+ */
+static constexpr const char *kMetricDbClientOperationDuration = "db.client.operation.duration";
+static constexpr const char *descrMetricDbClientOperationDuration =
+    "Duration of database client operations.";
+static constexpr const char *unitMetricDbClientOperationDuration = "s";
+
+static inline nostd::unique_ptr<metrics::Histogram<uint64_t>>
+CreateSyncInt64MetricDbClientOperationDuration(metrics::Meter *meter)
+{
+  return meter->CreateUInt64Histogram(kMetricDbClientOperationDuration,
+                                      descrMetricDbClientOperationDuration,
+                                      unitMetricDbClientOperationDuration);
+}
+
+static inline nostd::unique_ptr<metrics::Histogram<double>>
+CreateSyncDoubleMetricDbClientOperationDuration(metrics::Meter *meter)
+{
+  return meter->CreateDoubleHistogram(kMetricDbClientOperationDuration,
+                                      descrMetricDbClientOperationDuration,
+                                      unitMetricDbClientOperationDuration);
+}
+
+}  // namespace db
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 49 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/dns_metrics.h

@@ -0,0 +1,49 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_metrics-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/metrics/meter.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace dns
+{
+
+/**
+ * Measures the time taken to perform a DNS lookup.
+ * <p>
+ * histogram
+ */
+static constexpr const char *kMetricDnsLookupDuration = "dns.lookup.duration";
+static constexpr const char *descrMetricDnsLookupDuration =
+    "Measures the time taken to perform a DNS lookup.";
+static constexpr const char *unitMetricDnsLookupDuration = "s";
+
+static inline nostd::unique_ptr<metrics::Histogram<uint64_t>>
+CreateSyncInt64MetricDnsLookupDuration(metrics::Meter *meter)
+{
+  return meter->CreateUInt64Histogram(kMetricDnsLookupDuration, descrMetricDnsLookupDuration,
+                                      unitMetricDnsLookupDuration);
+}
+
+static inline nostd::unique_ptr<metrics::Histogram<double>> CreateSyncDoubleMetricDnsLookupDuration(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleHistogram(kMetricDnsLookupDuration, descrMetricDnsLookupDuration,
+                                      unitMetricDnsLookupDuration);
+}
+
+}  // namespace dns
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 57 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/error_attributes.h

@@ -0,0 +1,57 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_attributes-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace error
+{
+
+/**
+  Describes a class of error the operation ended with.
+  <p>
+  The @code error.type @endcode SHOULD be predictable, and SHOULD have low cardinality.
+  <p>
+  When @code error.type @endcode is set to a type (e.g., an exception type), its
+  canonical class name identifying the type within the artifact SHOULD be used.
+  <p>
+  Instrumentations SHOULD document the list of errors they report.
+  <p>
+  The cardinality of @code error.type @endcode within one instrumentation library SHOULD be low.
+  Telemetry consumers that aggregate data from multiple instrumentation libraries and applications
+  should be prepared for @code error.type @endcode to have high cardinality at query time when no
+  additional filters are applied.
+  <p>
+  If the operation has completed successfully, instrumentations SHOULD NOT set @code error.type
+  @endcode. <p> If a specific domain defines its own set of error identifiers (such as HTTP or gRPC
+  status codes), it's RECOMMENDED to: <ul> <li>Use a domain-specific attribute</li> <li>Set @code
+  error.type @endcode to capture all errors, regardless of whether they are defined within the
+  domain-specific set or not.</li>
+  </ul>
+ */
+static constexpr const char *kErrorType = "error.type";
+
+namespace ErrorTypeValues
+{
+/**
+  A fallback error value to be used when the instrumentation doesn't define a custom value.
+ */
+static constexpr const char *kOther = "_OTHER";
+
+}  // namespace ErrorTypeValues
+
+}  // namespace error
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 50 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/exception_attributes.h

@@ -0,0 +1,50 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_attributes-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace exception
+{
+
+/**
+  Indicates that the exception is escaping the scope of the span.
+
+  @deprecated
+  {"note": "It's no longer recommended to record exceptions that are handled and do not escape the
+  scope of a span.\n", "reason": "obsoleted"}
+ */
+OPENTELEMETRY_DEPRECATED static constexpr const char *kExceptionEscaped = "exception.escaped";
+
+/**
+  The exception message.
+ */
+static constexpr const char *kExceptionMessage = "exception.message";
+
+/**
+  A stacktrace as a string in the natural representation for the language runtime. The
+  representation is to be determined and documented by each language SIG.
+ */
+static constexpr const char *kExceptionStacktrace = "exception.stacktrace";
+
+/**
+  The type of the exception (its fully-qualified class name, if applicable). The dynamic type of the
+  exception should be preferred over the static type in languages that support it.
+ */
+static constexpr const char *kExceptionType = "exception.type";
+
+}  // namespace exception
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 287 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/faas_metrics.h

@@ -0,0 +1,287 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_metrics-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/metrics/meter.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace faas
+{
+
+/**
+ * Number of invocation cold starts
+ * <p>
+ * counter
+ */
+static constexpr const char *kMetricFaasColdstarts     = "faas.coldstarts";
+static constexpr const char *descrMetricFaasColdstarts = "Number of invocation cold starts";
+static constexpr const char *unitMetricFaasColdstarts  = "{coldstart}";
+
+static inline nostd::unique_ptr<metrics::Counter<uint64_t>> CreateSyncInt64MetricFaasColdstarts(
+    metrics::Meter *meter)
+{
+  return meter->CreateUInt64Counter(kMetricFaasColdstarts, descrMetricFaasColdstarts,
+                                    unitMetricFaasColdstarts);
+}
+
+static inline nostd::unique_ptr<metrics::Counter<double>> CreateSyncDoubleMetricFaasColdstarts(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleCounter(kMetricFaasColdstarts, descrMetricFaasColdstarts,
+                                    unitMetricFaasColdstarts);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncInt64MetricFaasColdstarts(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableCounter(kMetricFaasColdstarts, descrMetricFaasColdstarts,
+                                             unitMetricFaasColdstarts);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncDoubleMetricFaasColdstarts(metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableCounter(kMetricFaasColdstarts, descrMetricFaasColdstarts,
+                                              unitMetricFaasColdstarts);
+}
+
+/**
+ * Distribution of CPU usage per invocation
+ * <p>
+ * histogram
+ */
+static constexpr const char *kMetricFaasCpuUsage     = "faas.cpu_usage";
+static constexpr const char *descrMetricFaasCpuUsage = "Distribution of CPU usage per invocation";
+static constexpr const char *unitMetricFaasCpuUsage  = "s";
+
+static inline nostd::unique_ptr<metrics::Histogram<uint64_t>> CreateSyncInt64MetricFaasCpuUsage(
+    metrics::Meter *meter)
+{
+  return meter->CreateUInt64Histogram(kMetricFaasCpuUsage, descrMetricFaasCpuUsage,
+                                      unitMetricFaasCpuUsage);
+}
+
+static inline nostd::unique_ptr<metrics::Histogram<double>> CreateSyncDoubleMetricFaasCpuUsage(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleHistogram(kMetricFaasCpuUsage, descrMetricFaasCpuUsage,
+                                      unitMetricFaasCpuUsage);
+}
+
+/**
+ * Number of invocation errors
+ * <p>
+ * counter
+ */
+static constexpr const char *kMetricFaasErrors     = "faas.errors";
+static constexpr const char *descrMetricFaasErrors = "Number of invocation errors";
+static constexpr const char *unitMetricFaasErrors  = "{error}";
+
+static inline nostd::unique_ptr<metrics::Counter<uint64_t>> CreateSyncInt64MetricFaasErrors(
+    metrics::Meter *meter)
+{
+  return meter->CreateUInt64Counter(kMetricFaasErrors, descrMetricFaasErrors, unitMetricFaasErrors);
+}
+
+static inline nostd::unique_ptr<metrics::Counter<double>> CreateSyncDoubleMetricFaasErrors(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleCounter(kMetricFaasErrors, descrMetricFaasErrors, unitMetricFaasErrors);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncInt64MetricFaasErrors(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableCounter(kMetricFaasErrors, descrMetricFaasErrors,
+                                             unitMetricFaasErrors);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncDoubleMetricFaasErrors(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableCounter(kMetricFaasErrors, descrMetricFaasErrors,
+                                              unitMetricFaasErrors);
+}
+
+/**
+ * Measures the duration of the function's initialization, such as a cold start
+ * <p>
+ * histogram
+ */
+static constexpr const char *kMetricFaasInitDuration = "faas.init_duration";
+static constexpr const char *descrMetricFaasInitDuration =
+    "Measures the duration of the function's initialization, such as a cold start";
+static constexpr const char *unitMetricFaasInitDuration = "s";
+
+static inline nostd::unique_ptr<metrics::Histogram<uint64_t>> CreateSyncInt64MetricFaasInitDuration(
+    metrics::Meter *meter)
+{
+  return meter->CreateUInt64Histogram(kMetricFaasInitDuration, descrMetricFaasInitDuration,
+                                      unitMetricFaasInitDuration);
+}
+
+static inline nostd::unique_ptr<metrics::Histogram<double>> CreateSyncDoubleMetricFaasInitDuration(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleHistogram(kMetricFaasInitDuration, descrMetricFaasInitDuration,
+                                      unitMetricFaasInitDuration);
+}
+
+/**
+ * Number of successful invocations
+ * <p>
+ * counter
+ */
+static constexpr const char *kMetricFaasInvocations     = "faas.invocations";
+static constexpr const char *descrMetricFaasInvocations = "Number of successful invocations";
+static constexpr const char *unitMetricFaasInvocations  = "{invocation}";
+
+static inline nostd::unique_ptr<metrics::Counter<uint64_t>> CreateSyncInt64MetricFaasInvocations(
+    metrics::Meter *meter)
+{
+  return meter->CreateUInt64Counter(kMetricFaasInvocations, descrMetricFaasInvocations,
+                                    unitMetricFaasInvocations);
+}
+
+static inline nostd::unique_ptr<metrics::Counter<double>> CreateSyncDoubleMetricFaasInvocations(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleCounter(kMetricFaasInvocations, descrMetricFaasInvocations,
+                                    unitMetricFaasInvocations);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncInt64MetricFaasInvocations(metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableCounter(kMetricFaasInvocations, descrMetricFaasInvocations,
+                                             unitMetricFaasInvocations);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncDoubleMetricFaasInvocations(metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableCounter(kMetricFaasInvocations, descrMetricFaasInvocations,
+                                              unitMetricFaasInvocations);
+}
+
+/**
+ * Measures the duration of the function's logic execution
+ * <p>
+ * histogram
+ */
+static constexpr const char *kMetricFaasInvokeDuration = "faas.invoke_duration";
+static constexpr const char *descrMetricFaasInvokeDuration =
+    "Measures the duration of the function's logic execution";
+static constexpr const char *unitMetricFaasInvokeDuration = "s";
+
+static inline nostd::unique_ptr<metrics::Histogram<uint64_t>>
+CreateSyncInt64MetricFaasInvokeDuration(metrics::Meter *meter)
+{
+  return meter->CreateUInt64Histogram(kMetricFaasInvokeDuration, descrMetricFaasInvokeDuration,
+                                      unitMetricFaasInvokeDuration);
+}
+
+static inline nostd::unique_ptr<metrics::Histogram<double>>
+CreateSyncDoubleMetricFaasInvokeDuration(metrics::Meter *meter)
+{
+  return meter->CreateDoubleHistogram(kMetricFaasInvokeDuration, descrMetricFaasInvokeDuration,
+                                      unitMetricFaasInvokeDuration);
+}
+
+/**
+ * Distribution of max memory usage per invocation
+ * <p>
+ * histogram
+ */
+static constexpr const char *kMetricFaasMemUsage = "faas.mem_usage";
+static constexpr const char *descrMetricFaasMemUsage =
+    "Distribution of max memory usage per invocation";
+static constexpr const char *unitMetricFaasMemUsage = "By";
+
+static inline nostd::unique_ptr<metrics::Histogram<uint64_t>> CreateSyncInt64MetricFaasMemUsage(
+    metrics::Meter *meter)
+{
+  return meter->CreateUInt64Histogram(kMetricFaasMemUsage, descrMetricFaasMemUsage,
+                                      unitMetricFaasMemUsage);
+}
+
+static inline nostd::unique_ptr<metrics::Histogram<double>> CreateSyncDoubleMetricFaasMemUsage(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleHistogram(kMetricFaasMemUsage, descrMetricFaasMemUsage,
+                                      unitMetricFaasMemUsage);
+}
+
+/**
+ * Distribution of net I/O usage per invocation
+ * <p>
+ * histogram
+ */
+static constexpr const char *kMetricFaasNetIo     = "faas.net_io";
+static constexpr const char *descrMetricFaasNetIo = "Distribution of net I/O usage per invocation";
+static constexpr const char *unitMetricFaasNetIo  = "By";
+
+static inline nostd::unique_ptr<metrics::Histogram<uint64_t>> CreateSyncInt64MetricFaasNetIo(
+    metrics::Meter *meter)
+{
+  return meter->CreateUInt64Histogram(kMetricFaasNetIo, descrMetricFaasNetIo, unitMetricFaasNetIo);
+}
+
+static inline nostd::unique_ptr<metrics::Histogram<double>> CreateSyncDoubleMetricFaasNetIo(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleHistogram(kMetricFaasNetIo, descrMetricFaasNetIo, unitMetricFaasNetIo);
+}
+
+/**
+ * Number of invocation timeouts
+ * <p>
+ * counter
+ */
+static constexpr const char *kMetricFaasTimeouts     = "faas.timeouts";
+static constexpr const char *descrMetricFaasTimeouts = "Number of invocation timeouts";
+static constexpr const char *unitMetricFaasTimeouts  = "{timeout}";
+
+static inline nostd::unique_ptr<metrics::Counter<uint64_t>> CreateSyncInt64MetricFaasTimeouts(
+    metrics::Meter *meter)
+{
+  return meter->CreateUInt64Counter(kMetricFaasTimeouts, descrMetricFaasTimeouts,
+                                    unitMetricFaasTimeouts);
+}
+
+static inline nostd::unique_ptr<metrics::Counter<double>> CreateSyncDoubleMetricFaasTimeouts(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleCounter(kMetricFaasTimeouts, descrMetricFaasTimeouts,
+                                    unitMetricFaasTimeouts);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncInt64MetricFaasTimeouts(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableCounter(kMetricFaasTimeouts, descrMetricFaasTimeouts,
+                                             unitMetricFaasTimeouts);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncDoubleMetricFaasTimeouts(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableCounter(kMetricFaasTimeouts, descrMetricFaasTimeouts,
+                                              unitMetricFaasTimeouts);
+}
+
+}  // namespace faas
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 157 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/gen_ai_metrics.h

@@ -0,0 +1,157 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_metrics-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/metrics/meter.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace gen_ai
+{
+
+/**
+ * GenAI operation duration
+ * <p>
+ * histogram
+ */
+static constexpr const char *kMetricGenAiClientOperationDuration =
+    "gen_ai.client.operation.duration";
+static constexpr const char *descrMetricGenAiClientOperationDuration = "GenAI operation duration";
+static constexpr const char *unitMetricGenAiClientOperationDuration  = "s";
+
+static inline nostd::unique_ptr<metrics::Histogram<uint64_t>>
+CreateSyncInt64MetricGenAiClientOperationDuration(metrics::Meter *meter)
+{
+  return meter->CreateUInt64Histogram(kMetricGenAiClientOperationDuration,
+                                      descrMetricGenAiClientOperationDuration,
+                                      unitMetricGenAiClientOperationDuration);
+}
+
+static inline nostd::unique_ptr<metrics::Histogram<double>>
+CreateSyncDoubleMetricGenAiClientOperationDuration(metrics::Meter *meter)
+{
+  return meter->CreateDoubleHistogram(kMetricGenAiClientOperationDuration,
+                                      descrMetricGenAiClientOperationDuration,
+                                      unitMetricGenAiClientOperationDuration);
+}
+
+/**
+ * Measures number of input and output tokens used
+ * <p>
+ * histogram
+ */
+static constexpr const char *kMetricGenAiClientTokenUsage = "gen_ai.client.token.usage";
+static constexpr const char *descrMetricGenAiClientTokenUsage =
+    "Measures number of input and output tokens used";
+static constexpr const char *unitMetricGenAiClientTokenUsage = "{token}";
+
+static inline nostd::unique_ptr<metrics::Histogram<uint64_t>>
+CreateSyncInt64MetricGenAiClientTokenUsage(metrics::Meter *meter)
+{
+  return meter->CreateUInt64Histogram(kMetricGenAiClientTokenUsage,
+                                      descrMetricGenAiClientTokenUsage,
+                                      unitMetricGenAiClientTokenUsage);
+}
+
+static inline nostd::unique_ptr<metrics::Histogram<double>>
+CreateSyncDoubleMetricGenAiClientTokenUsage(metrics::Meter *meter)
+{
+  return meter->CreateDoubleHistogram(kMetricGenAiClientTokenUsage,
+                                      descrMetricGenAiClientTokenUsage,
+                                      unitMetricGenAiClientTokenUsage);
+}
+
+/**
+ * Generative AI server request duration such as time-to-last byte or last output token
+ * <p>
+ * histogram
+ */
+static constexpr const char *kMetricGenAiServerRequestDuration = "gen_ai.server.request.duration";
+static constexpr const char *descrMetricGenAiServerRequestDuration =
+    "Generative AI server request duration such as time-to-last byte or last output token";
+static constexpr const char *unitMetricGenAiServerRequestDuration = "s";
+
+static inline nostd::unique_ptr<metrics::Histogram<uint64_t>>
+CreateSyncInt64MetricGenAiServerRequestDuration(metrics::Meter *meter)
+{
+  return meter->CreateUInt64Histogram(kMetricGenAiServerRequestDuration,
+                                      descrMetricGenAiServerRequestDuration,
+                                      unitMetricGenAiServerRequestDuration);
+}
+
+static inline nostd::unique_ptr<metrics::Histogram<double>>
+CreateSyncDoubleMetricGenAiServerRequestDuration(metrics::Meter *meter)
+{
+  return meter->CreateDoubleHistogram(kMetricGenAiServerRequestDuration,
+                                      descrMetricGenAiServerRequestDuration,
+                                      unitMetricGenAiServerRequestDuration);
+}
+
+/**
+ * Time per output token generated after the first token for successful responses
+ * <p>
+ * histogram
+ */
+static constexpr const char *kMetricGenAiServerTimePerOutputToken =
+    "gen_ai.server.time_per_output_token";
+static constexpr const char *descrMetricGenAiServerTimePerOutputToken =
+    "Time per output token generated after the first token for successful responses";
+static constexpr const char *unitMetricGenAiServerTimePerOutputToken = "s";
+
+static inline nostd::unique_ptr<metrics::Histogram<uint64_t>>
+CreateSyncInt64MetricGenAiServerTimePerOutputToken(metrics::Meter *meter)
+{
+  return meter->CreateUInt64Histogram(kMetricGenAiServerTimePerOutputToken,
+                                      descrMetricGenAiServerTimePerOutputToken,
+                                      unitMetricGenAiServerTimePerOutputToken);
+}
+
+static inline nostd::unique_ptr<metrics::Histogram<double>>
+CreateSyncDoubleMetricGenAiServerTimePerOutputToken(metrics::Meter *meter)
+{
+  return meter->CreateDoubleHistogram(kMetricGenAiServerTimePerOutputToken,
+                                      descrMetricGenAiServerTimePerOutputToken,
+                                      unitMetricGenAiServerTimePerOutputToken);
+}
+
+/**
+ * Time to generate first token for successful responses
+ * <p>
+ * histogram
+ */
+static constexpr const char *kMetricGenAiServerTimeToFirstToken =
+    "gen_ai.server.time_to_first_token";
+static constexpr const char *descrMetricGenAiServerTimeToFirstToken =
+    "Time to generate first token for successful responses";
+static constexpr const char *unitMetricGenAiServerTimeToFirstToken = "s";
+
+static inline nostd::unique_ptr<metrics::Histogram<uint64_t>>
+CreateSyncInt64MetricGenAiServerTimeToFirstToken(metrics::Meter *meter)
+{
+  return meter->CreateUInt64Histogram(kMetricGenAiServerTimeToFirstToken,
+                                      descrMetricGenAiServerTimeToFirstToken,
+                                      unitMetricGenAiServerTimeToFirstToken);
+}
+
+static inline nostd::unique_ptr<metrics::Histogram<double>>
+CreateSyncDoubleMetricGenAiServerTimeToFirstToken(metrics::Meter *meter)
+{
+  return meter->CreateDoubleHistogram(kMetricGenAiServerTimeToFirstToken,
+                                      descrMetricGenAiServerTimeToFirstToken,
+                                      unitMetricGenAiServerTimeToFirstToken);
+}
+
+}  // namespace gen_ai
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 164 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/http_attributes.h

@@ -0,0 +1,164 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_attributes-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace http
+{
+
+/**
+  HTTP request headers, @code <key> @endcode being the normalized HTTP Header name (lowercase), the
+  value being the header values. <p> Instrumentations SHOULD require an explicit configuration of
+  which headers are to be captured. Including all request headers can be a security risk - explicit
+  configuration helps avoid leaking sensitive information. <p> The @code User-Agent @endcode header
+  is already captured in the @code user_agent.original @endcode attribute. Users MAY explicitly
+  configure instrumentations to capture them even though it is not recommended. <p> The attribute
+  value MUST consist of either multiple header values as an array of strings or a single-item array
+  containing a possibly comma-concatenated string, depending on the way the HTTP library provides
+  access to headers. <p> Examples: <ul> <li>A header @code Content-Type: application/json @endcode
+  SHOULD be recorded as the @code http.request.header.content-type @endcode attribute with value
+  @code ["application/json"] @endcode.</li> <li>A header @code X-Forwarded-For: 1.2.3.4, 1.2.3.5
+  @endcode SHOULD be recorded as the @code http.request.header.x-forwarded-for @endcode attribute
+  with value @code ["1.2.3.4", "1.2.3.5"] @endcode or @code ["1.2.3.4, 1.2.3.5"] @endcode depending
+  on the HTTP library.</li>
+  </ul>
+ */
+static constexpr const char *kHttpRequestHeader = "http.request.header";
+
+/**
+  HTTP request method.
+  <p>
+  HTTP request method value SHOULD be "known" to the instrumentation.
+  By default, this convention defines "known" methods as the ones listed in <a
+  href="https://www.rfc-editor.org/rfc/rfc9110.html#name-methods">RFC9110</a> and the PATCH method
+  defined in <a href="https://www.rfc-editor.org/rfc/rfc5789.html">RFC5789</a>. <p> If the HTTP
+  request method is not known to instrumentation, it MUST set the @code http.request.method @endcode
+  attribute to @code _OTHER @endcode. <p> If the HTTP instrumentation could end up converting valid
+  HTTP request methods to @code _OTHER @endcode, then it MUST provide a way to override the list of
+  known HTTP methods. If this override is done via environment variable, then the environment
+  variable MUST be named OTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated list
+  of case-sensitive known HTTP methods (this list MUST be a full override of the default known
+  method, it is not a list of known methods in addition to the defaults). <p> HTTP method names are
+  case-sensitive and @code http.request.method @endcode attribute value MUST match a known HTTP
+  method name exactly. Instrumentations for specific web frameworks that consider HTTP methods to be
+  case insensitive, SHOULD populate a canonical equivalent. Tracing instrumentations that do so,
+  MUST also set @code http.request.method_original @endcode to the original value.
+ */
+static constexpr const char *kHttpRequestMethod = "http.request.method";
+
+/**
+  Original HTTP method sent by the client in the request line.
+ */
+static constexpr const char *kHttpRequestMethodOriginal = "http.request.method_original";
+
+/**
+  The ordinal number of request resending attempt (for any reason, including redirects).
+  <p>
+  The resend count SHOULD be updated each time an HTTP request gets resent by the client, regardless
+  of what was the cause of the resending (e.g. redirection, authorization failure, 503 Server
+  Unavailable, network issues, or any other).
+ */
+static constexpr const char *kHttpRequestResendCount = "http.request.resend_count";
+
+/**
+  HTTP response headers, @code <key> @endcode being the normalized HTTP Header name (lowercase), the
+  value being the header values. <p> Instrumentations SHOULD require an explicit configuration of
+  which headers are to be captured. Including all response headers can be a security risk - explicit
+  configuration helps avoid leaking sensitive information. <p> Users MAY explicitly configure
+  instrumentations to capture them even though it is not recommended. <p> The attribute value MUST
+  consist of either multiple header values as an array of strings or a single-item array containing
+  a possibly comma-concatenated string, depending on the way the HTTP library provides access to
+  headers. <p> Examples: <ul> <li>A header @code Content-Type: application/json @endcode header
+  SHOULD be recorded as the @code http.request.response.content-type @endcode attribute with value
+  @code ["application/json"] @endcode.</li> <li>A header @code My-custom-header: abc, def @endcode
+  header SHOULD be recorded as the @code http.response.header.my-custom-header @endcode attribute
+  with value @code ["abc", "def"] @endcode or @code ["abc, def"] @endcode depending on the HTTP
+  library.</li>
+  </ul>
+ */
+static constexpr const char *kHttpResponseHeader = "http.response.header";
+
+/**
+  <a href="https://tools.ietf.org/html/rfc7231#section-6">HTTP response status code</a>.
+ */
+static constexpr const char *kHttpResponseStatusCode = "http.response.status_code";
+
+/**
+  The matched route, that is, the path template in the format used by the respective server
+  framework. <p> MUST NOT be populated when this is not supported by the HTTP server framework as
+  the route attribute should have low-cardinality and the URI path can NOT substitute it. SHOULD
+  include the <a href="/docs/http/http-spans.md#http-server-definitions">application root</a> if
+  there is one.
+ */
+static constexpr const char *kHttpRoute = "http.route";
+
+namespace HttpRequestMethodValues
+{
+/**
+  CONNECT method.
+ */
+static constexpr const char *kConnect = "CONNECT";
+
+/**
+  DELETE method.
+ */
+static constexpr const char *kDelete = "DELETE";
+
+/**
+  GET method.
+ */
+static constexpr const char *kGet = "GET";
+
+/**
+  HEAD method.
+ */
+static constexpr const char *kHead = "HEAD";
+
+/**
+  OPTIONS method.
+ */
+static constexpr const char *kOptions = "OPTIONS";
+
+/**
+  PATCH method.
+ */
+static constexpr const char *kPatch = "PATCH";
+
+/**
+  POST method.
+ */
+static constexpr const char *kPost = "POST";
+
+/**
+  PUT method.
+ */
+static constexpr const char *kPut = "PUT";
+
+/**
+  TRACE method.
+ */
+static constexpr const char *kTrace = "TRACE";
+
+/**
+  Any HTTP method that the instrumentation has no prior knowledge of.
+ */
+static constexpr const char *kOther = "_OTHER";
+
+}  // namespace HttpRequestMethodValues
+
+}  // namespace http
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 77 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/http_metrics.h

@@ -0,0 +1,77 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_metrics-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/metrics/meter.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace http
+{
+
+/**
+  Duration of HTTP client requests.
+  <p>
+  histogram
+ */
+static constexpr const char *kMetricHttpClientRequestDuration = "http.client.request.duration";
+static constexpr const char *descrMetricHttpClientRequestDuration =
+    "Duration of HTTP client requests.";
+static constexpr const char *unitMetricHttpClientRequestDuration = "s";
+
+static inline nostd::unique_ptr<metrics::Histogram<uint64_t>>
+CreateSyncInt64MetricHttpClientRequestDuration(metrics::Meter *meter)
+{
+  return meter->CreateUInt64Histogram(kMetricHttpClientRequestDuration,
+                                      descrMetricHttpClientRequestDuration,
+                                      unitMetricHttpClientRequestDuration);
+}
+
+static inline nostd::unique_ptr<metrics::Histogram<double>>
+CreateSyncDoubleMetricHttpClientRequestDuration(metrics::Meter *meter)
+{
+  return meter->CreateDoubleHistogram(kMetricHttpClientRequestDuration,
+                                      descrMetricHttpClientRequestDuration,
+                                      unitMetricHttpClientRequestDuration);
+}
+
+/**
+  Duration of HTTP server requests.
+  <p>
+  histogram
+ */
+static constexpr const char *kMetricHttpServerRequestDuration = "http.server.request.duration";
+static constexpr const char *descrMetricHttpServerRequestDuration =
+    "Duration of HTTP server requests.";
+static constexpr const char *unitMetricHttpServerRequestDuration = "s";
+
+static inline nostd::unique_ptr<metrics::Histogram<uint64_t>>
+CreateSyncInt64MetricHttpServerRequestDuration(metrics::Meter *meter)
+{
+  return meter->CreateUInt64Histogram(kMetricHttpServerRequestDuration,
+                                      descrMetricHttpServerRequestDuration,
+                                      unitMetricHttpServerRequestDuration);
+}
+
+static inline nostd::unique_ptr<metrics::Histogram<double>>
+CreateSyncDoubleMetricHttpServerRequestDuration(metrics::Meter *meter)
+{
+  return meter->CreateDoubleHistogram(kMetricHttpServerRequestDuration,
+                                      descrMetricHttpServerRequestDuration,
+                                      unitMetricHttpServerRequestDuration);
+}
+
+}  // namespace http
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 344 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/hw_metrics.h

@@ -0,0 +1,344 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_metrics-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/metrics/meter.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace hw
+{
+
+/**
+ * Energy consumed by the component
+ * <p>
+ * counter
+ */
+static constexpr const char *kMetricHwEnergy     = "hw.energy";
+static constexpr const char *descrMetricHwEnergy = "Energy consumed by the component";
+static constexpr const char *unitMetricHwEnergy  = "J";
+
+static inline nostd::unique_ptr<metrics::Counter<uint64_t>> CreateSyncInt64MetricHwEnergy(
+    metrics::Meter *meter)
+{
+  return meter->CreateUInt64Counter(kMetricHwEnergy, descrMetricHwEnergy, unitMetricHwEnergy);
+}
+
+static inline nostd::unique_ptr<metrics::Counter<double>> CreateSyncDoubleMetricHwEnergy(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleCounter(kMetricHwEnergy, descrMetricHwEnergy, unitMetricHwEnergy);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncInt64MetricHwEnergy(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableCounter(kMetricHwEnergy, descrMetricHwEnergy,
+                                             unitMetricHwEnergy);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncDoubleMetricHwEnergy(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableCounter(kMetricHwEnergy, descrMetricHwEnergy,
+                                              unitMetricHwEnergy);
+}
+
+/**
+ * Number of errors encountered by the component
+ * <p>
+ * counter
+ */
+static constexpr const char *kMetricHwErrors     = "hw.errors";
+static constexpr const char *descrMetricHwErrors = "Number of errors encountered by the component";
+static constexpr const char *unitMetricHwErrors  = "{error}";
+
+static inline nostd::unique_ptr<metrics::Counter<uint64_t>> CreateSyncInt64MetricHwErrors(
+    metrics::Meter *meter)
+{
+  return meter->CreateUInt64Counter(kMetricHwErrors, descrMetricHwErrors, unitMetricHwErrors);
+}
+
+static inline nostd::unique_ptr<metrics::Counter<double>> CreateSyncDoubleMetricHwErrors(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleCounter(kMetricHwErrors, descrMetricHwErrors, unitMetricHwErrors);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncInt64MetricHwErrors(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableCounter(kMetricHwErrors, descrMetricHwErrors,
+                                             unitMetricHwErrors);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncDoubleMetricHwErrors(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableCounter(kMetricHwErrors, descrMetricHwErrors,
+                                              unitMetricHwErrors);
+}
+
+/**
+ * Ambient (external) temperature of the physical host
+ * <p>
+ * gauge
+ */
+static constexpr const char *kMetricHwHostAmbientTemperature = "hw.host.ambient_temperature";
+static constexpr const char *descrMetricHwHostAmbientTemperature =
+    "Ambient (external) temperature of the physical host";
+static constexpr const char *unitMetricHwHostAmbientTemperature = "Cel";
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+
+static inline nostd::unique_ptr<metrics::Gauge<int64_t>>
+CreateSyncInt64MetricHwHostAmbientTemperature(metrics::Meter *meter)
+{
+  return meter->CreateInt64Gauge(kMetricHwHostAmbientTemperature,
+                                 descrMetricHwHostAmbientTemperature,
+                                 unitMetricHwHostAmbientTemperature);
+}
+
+static inline nostd::unique_ptr<metrics::Gauge<double>>
+CreateSyncDoubleMetricHwHostAmbientTemperature(metrics::Meter *meter)
+{
+  return meter->CreateDoubleGauge(kMetricHwHostAmbientTemperature,
+                                  descrMetricHwHostAmbientTemperature,
+                                  unitMetricHwHostAmbientTemperature);
+}
+#endif /* OPENTELEMETRY_ABI_VERSION_NO */
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncInt64MetricHwHostAmbientTemperature(metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableGauge(kMetricHwHostAmbientTemperature,
+                                           descrMetricHwHostAmbientTemperature,
+                                           unitMetricHwHostAmbientTemperature);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncDoubleMetricHwHostAmbientTemperature(metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableGauge(kMetricHwHostAmbientTemperature,
+                                            descrMetricHwHostAmbientTemperature,
+                                            unitMetricHwHostAmbientTemperature);
+}
+
+/**
+ * Total energy consumed by the entire physical host, in joules
+ * <p>
+ * The overall energy usage of a host MUST be reported using the specific @code hw.host.energy
+ * @endcode and @code hw.host.power @endcode metrics <strong>only</strong>, instead of the generic
+ * @code hw.energy @endcode and @code hw.power @endcode described in the previous section, to
+ * prevent summing up overlapping values. <p> counter
+ */
+static constexpr const char *kMetricHwHostEnergy = "hw.host.energy";
+static constexpr const char *descrMetricHwHostEnergy =
+    "Total energy consumed by the entire physical host, in joules";
+static constexpr const char *unitMetricHwHostEnergy = "J";
+
+static inline nostd::unique_ptr<metrics::Counter<uint64_t>> CreateSyncInt64MetricHwHostEnergy(
+    metrics::Meter *meter)
+{
+  return meter->CreateUInt64Counter(kMetricHwHostEnergy, descrMetricHwHostEnergy,
+                                    unitMetricHwHostEnergy);
+}
+
+static inline nostd::unique_ptr<metrics::Counter<double>> CreateSyncDoubleMetricHwHostEnergy(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleCounter(kMetricHwHostEnergy, descrMetricHwHostEnergy,
+                                    unitMetricHwHostEnergy);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncInt64MetricHwHostEnergy(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableCounter(kMetricHwHostEnergy, descrMetricHwHostEnergy,
+                                             unitMetricHwHostEnergy);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncDoubleMetricHwHostEnergy(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableCounter(kMetricHwHostEnergy, descrMetricHwHostEnergy,
+                                              unitMetricHwHostEnergy);
+}
+
+/**
+ * By how many degrees Celsius the temperature of the physical host can be increased, before
+ * reaching a warning threshold on one of the internal sensors <p> gauge
+ */
+static constexpr const char *kMetricHwHostHeatingMargin = "hw.host.heating_margin";
+static constexpr const char *descrMetricHwHostHeatingMargin =
+    "By how many degrees Celsius the temperature of the physical host can be increased, before reaching a warning threshold on one of the internal sensors
+    ";
+    static constexpr const char *unitMetricHwHostHeatingMargin = "Cel";
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+
+static inline nostd::unique_ptr<metrics::Gauge<int64_t>> CreateSyncInt64MetricHwHostHeatingMargin(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64Gauge(kMetricHwHostHeatingMargin, descrMetricHwHostHeatingMargin,
+                                 unitMetricHwHostHeatingMargin);
+}
+
+static inline nostd::unique_ptr<metrics::Gauge<double>> CreateSyncDoubleMetricHwHostHeatingMargin(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleGauge(kMetricHwHostHeatingMargin, descrMetricHwHostHeatingMargin,
+                                  unitMetricHwHostHeatingMargin);
+}
+#endif /* OPENTELEMETRY_ABI_VERSION_NO */
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncInt64MetricHwHostHeatingMargin(metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableGauge(
+      kMetricHwHostHeatingMargin, descrMetricHwHostHeatingMargin, unitMetricHwHostHeatingMargin);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument>
+CreateAsyncDoubleMetricHwHostHeatingMargin(metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableGauge(
+      kMetricHwHostHeatingMargin, descrMetricHwHostHeatingMargin, unitMetricHwHostHeatingMargin);
+}
+
+/**
+ * Instantaneous power consumed by the entire physical host in Watts (@code hw.host.energy @endcode
+ * is preferred) <p> The overall energy usage of a host MUST be reported using the specific @code
+ * hw.host.energy @endcode and @code hw.host.power @endcode metrics <strong>only</strong>, instead
+ * of the generic @code hw.energy @endcode and @code hw.power @endcode described in the previous
+ * section, to prevent summing up overlapping values. <p> gauge
+ */
+static constexpr const char *kMetricHwHostPower = "hw.host.power";
+static constexpr const char *descrMetricHwHostPower =
+    "Instantaneous power consumed by the entire physical host in Watts (`hw.host.energy` is preferred)
+    ";
+    static constexpr const char *unitMetricHwHostPower = "W";
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+
+static inline nostd::unique_ptr<metrics::Gauge<int64_t>> CreateSyncInt64MetricHwHostPower(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64Gauge(kMetricHwHostPower, descrMetricHwHostPower, unitMetricHwHostPower);
+}
+
+static inline nostd::unique_ptr<metrics::Gauge<double>> CreateSyncDoubleMetricHwHostPower(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleGauge(kMetricHwHostPower, descrMetricHwHostPower,
+                                  unitMetricHwHostPower);
+}
+#endif /* OPENTELEMETRY_ABI_VERSION_NO */
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncInt64MetricHwHostPower(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableGauge(kMetricHwHostPower, descrMetricHwHostPower,
+                                           unitMetricHwHostPower);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncDoubleMetricHwHostPower(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableGauge(kMetricHwHostPower, descrMetricHwHostPower,
+                                            unitMetricHwHostPower);
+}
+
+/**
+ * Instantaneous power consumed by the component
+ * <p>
+ * It is recommended to report @code hw.energy @endcode instead of @code hw.power @endcode when
+ * possible. <p> gauge
+ */
+static constexpr const char *kMetricHwPower     = "hw.power";
+static constexpr const char *descrMetricHwPower = "Instantaneous power consumed by the component";
+static constexpr const char *unitMetricHwPower  = "W";
+
+#if OPENTELEMETRY_ABI_VERSION_NO >= 2
+
+static inline nostd::unique_ptr<metrics::Gauge<int64_t>> CreateSyncInt64MetricHwPower(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64Gauge(kMetricHwPower, descrMetricHwPower, unitMetricHwPower);
+}
+
+static inline nostd::unique_ptr<metrics::Gauge<double>> CreateSyncDoubleMetricHwPower(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleGauge(kMetricHwPower, descrMetricHwPower, unitMetricHwPower);
+}
+#endif /* OPENTELEMETRY_ABI_VERSION_NO */
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncInt64MetricHwPower(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableGauge(kMetricHwPower, descrMetricHwPower, unitMetricHwPower);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncDoubleMetricHwPower(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableGauge(kMetricHwPower, descrMetricHwPower, unitMetricHwPower);
+}
+
+/**
+ * Operational status: @code 1 @endcode (true) or @code 0 @endcode (false) for each of the possible
+ * states <p>
+ * @code hw.status @endcode is currently specified as an <em>UpDownCounter</em> but would ideally be
+ * represented using a <a
+ * href="https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#stateset"><em>StateSet</em>
+ * as defined in OpenMetrics</a>. This semantic convention will be updated once <em>StateSet</em> is
+ * specified in OpenTelemetry. This planned change is not expected to have any consequence on the
+ * way users query their timeseries backend to retrieve the values of @code hw.status @endcode over
+ * time. <p> updowncounter
+ */
+static constexpr const char *kMetricHwStatus = "hw.status";
+static constexpr const char *descrMetricHwStatus =
+    "Operational status: `1` (true) or `0` (false) for each of the possible states";
+static constexpr const char *unitMetricHwStatus = "1";
+
+static inline nostd::unique_ptr<metrics::UpDownCounter<int64_t>> CreateSyncInt64MetricHwStatus(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64UpDownCounter(kMetricHwStatus, descrMetricHwStatus, unitMetricHwStatus);
+}
+
+static inline nostd::unique_ptr<metrics::UpDownCounter<double>> CreateSyncDoubleMetricHwStatus(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleUpDownCounter(kMetricHwStatus, descrMetricHwStatus, unitMetricHwStatus);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncInt64MetricHwStatus(
+    metrics::Meter *meter)
+{
+  return meter->CreateInt64ObservableUpDownCounter(kMetricHwStatus, descrMetricHwStatus,
+                                                   unitMetricHwStatus);
+}
+
+static inline nostd::shared_ptr<metrics::ObservableInstrument> CreateAsyncDoubleMetricHwStatus(
+    metrics::Meter *meter)
+{
+  return meter->CreateDoubleObservableUpDownCounter(kMetricHwStatus, descrMetricHwStatus,
+                                                    unitMetricHwStatus);
+}
+
+}  // namespace hw
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 76 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/incubating/app_attributes.h

@@ -0,0 +1,76 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_attributes-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace app
+{
+
+/**
+  A unique identifier representing the installation of an application on a specific device
+  <p>
+  Its value SHOULD persist across launches of the same application installation, including through
+  application upgrades. It SHOULD change if the application is uninstalled or if all applications of
+  the vendor are uninstalled. Additionally, users might be able to reset this value (e.g. by
+  clearing application data). If an app is installed multiple times on the same device (e.g. in
+  different accounts on Android), each @code app.installation.id @endcode SHOULD have a different
+  value. If multiple OpenTelemetry SDKs are used within the same application, they SHOULD use the
+  same value for @code app.installation.id @endcode. Hardware IDs (e.g. serial number, IMEI, MAC
+  address) MUST NOT be used as the @code app.installation.id @endcode. <p> For iOS, this value
+  SHOULD be equal to the <a
+  href="https://developer.apple.com/documentation/uikit/uidevice/identifierforvendor">vendor
+  identifier</a>. <p> For Android, examples of @code app.installation.id @endcode implementations
+  include: <ul> <li><a
+  href="https://firebase.google.com/docs/projects/manage-installations">Firebase Installation
+  ID</a>.</li> <li>A globally unique UUID which is persisted across sessions in your
+  application.</li> <li><a href="https://developer.android.com/identity/app-set-id">App set
+  ID</a>.</li> <li><a
+  href="https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID">@code
+  Settings.getString(Settings.Secure.ANDROID_ID) @endcode</a>.</li>
+  </ul>
+  <p>
+  More information about Android identifier best practices can be found <a
+  href="https://developer.android.com/training/articles/user-data-ids">here</a>.
+ */
+static constexpr const char *kAppInstallationId = "app.installation.id";
+
+/**
+  The x (horizontal) coordinate of a screen coordinate, in screen pixels.
+ */
+static constexpr const char *kAppScreenCoordinateX = "app.screen.coordinate.x";
+
+/**
+  The y (vertical) component of a screen coordinate, in screen pixels.
+ */
+static constexpr const char *kAppScreenCoordinateY = "app.screen.coordinate.y";
+
+/**
+  An identifier that uniquely differentiates this widget from other widgets in the same application.
+  <p>
+  A widget is an application component, typically an on-screen visual GUI element.
+ */
+static constexpr const char *kAppWidgetId = "app.widget.id";
+
+/**
+  The name of an application widget.
+  <p>
+  A widget is an application component, typically an on-screen visual GUI element.
+ */
+static constexpr const char *kAppWidgetName = "app.widget.name";
+
+}  // namespace app
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

+ 79 - 0
ext/opentelemetry-cpp-api-only/include/opentelemetry/semconv/incubating/artifact_attributes.h

@@ -0,0 +1,79 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * DO NOT EDIT, this is an Auto-generated file from:
+ * buildscripts/semantic-convention/templates/registry/semantic_attributes-h.j2
+ */
+
+#pragma once
+
+#include "opentelemetry/common/macros.h"
+#include "opentelemetry/version.h"
+
+OPENTELEMETRY_BEGIN_NAMESPACE
+namespace semconv
+{
+namespace artifact
+{
+
+/**
+  The provenance filename of the built attestation which directly relates to the build artifact
+  filename. This filename SHOULD accompany the artifact at publish time. See the <a
+  href="https://slsa.dev/spec/v1.0/distributing-provenance#relationship-between-artifacts-and-attestations">SLSA
+  Relationship</a> specification for more information.
+ */
+static constexpr const char *kArtifactAttestationFilename = "artifact.attestation.filename";
+
+/**
+  The full <a href="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf">hash value (see
+  glossary)</a>, of the built attestation. Some envelopes in the <a
+  href="https://github.com/in-toto/attestation/tree/main/spec">software attestation space</a> also
+  refer to this as the <strong>digest</strong>.
+ */
+static constexpr const char *kArtifactAttestationHash = "artifact.attestation.hash";
+
+/**
+  The id of the build <a href="https://slsa.dev/attestation-model">software attestation</a>.
+ */
+static constexpr const char *kArtifactAttestationId = "artifact.attestation.id";
+
+/**
+  The human readable file name of the artifact, typically generated during build and release
+  processes. Often includes the package name and version in the file name. <p> This file name can
+  also act as the <a href="https://slsa.dev/spec/v1.0/terminology#package-model">Package Name</a> in
+  cases where the package ecosystem maps accordingly. Additionally, the artifact <a
+  href="https://slsa.dev/spec/v1.0/terminology#software-supply-chain">can be published</a> for
+  others, but that is not a guarantee.
+ */
+static constexpr const char *kArtifactFilename = "artifact.filename";
+
+/**
+  The full <a href="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf">hash value (see
+  glossary)</a>, often found in checksum.txt on a release of the artifact and used to verify package
+  integrity. <p> The specific algorithm used to create the cryptographic hash value is not defined.
+  In situations where an artifact has multiple cryptographic hashes, it is up to the implementer to
+  choose which hash value to set here; this should be the most secure hash algorithm that is
+  suitable for the situation and consistent with the corresponding attestation. The implementer can
+  then provide the other hash values through an additional set of attribute extensions as they deem
+  necessary.
+ */
+static constexpr const char *kArtifactHash = "artifact.hash";
+
+/**
+  The <a href="https://github.com/package-url/purl-spec">Package URL</a> of the <a
+  href="https://slsa.dev/spec/v1.0/terminology#package-model">package artifact</a> provides a
+  standard way to identify and locate the packaged artifact.
+ */
+static constexpr const char *kArtifactPurl = "artifact.purl";
+
+/**
+  The version of the artifact.
+ */
+static constexpr const char *kArtifactVersion = "artifact.version";
+
+}  // namespace artifact
+}  // namespace semconv
+OPENTELEMETRY_END_NAMESPACE

Some files were not shown because too many files changed in this diff