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

This commit is contained in:
Grant Limberg 2025-07-11 13:12:13 -07:00
parent 8895ad182f
commit 7f835b414a
No known key found for this signature in database
GPG key ID: 8F2F97D3BE8D7735
241 changed files with 49967 additions and 3 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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_

View file

@ -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_

View file

@ -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_

View file

@ -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_

View file

@ -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_

View file

@ -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_

View file

@ -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_

View file

@ -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_

View file

@ -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_

View file

@ -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_

View file

@ -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_

View file

@ -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_

View file

@ -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_

View file

@ -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_

View file

@ -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 */

View file

@ -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

View file

@ -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 */

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 have changed in this diff Show more