mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2026-04-19 03:13:19 -07:00
include the otel header-only part directly for ease of use
This commit is contained in:
parent
8895ad182f
commit
7f835b414a
241 changed files with 49967 additions and 3 deletions
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 ©)
|
||||
{
|
||||
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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include "opentelemetry/common/attribute_value.h"
|
||||
#include "opentelemetry/common/key_value_iterable.h"
|
||||
#include "opentelemetry/common/timestamp.h"
|
||||
#include "opentelemetry/logs/event_id.h"
|
||||
#include "opentelemetry/logs/log_record.h"
|
||||
#include "opentelemetry/logs/severity.h"
|
||||
#include "opentelemetry/nostd/string_view.h"
|
||||
#include "opentelemetry/nostd/type_traits.h"
|
||||
#include "opentelemetry/trace/span_context.h"
|
||||
#include "opentelemetry/trace/span_id.h"
|
||||
#include "opentelemetry/trace/trace_flags.h"
|
||||
#include "opentelemetry/trace/trace_id.h"
|
||||
#include "opentelemetry/version.h"
|
||||
|
||||
OPENTELEMETRY_BEGIN_NAMESPACE
|
||||
namespace logs
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <class ValueType>
|
||||
struct LogRecordSetterTrait;
|
||||
|
||||
template <>
|
||||
struct LogRecordSetterTrait<Severity>
|
||||
{
|
||||
template <class ArgumentType>
|
||||
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
|
||||
{
|
||||
log_record->SetSeverity(std::forward<ArgumentType>(arg));
|
||||
|
||||
return log_record;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct LogRecordSetterTrait<EventId>
|
||||
{
|
||||
template <class ArgumentType>
|
||||
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
|
||||
{
|
||||
log_record->SetEventId(arg.id_, nostd::string_view{arg.name_.get()});
|
||||
|
||||
return log_record;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct LogRecordSetterTrait<trace::SpanContext>
|
||||
{
|
||||
template <class ArgumentType>
|
||||
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
|
||||
{
|
||||
log_record->SetSpanId(arg.span_id());
|
||||
log_record->SetTraceId(arg.trace_id());
|
||||
log_record->SetTraceFlags(arg.trace_flags());
|
||||
|
||||
return log_record;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct LogRecordSetterTrait<trace::SpanId>
|
||||
{
|
||||
template <class ArgumentType>
|
||||
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
|
||||
{
|
||||
log_record->SetSpanId(std::forward<ArgumentType>(arg));
|
||||
|
||||
return log_record;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct LogRecordSetterTrait<trace::TraceId>
|
||||
{
|
||||
template <class ArgumentType>
|
||||
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
|
||||
{
|
||||
log_record->SetTraceId(std::forward<ArgumentType>(arg));
|
||||
|
||||
return log_record;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct LogRecordSetterTrait<trace::TraceFlags>
|
||||
{
|
||||
template <class ArgumentType>
|
||||
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
|
||||
{
|
||||
log_record->SetTraceFlags(std::forward<ArgumentType>(arg));
|
||||
|
||||
return log_record;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct LogRecordSetterTrait<common::SystemTimestamp>
|
||||
{
|
||||
template <class ArgumentType>
|
||||
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
|
||||
{
|
||||
log_record->SetTimestamp(std::forward<ArgumentType>(arg));
|
||||
|
||||
return log_record;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct LogRecordSetterTrait<std::chrono::system_clock::time_point>
|
||||
{
|
||||
template <class ArgumentType>
|
||||
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
|
||||
{
|
||||
log_record->SetTimestamp(common::SystemTimestamp(std::forward<ArgumentType>(arg)));
|
||||
|
||||
return log_record;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct LogRecordSetterTrait<common::KeyValueIterable>
|
||||
{
|
||||
template <class ArgumentType>
|
||||
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
|
||||
{
|
||||
arg.ForEachKeyValue(
|
||||
[&log_record](nostd::string_view key, common::AttributeValue value) noexcept {
|
||||
log_record->SetAttribute(key, value);
|
||||
return true;
|
||||
});
|
||||
|
||||
return log_record;
|
||||
}
|
||||
};
|
||||
|
||||
template <class ValueType>
|
||||
struct LogRecordSetterTrait
|
||||
{
|
||||
static_assert(!std::is_same<nostd::unique_ptr<LogRecord>, ValueType>::value &&
|
||||
!std::is_same<std::unique_ptr<LogRecord>, ValueType>::value,
|
||||
"unique_ptr<LogRecord> is not allowed, please use std::move()");
|
||||
|
||||
template <class ArgumentType,
|
||||
nostd::enable_if_t<std::is_convertible<ArgumentType, nostd::string_view>::value ||
|
||||
std::is_convertible<ArgumentType, common::AttributeValue>::value,
|
||||
void> * = nullptr>
|
||||
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
|
||||
{
|
||||
log_record->SetBody(std::forward<ArgumentType>(arg));
|
||||
|
||||
return log_record;
|
||||
}
|
||||
|
||||
template <class ArgumentType,
|
||||
nostd::enable_if_t<std::is_base_of<common::KeyValueIterable, ArgumentType>::value, bool>
|
||||
* = nullptr>
|
||||
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
|
||||
{
|
||||
return LogRecordSetterTrait<common::KeyValueIterable>::Set(log_record,
|
||||
std::forward<ArgumentType>(arg));
|
||||
}
|
||||
|
||||
template <class ArgumentType,
|
||||
nostd::enable_if_t<common::detail::is_key_value_iterable<ArgumentType>::value, int> * =
|
||||
nullptr>
|
||||
inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept
|
||||
{
|
||||
for (auto &argv : arg)
|
||||
{
|
||||
log_record->SetAttribute(argv.first, argv.second);
|
||||
}
|
||||
|
||||
return log_record;
|
||||
}
|
||||
};
|
||||
|
||||
template <class ValueType, class... ArgumentType>
|
||||
struct LogRecordHasType;
|
||||
|
||||
template <class ValueType>
|
||||
struct LogRecordHasType<ValueType> : public std::false_type
|
||||
{};
|
||||
|
||||
template <class ValueType, class TargetType, class... ArgumentType>
|
||||
struct LogRecordHasType<ValueType, TargetType, ArgumentType...>
|
||||
: public std::conditional<std::is_same<ValueType, TargetType>::value,
|
||||
std::true_type,
|
||||
LogRecordHasType<ValueType, ArgumentType...>>::type
|
||||
{};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace logs
|
||||
OPENTELEMETRY_END_NAMESPACE
|
||||
131
ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/noop.h
Normal file
131
ext/opentelemetry-cpp-api-only/include/opentelemetry/logs/noop.h
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue