diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
commit | e6918187568dbd01842d8d1d2c808ce16a894239 (patch) | |
tree | 64f88b554b444a49f656b6c656111a145cbbaa28 /src/jaegertracing/opentelemetry-cpp/api/include | |
parent | Initial commit. (diff) | |
download | ceph-e6918187568dbd01842d8d1d2c808ce16a894239.tar.xz ceph-e6918187568dbd01842d8d1d2c808ce16a894239.zip |
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/jaegertracing/opentelemetry-cpp/api/include')
119 files changed, 16723 insertions, 0 deletions
diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/async_instruments.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/async_instruments.h new file mode 100644 index 000000000..53024b07a --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/async_instruments.h @@ -0,0 +1,88 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include "opentelemetry/_metrics/instrument.h" +# include "opentelemetry/_metrics/observer_result.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace metrics +{ + +template <class T> +class ValueObserver : virtual public AsynchronousInstrument<T> +{ + +public: + ValueObserver() = default; + + ValueObserver(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled, + void (*callback)(ObserverResult<T>)) + {} + + /* + * Updates the instruments aggregator with the new value. The labels should + * contain the keys and values to be associated with this value. + * + * @param value is the numerical representation of the metric being captured + * @param labels the set of labels, as key-value pairs + */ + virtual void observe(T value, const common::KeyValueIterable &labels) override = 0; + + /** + * Captures data by activating the callback function associated with the + * instrument and storing its return value. Callbacks for asynchronous + * instruments are defined during construction. + * + * @param none + * @return none + */ + virtual void run() override = 0; +}; + +template <class T> +class SumObserver : virtual public AsynchronousInstrument<T> +{ + +public: + SumObserver() = default; + + SumObserver(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled, + void (*callback)(ObserverResult<T>)) + {} + + virtual void observe(T value, const common::KeyValueIterable &labels) override = 0; + + virtual void run() override = 0; +}; + +template <class T> +class UpDownSumObserver : virtual public AsynchronousInstrument<T> +{ + +public: + UpDownSumObserver() = default; + + UpDownSumObserver(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled, + void (*callback)(ObserverResult<T>)) + {} + + virtual void observe(T value, const common::KeyValueIterable &labels) override = 0; + + virtual void run() override = 0; +}; + +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/instrument.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/instrument.h new file mode 100644 index 000000000..d0cffac4b --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/instrument.h @@ -0,0 +1,209 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include <iostream> +# include "opentelemetry/common/attribute_value.h" +# include "opentelemetry/common/key_value_iterable_view.h" +# include "opentelemetry/nostd/shared_ptr.h" +# include "opentelemetry/nostd/string_view.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace metrics +{ + +// Enum classes to help determine instrument types in other parts of the API +enum class InstrumentKind +{ + Counter = 0, + UpDownCounter = 1, + ValueRecorder = 2, + ValueObserver = 3, + SumObserver = 4, + UpDownSumObserver = 5, +}; + +class Instrument +{ + +public: + // Note that Instruments should be created using the Meter class. + // Please refer to meter.h for documentation. + Instrument() = default; + + /** + * Base class constructor for all other instrument types. Whether or not + * an instrument is synchronous or bound, it requires a name, description, + * unit, and enabled flag. + * + * @param name is the identifier of the instrumenting library + * @param description explains what the metric captures + * @param unit specifies the data type held in the instrument + * @param enabled determines if the metric is currently capturing data + * @return Instrument type with the specified attributes + */ + Instrument(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled) + {} + + // Returns true if the instrument is enabled and collecting data + virtual bool IsEnabled() = 0; + + // Return the instrument name + virtual nostd::string_view GetName() = 0; + + // Return the instrument description + virtual nostd::string_view GetDescription() = 0; + + // Return the insrument's units of measurement + virtual nostd::string_view GetUnits() = 0; + + // Return the intrument's kind + virtual InstrumentKind GetKind() = 0; + + virtual ~Instrument() = default; +}; + +template <class T> +class BoundSynchronousInstrument : virtual public Instrument +{ + +public: + BoundSynchronousInstrument() = default; + + BoundSynchronousInstrument(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled); + + /** + * Frees the resources associated with this Bound Instrument. + * The Metric from which this instrument was created is not impacted. + * + * @param none + * @return void + */ + virtual void unbind() {} + + /** + * Incremements the reference count of this bound object when a new instance is + * either created or the same instance is returned as a result of binding + * + * @param none + * @return void + */ + virtual void inc_ref() {} + + /** + * Return the object's current reference count. This information is used to remove + * stale objects from instrument registries. + */ + virtual int get_ref() { return 0; } + + /** + * Records a single synchronous metric event; a call to the aggregator + * Since this is a bound synchronous instrument, labels are not required in * metric capture + * calls. + * + * @param value is the numerical representation of the metric being captured + * @return void + */ + virtual void update(T value) {} +}; + +template <class T> +class SynchronousInstrument : virtual public Instrument +{ + +public: + SynchronousInstrument() = default; + + SynchronousInstrument(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled) + {} + + /** + * Returns a Bound Instrument associated with the specified labels. * Multiples requests + * with the same set of labels may return the same Bound Instrument instance. + * + * It is recommended that callers keep a reference to the Bound Instrument + * instead of repeatedly calling this operation. + * + * @param labels the set of labels, as key-value pairs + * @return a Bound Instrument + */ + virtual nostd::shared_ptr<BoundSynchronousInstrument<T>> bind( + const common::KeyValueIterable &labels) + { + return nostd::shared_ptr<BoundSynchronousInstrument<T>>(); + } + + /** + * Records a single synchronous metric event. + * Since this is an unbound synchronous instrument, labels are required in * metric capture + * calls. + * + * update can be used in instruments with both add or record since it simply + * activated the aggregator + * + * @param labels the set of labels, as key-value pairs + * @param value is the numerical representation of the metric being captured + * @return void + */ + virtual void update(T value, const common::KeyValueIterable &labels) = 0; +}; + +template <class T> +class ObserverResult; + +template <class T> +class AsynchronousInstrument : virtual public Instrument +{ + +public: + AsynchronousInstrument() = default; + + AsynchronousInstrument(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled, + void(callback)(ObserverResult<T>)) + {} + + /** + * Captures data through a manual call rather than the automatic collection process instituted + * in the run function. Asynchronous instruments are generally expected to obtain data from + * their callbacks rather than direct calls. This function is used by the callback to store data. + * + * @param value is the numerical representation of the metric being captured + * @param labels is the numerical representation of the metric being captured + * @return none + */ + virtual void observe(T value, const common::KeyValueIterable &labels) = 0; + + /** + * Captures data by activating the callback function associated with the + * instrument and storing its return value. Callbacks for asynchronous + * instruments are defined during construction. + * + * @param none + * @return none + */ + virtual void run() = 0; + +protected: + // Callback function which takes a pointer to an Asynchronous instrument (this) type which is + // stored in an observer result type and returns nothing. This function calls the instrument's + // observe. + void (*callback_)(ObserverResult<T>); +}; + +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/meter.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/meter.h new file mode 100644 index 000000000..11311cf14 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/meter.h @@ -0,0 +1,288 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include "opentelemetry/_metrics/async_instruments.h" +# include "opentelemetry/_metrics/instrument.h" +# include "opentelemetry/_metrics/sync_instruments.h" +# include "opentelemetry/nostd/shared_ptr.h" +# include "opentelemetry/nostd/span.h" +# include "opentelemetry/nostd/string_view.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace metrics +{ +/** + * 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 shared_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. + * @param enabled a boolean value that turns on or off the metric instrument. + * @return a shared pointer to the created Counter. + * @throws NullPointerException if {@code name} is null + * @throws IllegalArgumentException if a different metric by the same name exists in this meter. + * @throws IllegalArgumentException if the {@code name} does not match spec requirements. + */ + virtual nostd::shared_ptr<Counter<short>> NewShortCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) = 0; + + virtual nostd::shared_ptr<Counter<int>> NewIntCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) = 0; + + virtual nostd::shared_ptr<Counter<float>> NewFloatCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) = 0; + + virtual nostd::shared_ptr<Counter<double>> NewDoubleCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) = 0; + + /** + * Creates an UpDownCounter with the passed characteristics and returns a shared_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. + * @param enabled a boolean value that turns on or off the metric instrument. + * @return a shared pointer to the created UpDownCounter. + * @throws NullPointerException if {@code name} is null + * @throws IllegalArgumentException if a different metric by the same name exists in this meter. + * @throws IllegalArgumentException if the {@code name} does not match spec requirements. + */ + virtual nostd::shared_ptr<UpDownCounter<short>> NewShortUpDownCounter( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) = 0; + + virtual nostd::shared_ptr<UpDownCounter<int>> NewIntUpDownCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) = 0; + + virtual nostd::shared_ptr<UpDownCounter<float>> NewFloatUpDownCounter( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) = 0; + + virtual nostd::shared_ptr<UpDownCounter<double>> NewDoubleUpDownCounter( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) = 0; + + /** + * Creates a ValueRecorder with the passed characteristics and returns a shared_ptr to that + * ValueRecorder. + * + * @param name the name of the new ValueRecorder. + * @param description a brief description of what the ValueRecorder is used for. + * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. + * @param enabled a boolean value that turns on or off the metric instrument. + * @return a shared pointer to the created DoubleValueRecorder. + * @throws NullPointerException if {@code name} is null + * @throws IllegalArgumentException if a different metric by the same name exists in this meter. + * @throws IllegalArgumentException if the {@code name} does not match spec requirements. + */ + virtual nostd::shared_ptr<ValueRecorder<short>> NewShortValueRecorder( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) = 0; + + virtual nostd::shared_ptr<ValueRecorder<int>> NewIntValueRecorder(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) = 0; + + virtual nostd::shared_ptr<ValueRecorder<float>> NewFloatValueRecorder( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) = 0; + + virtual nostd::shared_ptr<ValueRecorder<double>> NewDoubleValueRecorder( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) = 0; + + /** + * Creates a SumObserver with the passed characteristics and returns a shared_ptr to that + * SumObserver. + * + * @param name the name of the new SumObserver. + * @param description a brief description of what the SumObserver is used for. + * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. + * @param enabled a boolean value that turns on or off the metric instrument. + * @param callback the function to be observed by the instrument. + * @return a shared pointer to the created SumObserver. + * @throws NullPointerException if {@code name} is null + * @throws IllegalArgumentException if a different metric by the same name exists in this meter. + * @throws IllegalArgumentException if the {@code name} does not match spec requirements. + */ + virtual nostd::shared_ptr<SumObserver<short>> NewShortSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<short>)) = 0; + + virtual nostd::shared_ptr<SumObserver<int>> NewIntSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<int>)) = 0; + + virtual nostd::shared_ptr<SumObserver<float>> NewFloatSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<float>)) = 0; + + virtual nostd::shared_ptr<SumObserver<double>> NewDoubleSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<double>)) = 0; + + /** + * Creates an UpDownSumObserver with the passed characteristics and returns a shared_ptr to + * that UpDowNSumObserver. + * + * @param name the name of the new UpDownSumObserver. + * @param description a brief description of what the UpDownSumObserver is used for. + * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. + * @param enabled a boolean value that turns on or off the metric instrument. + * @param callback the function to be observed by the instrument. + * @return a shared pointer to the created UpDownSumObserver. + * @throws NullPointerException if {@code name} is null + * @throws IllegalArgumentException if a different metric by the same name exists in this meter. + * @throws IllegalArgumentException if the {@code name} does not match spec requirements. + */ + virtual nostd::shared_ptr<UpDownSumObserver<short>> NewShortUpDownSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<short>)) = 0; + + virtual nostd::shared_ptr<UpDownSumObserver<int>> NewIntUpDownSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<int>)) = 0; + + virtual nostd::shared_ptr<UpDownSumObserver<float>> NewFloatUpDownSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<float>)) = 0; + + virtual nostd::shared_ptr<UpDownSumObserver<double>> NewDoubleUpDownSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<double>)) = 0; + + /** + * Creates a ValueObserver with the passed characteristics and returns a shared_ptr to that + * ValueObserver. + * + * @param name the name of the new ValueObserver. + * @param description a brief description of what the ValueObserver is used for. + * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. + * @param enabled a boolean value that turns on or off the metric instrument. + * @param callback the function to be observed by the instrument. + * @return a shared pointer to the created ValueObserver. + * @throws NullPointerException if {@code name} is null + * @throws IllegalArgumentException if a different metric by the same name exists in this meter. + * @throws IllegalArgumentException if the {@code name} does not match spec requirements. + */ + virtual nostd::shared_ptr<ValueObserver<short>> NewShortValueObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<short>)) = 0; + + virtual nostd::shared_ptr<ValueObserver<int>> NewIntValueObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<int>)) = 0; + + virtual nostd::shared_ptr<ValueObserver<float>> NewFloatValueObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<float>)) = 0; + + virtual nostd::shared_ptr<ValueObserver<double>> NewDoubleValueObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<double>)) = 0; + + /** + * Utility method that allows users to atomically record measurements to a set of + * synchronous metric instruments with a common set of labels. + * + * @param labels the set of labels to associate with this recorder. + * @param instruments a span of pointers to the instruments to record to. + * @param values a span of values to record to the instruments in the corresponding + * position in the instruments span. + */ + virtual void RecordShortBatch(const common::KeyValueIterable &labels, + nostd::span<SynchronousInstrument<short> *> instruments, + nostd::span<const short> values) noexcept = 0; + + virtual void RecordIntBatch(const common::KeyValueIterable &labels, + nostd::span<SynchronousInstrument<int> *> instruments, + nostd::span<const int> values) noexcept = 0; + + virtual void RecordFloatBatch(const common::KeyValueIterable &labels, + nostd::span<SynchronousInstrument<float> *> instruments, + nostd::span<const float> values) noexcept = 0; + + virtual void RecordDoubleBatch(const common::KeyValueIterable &labels, + nostd::span<SynchronousInstrument<double> *> instruments, + nostd::span<const double> values) noexcept = 0; +}; +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/meter_provider.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/meter_provider.h new file mode 100644 index 000000000..78ce42ee9 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/meter_provider.h @@ -0,0 +1,32 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include "opentelemetry/_metrics/meter.h" +# include "opentelemetry/nostd/shared_ptr.h" +# include "opentelemetry/nostd/string_view.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace metrics +{ +/** + * Creates new Meter instances. + */ +class MeterProvider +{ +public: + virtual ~MeterProvider() = default; + /** + * Gets or creates a named Meter instance. + * + * Optionally a version can be passed to create a named and versioned Meter + * instance. + */ + virtual nostd::shared_ptr<Meter> GetMeter(nostd::string_view library_name, + nostd::string_view library_version = "") = 0; +}; +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/noop.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/noop.h new file mode 100644 index 000000000..ecd5c5317 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/noop.h @@ -0,0 +1,654 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW +// Please refer to provider.h for documentation on how to obtain a Meter object. +// +// This file is part of the internal implementation of OpenTelemetry. Nothing in this file should be +// used directly. Please refer to meter.h for documentation on these interfaces. + +# include "opentelemetry/_metrics/async_instruments.h" +# include "opentelemetry/_metrics/instrument.h" +# include "opentelemetry/_metrics/meter.h" +# include "opentelemetry/_metrics/meter_provider.h" +# include "opentelemetry/_metrics/sync_instruments.h" +# include "opentelemetry/nostd/string_view.h" +# include "opentelemetry/nostd/unique_ptr.h" +# include "opentelemetry/version.h" + +# include <memory> + +// TODO: Create generic short pattern for opentelemetry::common and opentelemetry::trace and others +// as necessary + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace metrics +{ +template <class T> +class NoopValueObserver : public ValueObserver<T> +{ + +public: + NoopValueObserver(nostd::string_view /*name*/, + nostd::string_view /*description*/, + nostd::string_view /*unit*/, + bool /*enabled*/, + void (*callback)(ObserverResult<T>)) + {} + + virtual bool IsEnabled() override { return false; } + + virtual nostd::string_view GetName() override { return nostd::string_view(""); } + + virtual nostd::string_view GetDescription() override { return nostd::string_view(""); } + + virtual nostd::string_view GetUnits() override { return nostd::string_view(""); } + + virtual void observe(T value, const common::KeyValueIterable &labels) override {} + + virtual void run() override {} + + virtual InstrumentKind GetKind() override { return InstrumentKind::Counter; } +}; + +template <class T> +class NoopSumObserver : public SumObserver<T> +{ + +public: + NoopSumObserver(nostd::string_view /*name*/, + nostd::string_view /*description*/, + nostd::string_view /*unit*/, + bool /*enabled*/, + void (*callback)(ObserverResult<T>)) + {} + + virtual bool IsEnabled() override { return false; } + + virtual nostd::string_view GetName() override { return nostd::string_view(""); } + + virtual nostd::string_view GetDescription() override { return nostd::string_view(""); } + + virtual nostd::string_view GetUnits() override { return nostd::string_view(""); } + + virtual void observe(T value, const common::KeyValueIterable &labels) override {} + + virtual void run() override {} + + virtual InstrumentKind GetKind() override { return InstrumentKind::Counter; } +}; + +template <class T> +class NoopUpDownSumObserver : public UpDownSumObserver<T> +{ + +public: + NoopUpDownSumObserver(nostd::string_view /*name*/, + nostd::string_view /*description*/, + nostd::string_view /*unit*/, + bool /*enabled*/, + void (*callback)(ObserverResult<T>)) + {} + + virtual bool IsEnabled() override { return false; } + + virtual nostd::string_view GetName() override { return nostd::string_view(""); } + + virtual nostd::string_view GetDescription() override { return nostd::string_view(""); } + + virtual nostd::string_view GetUnits() override { return nostd::string_view(""); } + + virtual void observe(T value, const common::KeyValueIterable &labels) override {} + + virtual void run() override {} + + virtual InstrumentKind GetKind() override { return InstrumentKind::Counter; } +}; + +template <class T> +class BoundNoopCounter : public BoundCounter<T> +{ + +public: + BoundNoopCounter() = default; + + BoundNoopCounter(nostd::string_view /*name*/, + nostd::string_view /*description*/, + nostd::string_view /*unit*/, + bool /*enabled*/) + {} + + virtual void add(T value) override {} + + virtual bool IsEnabled() override { return false; } + + virtual nostd::string_view GetName() override { return nostd::string_view(""); } + + virtual nostd::string_view GetDescription() override { return nostd::string_view(""); } + + virtual nostd::string_view GetUnits() override { return nostd::string_view(""); } + + virtual InstrumentKind GetKind() override { return InstrumentKind::Counter; } +}; + +template <class T> +class NoopCounter : public Counter<T> +{ + +public: + NoopCounter() = default; + + NoopCounter(nostd::string_view /*name*/, + nostd::string_view /*description*/, + nostd::string_view /*unit*/, + bool /*enabled*/) + {} + + nostd::shared_ptr<BoundNoopCounter<T>> bindNoopCounter( + const common::KeyValueIterable & /*labels*/) + { + return nostd::shared_ptr<BoundNoopCounter<T>>(new BoundNoopCounter<T>()); + } + + virtual void add(T value, const common::KeyValueIterable & /*labels*/) override {} + + virtual void update(T value, const common::KeyValueIterable & /*labels*/) override {} + + virtual bool IsEnabled() override { return false; } + + virtual nostd::string_view GetName() override { return nostd::string_view(""); } + + virtual nostd::string_view GetDescription() override { return nostd::string_view(""); } + + virtual nostd::string_view GetUnits() override { return nostd::string_view(""); } + + virtual InstrumentKind GetKind() override { return InstrumentKind::Counter; } +}; + +template <class T> +class BoundNoopUpDownCounter : public BoundUpDownCounter<T> +{ + +public: + BoundNoopUpDownCounter() = default; + + BoundNoopUpDownCounter(nostd::string_view /*name*/, + nostd::string_view /*description*/, + nostd::string_view /*unit*/, + bool /*enabled*/) + {} + + virtual void add(T value) override {} + + virtual bool IsEnabled() override { return false; } + + virtual nostd::string_view GetName() override { return nostd::string_view(""); } + + virtual nostd::string_view GetDescription() override { return nostd::string_view(""); } + + virtual nostd::string_view GetUnits() override { return nostd::string_view(""); } + + virtual InstrumentKind GetKind() override { return InstrumentKind::UpDownCounter; } +}; + +template <class T> +class NoopUpDownCounter : public UpDownCounter<T> +{ + +public: + NoopUpDownCounter() = default; + + NoopUpDownCounter(nostd::string_view /*name*/, + nostd::string_view /*description*/, + nostd::string_view /*unit*/, + bool /*enabled*/) + {} + + nostd::shared_ptr<BoundNoopUpDownCounter<T>> bindNoopUpDownCounter( + const common::KeyValueIterable & /*labels*/) + { + return nostd::shared_ptr<BoundNoopUpDownCounter<T>>(new BoundNoopUpDownCounter<T>()); + } + + virtual void add(T value, const common::KeyValueIterable & /*labels*/) override {} + + virtual void update(T value, const common::KeyValueIterable & /*labels*/) override {} + + virtual bool IsEnabled() override { return false; } + + virtual nostd::string_view GetName() override { return nostd::string_view(""); } + + virtual nostd::string_view GetDescription() override { return nostd::string_view(""); } + + virtual nostd::string_view GetUnits() override { return nostd::string_view(""); } + + virtual InstrumentKind GetKind() override { return InstrumentKind::UpDownCounter; } +}; + +template <class T> +class BoundNoopValueRecorder : public BoundValueRecorder<T> +{ + +public: + BoundNoopValueRecorder() = default; + + BoundNoopValueRecorder(nostd::string_view /*name*/, + nostd::string_view /*description*/, + nostd::string_view /*unit*/, + bool /*enabled*/) + {} + + virtual void record(T value) override {} + + virtual bool IsEnabled() override { return false; } + + virtual nostd::string_view GetName() override { return nostd::string_view(""); } + + virtual nostd::string_view GetDescription() override { return nostd::string_view(""); } + + virtual nostd::string_view GetUnits() override { return nostd::string_view(""); } + + virtual InstrumentKind GetKind() override { return InstrumentKind::ValueRecorder; } +}; + +template <class T> +class NoopValueRecorder : public ValueRecorder<T> +{ + +public: + NoopValueRecorder() = default; + + NoopValueRecorder(nostd::string_view /*name*/, + nostd::string_view /*description*/, + nostd::string_view /*unit*/, + bool /*enabled*/) + {} + + nostd::shared_ptr<BoundNoopValueRecorder<T>> bindNoopValueRecorder( + const common::KeyValueIterable & /*labels*/) + { + return nostd::shared_ptr<BoundNoopValueRecorder<T>>(new BoundNoopValueRecorder<T>()); + } + + virtual void record(T value, const common::KeyValueIterable & /*labels*/) override {} + + virtual void update(T value, const common::KeyValueIterable & /*labels*/) override {} + + virtual bool IsEnabled() override { return false; } + + virtual nostd::string_view GetName() override { return nostd::string_view(""); } + + virtual nostd::string_view GetDescription() override { return nostd::string_view(""); } + + virtual nostd::string_view GetUnits() override { return nostd::string_view(""); } + + virtual InstrumentKind GetKind() override { return InstrumentKind::ValueRecorder; } +}; + +/** + * No-op implementation of Meter. This class should not be used directly. + */ +class NoopMeter : public Meter +{ +public: + NoopMeter() = default; + + /** + * + * Creates a new NoopCounter<T> and returns a shared ptr to that counter. + * + * @param name the name of the instrument. + * @param description a brief description of the instrument. + * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. + * @param enabled a boolean that turns the metric instrument on and off. + * @return + */ + nostd::shared_ptr<Counter<short>> NewShortCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override + { + return nostd::shared_ptr<Counter<short>>{ + new NoopCounter<short>(name, description, unit, enabled)}; + } + + nostd::shared_ptr<Counter<int>> NewIntCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override + { + return nostd::shared_ptr<Counter<int>>{new NoopCounter<int>(name, description, unit, enabled)}; + } + + nostd::shared_ptr<Counter<float>> NewFloatCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override + { + return nostd::shared_ptr<Counter<float>>{ + new NoopCounter<float>(name, description, unit, enabled)}; + } + + nostd::shared_ptr<Counter<double>> NewDoubleCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override + { + return nostd::shared_ptr<Counter<double>>{ + new NoopCounter<double>(name, description, unit, enabled)}; + } + + /** + * + * Creates a new NoopCounter<T> and returns a shared ptr to that counter. + * + * @param name the name of the instrument. + * @param description a brief description of the instrument. + * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. + * @param enabled a boolean that turns the metric instrument on and off. + * @return + */ + nostd::shared_ptr<UpDownCounter<short>> NewShortUpDownCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override + { + return nostd::shared_ptr<UpDownCounter<short>>{ + new NoopUpDownCounter<short>(name, description, unit, enabled)}; + } + + nostd::shared_ptr<UpDownCounter<int>> NewIntUpDownCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override + { + return nostd::shared_ptr<UpDownCounter<int>>{ + new NoopUpDownCounter<int>(name, description, unit, enabled)}; + } + + nostd::shared_ptr<UpDownCounter<float>> NewFloatUpDownCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override + { + return nostd::shared_ptr<UpDownCounter<float>>{ + new NoopUpDownCounter<float>(name, description, unit, enabled)}; + } + + nostd::shared_ptr<UpDownCounter<double>> NewDoubleUpDownCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override + { + return nostd::shared_ptr<UpDownCounter<double>>{ + new NoopUpDownCounter<double>(name, description, unit, enabled)}; + } + + /** + * + * Creates a new ValueRecorder<T> and returns a shared ptr to that counter. + * + * @param name the name of the instrument. + * @param description a brief description of the instrument. + * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. + * @param enabled a boolean that turns the metric instrument on and off. + * @return + */ + nostd::shared_ptr<ValueRecorder<short>> NewShortValueRecorder(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override + { + return nostd::shared_ptr<ValueRecorder<short>>{ + new NoopValueRecorder<short>(name, description, unit, enabled)}; + } + + nostd::shared_ptr<ValueRecorder<int>> NewIntValueRecorder(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override + { + return nostd::shared_ptr<ValueRecorder<int>>{ + new NoopValueRecorder<int>(name, description, unit, enabled)}; + } + + nostd::shared_ptr<ValueRecorder<float>> NewFloatValueRecorder(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override + { + return nostd::shared_ptr<ValueRecorder<float>>{ + new NoopValueRecorder<float>(name, description, unit, enabled)}; + } + + nostd::shared_ptr<ValueRecorder<double>> NewDoubleValueRecorder(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override + { + return nostd::shared_ptr<ValueRecorder<double>>{ + new NoopValueRecorder<double>(name, description, unit, enabled)}; + } + + /** + * + * Creates a new SumObserver<T> and returns a shared ptr to that counter. + * + * @param name the name of the instrument. + * @param description a brief description of the instrument. + * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. + * @param enabled a boolean that turns the metric instrument on and off. + * @return + */ + nostd::shared_ptr<SumObserver<short>> NewShortSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<short>)) override + { + return nostd::shared_ptr<SumObserver<short>>{ + new NoopSumObserver<short>(name, description, unit, enabled, callback)}; + } + + nostd::shared_ptr<SumObserver<int>> NewIntSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<int>)) override + { + return nostd::shared_ptr<SumObserver<int>>{ + new NoopSumObserver<int>(name, description, unit, enabled, callback)}; + } + + nostd::shared_ptr<SumObserver<float>> NewFloatSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<float>)) override + { + return nostd::shared_ptr<SumObserver<float>>{ + new NoopSumObserver<float>(name, description, unit, enabled, callback)}; + } + + nostd::shared_ptr<SumObserver<double>> NewDoubleSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<double>)) override + { + return nostd::shared_ptr<SumObserver<double>>{ + new NoopSumObserver<double>(name, description, unit, enabled, callback)}; + } + + /** + * + * Creates a new UpDownSumObserver<T> and returns a shared ptr to that counter. + * + * @param name the name of the instrument. + * @param description a brief description of the instrument. + * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. + * @param enabled a boolean that turns the metric instrument on and off. + * @return + */ + nostd::shared_ptr<UpDownSumObserver<short>> NewShortUpDownSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<short>)) override + { + return nostd::shared_ptr<UpDownSumObserver<short>>{ + new NoopUpDownSumObserver<short>(name, description, unit, enabled, callback)}; + } + + nostd::shared_ptr<UpDownSumObserver<int>> NewIntUpDownSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<int>)) override + { + return nostd::shared_ptr<UpDownSumObserver<int>>{ + new NoopUpDownSumObserver<int>(name, description, unit, enabled, callback)}; + } + + nostd::shared_ptr<UpDownSumObserver<float>> NewFloatUpDownSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<float>)) override + { + return nostd::shared_ptr<UpDownSumObserver<float>>{ + new NoopUpDownSumObserver<float>(name, description, unit, enabled, callback)}; + } + + nostd::shared_ptr<UpDownSumObserver<double>> NewDoubleUpDownSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<double>)) override + { + return nostd::shared_ptr<UpDownSumObserver<double>>{ + new NoopUpDownSumObserver<double>(name, description, unit, enabled, callback)}; + } + + /** + * + * Creates a new ValueObserverObserver<T> and returns a shared ptr to that counter. + * + * @param name the name of the instrument. + * @param description a brief description of the instrument. + * @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html. + * @param enabled a boolean that turns the metric instrument on and off. + * @return + */ + nostd::shared_ptr<ValueObserver<short>> NewShortValueObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<short>)) override + { + return nostd::shared_ptr<ValueObserver<short>>{ + new NoopValueObserver<short>(name, description, unit, enabled, callback)}; + } + + nostd::shared_ptr<ValueObserver<int>> NewIntValueObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<int>)) override + { + return nostd::shared_ptr<ValueObserver<int>>{ + new NoopValueObserver<int>(name, description, unit, enabled, callback)}; + } + + nostd::shared_ptr<ValueObserver<float>> NewFloatValueObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<float>)) override + { + return nostd::shared_ptr<ValueObserver<float>>{ + new NoopValueObserver<float>(name, description, unit, enabled, callback)}; + } + + nostd::shared_ptr<ValueObserver<double>> NewDoubleValueObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(ObserverResult<double>)) override + { + return nostd::shared_ptr<ValueObserver<double>>{ + new NoopValueObserver<double>(name, description, unit, enabled, callback)}; + } + + /** + * + * Utility method that allows users to atomically record measurements to a set of + * synchronous metric instruments with a common set of labels. + * + * @param labels the set of labels to associate with this recorder. + * @param instrs the instruments to record to. + * @param values the value to record to those instruments. + */ + void RecordShortBatch(const common::KeyValueIterable &labels, + nostd::span<SynchronousInstrument<short> *> instruments, + nostd::span<const short> values) noexcept override + { + // No-op + } + + void RecordIntBatch(const common::KeyValueIterable &labels, + nostd::span<SynchronousInstrument<int> *> instruments, + nostd::span<const int> values) noexcept override + { + // No-op + } + + void RecordFloatBatch(const common::KeyValueIterable &labels, + nostd::span<SynchronousInstrument<float> *> instruments, + nostd::span<const float> values) noexcept override + { + // No-op + } + + void RecordDoubleBatch(const common::KeyValueIterable &labels, + nostd::span<SynchronousInstrument<double> *> instruments, + nostd::span<const double> values) noexcept override + { + // No-op + } +}; + +class NoopMeterProvider final : public opentelemetry::metrics::MeterProvider +{ +public: + NoopMeterProvider() + : meter_{nostd::shared_ptr<opentelemetry::metrics::NoopMeter>( + new opentelemetry::metrics::NoopMeter)} + {} + + nostd::shared_ptr<opentelemetry::metrics::Meter> GetMeter( + nostd::string_view library_name, + nostd::string_view library_version) override + { + return meter_; + } + +private: + nostd::shared_ptr<opentelemetry::metrics::Meter> meter_; +}; +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/observer_result.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/observer_result.h new file mode 100644 index 000000000..de4b36c0d --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/observer_result.h @@ -0,0 +1,41 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include "opentelemetry/_metrics/instrument.h" +# include "opentelemetry/nostd/shared_ptr.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace metrics +{ + +/** + * ObserverResult class is necessary for the callback recording asynchronous + * instrument use. Callback functions asynchronous instruments are designed to + * accept a single ObserverResult object and update using its pointer to the + * instrument itself. + */ + +template <class T> +class ObserverResult +{ + +public: + ObserverResult() = default; + + ObserverResult(AsynchronousInstrument<T> *instrument) : instrument_(instrument) {} + + virtual void observe(T value, const common::KeyValueIterable &labels) + { + instrument_->observe(value, labels); + } + +private: + AsynchronousInstrument<T> *instrument_; +}; + +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/provider.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/provider.h new file mode 100644 index 000000000..e079b34d5 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/provider.h @@ -0,0 +1,59 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW +# include <mutex> + +# include "opentelemetry/_metrics/meter_provider.h" +# include "opentelemetry/_metrics/noop.h" +# include "opentelemetry/common/spin_lock_mutex.h" +# include "opentelemetry/nostd/shared_ptr.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(nostd::shared_ptr<MeterProvider> tp) noexcept + { + std::lock_guard<common::SpinLockMutex> guard(GetLock()); + GetProvider() = tp; + } + +private: + static nostd::shared_ptr<MeterProvider> &GetProvider() noexcept + { + static nostd::shared_ptr<MeterProvider> provider(new NoopMeterProvider); + return provider; + } + + static common::SpinLockMutex &GetLock() noexcept + { + static common::SpinLockMutex lock; + return lock; + } +}; + +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/sync_instruments.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/sync_instruments.h new file mode 100644 index 000000000..56ccea707 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/_metrics/sync_instruments.h @@ -0,0 +1,181 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include "opentelemetry/_metrics/instrument.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace metrics +{ + +template <class T> +class BoundCounter : virtual public BoundSynchronousInstrument<T> +{ + +public: + BoundCounter() = default; + + BoundCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled); + + /* + * Add adds the value to the counter's sum. The labels are already linked * to the instrument + * and are not specified. + * + * @param value the numerical representation of the metric being captured + * @param labels the set of labels, as key-value pairs + */ + virtual void add(T value) = 0; +}; + +template <class T> +class Counter : virtual public SynchronousInstrument<T> +{ + +public: + Counter() = default; + + Counter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled) + {} + + /* + * Bind creates a bound instrument for this counter. The labels are + * associated with values recorded via subsequent calls to Record. + * + * @param labels the set of labels, as key-value pairs. + * @return a BoundIntCounter tied to the specified labels + */ + virtual nostd::shared_ptr<BoundCounter<T>> bindCounter(const common::KeyValueIterable &labels) + { + return nostd::shared_ptr<BoundCounter<T>>(); + } + + /* + * Add adds the value to the counter's sum. The labels should contain + * the keys and values to be associated with this value. Counters only * accept positive + * valued updates. + * + * @param value the numerical representation of the metric being captured + * @param labels the set of labels, as key-value pairs + */ + virtual void add(T value, const common::KeyValueIterable &labels) = 0; + + virtual void update(T value, const common::KeyValueIterable &labels) override = 0; +}; + +template <class T> +class BoundUpDownCounter : virtual public BoundSynchronousInstrument<T> +{ + +public: + BoundUpDownCounter() = default; + + BoundUpDownCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled); + + /* + * Add adds the value to the counter's sum. The labels are already linked to * the instrument and + * do not need to specified again. UpDownCounters can accept positive and negative values. + * + * @param value the numerical representation of the metric being captured + * @param labels the set of labels, as key-value pairs + */ + virtual void add(T value) = 0; +}; + +template <class T> +class UpDownCounter : virtual public SynchronousInstrument<T> +{ + +public: + UpDownCounter() = default; + + UpDownCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled); + + virtual nostd::shared_ptr<BoundUpDownCounter<T>> bindUpDownCounter( + const common::KeyValueIterable &labels) + { + return nostd::shared_ptr<BoundUpDownCounter<T>>(); + } + + /* + * Add adds the value to the counter's sum. The labels should contain + * the keys and values to be associated with this value. UpDownCounters can + * accept positive and negative values. + * + * @param value the numerical representation of the metric being captured + * @param labels the set of labels, as key-value pairs + */ + virtual void add(T value, const common::KeyValueIterable &labels) = 0; + + virtual void update(T value, const common::KeyValueIterable &labels) override = 0; +}; + +template <class T> +class BoundValueRecorder : virtual public BoundSynchronousInstrument<T> +{ + +public: + BoundValueRecorder() = default; + + BoundValueRecorder(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled); + + /* + * Records the value by summing it with previous measurements and checking * previously stored + * minimum and maximum values. The labels associated with * new values are already linked to the + * instrument as it is bound. * ValueRecorders can accept positive and negative values. + * + * @param value the numerical representation of the metric being captured + */ + virtual void record(T value) = 0; +}; + +template <class T> +class ValueRecorder : virtual public SynchronousInstrument<T> +{ + +public: + ValueRecorder() = default; + + ValueRecorder(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled); + + virtual nostd::shared_ptr<BoundValueRecorder<T>> bindValueRecorder( + const common::KeyValueIterable &labels) + { + return nostd::shared_ptr<BoundValueRecorder<T>>(); + } + + /* + * Records the value by summing it with previous measurements and checking * previously stored + * minimum and maximum values. The labels should contain the keys and values to be associated with + * this value. ValueRecorders can accept positive and negative values. + * + * @param value the numerical representation of the metric being captured + * @param labels the set of labels, as key-value pairs + */ + virtual void record(T value, const common::KeyValueIterable &labels) = 0; + + virtual void update(T value, const common::KeyValueIterable &labels) override = 0; +}; + +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/baggage.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/baggage.h new file mode 100644 index 000000000..eb5e4dcc7 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/baggage.h @@ -0,0 +1,299 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <cctype> + +#include "opentelemetry/common/kv_properties.h" +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE + +namespace baggage +{ + +class Baggage +{ +public: + static constexpr size_t kMaxKeyValuePairs = 180; + static constexpr size_t kMaxKeyValueSize = 4096; + static constexpr size_t kMaxSize = 8192; + static constexpr char kKeyValueSeparator = '='; + static constexpr char kMembersSeparator = ','; + static constexpr char kMetadataSeparator = ';'; + + Baggage() noexcept : kv_properties_(new opentelemetry::common::KeyValueProperties()) {} + Baggage(size_t size) noexcept + : kv_properties_(new opentelemetry::common::KeyValueProperties(size)){}; + + template <class T> + Baggage(const T &keys_and_values) noexcept + : kv_properties_(new opentelemetry::common::KeyValueProperties(keys_and_values)) + {} + + static nostd::shared_ptr<Baggage> GetDefault() + { + static nostd::shared_ptr<Baggage> baggage{new Baggage()}; + return baggage; + } + + /* Get value for key in the baggage + @returns true if key is found, false otherwise + */ + bool GetValue(nostd::string_view key, std::string &value) const noexcept + { + return kv_properties_->GetValue(key, value); + } + + /* Returns shared_ptr of new baggage object which contains new key-value pair. If key or value is + invalid, copy of current baggage is returned + */ + nostd::shared_ptr<Baggage> Set(const nostd::string_view &key, + const nostd::string_view &value) noexcept + { + + nostd::shared_ptr<Baggage> baggage(new Baggage(kv_properties_->Size() + 1)); + const bool valid_kv = IsValidKey(key) && IsValidValue(value); + + if (valid_kv) + { + baggage->kv_properties_->AddEntry(key, value); + } + + // add rest of the fields. + kv_properties_->GetAllEntries( + [&baggage, &key, &valid_kv](nostd::string_view e_key, nostd::string_view e_value) { + // if key or value was not valid, add all the entries. Add only remaining entries + // otherwise. + if (!valid_kv || key != e_key) + { + baggage->kv_properties_->AddEntry(e_key, e_value); + } + + return true; + }); + + return baggage; + } + + // @return all key-values entries by repeatedly invoking the function reference passed as argument + // for each entry + bool GetAllEntries( + nostd::function_ref<bool(nostd::string_view, nostd::string_view)> callback) const noexcept + { + return kv_properties_->GetAllEntries(callback); + } + + // delete key from the baggage if it exists. Returns shared_ptr of new baggage object. + // if key does not exist, copy of current baggage is returned. + // Validity of key is not checked as invalid keys should never be populated in baggage in the + // first place. + nostd::shared_ptr<Baggage> Delete(nostd::string_view key) noexcept + { + // keeping size of baggage same as key might not be found in it + nostd::shared_ptr<Baggage> baggage(new Baggage(kv_properties_->Size())); + kv_properties_->GetAllEntries( + [&baggage, &key](nostd::string_view e_key, nostd::string_view e_value) { + if (key != e_key) + baggage->kv_properties_->AddEntry(e_key, e_value); + return true; + }); + return baggage; + } + + // Returns shared_ptr of baggage after extracting key-value pairs from header + static nostd::shared_ptr<Baggage> FromHeader(nostd::string_view header) noexcept + { + if (header.size() > kMaxSize) + { + // header size exceeds maximum threshold, return empty baggage + return GetDefault(); + } + + common::KeyValueStringTokenizer kv_str_tokenizer(header); + size_t cnt = kv_str_tokenizer.NumTokens(); // upper bound on number of kv pairs + if (cnt > kMaxKeyValuePairs) + { + cnt = kMaxKeyValuePairs; + } + + nostd::shared_ptr<Baggage> baggage(new Baggage(cnt)); + bool kv_valid; + nostd::string_view key, value; + + while (kv_str_tokenizer.next(kv_valid, key, value) && baggage->kv_properties_->Size() < cnt) + { + if (!kv_valid || (key.size() + value.size() > kMaxKeyValueSize)) + { + // if kv pair is not valid, skip it + continue; + } + + // NOTE : metadata is kept as part of value only as it does not have any semantic meaning. + // but, we need to extract it (else Decode on value will return error) + nostd::string_view metadata; + auto metadata_separator = value.find(kMetadataSeparator); + if (metadata_separator != std::string::npos) + { + metadata = value.substr(metadata_separator); + value = value.substr(0, metadata_separator); + } + + bool err = 0; + auto key_str = UrlDecode(common::StringUtil::Trim(key), err); + auto value_str = UrlDecode(common::StringUtil::Trim(value), err); + + if (err == false && IsValidKey(key_str) && IsValidValue(value_str)) + { + if (!metadata.empty()) + { + value_str.append(metadata.data(), metadata.size()); + } + baggage->kv_properties_->AddEntry(key_str, value_str); + } + } + + return baggage; + } + + // Creates string from baggage object. + std::string ToHeader() const noexcept + { + std::string header_s; + bool first = true; + kv_properties_->GetAllEntries([&](nostd::string_view key, nostd::string_view value) { + if (!first) + { + header_s.push_back(kMembersSeparator); + } + else + { + first = false; + } + header_s.append(UrlEncode(key)); + header_s.push_back(kKeyValueSeparator); + + // extracting metadata from value. We do not encode metadata + auto metadata_separator = value.find(kMetadataSeparator); + if (metadata_separator != std::string::npos) + { + header_s.append(UrlEncode(value.substr(0, metadata_separator))); + auto metadata = value.substr(metadata_separator); + header_s.append(std::string(metadata.data(), metadata.size())); + } + else + { + header_s.append(UrlEncode(value)); + } + return true; + }); + return header_s; + } + +private: + static bool IsPrintableString(nostd::string_view str) + { + for (const auto ch : str) + { + if (ch < ' ' || ch > '~') + { + return false; + } + } + + return true; + } + + static bool IsValidKey(nostd::string_view key) { return key.size() && IsPrintableString(key); } + + static bool IsValidValue(nostd::string_view value) { return IsPrintableString(value); } + + // Uri encode key value pairs before injecting into header + // Implementation inspired from : https://golang.org/src/net/url/url.go?s=7851:7884#L264 + static std::string UrlEncode(nostd::string_view str) + { + auto to_hex = [](char c) -> char { + static const char *hex = "0123456789ABCDEF"; + return hex[c & 15]; + }; + + std::string ret; + + for (auto c : str) + { + if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') + { + ret.push_back(c); + } + else if (c == ' ') + { + ret.push_back('+'); + } + else + { + ret.push_back('%'); + ret.push_back(to_hex(c >> 4)); + ret.push_back(to_hex(c & 15)); + } + } + + return ret; + } + + // Uri decode key value pairs after extracting from header + static std::string UrlDecode(nostd::string_view str, bool &err) + { + auto IsHex = [](char c) { + return std::isdigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); + }; + + auto from_hex = [](char c) -> char { + // c - '0' produces integer type which could trigger error/warning when casting to char, + // but the cast is safe here. + return static_cast<char>(std::isdigit(c) ? c - '0' : std::toupper(c) - 'A' + 10); + }; + + std::string ret; + + for (size_t i = 0; i < str.size(); i++) + { + if (str[i] == '%') + { + if (i + 2 >= str.size() || !IsHex(str[i + 1]) || !IsHex(str[i + 2])) + { + err = 1; + return ""; + } + ret.push_back(from_hex(str[i + 1]) << 4 | from_hex(str[i + 2])); + i += 2; + } + else if (str[i] == '+') + { + ret.push_back(' '); + } + else if (std::isalnum(str[i]) || str[i] == '-' || str[i] == '_' || str[i] == '.' || + str[i] == '~') + { + ret.push_back(str[i]); + } + else + { + err = 1; + return ""; + } + } + + return ret; + } + +private: + // Store entries in a C-style array to avoid using std::array or std::vector. + nostd::unique_ptr<opentelemetry::common::KeyValueProperties> kv_properties_; +}; + +} // namespace baggage + +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/baggage_context.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/baggage_context.h new file mode 100644 index 000000000..9a92bac77 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/baggage_context.h @@ -0,0 +1,39 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/baggage/baggage.h" +#include "opentelemetry/context/context.h" +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE + +namespace baggage +{ + +static const std::string kBaggageHeader = "baggage"; + +inline nostd::shared_ptr<opentelemetry::baggage::Baggage> GetBaggage( + const opentelemetry::context::Context &context) noexcept +{ + context::ContextValue context_value = context.GetValue(kBaggageHeader); + if (nostd::holds_alternative<nostd::shared_ptr<opentelemetry::baggage::Baggage>>(context_value)) + { + return nostd::get<nostd::shared_ptr<opentelemetry::baggage::Baggage>>(context_value); + } + static nostd::shared_ptr<opentelemetry::baggage::Baggage> empty_baggage{ + new opentelemetry::baggage::Baggage()}; + return empty_baggage; +} + +inline context::Context SetBaggage( + opentelemetry::context::Context &context, + nostd::shared_ptr<opentelemetry::baggage::Baggage> baggage) noexcept +{ + return context.SetValue(kBaggageHeader, baggage); +} + +} // namespace baggage +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/propagation/baggage_propagator.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/propagation/baggage_propagator.h new file mode 100644 index 000000000..3de60860b --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/baggage/propagation/baggage_propagator.h @@ -0,0 +1,54 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/baggage/baggage.h" +#include "opentelemetry/baggage/baggage_context.h" +#include "opentelemetry/context/propagation/text_map_propagator.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace baggage +{ +namespace propagation +{ + +class BaggagePropagator : public opentelemetry::context::propagation::TextMapPropagator +{ +public: + void Inject(opentelemetry::context::propagation::TextMapCarrier &carrier, + const opentelemetry::context::Context &context) noexcept override + { + auto baggage = opentelemetry::baggage::GetBaggage(context); + auto header = baggage->ToHeader(); + if (header.size()) + { + carrier.Set(kBaggageHeader, header); + } + } + + context::Context Extract(const opentelemetry::context::propagation::TextMapCarrier &carrier, + opentelemetry::context::Context &context) noexcept override + { + nostd::string_view baggage_str = carrier.Get(opentelemetry::baggage::kBaggageHeader); + auto baggage = opentelemetry::baggage::Baggage::FromHeader(baggage_str); + + if (baggage->ToHeader().size()) + { + return opentelemetry::baggage::SetBaggage(context, baggage); + } + else + { + return context; + } + } + + bool Fields(nostd::function_ref<bool(nostd::string_view)> callback) const noexcept override + { + return callback(kBaggageHeader); + } +}; +} // namespace propagation +} // namespace baggage +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/attribute_value.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/attribute_value.h new file mode 100644 index 000000000..af4cc83d4 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/attribute_value.h @@ -0,0 +1,82 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <cstdint> + +#include "opentelemetry/nostd/span.h" +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/nostd/variant.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace common +{ +/// OpenTelemetry signals can be enriched by adding attributes. The +/// \c AttributeValue type is defined as a variant of all attribute value +/// types the OpenTelemetry C++ API supports. +/// +/// The following attribute value types are supported by the OpenTelemetry +/// specification: +/// - Primitive types: string, boolean, double precision floating point +/// (IEEE 754-1985) or signed 64 bit integer. +/// - Homogenous arrays of primitive type values. +/// +/// \warning +/// \parblock The OpenTelemetry C++ API currently supports several attribute +/// value types that are not covered by the OpenTelemetry specification: +/// - \c uint64_t +/// - \c nostd::span<const uint64_t> +/// - \c nostd::span<uint8_t> +/// +/// Those types are reserved for future use and currently should not be +/// used. There are no guarantees around how those values are handled by +/// exporters. +/// \endparblock +using AttributeValue = + nostd::variant<bool, + int32_t, + int64_t, + uint32_t, + double, + const char *, + nostd::string_view, + nostd::span<const bool>, + nostd::span<const int32_t>, + nostd::span<const int64_t>, + nostd::span<const uint32_t>, + nostd::span<const double>, + nostd::span<const nostd::string_view>, + // Not currently supported by the specification, but reserved for future use. + // Added to provide support for all primitive C++ types. + uint64_t, + // Not currently supported by the specification, but reserved for future use. + // Added to provide support for all primitive C++ types. + nostd::span<const uint64_t>, + // Not currently supported by the specification, but reserved for future use. + // See https://github.com/open-telemetry/opentelemetry-specification/issues/780 + nostd::span<const uint8_t>>; + +enum AttributeType +{ + kTypeBool, + kTypeInt, + kTypeInt64, + kTypeUInt, + kTypeDouble, + kTypeCString, + kTypeString, + kTypeSpanBool, + kTypeSpanInt, + kTypeSpanInt64, + kTypeSpanUInt, + kTypeSpanDouble, + kTypeSpanString, + kTypeUInt64, + kTypeSpanUInt64, + kTypeSpanByte +}; + +} // namespace common +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/key_value_iterable.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/key_value_iterable.h new file mode 100644 index 000000000..f187f75b8 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/key_value_iterable.h @@ -0,0 +1,36 @@ +// 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/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; +}; +} // namespace common +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/key_value_iterable_view.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/key_value_iterable_view.h new file mode 100644 index 000000000..2a0cbbc44 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/key_value_iterable_view.h @@ -0,0 +1,77 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <iterator> +#include <type_traits> +#include <utility> + +#include "opentelemetry/common/key_value_iterable.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_; +}; +} // namespace common +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/kv_properties.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/kv_properties.h new file mode 100644 index 000000000..7ac747a73 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/kv_properties.h @@ -0,0 +1,273 @@ +// 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/shared_ptr.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
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/macros.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/macros.h new file mode 100644 index 000000000..204c1ed04 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/macros.h @@ -0,0 +1,91 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <cstdint> + +#include "opentelemetry/version.h" + +#if !defined(OPENTELEMETRY_LIKELY_IF) && defined(__cplusplus) +// 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_IF(...) \ + if (__VA_ARGS__) \ + [[likely]] +# endif +# endif +#endif +#if !defined(OPENTELEMETRY_LIKELY_IF) && (defined(__clang__) || defined(__GNUC__)) +# define OPENTELEMETRY_LIKELY_IF(...) if (__builtin_expect(!!(__VA_ARGS__), true)) +#endif +#ifndef OPENTELEMETRY_LIKELY_IF +# define OPENTELEMETRY_LIKELY_IF(...) if (__VA_ARGS__) +#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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/spin_lock_mutex.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/spin_lock_mutex.h new file mode 100644 index 000000000..d38d5791d --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/spin_lock_mutex.h @@ -0,0 +1,128 @@ +// 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) +# ifndef NOMINMAX +# define NOMINMAX +# endif +# define _WINSOCKAPI_ // stops including winsock.h +# include <windows.h> +#elif defined(__i386__) || defined(__x86_64__) +# if defined(__clang__) +# include <emmintrin.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; + SpinLockMutex &operator=(const SpinLockMutex &) volatile = delete; + + /** + * 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; + } +// Issue a Pause/Yield instruction while spinning. +#if defined(_MSC_VER) + YieldProcessor(); +#elif defined(__i386__) || defined(__x86_64__) +# if defined(__clang__) + _mm_pause(); +# else + __builtin_ia32_pause(); +# endif +#elif defined(__arm__) + __asm__ volatile("yield" ::: "memory"); +#else + // TODO: Issue PAGE/YIELD on other architectures. +#endif + } + // 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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/string_util.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/string_util.h new file mode 100644 index 000000000..ffee86c96 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/string_util.h @@ -0,0 +1,55 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/nostd/string_view.h" + +/** DJB2 hash function below is near-perfect hash used by several systems. + * Ref. http://www.cse.yorku.ca/~oz/hash.html + * </summary> + * <param name="str">String to hash</param> + * <param name="h">Initial offset</param> + * <returns>32 bit code</returns> + */ +constexpr uint32_t hashCode(const char *str, uint32_t h = 0) +{ + return (uint32_t)(!str[h] ? 5381 : ((uint32_t)hashCode(str, h + 1) * (uint32_t)33) ^ str[h]); +} +#define OTEL_CPP_CONST_UINT32_T(x) std::integral_constant<uint32_t, (uint32_t)x>::value +#define OTEL_CPP_CONST_HASHCODE(name) OTEL_CPP_CONST_UINT32_T(hashCode(#name)) + +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 (str[static_cast<std::size_t>(left)] == ' ' && left <= right) + { + left++; + } + while (str[static_cast<std::size_t>(right)] == ' ' && left <= 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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/timestamp.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/timestamp.h new file mode 100644 index 000000000..54e7b7aa6 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/common/timestamp.h @@ -0,0 +1,173 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <algorithm> +#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_; +}; +} // namespace common +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/config.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/config.h new file mode 100644 index 000000000..21a2947e2 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/config.h @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifndef __has_include +# define OPENTELEMETRY_HAS_INCLUDE(x) 0 +#else +# define OPENTELEMETRY_HAS_INCLUDE(x) __has_include(x) +#endif + +#if !defined(__GLIBCXX__) || OPENTELEMETRY_HAS_INCLUDE(<codecvt>) // >= libstdc++-5 +# define OPENTELEMETRY_TRIVIALITY_TYPE_TRAITS +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/context.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/context.h new file mode 100644 index 000000000..923b396c7 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/context.h @@ -0,0 +1,161 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <cstring> +#include "opentelemetry/context/context_value.h" +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/nostd/string_view.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 + class DataList + { + public: + char *key_; + + nostd::shared_ptr<DataList> next_; + + size_t key_length_; + + ContextValue value_; + + DataList() { next_ = nullptr; } + + // Builds a data list off of a key and value iterable and returns the head + template <class T> + DataList(const T &keys_and_vals) : key_{nullptr}, next_(nostd::shared_ptr<DataList>{nullptr}) + { + 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(); + memcpy(key_, key.data(), key.size() * sizeof(char)); + value_ = value; + next_ = nostd::shared_ptr<DataList>{nullptr}; + } + + 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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/context_value.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/context_value.h new file mode 100644 index 000000000..013b3a460 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/context_value.h @@ -0,0 +1,29 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <cstdint> + +#include "opentelemetry/baggage/baggage.h" +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/nostd/span.h" +#include "opentelemetry/nostd/unique_ptr.h" +#include "opentelemetry/nostd/variant.h" +#include "opentelemetry/trace/span.h" +#include "opentelemetry/trace/span_context.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/propagation/composite_propagator.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/propagation/composite_propagator.h new file mode 100644 index 000000000..d7a6cbda1 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/propagation/composite_propagator.h @@ -0,0 +1,92 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <initializer_list> +#include <memory> +#include <vector> +#include "opentelemetry/context/propagation/text_map_propagator.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; diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/propagation/global_propagator.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/propagation/global_propagator.h new file mode 100644 index 000000000..b4e49325c --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/propagation/global_propagator.h @@ -0,0 +1,55 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <mutex> + +#include "opentelemetry/context/propagation/noop_propagator.h" +#include "opentelemetry/context/propagation/text_map_propagator.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 +{ + +/* Stores the singleton TextMapPropagator */ + +class 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(nostd::shared_ptr<TextMapPropagator> prop) noexcept + { + std::lock_guard<common::SpinLockMutex> guard(GetLock()); + GetPropagator() = prop; + } + +private: + static nostd::shared_ptr<TextMapPropagator> &GetPropagator() noexcept + { + static nostd::shared_ptr<TextMapPropagator> propagator(new NoOpPropagator()); + return propagator; + } + + static common::SpinLockMutex &GetLock() noexcept + { + static common::SpinLockMutex lock; + return lock; + } +}; + +} // namespace propagation +} // namespace context +OPENTELEMETRY_END_NAMESPACE
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/propagation/noop_propagator.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/propagation/noop_propagator.h new file mode 100644 index 000000000..7c5edc5f8 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/propagation/noop_propagator.h @@ -0,0 +1,38 @@ +// 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
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/propagation/text_map_propagator.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/propagation/text_map_propagator.h new file mode 100644 index 000000000..7efdc4919 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/propagation/text_map_propagator.h @@ -0,0 +1,59 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <cstdint> +#include "opentelemetry/context/context.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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/runtime_context.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/runtime_context.h new file mode 100644 index 000000000..167a928f1 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/context/runtime_context.h @@ -0,0 +1,330 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/context/context.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(); + +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 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 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(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(); + } + + 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_; + }; + + Stack &GetStack() + { + static thread_local Stack stack_ = Stack(); + return stack_; + } +}; + +static RuntimeContextStorage *GetDefaultStorage() noexcept +{ + return new ThreadLocalContextStorage(); +} +} // namespace context +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/detail/preprocessor.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/detail/preprocessor.h new file mode 100644 index 000000000..dc8eb5782 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/detail/preprocessor.h @@ -0,0 +1,13 @@ +// 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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/logs/logger.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/logs/logger.h new file mode 100644 index 000000000..32c3974a1 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/logs/logger.h @@ -0,0 +1,641 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include <chrono> +# include <map> +# include <vector> + +# include "opentelemetry/common/attribute_value.h" +# include "opentelemetry/common/key_value_iterable.h" +# include "opentelemetry/common/key_value_iterable_view.h" +# include "opentelemetry/common/macros.h" +# include "opentelemetry/common/timestamp.h" +# include "opentelemetry/logs/severity.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/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 +{ +/** + * Handles log record creation. + **/ +class Logger +{ +public: + virtual ~Logger() = default; + + /* Returns the name of the logger */ + virtual const nostd::string_view GetName() noexcept = 0; + + /** + * Each of the following overloaded Log(...) methods + * creates a log message with the specific parameters passed. + * + * @param severity the severity level of the log event. + * @param message the string message of the log (perhaps support std::fmt or fmt-lib format). + * @param attributes the attributes, stored as a 2D list of key/value pairs, that are associated + * with the log event. + * @param trace_id the trace id associated with the log event. + * @param span_id the span id associate with the log event. + * @param trace_flags the trace flags associated with the log event. + * @param timestamp the timestamp the log record was created. + * @throws No exceptions under any circumstances. + */ + + /** + * The base Log(...) method that all other Log(...) overloaded methods will eventually call, + * in order to create a log record. + */ + virtual void Log(Severity severity, + nostd::string_view body, + const common::KeyValueIterable &attributes, + trace::TraceId trace_id, + trace::SpanId span_id, + trace::TraceFlags trace_flags, + common::SystemTimestamp timestamp) noexcept = 0; + + /** + * Each of the following overloaded Log(...) methods + * creates a log message with the specific parameters passed. + * + * @param severity the severity level of the log event. + * @param name the name of the log event. + * @param message the string message of the log (perhaps support std::fmt or fmt-lib format). + * @param attributes the attributes, stored as a 2D list of key/value pairs, that are associated + * with the log event. + * @param trace_id the trace id associated with the log event. + * @param span_id the span id associate with the log event. + * @param trace_flags the trace flags associated with the log event. + * @param timestamp the timestamp the log record was created. + * @throws No exceptions under any circumstances. + */ + OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") + virtual void Log(Severity severity, + OPENTELEMETRY_MAYBE_UNUSED nostd::string_view name, + nostd::string_view body, + const common::KeyValueIterable &attributes, + trace::TraceId trace_id, + trace::SpanId span_id, + trace::TraceFlags trace_flags, + common::SystemTimestamp timestamp) noexcept + { + Log(severity, body, attributes, trace_id, span_id, trace_flags, timestamp); + } + + /*** Overloaded methods for KeyValueIterables ***/ + /** + * The secondary base Log(...) method that all other Log(...) overloaded methods except the one + * above will eventually call, in order to create a log record. + */ + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void Log(Severity severity, + nostd::string_view body, + const T &attributes, + trace::TraceId trace_id, + trace::SpanId span_id, + trace::TraceFlags trace_flags, + common::SystemTimestamp timestamp) noexcept + { + Log(severity, body, common::KeyValueIterableView<T>(attributes), trace_id, span_id, trace_flags, + timestamp); + } + + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") + void Log(Severity severity, + nostd::string_view name, + nostd::string_view body, + const T &attributes, + trace::TraceId trace_id, + trace::SpanId span_id, + trace::TraceFlags trace_flags, + common::SystemTimestamp timestamp) noexcept + { + Log(severity, name, body, common::KeyValueIterableView<T>(attributes), trace_id, span_id, + trace_flags, timestamp); + } + + void Log(Severity severity, + nostd::string_view body, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes, + trace::TraceId trace_id, + trace::SpanId span_id, + trace::TraceFlags trace_flags, + common::SystemTimestamp timestamp) noexcept + { + return this->Log(severity, body, + nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{ + attributes.begin(), attributes.end()}, + trace_id, span_id, trace_flags, timestamp); + } + + OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") + void Log(Severity severity, + nostd::string_view name, + nostd::string_view body, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes, + trace::TraceId trace_id, + trace::SpanId span_id, + trace::TraceFlags trace_flags, + common::SystemTimestamp timestamp) noexcept + { + return this->Log(severity, name, body, + nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{ + attributes.begin(), attributes.end()}, + trace_id, span_id, trace_flags, timestamp); + } + + /** Wrapper methods that the user could call for convenience when logging **/ + + /** + * Writes a log. + * @param severity The severity of the log + * @param message The message to log + */ + void Log(Severity severity, nostd::string_view message) noexcept + { + this->Log(severity, message, {}, {}, {}, {}, std::chrono::system_clock::now()); + } + + OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") + void Log(Severity severity, nostd::string_view name, nostd::string_view message) noexcept + { + this->Log(severity, name, message, {}, {}, {}, {}, std::chrono::system_clock::now()); + } + + /** + * Writes a log. + * @param severity The severity of the log + * @param attributes The attributes of the log as a key/value object + */ + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void Log(Severity severity, const T &attributes) noexcept + { + this->Log(severity, "", attributes, {}, {}, {}, std::chrono::system_clock::now()); + } + + /** + * Writes a log. + * @param severity The severity of the log + * @param message The message to log + * @param attributes The attributes of the log as a key/value object + */ + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void Log(Severity severity, nostd::string_view message, const T &attributes) noexcept + { + this->Log(severity, message, attributes, {}, {}, {}, std::chrono::system_clock::now()); + } + + /** + * Writes a log. + * @param severity The severity of the log + * @param attributes The attributes of the log as an initializer list + */ + void Log(Severity severity, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> + attributes) noexcept + { + this->Log(severity, "", attributes, {}, {}, {}, std::chrono::system_clock::now()); + } + + /** + * Writes a log. + * @param severity The severity of the log + * @param message The message to log + * @param attributes The attributes of the log as an initializer list + */ + void Log(Severity severity, + nostd::string_view message, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> + attributes) noexcept + { + this->Log(severity, message, attributes, {}, {}, {}, std::chrono::system_clock::now()); + } + + /** + * Writes a log. + * @param severity The severity of the log + * @param attributes The attributes, stored as a 2D list of key/value pairs, that are associated + * with the log event + */ + void Log(Severity severity, const common::KeyValueIterable &attributes) noexcept + { + this->Log(severity, "", attributes, {}, {}, {}, std::chrono::system_clock::now()); + } + + /** + * Writes a log. + * @param severity The severity of the log + * @param message The message to log + * @param attributes The attributes, stored as a 2D list of key/value pairs, that are associated + * with the log event + */ + void Log(Severity severity, + nostd::string_view message, + const common::KeyValueIterable &attributes) noexcept + { + this->Log(severity, message, attributes, {}, {}, {}, std::chrono::system_clock::now()); + } + + /** Trace severity overloads **/ + + /** + * Writes a log with a severity of trace. + * @param message The message to log + */ + void Trace(nostd::string_view message) noexcept { this->Log(Severity::kTrace, message); } + + /** + * Writes a log with a severity of trace. + * @param name The name of the log + * @param message The message to log + */ + OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") + void Trace(nostd::string_view name, nostd::string_view message) noexcept + { + this->Log(Severity::kTrace, name, message); + } + + /** + * Writes a log with a severity of trace. + * @param attributes The attributes of the log as a key/value object + */ + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void Trace(const T &attributes) noexcept + { + this->Log(Severity::kTrace, attributes); + } + + /** + * Writes a log with a severity of trace. + * @param message The message of the log + * @param attributes The attributes of the log as a key/value object + */ + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void Trace(nostd::string_view message, const T &attributes) noexcept + { + this->Log(Severity::kTrace, message, attributes); + } + + /** + * Writes a log with a severity of trace. + * @param attributes The attributes of the log as an initializer list + */ + void Trace(std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> + attributes) noexcept + { + this->Log(Severity::kTrace, attributes); + } + + /** + * Writes a log with a severity of trace. + * @param message The message of the log + * @param attributes The attributes of the log as an initializer list + */ + void Trace(nostd::string_view message, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> + attributes) noexcept + { + this->Log(Severity::kTrace, message, attributes); + } + + /** Debug severity overloads **/ + + /** + * Writes a log with a severity of debug. + * @param message The message to log + */ + void Debug(nostd::string_view message) noexcept { this->Log(Severity::kDebug, message); } + + /** + * Writes a log with a severity of debug. + * @param name The name of the log + * @param message The message to log + */ + OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") + void Debug(nostd::string_view name, nostd::string_view message) noexcept + { + this->Log(Severity::kDebug, name, message); + } + + /** + * Writes a log with a severity of debug. + * @param attributes The attributes of the log as a key/value object + */ + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void Debug(const T &attributes) noexcept + { + this->Log(Severity::kDebug, attributes); + } + + /** + * Writes a log with a severity of debug. + * @param message The message of the log + * @param attributes The attributes of the log as a key/value object + */ + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void Debug(nostd::string_view message, const T &attributes) noexcept + { + this->Log(Severity::kDebug, message, attributes); + } + + /** + * Writes a log with a severity of debug. + * @param attributes The attributes of the log as an initializer list + */ + void Debug(std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> + attributes) noexcept + { + this->Log(Severity::kDebug, attributes); + } + + /** + * Writes a log with a severity of debug. + * @param message The message of the log + * @param attributes The attributes of the log as an initializer list + */ + void Debug(nostd::string_view message, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> + attributes) noexcept + { + this->Log(Severity::kDebug, message, attributes); + } + + /** Info severity overloads **/ + + /** + * Writes a log with a severity of info. + * @param message The message to log + */ + void Info(nostd::string_view message) noexcept { this->Log(Severity::kInfo, message); } + + /** + * Writes a log with a severity of info. + * @param name The name of the log + * @param message The message to log + */ + OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") + void Info(nostd::string_view name, nostd::string_view message) noexcept + { + this->Log(Severity::kInfo, name, message); + } + + /** + * Writes a log with a severity of info. + * @param attributes The attributes of the log as a key/value object + */ + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void Info(const T &attributes) noexcept + { + this->Log(Severity::kInfo, attributes); + } + + /** + * Writes a log with a severity of info. + * @param message The message of the log + * @param attributes The attributes of the log as a key/value object + */ + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void Info(nostd::string_view message, const T &attributes) noexcept + { + this->Log(Severity::kInfo, message, attributes); + } + + /** + * Writes a log with a severity of info. + * @param attributes The attributes of the log as an initializer list + */ + void Info(std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> + attributes) noexcept + { + this->Log(Severity::kInfo, attributes); + } + + /** + * Writes a log with a severity of info. + * @param message The message of the log + * @param attributes The attributes of the log as an initializer list + */ + void Info(nostd::string_view message, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> + attributes) noexcept + { + this->Log(Severity::kInfo, message, attributes); + } + + /** Warn severity overloads **/ + + /** + * Writes a log with a severity of warn. + * @param message The message to log + */ + void Warn(nostd::string_view message) noexcept { this->Log(Severity::kWarn, message); } + + /** + * Writes a log with a severity of warn. + * @param name The name of the log + * @param message The message to log + */ + OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") + void Warn(nostd::string_view name, nostd::string_view message) noexcept + { + this->Log(Severity::kWarn, name, message); + } + + /** + * Writes a log with a severity of warn. + * @param attributes The attributes of the log as a key/value object + */ + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void Warn(const T &attributes) noexcept + { + this->Log(Severity::kWarn, attributes); + } + + /** + * Writes a log with a severity of warn. + * @param message The message of the log + * @param attributes The attributes of the log as a key/value object + */ + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void Warn(nostd::string_view message, const T &attributes) noexcept + { + this->Log(Severity::kWarn, message, attributes); + } + + /** + * Writes a log with a severity of warn. + * @param attributes The attributes of the log as an initializer list + */ + void Warn(std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> + attributes) noexcept + { + this->Log(Severity::kWarn, attributes); + } + + /** + * Writes a log with a severity of warn. + * @param message The message of the log + * @param attributes The attributes of the log as an initializer list + */ + void Warn(nostd::string_view message, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> + attributes) noexcept + { + this->Log(Severity::kWarn, message, attributes); + } + + /** Error severity overloads **/ + + /** + * Writes a log with a severity of error. + * @param message The message to log + */ + void Error(nostd::string_view message) noexcept { this->Log(Severity::kError, message); } + + /** + * Writes a log with a severity of error. + * @param name The name of the log + * @param message The message to log + */ + OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") + void Error(nostd::string_view name, nostd::string_view message) noexcept + { + this->Log(Severity::kError, name, message); + } + + /** + * Writes a log with a severity of error. + * @param attributes The attributes of the log as a key/value object + */ + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void Error(const T &attributes) noexcept + { + this->Log(Severity::kError, attributes); + } + + /** + * Writes a log with a severity of error. + * @param message The message of the log + * @param attributes The attributes of the log as a key/value object + */ + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void Error(nostd::string_view message, const T &attributes) noexcept + { + this->Log(Severity::kError, message, attributes); + } + + /** + * Writes a log with a severity of error. + * @param attributes The attributes of the log as an initializer list + */ + void Error(std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> + attributes) noexcept + { + this->Log(Severity::kError, attributes); + } + + /** + * Writes a log with a severity of error. + * @param message The message of the log + * @param attributes The attributes of the log as an initializer list + */ + void Error(nostd::string_view message, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> + attributes) noexcept + { + this->Log(Severity::kError, message, attributes); + } + + /** Fatal severity overloads **/ + + /** + * Writes a log with a severity of fatal. + * @param message The message to log + */ + void Fatal(nostd::string_view message) noexcept { this->Log(Severity::kFatal, message); } + + /** + * Writes a log with a severity of fatal. + * @param name The name of the log + * @param message The message to log + */ + OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") + void Fatal(nostd::string_view name, nostd::string_view message) noexcept + { + this->Log(Severity::kFatal, name, message); + } + + /** + * Writes a log with a severity of fatal. + * @param attributes The attributes of the log as a key/value object + */ + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void Fatal(const T &attributes) noexcept + { + this->Log(Severity::kFatal, attributes); + } + + /** + * Writes a log with a severity of fatal. + * @param message The message of the log + * @param attributes The attributes of the log as a key/value object + */ + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void Fatal(nostd::string_view message, const T &attributes) noexcept + { + this->Log(Severity::kFatal, message, attributes); + } + + /** + * Writes a log with a severity of fatal. + * @param attributes The attributes of the log as an initializer list + */ + void Fatal(std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> + attributes) noexcept + { + this->Log(Severity::kFatal, attributes); + } + + /** + * Writes a log with a severity of fatal. + * @param message The message of the log + * @param attributes The attributes of the log as an initializer list + */ + void Fatal(nostd::string_view message, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> + attributes) noexcept + { + this->Log(Severity::kFatal, message, attributes); + } +}; +} // namespace logs +OPENTELEMETRY_END_NAMESPACE + +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/logs/logger_provider.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/logs/logger_provider.h new file mode 100644 index 000000000..5f1795c8e --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/logs/logger_provider.h @@ -0,0 +1,47 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include "opentelemetry/logs/logger.h" +# include "opentelemetry/nostd/shared_ptr.h" +# include "opentelemetry/nostd/string_view.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace logs +{ +/** + * Creates new Logger instances. + */ +class 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 options, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") = 0; + + virtual nostd::shared_ptr<Logger> GetLogger(nostd::string_view logger_name, + nostd::span<nostd::string_view> args, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") = 0; +}; +} // namespace logs +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/logs/noop.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/logs/noop.h new file mode 100644 index 000000000..2816123fd --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/logs/noop.h @@ -0,0 +1,88 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +// 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 <memory> + +# include "opentelemetry/common/attribute_value.h" +# include "opentelemetry/common/key_value_iterable.h" +# include "opentelemetry/common/timestamp.h" +# include "opentelemetry/context/runtime_context.h" +# include "opentelemetry/logs/logger.h" +# include "opentelemetry/logs/logger_provider.h" +# include "opentelemetry/logs/severity.h" +# include "opentelemetry/nostd/shared_ptr.h" +# include "opentelemetry/nostd/span.h" +# include "opentelemetry/nostd/string_view.h" +# include "opentelemetry/nostd/unique_ptr.h" +# include "opentelemetry/trace/span_id.h" +# include "opentelemetry/trace/trace_flags.h" +# include "opentelemetry/trace/trace_id.h" +# include "opentelemetry/version.h" + +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +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"; } + + void Log(Severity severity, + nostd::string_view body, + const common::KeyValueIterable &attributes, + trace::TraceId trace_id, + trace::SpanId span_id, + trace::TraceFlags trace_flags, + common::SystemTimestamp timestamp) noexcept override + {} +}; + +/** + * No-op implementation of a LoggerProvider. + */ +class NoopLoggerProvider final : public opentelemetry::logs::LoggerProvider +{ +public: + NoopLoggerProvider() + : logger_{ + nostd::shared_ptr<opentelemetry::logs::NoopLogger>(new opentelemetry::logs::NoopLogger)} + {} + + nostd::shared_ptr<Logger> GetLogger(nostd::string_view logger_name, + nostd::string_view options, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") override + { + return logger_; + } + + nostd::shared_ptr<Logger> GetLogger(nostd::string_view logger_name, + nostd::span<nostd::string_view> args, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") override + { + return logger_; + } + +private: + nostd::shared_ptr<opentelemetry::logs::Logger> logger_; +}; +} // namespace logs +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/logs/provider.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/logs/provider.h new file mode 100644 index 000000000..38186bbe7 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/logs/provider.h @@ -0,0 +1,60 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include <mutex> + +# include "opentelemetry/common/spin_lock_mutex.h" +# include "opentelemetry/logs/logger_provider.h" +# include "opentelemetry/logs/noop.h" +# include "opentelemetry/nostd/shared_ptr.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace logs +{ +/** + * Stores the singleton global LoggerProvider. + */ +class 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(nostd::shared_ptr<LoggerProvider> tp) noexcept + { + std::lock_guard<common::SpinLockMutex> guard(GetLock()); + GetProvider() = tp; + } + +private: + static nostd::shared_ptr<LoggerProvider> &GetProvider() noexcept + { + static nostd::shared_ptr<LoggerProvider> provider(new NoopLoggerProvider); + return provider; + } + + static common::SpinLockMutex &GetLock() noexcept + { + static common::SpinLockMutex lock; + return lock; + } +}; + +} // namespace logs +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/logs/severity.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/logs/severity.h new file mode 100644 index 000000000..9fcf457b2 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/logs/severity.h @@ -0,0 +1,61 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# 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). + */ +enum class Severity : uint8_t +{ + kInvalid, + kTrace, + kTrace2, + kTrace3, + kTrace4, + kDebug, + kDebug2, + kDebug3, + kDebug4, + kInfo, + kInfo2, + kInfo3, + kInfo4, + kWarn, + kWarn2, + kWarn3, + kWarn4, + kError, + kError2, + kError3, + kError4, + kFatal, + kFatal2, + kFatal3, + kFatal4 +}; + +/** + * 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 opentelemetry::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 +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/async_instruments.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/async_instruments.h new file mode 100644 index 000000000..065a47649 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/async_instruments.h @@ -0,0 +1,29 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW + +# include "opentelemetry/metrics/observer_result.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace metrics +{ +class AsynchronousInstrument +{}; + +template <class T> +class ObservableCounter : public AsynchronousInstrument +{}; + +template <class T> +class ObservableGauge : public AsynchronousInstrument +{}; + +template <class T> +class ObservableUpDownCounter : public AsynchronousInstrument +{}; + +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/meter.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/meter.h new file mode 100644 index 000000000..e0454e360 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/meter.h @@ -0,0 +1,155 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW + +# include "opentelemetry/metrics/async_instruments.h" +# include "opentelemetry/metrics/sync_instruments.h" +# include "opentelemetry/nostd/shared_ptr.h" +# include "opentelemetry/nostd/span.h" +# include "opentelemetry/nostd/string_view.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace metrics +{ +/** + * 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 shared_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::shared_ptr<Counter<long>> CreateLongCounter( + nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept = 0; + + virtual nostd::shared_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 callback the function to be observed by the instrument. + * @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. + * @param state to be passed back to callback + */ + virtual void CreateLongObservableCounter(nostd::string_view name, + void (*callback)(ObserverResult<long> &, void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept = 0; + + virtual void CreateDoubleObservableCounter(nostd::string_view name, + void (*callback)(ObserverResult<double> &, void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept = 0; + + /** + * Creates a Histogram with the passed characteristics and returns a shared_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::shared_ptr<Histogram<long>> CreateLongHistogram( + nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept = 0; + + virtual nostd::shared_ptr<Histogram<double>> CreateDoubleHistogram( + nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept = 0; + + /** + * Creates a Asynchronouse (Observable) Gauge with the passed characteristics and returns a + * shared_ptr to that Observable Counter + * + * @param name the name of the new Observable Gauge. + * @param callback the function to be observed by the instrument. + * @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. + * @param state to be passed back to callback + */ + virtual void CreateLongObservableGauge(nostd::string_view name, + void (*callback)(ObserverResult<long> &, void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept = 0; + + virtual void CreateDoubleObservableGauge(nostd::string_view name, + void (*callback)(ObserverResult<double> &, void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept = 0; + + /** + * Creates an UpDownCounter with the passed characteristics and returns a shared_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::shared_ptr<UpDownCounter<long>> CreateLongUpDownCounter( + nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept = 0; + + virtual nostd::shared_ptr<UpDownCounter<double>> CreateDoubleUpDownCounter( + nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept = 0; + + /** + * Creates a Asynchronouse (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 callback the function to be observed by the instrument. + * @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. + * @param state to be passed back to callback + */ + virtual void CreateLongObservableUpDownCounter(nostd::string_view name, + void (*callback)(ObserverResult<long> &, void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept = 0; + + virtual void CreateDoubleObservableUpDownCounter(nostd::string_view name, + void (*callback)(ObserverResult<double> &, + void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept = 0; +}; +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/meter_provider.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/meter_provider.h new file mode 100644 index 000000000..1892c7d8f --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/meter_provider.h @@ -0,0 +1,33 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW + +# include "opentelemetry/metrics/meter.h" +# include "opentelemetry/nostd/shared_ptr.h" +# include "opentelemetry/nostd/string_view.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace metrics +{ +/** + * Creates new Meter instances. + */ +class MeterProvider +{ +public: + virtual ~MeterProvider() = default; + /** + * Gets or creates a named Meter instance. + * + * Optionally a version can be passed to create a named and versioned Meter + * instance. + */ + virtual nostd::shared_ptr<Meter> GetMeter(nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") noexcept = 0; +}; +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/noop.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/noop.h new file mode 100644 index 000000000..c47f7489f --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/noop.h @@ -0,0 +1,237 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW + +# 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 opentelemetry::context::Context &context) noexcept override {} + void Add(T value, const common::KeyValueIterable &attributes) noexcept override {} + void Add(T value, + const common::KeyValueIterable &attributes, + const opentelemetry::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 opentelemetry::context::Context &context) noexcept override {} + void Record(T value, + const common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept override + {} +}; + +template <class T> +class NoopUpDownCounter : public UpDownCounter<T> +{ +public: + NoopUpDownCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit) noexcept + {} + void Add(T value) noexcept override {} + void Add(T value, const opentelemetry::context::Context &context) noexcept override {} + void Add(T value, const common::KeyValueIterable &attributes) noexcept override {} + void Add(T value, + const common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept override + {} +}; + +template <class T> +class NoopObservableCounter : public ObservableCounter<T> +{ +public: + NoopObservableCounter(nostd::string_view name, + void (*callback)(ObserverResult<T> &), + nostd::string_view description, + nostd::string_view unit) noexcept + {} + + NoopObservableCounter(nostd::string_view name, + void (*callback)(ObserverResult<T> &, const common::KeyValueIterable &), + nostd::string_view description, + nostd::string_view unit) noexcept + {} +}; + +template <class T> +class NoopObservableGauge : public ObservableGauge<T> +{ +public: + NoopObservableGauge(nostd::string_view name, + void (*callback)(ObserverResult<T> &), + nostd::string_view description, + nostd::string_view unit) noexcept + {} + + NoopObservableGauge(nostd::string_view name, + void (*callback)(ObserverResult<T> &, const common::KeyValueIterable &), + nostd::string_view description, + nostd::string_view unit) noexcept + {} +}; + +template <class T> +class NoopObservableUpDownCounter : public ObservableUpDownCounter<T> +{ +public: + NoopObservableUpDownCounter(nostd::string_view name, + void (*callback)(ObserverResult<T> &), + nostd::string_view description, + nostd::string_view unit) noexcept + {} + + NoopObservableUpDownCounter(nostd::string_view name, + void (*callback)(ObserverResult<T> &, + const common::KeyValueIterable &), + nostd::string_view description, + nostd::string_view unit) noexcept + {} +}; + +/** + * No-op implementation of Meter. + */ +class NoopMeter final : public Meter +{ +public: + nostd::shared_ptr<Counter<long>> CreateLongCounter(nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept override + { + return nostd::shared_ptr<Counter<long>>{new NoopCounter<long>(name, description, unit)}; + } + + nostd::shared_ptr<Counter<double>> CreateDoubleCounter( + nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept override + { + return nostd::shared_ptr<Counter<double>>{new NoopCounter<double>(name, description, unit)}; + } + + void CreateLongObservableCounter(nostd::string_view name, + void (*callback)(ObserverResult<long> &, void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept override + {} + + void CreateDoubleObservableCounter(nostd::string_view name, + void (*callback)(ObserverResult<double> &, void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept override + {} + + nostd::shared_ptr<Histogram<long>> CreateLongHistogram( + nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept override + { + return nostd::shared_ptr<Histogram<long>>{new NoopHistogram<long>(name, description, unit)}; + } + + nostd::shared_ptr<Histogram<double>> CreateDoubleHistogram( + nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept override + { + return nostd::shared_ptr<Histogram<double>>{new NoopHistogram<double>(name, description, unit)}; + } + + void CreateLongObservableGauge(nostd::string_view name, + void (*callback)(ObserverResult<long> &, void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept override + {} + + void CreateDoubleObservableGauge(nostd::string_view name, + void (*callback)(ObserverResult<double> &, void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept override + {} + + nostd::shared_ptr<UpDownCounter<long>> CreateLongUpDownCounter( + nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept override + { + return nostd::shared_ptr<UpDownCounter<long>>{ + new NoopUpDownCounter<long>(name, description, unit)}; + } + + nostd::shared_ptr<UpDownCounter<double>> CreateDoubleUpDownCounter( + nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept override + { + return nostd::shared_ptr<UpDownCounter<double>>{ + new NoopUpDownCounter<double>(name, description, unit)}; + } + + void CreateLongObservableUpDownCounter(nostd::string_view name, + void (*callback)(ObserverResult<long> &, void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept override + {} + + void CreateDoubleObservableUpDownCounter(nostd::string_view name, + void (*callback)(ObserverResult<double> &, void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept override + {} +}; + +/** + * No-op implementation of a MeterProvider. + */ +class NoopMeterProvider final : public MeterProvider +{ +public: + NoopMeterProvider() : meter_{nostd::shared_ptr<Meter>(new NoopMeter)} {} + + nostd::shared_ptr<Meter> GetMeter(nostd::string_view library_name, + nostd::string_view library_version, + nostd::string_view schema_url) noexcept override + { + return meter_; + } + +private: + nostd::shared_ptr<Meter> meter_; +}; +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE +#endif
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/observer_result.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/observer_result.h new file mode 100644 index 000000000..84893deef --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/observer_result.h @@ -0,0 +1,49 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW + +# include "opentelemetry/common/attribute_value.h" +# include "opentelemetry/common/key_value_iterable_view.h" +# include "opentelemetry/nostd/span.h" +# include "opentelemetry/nostd/string_view.h" +# include "opentelemetry/nostd/type_traits.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace metrics +{ + +/** + * ObserverResult class is necessary for the callback recording asynchronous + * instrument use. + */ + +template <class T> +class ObserverResult +{ + +public: + 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()}); + } +}; + +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/provider.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/provider.h new file mode 100644 index 000000000..3bacac976 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/provider.h @@ -0,0 +1,60 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW + +# 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" + +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(nostd::shared_ptr<MeterProvider> tp) noexcept + { + std::lock_guard<common::SpinLockMutex> guard(GetLock()); + GetProvider() = tp; + } + +private: + static nostd::shared_ptr<MeterProvider> &GetProvider() noexcept + { + static nostd::shared_ptr<MeterProvider> provider(new NoopMeterProvider); + return provider; + } + + static common::SpinLockMutex &GetLock() noexcept + { + static common::SpinLockMutex lock; + return lock; + } +}; + +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE +#endif
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/sync_instruments.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/sync_instruments.h new file mode 100644 index 000000000..e8239743a --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/metrics/sync_instruments.h @@ -0,0 +1,195 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW + +# 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" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace metrics +{ + +class SynchronousInstrument +{}; + +template <class T> +class Counter : public SynchronousInstrument +{ + +public: + /** + * Add adds the value to the counter's sum + * + * @param value The increment amount. MUST be non-negative. + */ + virtual void Add(T value) noexcept = 0; + + virtual void Add(T value, const opentelemetry::context::Context &context) noexcept = 0; + + /** + * Add adds the value to the counter's sum. The attributes should contain + * the keys and values to be associated with this value. Counters only + * accept positive valued updates. + * + * @param value The increment amount. MUST be non-negative. + * @param attributes the set of attributes, as key-value pairs + */ + + virtual void Add(T value, const common::KeyValueIterable &attributes) noexcept = 0; + + virtual void Add(T value, + const common::KeyValueIterable &attributes, + const opentelemetry::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 + { + auto context = opentelemetry::context::Context{}; + this->Add(value, common::KeyValueIterableView<U>{attributes}, context); + } + + template <class U, + nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr> + void Add(T value, const U &attributes, const opentelemetry::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 + { + auto context = opentelemetry::context::Context{}; + this->Add(value, + nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{ + attributes.begin(), attributes.end()}, + context); + } + + void Add(T value, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes, + const opentelemetry::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: + /** + * Records a value. + * + * @param value The increment amount. May be positive, negative or zero. + */ + virtual void Record(T value, const opentelemetry::context::Context &context) noexcept = 0; + + /** + * Records 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 Record(T value, + const common::KeyValueIterable &attributes, + const opentelemetry::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 opentelemetry::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 opentelemetry::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: + /** + * Adds a value. + * + * @param value The amount of the measurement. + */ + virtual void Add(T value) noexcept = 0; + + virtual void Add(T value, const opentelemetry::context::Context &context) noexcept = 0; + + /** + * Add 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; + + virtual void Add(T value, + const common::KeyValueIterable &attributes, + const opentelemetry::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 + { + auto context = opentelemetry::context::Context{}; + this->Add(value, common::KeyValueIterableView<U>{attributes}, context); + } + + template <class U, + nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr> + void Add(T value, const U &attributes, const opentelemetry::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 + { + auto context = opentelemetry::context::Context{}; + this->Add(value, + nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{ + attributes.begin(), attributes.end()}, + context); + } + + void Add(T value, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes, + const opentelemetry::context::Context &context) noexcept + { + this->Add(value, + nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{ + attributes.begin(), attributes.end()}, + context); + } +}; + +} // namespace metrics +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/all.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/all.h new file mode 100644 index 000000000..dc12a5a5f --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/all.h @@ -0,0 +1,18 @@ +#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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/decay.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/decay.h new file mode 100644 index 000000000..23aaaee2e --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/decay.h @@ -0,0 +1,13 @@ +#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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/dependent_type.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/dependent_type.h new file mode 100644 index 000000000..0f58bcf7f --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/dependent_type.h @@ -0,0 +1,17 @@ +#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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/functional.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/functional.h new file mode 100644 index 000000000..a3546f2be --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/functional.h @@ -0,0 +1,60 @@ +#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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/invoke.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/invoke.h new file mode 100644 index 000000000..e713d93db --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/invoke.h @@ -0,0 +1,155 @@ +#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 + +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 +{ + +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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/trait.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/trait.h new file mode 100644 index 000000000..d4ed09cbb --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/trait.h @@ -0,0 +1,72 @@ +#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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/type_pack_element.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/type_pack_element.h new file mode 100644 index 000000000..0c522dd28 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/type_pack_element.h @@ -0,0 +1,50 @@ +#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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/valueless.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/valueless.h new file mode 100644 index 000000000..2a89b575e --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/valueless.h @@ -0,0 +1,11 @@ +#pragma once + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +struct valueless_t +{}; +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/variant_alternative.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/variant_alternative.h new file mode 100644 index 000000000..70486cfc1 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/variant_alternative.h @@ -0,0 +1,37 @@ +#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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/variant_fwd.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/variant_fwd.h new file mode 100644 index 000000000..6d2d1ef9e --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/variant_fwd.h @@ -0,0 +1,11 @@ +#pragma once + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +template <typename... Ts> +class variant; +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/variant_size.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/variant_size.h new file mode 100644 index 000000000..081471030 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/variant_size.h @@ -0,0 +1,30 @@ +#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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/void.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/void.h new file mode 100644 index 000000000..e8d4a48c0 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/detail/void.h @@ -0,0 +1,25 @@ +#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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/function_ref.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/function_ref.h new file mode 100644 index 000000000..edc200776 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/function_ref.h @@ -0,0 +1,92 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <memory> +#include <type_traits> + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +template <class Sig> +class function_ref; + +/** + * 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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/.clang-format b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/.clang-format new file mode 100644 index 000000000..001170f7e --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/.clang-format @@ -0,0 +1,3 @@ +# Disable formatting for Google Abseil library snapshot +DisableFormat: true +SortIncludes: false diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/README.md b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/README.md new file mode 100644 index 000000000..6a4085570 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/README.md @@ -0,0 +1,4 @@ +# Notes on Abseil Variant implementation + +This is a snapshot of Abseil Variant `absl::variant` from Abseil +`v2020-03-03#8`. diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/attributes.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/attributes.h new file mode 100644 index 000000000..72901a84c --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/attributes.h @@ -0,0 +1,621 @@ +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This header file defines macros for declaring attributes for functions, +// types, and variables. +// +// These macros are used within Abseil and allow the compiler to optimize, where +// applicable, certain function calls. +// +// This file is used for both C and C++! +// +// Most macros here are exposing GCC or Clang features, and are stubbed out for +// other compilers. +// +// GCC attributes documentation: +// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html +// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Variable-Attributes.html +// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Type-Attributes.html +// +// Most attributes in this file are already supported by GCC 4.7. However, some +// of them are not supported in older version of Clang. Thus, we check +// `__has_attribute()` first. If the check fails, we check if we are on GCC and +// assume the attribute exists on GCC (which is verified on GCC 4.7). +// +// ----------------------------------------------------------------------------- +// Sanitizer Attributes +// ----------------------------------------------------------------------------- +// +// Sanitizer-related attributes are not "defined" in this file (and indeed +// are not defined as such in any file). To utilize the following +// sanitizer-related attributes within your builds, define the following macros +// within your build using a `-D` flag, along with the given value for +// `-fsanitize`: +// +// * `ADDRESS_SANITIZER` + `-fsanitize=address` (Clang, GCC 4.8) +// * `MEMORY_SANITIZER` + `-fsanitize=memory` (Clang-only) +// * `THREAD_SANITIZER + `-fsanitize=thread` (Clang, GCC 4.8+) +// * `UNDEFINED_BEHAVIOR_SANITIZER` + `-fsanitize=undefined` (Clang, GCC 4.9+) +// * `CONTROL_FLOW_INTEGRITY` + -fsanitize=cfi (Clang-only) +// +// Example: +// +// // Enable branches in the Abseil code that are tagged for ASan: +// $ bazel build --copt=-DADDRESS_SANITIZER --copt=-fsanitize=address +// --linkopt=-fsanitize=address *target* +// +// Since these macro names are only supported by GCC and Clang, we only check +// for `__GNUC__` (GCC or Clang) and the above macros. +#ifndef OTABSL_BASE_ATTRIBUTES_H_ +#define OTABSL_BASE_ATTRIBUTES_H_ + +// OTABSL_HAVE_ATTRIBUTE +// +// A function-like feature checking macro that is a wrapper around +// `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a +// nonzero constant integer if the attribute is supported or 0 if not. +// +// It evaluates to zero if `__has_attribute` is not defined by the compiler. +// +// GCC: https://gcc.gnu.org/gcc-5/changes.html +// Clang: https://clang.llvm.org/docs/LanguageExtensions.html +#ifdef __has_attribute +#define OTABSL_HAVE_ATTRIBUTE(x) __has_attribute(x) +#else +#define OTABSL_HAVE_ATTRIBUTE(x) 0 +#endif + +// OTABSL_HAVE_CPP_ATTRIBUTE +// +// A function-like feature checking macro that accepts C++11 style attributes. +// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6 +// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't +// find `__has_cpp_attribute`, will evaluate to 0. +#if defined(__cplusplus) && defined(__has_cpp_attribute) +// NOTE: requiring __cplusplus above should not be necessary, but +// works around https://bugs.llvm.org/show_bug.cgi?id=23435. +#define OTABSL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +#define OTABSL_HAVE_CPP_ATTRIBUTE(x) 0 +#endif + +// ----------------------------------------------------------------------------- +// Function Attributes +// ----------------------------------------------------------------------------- +// +// GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html +// Clang: https://clang.llvm.org/docs/AttributeReference.html + +// OTABSL_PRINTF_ATTRIBUTE +// OTABSL_SCANF_ATTRIBUTE +// +// Tells the compiler to perform `printf` format string checking if the +// compiler supports it; see the 'format' attribute in +// <https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html>. +// +// Note: As the GCC manual states, "[s]ince non-static C++ methods +// have an implicit 'this' argument, the arguments of such methods +// should be counted from two, not one." +#if OTABSL_HAVE_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__)) +#define OTABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((__format__(__printf__, string_index, first_to_check))) +#define OTABSL_SCANF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((__format__(__scanf__, string_index, first_to_check))) +#else +#define OTABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) +#define OTABSL_SCANF_ATTRIBUTE(string_index, first_to_check) +#endif + +// OTABSL_ATTRIBUTE_ALWAYS_INLINE +// OTABSL_ATTRIBUTE_NOINLINE +// +// Forces functions to either inline or not inline. Introduced in gcc 3.1. +#if OTABSL_HAVE_ATTRIBUTE(always_inline) || \ + (defined(__GNUC__) && !defined(__clang__)) +#define OTABSL_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) +#define OTABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE 1 +#else +#define OTABSL_ATTRIBUTE_ALWAYS_INLINE +#endif + +#if OTABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__)) +#define OTABSL_ATTRIBUTE_NOINLINE __attribute__((noinline)) +#define OTABSL_HAVE_ATTRIBUTE_NOINLINE 1 +#else +#define OTABSL_ATTRIBUTE_NOINLINE +#endif + +// OTABSL_ATTRIBUTE_NO_TAIL_CALL +// +// Prevents the compiler from optimizing away stack frames for functions which +// end in a call to another function. +#if OTABSL_HAVE_ATTRIBUTE(disable_tail_calls) +#define OTABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 +#define OTABSL_ATTRIBUTE_NO_TAIL_CALL __attribute__((disable_tail_calls)) +#elif defined(__GNUC__) && !defined(__clang__) +#define OTABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 +#define OTABSL_ATTRIBUTE_NO_TAIL_CALL \ + __attribute__((optimize("no-optimize-sibling-calls"))) +#else +#define OTABSL_ATTRIBUTE_NO_TAIL_CALL +#define OTABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 0 +#endif + +// OTABSL_ATTRIBUTE_WEAK +// +// Tags a function as weak for the purposes of compilation and linking. +// Weak attributes currently do not work properly in LLVM's Windows backend, +// so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598 +// for further information. +// The MinGW compiler doesn't complain about the weak attribute until the link +// step, presumably because Windows doesn't use ELF binaries. +#if (OTABSL_HAVE_ATTRIBUTE(weak) || \ + (defined(__GNUC__) && !defined(__clang__))) && \ + !(defined(__llvm__) && defined(_WIN32)) && !defined(__MINGW32__) +#undef OTABSL_ATTRIBUTE_WEAK +#define OTABSL_ATTRIBUTE_WEAK __attribute__((weak)) +#define OTABSL_HAVE_ATTRIBUTE_WEAK 1 +#else +#define OTABSL_ATTRIBUTE_WEAK +#define OTABSL_HAVE_ATTRIBUTE_WEAK 0 +#endif + +// OTABSL_ATTRIBUTE_NONNULL +// +// Tells the compiler either (a) that a particular function parameter +// should be a non-null pointer, or (b) that all pointer arguments should +// be non-null. +// +// Note: As the GCC manual states, "[s]ince non-static C++ methods +// have an implicit 'this' argument, the arguments of such methods +// should be counted from two, not one." +// +// Args are indexed starting at 1. +// +// For non-static class member functions, the implicit `this` argument +// is arg 1, and the first explicit argument is arg 2. For static class member +// functions, there is no implicit `this`, and the first explicit argument is +// arg 1. +// +// Example: +// +// /* arg_a cannot be null, but arg_b can */ +// void Function(void* arg_a, void* arg_b) OTABSL_ATTRIBUTE_NONNULL(1); +// +// class C { +// /* arg_a cannot be null, but arg_b can */ +// void Method(void* arg_a, void* arg_b) OTABSL_ATTRIBUTE_NONNULL(2); +// +// /* arg_a cannot be null, but arg_b can */ +// static void StaticMethod(void* arg_a, void* arg_b) +// OTABSL_ATTRIBUTE_NONNULL(1); +// }; +// +// If no arguments are provided, then all pointer arguments should be non-null. +// +// /* No pointer arguments may be null. */ +// void Function(void* arg_a, void* arg_b, int arg_c) OTABSL_ATTRIBUTE_NONNULL(); +// +// NOTE: The GCC nonnull attribute actually accepts a list of arguments, but +// OTABSL_ATTRIBUTE_NONNULL does not. +#if OTABSL_HAVE_ATTRIBUTE(nonnull) || (defined(__GNUC__) && !defined(__clang__)) +#define OTABSL_ATTRIBUTE_NONNULL(arg_index) __attribute__((nonnull(arg_index))) +#else +#define OTABSL_ATTRIBUTE_NONNULL(...) +#endif + +// OTABSL_ATTRIBUTE_NORETURN +// +// Tells the compiler that a given function never returns. +#if OTABSL_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__)) +#define OTABSL_ATTRIBUTE_NORETURN __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define OTABSL_ATTRIBUTE_NORETURN __declspec(noreturn) +#else +#define OTABSL_ATTRIBUTE_NORETURN +#endif + +// OTABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS +// +// Tells the AddressSanitizer (or other memory testing tools) to ignore a given +// function. Useful for cases when a function reads random locations on stack, +// calls _exit from a cloned subprocess, deliberately accesses buffer +// out of bounds or does other scary things with memory. +// NOTE: GCC supports AddressSanitizer(asan) since 4.8. +// https://gcc.gnu.org/gcc-4.8/changes.html +#if defined(__GNUC__) +#define OTABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) +#else +#define OTABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS +#endif + +// OTABSL_ATTRIBUTE_NO_SANITIZE_MEMORY +// +// Tells the MemorySanitizer to relax the handling of a given function. All +// "Use of uninitialized value" warnings from such functions will be suppressed, +// and all values loaded from memory will be considered fully initialized. +// This attribute is similar to the ADDRESS_SANITIZER attribute above, but deals +// with initialized-ness rather than addressability issues. +// NOTE: MemorySanitizer(msan) is supported by Clang but not GCC. +#if defined(__clang__) +#define OTABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) +#else +#define OTABSL_ATTRIBUTE_NO_SANITIZE_MEMORY +#endif + +// OTABSL_ATTRIBUTE_NO_SANITIZE_THREAD +// +// Tells the ThreadSanitizer to not instrument a given function. +// NOTE: GCC supports ThreadSanitizer(tsan) since 4.8. +// https://gcc.gnu.org/gcc-4.8/changes.html +#if defined(__GNUC__) +#define OTABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) +#else +#define OTABSL_ATTRIBUTE_NO_SANITIZE_THREAD +#endif + +// OTABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED +// +// Tells the UndefinedSanitizer to ignore a given function. Useful for cases +// where certain behavior (eg. division by zero) is being used intentionally. +// NOTE: GCC supports UndefinedBehaviorSanitizer(ubsan) since 4.9. +// https://gcc.gnu.org/gcc-4.9/changes.html +#if defined(__GNUC__) && \ + (defined(UNDEFINED_BEHAVIOR_SANITIZER) || defined(ADDRESS_SANITIZER)) +#define OTABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ + __attribute__((no_sanitize("undefined"))) +#else +#define OTABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED +#endif + +// OTABSL_ATTRIBUTE_NO_SANITIZE_CFI +// +// Tells the ControlFlowIntegrity sanitizer to not instrument a given function. +// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details. +#if defined(__GNUC__) && defined(CONTROL_FLOW_INTEGRITY) +#define OTABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) +#else +#define OTABSL_ATTRIBUTE_NO_SANITIZE_CFI +#endif + +// OTABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK +// +// Tells the SafeStack to not instrument a given function. +// See https://clang.llvm.org/docs/SafeStack.html for details. +#if defined(__GNUC__) && defined(SAFESTACK_SANITIZER) +#define OTABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \ + __attribute__((no_sanitize("safe-stack"))) +#else +#define OTABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK +#endif + +// OTABSL_ATTRIBUTE_RETURNS_NONNULL +// +// Tells the compiler that a particular function never returns a null pointer. +#if OTABSL_HAVE_ATTRIBUTE(returns_nonnull) || \ + (defined(__GNUC__) && \ + (__GNUC__ > 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) && \ + !defined(__clang__)) +#define OTABSL_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) +#else +#define OTABSL_ATTRIBUTE_RETURNS_NONNULL +#endif + +// OTABSL_HAVE_ATTRIBUTE_SECTION +// +// Indicates whether labeled sections are supported. Weak symbol support is +// a prerequisite. Labeled sections are not supported on Darwin/iOS. +#ifdef OTABSL_HAVE_ATTRIBUTE_SECTION +#error OTABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set +#elif (OTABSL_HAVE_ATTRIBUTE(section) || \ + (defined(__GNUC__) && !defined(__clang__))) && \ + !defined(__APPLE__) && OTABSL_HAVE_ATTRIBUTE_WEAK +#define OTABSL_HAVE_ATTRIBUTE_SECTION 1 + +// OTABSL_ATTRIBUTE_SECTION +// +// Tells the compiler/linker to put a given function into a section and define +// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. +// This functionality is supported by GNU linker. Any function annotated with +// `OTABSL_ATTRIBUTE_SECTION` must not be inlined, or it will be placed into +// whatever section its caller is placed into. +// +#ifndef OTABSL_ATTRIBUTE_SECTION +#define OTABSL_ATTRIBUTE_SECTION(name) \ + __attribute__((section(#name))) __attribute__((noinline)) +#endif + + +// OTABSL_ATTRIBUTE_SECTION_VARIABLE +// +// Tells the compiler/linker to put a given variable into a section and define +// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. +// This functionality is supported by GNU linker. +#ifndef OTABSL_ATTRIBUTE_SECTION_VARIABLE +#define OTABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name))) +#endif + +// OTABSL_DECLARE_ATTRIBUTE_SECTION_VARS +// +// A weak section declaration to be used as a global declaration +// for OTABSL_ATTRIBUTE_SECTION_START|STOP(name) to compile and link +// even without functions with OTABSL_ATTRIBUTE_SECTION(name). +// OTABSL_DEFINE_ATTRIBUTE_SECTION should be in the exactly one file; it's +// a no-op on ELF but not on Mach-O. +// +#ifndef OTABSL_DECLARE_ATTRIBUTE_SECTION_VARS +#define OTABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) \ + extern char __start_##name[] OTABSL_ATTRIBUTE_WEAK; \ + extern char __stop_##name[] OTABSL_ATTRIBUTE_WEAK +#endif +#ifndef OTABSL_DEFINE_ATTRIBUTE_SECTION_VARS +#define OTABSL_INIT_ATTRIBUTE_SECTION_VARS(name) +#define OTABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) +#endif + +// OTABSL_ATTRIBUTE_SECTION_START +// +// Returns `void*` pointers to start/end of a section of code with +// functions having OTABSL_ATTRIBUTE_SECTION(name). +// Returns 0 if no such functions exist. +// One must OTABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) for this to compile and +// link. +// +#define OTABSL_ATTRIBUTE_SECTION_START(name) \ + (reinterpret_cast<void *>(__start_##name)) +#define OTABSL_ATTRIBUTE_SECTION_STOP(name) \ + (reinterpret_cast<void *>(__stop_##name)) + +#else // !OTABSL_HAVE_ATTRIBUTE_SECTION + +#define OTABSL_HAVE_ATTRIBUTE_SECTION 0 + +// provide dummy definitions +#define OTABSL_ATTRIBUTE_SECTION(name) +#define OTABSL_ATTRIBUTE_SECTION_VARIABLE(name) +#define OTABSL_INIT_ATTRIBUTE_SECTION_VARS(name) +#define OTABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) +#define OTABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) +#define OTABSL_ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void *>(0)) +#define OTABSL_ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void *>(0)) + +#endif // OTABSL_ATTRIBUTE_SECTION + +// OTABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +// +// Support for aligning the stack on 32-bit x86. +#if OTABSL_HAVE_ATTRIBUTE(force_align_arg_pointer) || \ + (defined(__GNUC__) && !defined(__clang__)) +#if defined(__i386__) +#define OTABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC \ + __attribute__((force_align_arg_pointer)) +#define OTABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) +#elif defined(__x86_64__) +#define OTABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (1) +#define OTABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +#else // !__i386__ && !__x86_64 +#define OTABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) +#define OTABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +#endif // __i386__ +#else +#define OTABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +#define OTABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) +#endif + +// OTABSL_MUST_USE_RESULT +// +// Tells the compiler to warn about unused results. +// +// When annotating a function, it must appear as the first part of the +// declaration or definition. The compiler will warn if the return value from +// such a function is unused: +// +// OTABSL_MUST_USE_RESULT Sprocket* AllocateSprocket(); +// AllocateSprocket(); // Triggers a warning. +// +// When annotating a class, it is equivalent to annotating every function which +// returns an instance. +// +// class OTABSL_MUST_USE_RESULT Sprocket {}; +// Sprocket(); // Triggers a warning. +// +// Sprocket MakeSprocket(); +// MakeSprocket(); // Triggers a warning. +// +// Note that references and pointers are not instances: +// +// Sprocket* SprocketPointer(); +// SprocketPointer(); // Does *not* trigger a warning. +// +// OTABSL_MUST_USE_RESULT allows using cast-to-void to suppress the unused result +// warning. For that, warn_unused_result is used only for clang but not for gcc. +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 +// +// Note: past advice was to place the macro after the argument list. +#if OTABSL_HAVE_ATTRIBUTE(nodiscard) +#define OTABSL_MUST_USE_RESULT [[nodiscard]] +#elif defined(__clang__) && OTABSL_HAVE_ATTRIBUTE(warn_unused_result) +#define OTABSL_MUST_USE_RESULT __attribute__((warn_unused_result)) +#else +#define OTABSL_MUST_USE_RESULT +#endif + +// OTABSL_ATTRIBUTE_HOT, OTABSL_ATTRIBUTE_COLD +// +// Tells GCC that a function is hot or cold. GCC can use this information to +// improve static analysis, i.e. a conditional branch to a cold function +// is likely to be not-taken. +// This annotation is used for function declarations. +// +// Example: +// +// int foo() OTABSL_ATTRIBUTE_HOT; +#if OTABSL_HAVE_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__)) +#define OTABSL_ATTRIBUTE_HOT __attribute__((hot)) +#else +#define OTABSL_ATTRIBUTE_HOT +#endif + +#if OTABSL_HAVE_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__)) +#define OTABSL_ATTRIBUTE_COLD __attribute__((cold)) +#else +#define OTABSL_ATTRIBUTE_COLD +#endif + +// OTABSL_XRAY_ALWAYS_INSTRUMENT, OTABSL_XRAY_NEVER_INSTRUMENT, OTABSL_XRAY_LOG_ARGS +// +// We define the OTABSL_XRAY_ALWAYS_INSTRUMENT and OTABSL_XRAY_NEVER_INSTRUMENT +// macro used as an attribute to mark functions that must always or never be +// instrumented by XRay. Currently, this is only supported in Clang/LLVM. +// +// For reference on the LLVM XRay instrumentation, see +// http://llvm.org/docs/XRay.html. +// +// A function with the XRAY_ALWAYS_INSTRUMENT macro attribute in its declaration +// will always get the XRay instrumentation sleds. These sleds may introduce +// some binary size and runtime overhead and must be used sparingly. +// +// These attributes only take effect when the following conditions are met: +// +// * The file/target is built in at least C++11 mode, with a Clang compiler +// that supports XRay attributes. +// * The file/target is built with the -fxray-instrument flag set for the +// Clang/LLVM compiler. +// * The function is defined in the translation unit (the compiler honors the +// attribute in either the definition or the declaration, and must match). +// +// There are cases when, even when building with XRay instrumentation, users +// might want to control specifically which functions are instrumented for a +// particular build using special-case lists provided to the compiler. These +// special case lists are provided to Clang via the +// -fxray-always-instrument=... and -fxray-never-instrument=... flags. The +// attributes in source take precedence over these special-case lists. +// +// To disable the XRay attributes at build-time, users may define +// OTABSL_NO_XRAY_ATTRIBUTES. Do NOT define OTABSL_NO_XRAY_ATTRIBUTES on specific +// packages/targets, as this may lead to conflicting definitions of functions at +// link-time. +// +#if OTABSL_HAVE_CPP_ATTRIBUTE(clang::xray_always_instrument) && \ + !defined(OTABSL_NO_XRAY_ATTRIBUTES) +#define OTABSL_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]] +#define OTABSL_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]] +#if OTABSL_HAVE_CPP_ATTRIBUTE(clang::xray_log_args) +#define OTABSL_XRAY_LOG_ARGS(N) \ + [[clang::xray_always_instrument, clang::xray_log_args(N)]] +#else +#define OTABSL_XRAY_LOG_ARGS(N) [[clang::xray_always_instrument]] +#endif +#else +#define OTABSL_XRAY_ALWAYS_INSTRUMENT +#define OTABSL_XRAY_NEVER_INSTRUMENT +#define OTABSL_XRAY_LOG_ARGS(N) +#endif + +// OTABSL_ATTRIBUTE_REINITIALIZES +// +// Indicates that a member function reinitializes the entire object to a known +// state, independent of the previous state of the object. +// +// The clang-tidy check bugprone-use-after-move allows member functions marked +// with this attribute to be called on objects that have been moved from; +// without the attribute, this would result in a use-after-move warning. +#if OTABSL_HAVE_CPP_ATTRIBUTE(clang::reinitializes) +#define OTABSL_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]] +#else +#define OTABSL_ATTRIBUTE_REINITIALIZES +#endif + +// ----------------------------------------------------------------------------- +// Variable Attributes +// ----------------------------------------------------------------------------- + +// OTABSL_ATTRIBUTE_UNUSED +// +// Prevents the compiler from complaining about variables that appear unused. +#if OTABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__)) +#undef OTABSL_ATTRIBUTE_UNUSED +#define OTABSL_ATTRIBUTE_UNUSED __attribute__((__unused__)) +#else +#define OTABSL_ATTRIBUTE_UNUSED +#endif + +// OTABSL_ATTRIBUTE_INITIAL_EXEC +// +// Tells the compiler to use "initial-exec" mode for a thread-local variable. +// See http://people.redhat.com/drepper/tls.pdf for the gory details. +#if OTABSL_HAVE_ATTRIBUTE(tls_model) || (defined(__GNUC__) && !defined(__clang__)) +#define OTABSL_ATTRIBUTE_INITIAL_EXEC __attribute__((tls_model("initial-exec"))) +#else +#define OTABSL_ATTRIBUTE_INITIAL_EXEC +#endif + +// OTABSL_ATTRIBUTE_PACKED +// +// Instructs the compiler not to use natural alignment for a tagged data +// structure, but instead to reduce its alignment to 1. This attribute can +// either be applied to members of a structure or to a structure in its +// entirety. Applying this attribute (judiciously) to a structure in its +// entirety to optimize the memory footprint of very commonly-used structs is +// fine. Do not apply this attribute to a structure in its entirety if the +// purpose is to control the offsets of the members in the structure. Instead, +// apply this attribute only to structure members that need it. +// +// When applying OTABSL_ATTRIBUTE_PACKED only to specific structure members the +// natural alignment of structure members not annotated is preserved. Aligned +// member accesses are faster than non-aligned member accesses even if the +// targeted microprocessor supports non-aligned accesses. +#if OTABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__)) +#define OTABSL_ATTRIBUTE_PACKED __attribute__((__packed__)) +#else +#define OTABSL_ATTRIBUTE_PACKED +#endif + +// OTABSL_ATTRIBUTE_FUNC_ALIGN +// +// Tells the compiler to align the function start at least to certain +// alignment boundary +#if OTABSL_HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__)) +#define OTABSL_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__((aligned(bytes))) +#else +#define OTABSL_ATTRIBUTE_FUNC_ALIGN(bytes) +#endif + +// OTABSL_CONST_INIT +// +// A variable declaration annotated with the `OTABSL_CONST_INIT` attribute will +// not compile (on supported platforms) unless the variable has a constant +// initializer. This is useful for variables with static and thread storage +// duration, because it guarantees that they will not suffer from the so-called +// "static init order fiasco". Prefer to put this attribute on the most visible +// declaration of the variable, if there's more than one, because code that +// accesses the variable can then use the attribute for optimization. +// +// Example: +// +// class MyClass { +// public: +// OTABSL_CONST_INIT static MyType my_var; +// }; +// +// MyType MyClass::my_var = MakeMyType(...); +// +// Note that this attribute is redundant if the variable is declared constexpr. +#if OTABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) +#define OTABSL_CONST_INIT [[clang::require_constant_initialization]] +#else +#define OTABSL_CONST_INIT +#endif // OTABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) + +#endif // OTABSL_BASE_ATTRIBUTES_H_ diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/config.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/config.h new file mode 100644 index 000000000..5eaeb4636 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/config.h @@ -0,0 +1,671 @@ +// +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: config.h +// ----------------------------------------------------------------------------- +// +// This header file defines a set of macros for checking the presence of +// important compiler and platform features. Such macros can be used to +// produce portable code by parameterizing compilation based on the presence or +// lack of a given feature. +// +// We define a "feature" as some interface we wish to program to: for example, +// a library function or system call. A value of `1` indicates support for +// that feature; any other value indicates the feature support is undefined. +// +// Example: +// +// Suppose a programmer wants to write a program that uses the 'mmap()' system +// call. The Abseil macro for that feature (`OTABSL_HAVE_MMAP`) allows you to +// selectively include the `mmap.h` header and bracket code using that feature +// in the macro: +// +// #include "absl/base/config.h" +// +// #ifdef OTABSL_HAVE_MMAP +// #include "sys/mman.h" +// #endif //OTABSL_HAVE_MMAP +// +// ... +// #ifdef OTABSL_HAVE_MMAP +// void *ptr = mmap(...); +// ... +// #endif // OTABSL_HAVE_MMAP + +#ifndef OTABSL_BASE_CONFIG_H_ +#define OTABSL_BASE_CONFIG_H_ + +// Included for the __GLIBC__ macro (or similar macros on other systems). +#include <limits.h> + +#ifdef __cplusplus +// Included for __GLIBCXX__, _LIBCPP_VERSION +#include <cstddef> +#endif // __cplusplus + +#if defined(__APPLE__) +// Included for TARGET_OS_IPHONE, __IPHONE_OS_VERSION_MIN_REQUIRED, +// __IPHONE_8_0. +#include <Availability.h> +#include <TargetConditionals.h> +#endif + +#include "options.h" +#include "policy_checks.h" + +// Helper macro to convert a CPP variable to a string literal. +#define OTABSL_INTERNAL_DO_TOKEN_STR(x) #x +#define OTABSL_INTERNAL_TOKEN_STR(x) OTABSL_INTERNAL_DO_TOKEN_STR(x) + +// ----------------------------------------------------------------------------- +// Abseil namespace annotations +// ----------------------------------------------------------------------------- + +// OTABSL_NAMESPACE_BEGIN/OTABSL_NAMESPACE_END +// +// An annotation placed at the beginning/end of each `namespace absl` scope. +// This is used to inject an inline namespace. +// +// The proper way to write Abseil code in the `absl` namespace is: +// +// namespace absl { +// OTABSL_NAMESPACE_BEGIN +// +// void Foo(); // absl::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_USE_INLINE_NAMESPACE) || \ + !defined(OTABSL_OPTION_INLINE_NAMESPACE_NAME) +#error options.h is misconfigured. +#endif + +// Check that OTABSL_OPTION_INLINE_NAMESPACE_NAME is neither "head" nor "" +#if defined(__cplusplus) && OTABSL_OPTION_USE_INLINE_NAMESPACE == 1 + +#define OTABSL_INTERNAL_INLINE_NAMESPACE_STR \ + OTABSL_INTERNAL_TOKEN_STR(OTABSL_OPTION_INLINE_NAMESPACE_NAME) + +static_assert(OTABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != '\0', + "options.h misconfigured: OTABSL_OPTION_INLINE_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_INLINE_NAMESPACE_NAME must " + "be changed to a new, unique identifier name."); + +#endif + +#if OTABSL_OPTION_USE_INLINE_NAMESPACE == 0 +#define OTABSL_NAMESPACE_BEGIN +#define OTABSL_NAMESPACE_END +#elif OTABSL_OPTION_USE_INLINE_NAMESPACE == 1 +#define OTABSL_NAMESPACE_BEGIN \ + inline namespace OTABSL_OPTION_INLINE_NAMESPACE_NAME { +#define OTABSL_NAMESPACE_END } +#else +#error options.h is misconfigured. +#endif + +// ----------------------------------------------------------------------------- +// 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__) && 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__) && 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_SOURCE_LOCATION_CURRENT +// +// Indicates whether `absl::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::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::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::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::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) +#if OTABSL_OPTION_USE_INLINE_NAMESPACE == 0 +#define OTABSL_INTERNAL_MANGLED_NS "absl" +#define OTABSL_INTERNAL_MANGLED_BACKREFERENCE "5" +#else +#define OTABSL_INTERNAL_MANGLED_NS \ + OTABSL_INTERNAL_TOKEN_STR(OTABSL_OPTION_INLINE_NAMESPACE_NAME) "@absl" +#define OTABSL_INTERNAL_MANGLED_BACKREFERENCE "6" +#endif +#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_ diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/internal/identity.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/internal/identity.h new file mode 100644 index 000000000..4afba3179 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/internal/identity.h @@ -0,0 +1,37 @@ +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef OTABSL_BASE_INTERNAL_IDENTITY_H_ +#define OTABSL_BASE_INTERNAL_IDENTITY_H_ + +#include "../config.h" + +namespace absl { +OTABSL_NAMESPACE_BEGIN +namespace internal { + +template <typename T> +struct identity { + typedef T type; +}; + +template <typename T> +using identity_t = typename identity<T>::type; + +} // namespace internal +OTABSL_NAMESPACE_END +} // namespace absl + +#endif // OTABSL_BASE_INTERNAL_IDENTITY_H_ diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/internal/inline_variable.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/internal/inline_variable.h new file mode 100644 index 000000000..9d024a2d9 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/internal/inline_variable.h @@ -0,0 +1,107 @@ +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef OTABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_ +#define OTABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_ + +#include <type_traits> + +#include "identity.h" + +// File: +// This file define a macro that allows the creation of or emulation of C++17 +// inline variables based on whether or not the feature is supported. + +//////////////////////////////////////////////////////////////////////////////// +// Macro: OTABSL_INTERNAL_INLINE_CONSTEXPR(type, name, init) +// +// Description: +// Expands to the equivalent of an inline constexpr instance of the specified +// `type` and `name`, initialized to the value `init`. If the compiler being +// used is detected as supporting actual inline variables as a language +// feature, then the macro expands to an actual inline variable definition. +// +// Requires: +// `type` is a type that is usable in an extern variable declaration. +// +// Requires: `name` is a valid identifier +// +// Requires: +// `init` is an expression that can be used in the following definition: +// constexpr type name = init; +// +// Usage: +// +// // Equivalent to: `inline constexpr size_t variant_npos = -1;` +// OTABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1); +// +// Differences in implementation: +// For a direct, language-level inline variable, decltype(name) will be the +// type that was specified along with const qualification, whereas for +// emulated inline variables, decltype(name) may be different (in practice +// it will likely be a reference type). +//////////////////////////////////////////////////////////////////////////////// + +#ifdef __cpp_inline_variables + +// Clang's -Wmissing-variable-declarations option erroneously warned that +// inline constexpr objects need to be pre-declared. This has now been fixed, +// but we will need to support this workaround for people building with older +// versions of clang. +// +// Bug: https://bugs.llvm.org/show_bug.cgi?id=35862 +// +// Note: +// identity_t is used here so that the const and name are in the +// appropriate place for pointer types, reference types, function pointer +// types, etc.. +#if defined(__clang__) +#define OTABSL_INTERNAL_EXTERN_DECL(type, name) \ + extern const ::absl::OTABSL_OPTION_INLINE_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_INLINE_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_INLINE_NAMESPACE_NAME::internal::identity_t<var_type> kInstance = init; \ + }; \ + \ + template <class AbslInternalDummy> \ + constexpr ::absl::OTABSL_OPTION_INLINE_NAMESPACE_NAME::internal::identity_t<var_type> \ + AbslInternalInlineVariableHolder##name<AbslInternalDummy>::kInstance; \ + \ + static constexpr const ::absl::OTABSL_OPTION_INLINE_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_ diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/internal/invoke.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/internal/invoke.h new file mode 100644 index 000000000..99c37ba24 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/internal/invoke.h @@ -0,0 +1,188 @@ +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// absl::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::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::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::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::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_ diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/macros.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/macros.h new file mode 100644 index 000000000..7b4f427d3 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/macros.h @@ -0,0 +1,220 @@ +// +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: macros.h +// ----------------------------------------------------------------------------- +// +// This header file defines the set of language macros used within Abseil code. +// For the set of macros used to determine supported compilers and platforms, +// see absl/base/config.h instead. +// +// This code is compiled directly on many platforms, including client +// platforms like Windows, Mac, and embedded systems. Before making +// any changes here, make sure that you're not breaking any platforms. + +#ifndef OTABSL_BASE_MACROS_H_ +#define OTABSL_BASE_MACROS_H_ + +#include <cassert> +#include <cstddef> + +#include "attributes.h" +#include "optimization.h" +#include "port.h" + +// OTABSL_ARRAYSIZE() +// +// Returns the number of elements in an array as a compile-time constant, which +// can be used in defining new arrays. If you use this macro on a pointer by +// mistake, you will get a compile-time error. +#define OTABSL_ARRAYSIZE(array) \ + (sizeof(::absl::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::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::base_internal:LinkerInitialized x) {} +// +// // Invocation +// static MyClass my_global(absl::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_ diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/optimization.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/optimization.h new file mode 100644 index 000000000..69713654a --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/optimization.h @@ -0,0 +1,181 @@ +// +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: optimization.h +// ----------------------------------------------------------------------------- +// +// This header file defines portable macros for performance optimization. + +#ifndef OTABSL_BASE_OPTIMIZATION_H_ +#define OTABSL_BASE_OPTIMIZATION_H_ + +#include "config.h" + +// OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION +// +// Instructs the compiler to avoid optimizing tail-call recursion. Use of this +// macro is useful when you wish to preserve the existing function order within +// a stack trace for logging, debugging, or profiling purposes. +// +// Example: +// +// int f() { +// int result = g(); +// OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); +// return result; +// } +#if defined(__pnacl__) +#define OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; } +#elif defined(__clang__) +// Clang will not tail call given inline volatile assembly. +#define OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("") +#elif defined(__GNUC__) +// GCC will not tail call given inline volatile assembly. +#define OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("") +#elif defined(_MSC_VER) +#include <intrin.h> +// The __nop() intrinsic blocks the optimisation. +#define OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __nop() +#else +#define OTABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; } +#endif + +// OTABSL_CACHELINE_SIZE +// +// Explicitly defines the size of the L1 cache for purposes of alignment. +// Setting the cacheline size allows you to specify that certain objects be +// aligned on a cacheline boundary with `OTABSL_CACHELINE_ALIGNED` declarations. +// (See below.) +// +// NOTE: this macro should be replaced with the following C++17 features, when +// those are generally available: +// +// * `std::hardware_constructive_interference_size` +// * `std::hardware_destructive_interference_size` +// +// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html +// for more information. +#if defined(__GNUC__) +// Cache line alignment +#if defined(__i386__) || defined(__x86_64__) +#define OTABSL_CACHELINE_SIZE 64 +#elif defined(__powerpc64__) +#define OTABSL_CACHELINE_SIZE 128 +#elif defined(__aarch64__) +// We would need to read special register ctr_el0 to find out L1 dcache size. +// This value is a good estimate based on a real aarch64 machine. +#define OTABSL_CACHELINE_SIZE 64 +#elif defined(__arm__) +// Cache line sizes for ARM: These values are not strictly correct since +// cache line sizes depend on implementations, not architectures. There +// are even implementations with cache line sizes configurable at boot +// time. +#if defined(__ARM_ARCH_5T__) +#define OTABSL_CACHELINE_SIZE 32 +#elif defined(__ARM_ARCH_7A__) +#define OTABSL_CACHELINE_SIZE 64 +#endif +#endif + +#ifndef OTABSL_CACHELINE_SIZE +// A reasonable default guess. Note that overestimates tend to waste more +// space, while underestimates tend to waste more time. +#define OTABSL_CACHELINE_SIZE 64 +#endif + +// OTABSL_CACHELINE_ALIGNED +// +// Indicates that the declared object be cache aligned using +// `OTABSL_CACHELINE_SIZE` (see above). Cacheline aligning objects allows you to +// load a set of related objects in the L1 cache for performance improvements. +// Cacheline aligning objects properly allows constructive memory sharing and +// prevents destructive (or "false") memory sharing. +// +// NOTE: this macro should be replaced with usage of `alignas()` using +// `std::hardware_constructive_interference_size` and/or +// `std::hardware_destructive_interference_size` when available within C++17. +// +// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html +// for more information. +// +// On some compilers, `OTABSL_CACHELINE_ALIGNED` expands to an `__attribute__` +// or `__declspec` attribute. For compilers where this is not known to work, +// the macro expands to nothing. +// +// No further guarantees are made here. The result of applying the macro +// to variables and types is always implementation-defined. +// +// WARNING: It is easy to use this attribute incorrectly, even to the point +// of causing bugs that are difficult to diagnose, crash, etc. It does not +// of itself guarantee that objects are aligned to a cache line. +// +// NOTE: Some compilers are picky about the locations of annotations such as +// this attribute, so prefer to put it at the beginning of your declaration. +// For example, +// +// OTABSL_CACHELINE_ALIGNED static Foo* foo = ... +// +// class OTABSL_CACHELINE_ALIGNED Bar { ... +// +// Recommendations: +// +// 1) Consult compiler documentation; this comment is not kept in sync as +// toolchains evolve. +// 2) Verify your use has the intended effect. This often requires inspecting +// the generated machine code. +// 3) Prefer applying this attribute to individual variables. Avoid +// applying it to types. This tends to localize the effect. +#define OTABSL_CACHELINE_ALIGNED __attribute__((aligned(OTABSL_CACHELINE_SIZE))) +#elif defined(_MSC_VER) +#define OTABSL_CACHELINE_SIZE 64 +#define OTABSL_CACHELINE_ALIGNED __declspec(align(OTABSL_CACHELINE_SIZE)) +#else +#define OTABSL_CACHELINE_SIZE 64 +#define OTABSL_CACHELINE_ALIGNED +#endif + +// OTABSL_PREDICT_TRUE, OTABSL_PREDICT_FALSE +// +// Enables the compiler to prioritize compilation using static analysis for +// likely paths within a boolean branch. +// +// Example: +// +// if (OTABSL_PREDICT_TRUE(expression)) { +// return result; // Faster if more likely +// } else { +// return 0; +// } +// +// Compilers can use the information that a certain branch is not likely to be +// taken (for instance, a CHECK failure) to optimize for the common case in +// the absence of better information (ie. compiling gcc with `-fprofile-arcs`). +// +// Recommendation: Modern CPUs dynamically predict branch execution paths, +// typically with accuracy greater than 97%. As a result, annotating every +// branch in a codebase is likely counterproductive; however, annotating +// specific branches that are both hot and consistently mispredicted is likely +// to yield performance improvements. +#if OTABSL_HAVE_BUILTIN(__builtin_expect) || \ + (defined(__GNUC__) && !defined(__clang__)) +#define OTABSL_PREDICT_FALSE(x) (__builtin_expect(x, 0)) +#define OTABSL_PREDICT_TRUE(x) (__builtin_expect(false || (x), true)) +#else +#define OTABSL_PREDICT_FALSE(x) (x) +#define OTABSL_PREDICT_TRUE(x) (x) +#endif + +#endif // OTABSL_BASE_OPTIMIZATION_H_ diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/options.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/options.h new file mode 100644 index 000000000..3632b74f6 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/options.h @@ -0,0 +1,211 @@ +#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. +#ifdef __cplusplus +#include <ciso646> +#endif + +// ----------------------------------------------------------------------------- +// Type Compatibility Options +// ----------------------------------------------------------------------------- +// +// OTABSL_OPTION_USE_STD_ANY +// +// This option controls whether absl::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::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::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::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::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::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::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::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::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::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::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::variant is a typedef of std::variant, use the feature macro +// OTABSL_USES_STD_VARIANT. + +#define OTABSL_OPTION_USE_STD_VARIANT 0 + + +// OTABSL_OPTION_USE_INLINE_NAMESPACE +// OTABSL_OPTION_INLINE_NAMESPACE_NAME +// +// These options controls whether all entities in the absl namespace are +// contained within an inner inline namespace. This does not affect the +// user-visible API of Abseil, but it changes the mangled names of all symbols. +// +// This can be useful as a version tag if you are distributing Abseil in +// precompiled form. This will prevent a binary library build of Abseil with +// one inline namespace being used with headers configured with a different +// inline namespace name. Binary packagers are reminded that Abseil does not +// guarantee any ABI stability in Abseil, so any update of Abseil or +// configuration change in such a binary package should be combined with a +// new, unique value for the inline namespace name. +// +// A value of 0 means not to use inline namespaces. +// +// A value of 1 means to use an inline namespace with the given name inside +// namespace absl. If this is set, OTABSL_OPTION_INLINE_NAMESPACE_NAME must also +// be changed to a new, unique identifier name. In particular "head" is not +// allowed. + +#define OTABSL_OPTION_USE_INLINE_NAMESPACE 1 +#define OTABSL_OPTION_INLINE_NAMESPACE_NAME otel_v1 + +#endif // OTABSL_BASE_OPTIONS_H_ diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/policy_checks.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/policy_checks.h new file mode 100644 index 000000000..02bdda4b6 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/policy_checks.h @@ -0,0 +1,113 @@ +// 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. Note that Visual Studio has not +// advanced __cplusplus despite being good enough for our purposes, so +// so we exempt it from the check. +#if defined(__cplusplus) && !defined(_MSC_VER) +#if __cplusplus < 201103L +#error "C++ versions less than C++11 are not supported." +#endif +#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_ diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/port.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/port.h new file mode 100644 index 000000000..aaba551b5 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/base/port.h @@ -0,0 +1,26 @@ +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This files is a forwarding header for other headers containing various +// portability macros and functions. +// This file is used for both C and C++! + +#ifndef OTABSL_BASE_PORT_H_ +#define OTABSL_BASE_PORT_H_ + +#include "attributes.h" +#include "config.h" +#include "optimization.h" + +#endif // OTABSL_BASE_PORT_H_ diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/meta/type_traits.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/meta/type_traits.h new file mode 100644 index 000000000..74ae82a6b --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/meta/type_traits.h @@ -0,0 +1,772 @@ +// +// 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::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::is_trivially_destructible<T>::value> {}; + +template <class T> +struct IsTriviallyMoveAssignableReference : std::false_type {}; + +template <class T> +struct IsTriviallyMoveAssignableReference<T&> + : absl::is_trivially_move_assignable<T>::type {}; + +template <class T> +struct IsTriviallyMoveAssignableReference<T&&> + : absl::is_trivially_move_assignable<T>::type {}; + +template <typename... Ts> +struct VoidTImpl { + using type = void; +}; + +// This trick to retrieve a default alignment is necessary for our +// implementation of aligned_storage_t to be consistent with any implementation +// of std::aligned_storage. +template <size_t Len, typename T = std::aligned_storage<Len>> +struct default_alignment_of_aligned_storage; + +template <size_t Len, size_t Align> +struct default_alignment_of_aligned_storage<Len, + std::aligned_storage<Len, Align>> { + static constexpr size_t value = Align; +}; + +//////////////////////////////// +// 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.20 has 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 >= 1920) + +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::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 + : std::integral_constant<bool, __has_trivial_destructor(T) && + std::is_destructible<T>::value> { +#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 + : std::integral_constant<bool, __has_trivial_constructor(T) && + std::is_default_constructible<T>::value && + is_trivially_destructible<T>::value> { +#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 + : std::conditional< + std::is_object<T>::value && !std::is_array<T>::value, + type_traits_internal::IsTriviallyMoveConstructibleObject<T>, + std::is_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_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 + : std::integral_constant< + bool, __has_trivial_assign(typename std::remove_reference<T>::type) && + absl::is_copy_assignable<T>::value> { +#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. +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::is_copy_assignable<ExtentsRemoved>::value || + absl::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> {}; +} // 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 <size_t Len, size_t Align = type_traits_internal:: + default_alignment_of_aligned_storage<Len>::value> +using aligned_storage_t = typename std::aligned_storage<Len, Align>::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 __cplusplus >= 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::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::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::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::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::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::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_ diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/types/bad_variant_access.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/types/bad_variant_access.h new file mode 100644 index 000000000..9783504d2 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/types/bad_variant_access.h @@ -0,0 +1,94 @@ +// Copyright 2018 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// bad_variant_access.h +// ----------------------------------------------------------------------------- +// +// This header file defines the `absl::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::bad_variant_access` type is an exception type that is thrown in +// the following cases: +// +// * Calling `absl::get(absl::variant) with an index or type that does not +// match the currently selected alternative type +// * Calling `absl::visit on an `absl::variant` that is in the +// `variant::valueless_by_exception` state. +// +// Example: +// +// absl::variant<int, std::string> v; +// v = 1; +// try { +// absl::get<std::string>(v); +// } catch(const absl::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_ diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/types/internal/variant.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/types/internal/variant.h new file mode 100644 index 000000000..ee42da7c9 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/types/internal/variant.h @@ -0,0 +1,1646 @@ +// Copyright 2018 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Implementation details of absl/types/variant.h, pulled into a +// separate file to avoid cluttering the top of the API header with +// implementation details. + +#ifndef OTABSL_TYPES_variant_internal_H_ +#define OTABSL_TYPES_variant_internal_H_ + +#include <cassert> +#include <cstddef> +#include <cstdlib> +#include <memory> +#include <stdexcept> +#include <tuple> +#include <type_traits> + +#include "../../base/config.h" +#include "../../base/internal/identity.h" +#include "../../base/internal/inline_variable.h" +#include "../../base/internal/invoke.h" +#include "../../base/macros.h" +#include "../../base/optimization.h" +#include "../../meta/type_traits.h" +#include "../../types/bad_variant_access.h" +#include "../../utility/utility.h" + +#if !defined(OTABSL_USES_STD_VARIANT) + +namespace absl { +OTABSL_NAMESPACE_BEGIN + +template <class... Types> +class variant; + +OTABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1); + +template <class T> +struct variant_size; + +template <std::size_t I, class T> +struct variant_alternative; + +namespace variant_internal { + +// NOTE: See specializations below for details. +template <std::size_t I, class T> +struct VariantAlternativeSfinae {}; + +// Requires: I < variant_size_v<T>. +// +// Value: The Ith type of Types... +template <std::size_t I, class T0, class... Tn> +struct VariantAlternativeSfinae<I, variant<T0, Tn...>> + : VariantAlternativeSfinae<I - 1, variant<Tn...>> {}; + +// Value: T0 +template <class T0, class... Ts> +struct VariantAlternativeSfinae<0, variant<T0, Ts...>> { + using type = T0; +}; + +template <std::size_t I, class T> +using VariantAlternativeSfinaeT = typename VariantAlternativeSfinae<I, T>::type; + +// NOTE: Requires T to be a reference type. +template <class T, class U> +struct GiveQualsTo; + +template <class T, class U> +struct GiveQualsTo<T&, U> { + using type = U&; +}; + +template <class T, class U> +struct GiveQualsTo<T&&, U> { + using type = U&&; +}; + +template <class T, class U> +struct GiveQualsTo<const T&, U> { + using type = const U&; +}; + +template <class T, class U> +struct GiveQualsTo<const T&&, U> { + using type = const U&&; +}; + +template <class T, class U> +struct GiveQualsTo<volatile T&, U> { + using type = volatile U&; +}; + +template <class T, class U> +struct GiveQualsTo<volatile T&&, U> { + using type = volatile U&&; +}; + +template <class T, class U> +struct GiveQualsTo<volatile const T&, U> { + using type = volatile const U&; +}; + +template <class T, class U> +struct GiveQualsTo<volatile const T&&, U> { + using type = volatile const U&&; +}; + +template <class T, class U> +using GiveQualsToT = typename GiveQualsTo<T, U>::type; + +// Convenience alias, since size_t integral_constant is used a lot in this file. +template <std::size_t I> +using SizeT = std::integral_constant<std::size_t, I>; + +using NPos = SizeT<variant_npos>; + +template <class Variant, class T, class = void> +struct IndexOfConstructedType {}; + +template <std::size_t I, class Variant> +struct VariantAccessResultImpl; + +template <std::size_t I, template <class...> class Variantemplate, class... T> +struct VariantAccessResultImpl<I, Variantemplate<T...>&> { + using type = typename absl::variant_alternative<I, variant<T...>>::type&; +}; + +template <std::size_t I, template <class...> class Variantemplate, class... T> +struct VariantAccessResultImpl<I, const Variantemplate<T...>&> { + using type = + const typename absl::variant_alternative<I, variant<T...>>::type&; +}; + +template <std::size_t I, template <class...> class Variantemplate, class... T> +struct VariantAccessResultImpl<I, Variantemplate<T...>&&> { + using type = typename absl::variant_alternative<I, variant<T...>>::type&&; +}; + +template <std::size_t I, template <class...> class Variantemplate, class... T> +struct VariantAccessResultImpl<I, const Variantemplate<T...>&&> { + using type = + const typename absl::variant_alternative<I, variant<T...>>::type&&; +}; + +template <std::size_t I, class Variant> +using VariantAccessResult = + typename VariantAccessResultImpl<I, Variant&&>::type; + +// NOTE: This is used instead of std::array to reduce instantiation overhead. +template <class T, std::size_t Size> +struct SimpleArray { + static_assert(Size != 0, ""); + T value[Size]; +}; + +template <class T> +struct AccessedType { + using type = T; +}; + +template <class T> +using AccessedTypeT = typename AccessedType<T>::type; + +template <class T, std::size_t Size> +struct AccessedType<SimpleArray<T, Size>> { + using type = AccessedTypeT<T>; +}; + +template <class T> +constexpr T AccessSimpleArray(const T& value) { + return value; +} + +template <class T, std::size_t Size, class... SizeT> +constexpr AccessedTypeT<T> AccessSimpleArray(const SimpleArray<T, Size>& table, + std::size_t head_index, + SizeT... tail_indices) { + return AccessSimpleArray(table.value[head_index], tail_indices...); +} + +// Note: Intentionally is an alias. +template <class T> +using AlwaysZero = SizeT<0>; + +template <class Op, class... Vs> +struct VisitIndicesResultImpl { + using type = absl::result_of_t<Op(AlwaysZero<Vs>...)>; +}; + +template <class Op, class... Vs> +using VisitIndicesResultT = typename VisitIndicesResultImpl<Op, Vs...>::type; + +template <class ReturnType, class FunctionObject, class EndIndices, + class BoundIndices> +struct MakeVisitationMatrix; + +template <class ReturnType, class FunctionObject, std::size_t... Indices> +constexpr ReturnType call_with_indices(FunctionObject&& function) { + static_assert( + std::is_same<ReturnType, decltype(std::declval<FunctionObject>()( + SizeT<Indices>()...))>::value, + "Not all visitation overloads have the same return type."); + return absl::forward<FunctionObject>(function)(SizeT<Indices>()...); +} + +template <class ReturnType, class FunctionObject, std::size_t... BoundIndices> +struct MakeVisitationMatrix<ReturnType, FunctionObject, index_sequence<>, + index_sequence<BoundIndices...>> { + using ResultType = ReturnType (*)(FunctionObject&&); + static constexpr ResultType Run() { + return &call_with_indices<ReturnType, FunctionObject, + (BoundIndices - 1)...>; + } +}; + +template <typename Is, std::size_t J> +struct AppendToIndexSequence; + +template <typename Is, std::size_t J> +using AppendToIndexSequenceT = typename AppendToIndexSequence<Is, J>::type; + +template <std::size_t... Is, std::size_t J> +struct AppendToIndexSequence<index_sequence<Is...>, J> { + using type = index_sequence<Is..., J>; +}; + +template <class ReturnType, class FunctionObject, class EndIndices, + class CurrIndices, class BoundIndices> +struct MakeVisitationMatrixImpl; + +template <class ReturnType, class FunctionObject, class EndIndices, + std::size_t... CurrIndices, class BoundIndices> +struct MakeVisitationMatrixImpl<ReturnType, FunctionObject, EndIndices, + index_sequence<CurrIndices...>, BoundIndices> { + using ResultType = SimpleArray< + typename MakeVisitationMatrix<ReturnType, FunctionObject, EndIndices, + index_sequence<>>::ResultType, + sizeof...(CurrIndices)>; + + static constexpr ResultType Run() { + return {{MakeVisitationMatrix< + ReturnType, FunctionObject, EndIndices, + AppendToIndexSequenceT<BoundIndices, CurrIndices>>::Run()...}}; + } +}; + +template <class ReturnType, class FunctionObject, std::size_t HeadEndIndex, + std::size_t... TailEndIndices, std::size_t... BoundIndices> +struct MakeVisitationMatrix<ReturnType, FunctionObject, + index_sequence<HeadEndIndex, TailEndIndices...>, + index_sequence<BoundIndices...>> + : MakeVisitationMatrixImpl<ReturnType, FunctionObject, + index_sequence<TailEndIndices...>, + absl::make_index_sequence<HeadEndIndex>, + index_sequence<BoundIndices...>> {}; + +struct UnreachableSwitchCase { + template <class Op> + [[noreturn]] static VisitIndicesResultT<Op, std::size_t> Run( + Op&& /*ignored*/) { +#if OTABSL_HAVE_BUILTIN(__builtin_unreachable) || \ + (defined(__GNUC__) && !defined(__clang__)) + __builtin_unreachable(); +#elif defined(_MSC_VER) + __assume(false); +#else + // Try to use assert of false being identified as an unreachable intrinsic. + // NOTE: We use assert directly to increase chances of exploiting an assume + // intrinsic. + assert(false); // NOLINT + + // Hack to silence potential no return warning -- cause an infinite loop. + return Run(absl::forward<Op>(op)); +#endif // Checks for __builtin_unreachable + } +}; + +template <class Op, std::size_t I> +struct ReachableSwitchCase { + static VisitIndicesResultT<Op, std::size_t> Run(Op&& op) { + return absl::OTABSL_OPTION_INLINE_NAMESPACE_NAME::base_internal::Invoke(absl::forward<Op>(op), SizeT<I>()); + } +}; + +// The number 33 is just a guess at a reasonable maximum to our switch. It is +// not based on any analysis. The reason it is a power of 2 plus 1 instead of a +// power of 2 is because the number was picked to correspond to a power of 2 +// amount of "normal" alternatives, plus one for the possibility of the user +// providing "monostate" in addition to the more natural alternatives. +OTABSL_INTERNAL_INLINE_CONSTEXPR(std::size_t, MaxUnrolledVisitCases, 33); + +// Note: The default-definition is for unreachable cases. +template <bool IsReachable> +struct PickCaseImpl { + template <class Op, std::size_t I> + using Apply = UnreachableSwitchCase; +}; + +template <> +struct PickCaseImpl</*IsReachable =*/true> { + template <class Op, std::size_t I> + using Apply = ReachableSwitchCase<Op, I>; +}; + +// Note: This form of dance with template aliases is to make sure that we +// instantiate a number of templates proportional to the number of variant +// alternatives rather than a number of templates proportional to our +// maximum unrolled amount of visitation cases (aliases are effectively +// "free" whereas other template instantiations are costly). +template <class Op, std::size_t I, std::size_t EndIndex> +using PickCase = typename PickCaseImpl<(I < EndIndex)>::template Apply<Op, I>; + +template <class ReturnType> +[[noreturn]] ReturnType TypedThrowBadVariantAccess() { + absl::variant_internal::ThrowBadVariantAccess(); +} + +// Given N variant sizes, determine the number of cases there would need to be +// in a single switch-statement that would cover every possibility in the +// corresponding N-ary visit operation. +template <std::size_t... NumAlternatives> +struct NumCasesOfSwitch; + +template <std::size_t HeadNumAlternatives, std::size_t... TailNumAlternatives> +struct NumCasesOfSwitch<HeadNumAlternatives, TailNumAlternatives...> { + static constexpr std::size_t value = + (HeadNumAlternatives + 1) * + NumCasesOfSwitch<TailNumAlternatives...>::value; +}; + +template <> +struct NumCasesOfSwitch<> { + static constexpr std::size_t value = 1; +}; + +// A switch statement optimizes better than the table of function pointers. +template <std::size_t EndIndex> +struct VisitIndicesSwitch { + static_assert(EndIndex <= MaxUnrolledVisitCases, + "Maximum unrolled switch size exceeded."); + + template <class Op> + static VisitIndicesResultT<Op, std::size_t> Run(Op&& op, std::size_t i) { + switch (i) { + case 0: + return PickCase<Op, 0, EndIndex>::Run(absl::forward<Op>(op)); + case 1: + return PickCase<Op, 1, EndIndex>::Run(absl::forward<Op>(op)); + case 2: + return PickCase<Op, 2, EndIndex>::Run(absl::forward<Op>(op)); + case 3: + return PickCase<Op, 3, EndIndex>::Run(absl::forward<Op>(op)); + case 4: + return PickCase<Op, 4, EndIndex>::Run(absl::forward<Op>(op)); + case 5: + return PickCase<Op, 5, EndIndex>::Run(absl::forward<Op>(op)); + case 6: + return PickCase<Op, 6, EndIndex>::Run(absl::forward<Op>(op)); + case 7: + return PickCase<Op, 7, EndIndex>::Run(absl::forward<Op>(op)); + case 8: + return PickCase<Op, 8, EndIndex>::Run(absl::forward<Op>(op)); + case 9: + return PickCase<Op, 9, EndIndex>::Run(absl::forward<Op>(op)); + case 10: + return PickCase<Op, 10, EndIndex>::Run(absl::forward<Op>(op)); + case 11: + return PickCase<Op, 11, EndIndex>::Run(absl::forward<Op>(op)); + case 12: + return PickCase<Op, 12, EndIndex>::Run(absl::forward<Op>(op)); + case 13: + return PickCase<Op, 13, EndIndex>::Run(absl::forward<Op>(op)); + case 14: + return PickCase<Op, 14, EndIndex>::Run(absl::forward<Op>(op)); + case 15: + return PickCase<Op, 15, EndIndex>::Run(absl::forward<Op>(op)); + case 16: + return PickCase<Op, 16, EndIndex>::Run(absl::forward<Op>(op)); + case 17: + return PickCase<Op, 17, EndIndex>::Run(absl::forward<Op>(op)); + case 18: + return PickCase<Op, 18, EndIndex>::Run(absl::forward<Op>(op)); + case 19: + return PickCase<Op, 19, EndIndex>::Run(absl::forward<Op>(op)); + case 20: + return PickCase<Op, 20, EndIndex>::Run(absl::forward<Op>(op)); + case 21: + return PickCase<Op, 21, EndIndex>::Run(absl::forward<Op>(op)); + case 22: + return PickCase<Op, 22, EndIndex>::Run(absl::forward<Op>(op)); + case 23: + return PickCase<Op, 23, EndIndex>::Run(absl::forward<Op>(op)); + case 24: + return PickCase<Op, 24, EndIndex>::Run(absl::forward<Op>(op)); + case 25: + return PickCase<Op, 25, EndIndex>::Run(absl::forward<Op>(op)); + case 26: + return PickCase<Op, 26, EndIndex>::Run(absl::forward<Op>(op)); + case 27: + return PickCase<Op, 27, EndIndex>::Run(absl::forward<Op>(op)); + case 28: + return PickCase<Op, 28, EndIndex>::Run(absl::forward<Op>(op)); + case 29: + return PickCase<Op, 29, EndIndex>::Run(absl::forward<Op>(op)); + case 30: + return PickCase<Op, 30, EndIndex>::Run(absl::forward<Op>(op)); + case 31: + return PickCase<Op, 31, EndIndex>::Run(absl::forward<Op>(op)); + case 32: + return PickCase<Op, 32, EndIndex>::Run(absl::forward<Op>(op)); + default: + OTABSL_ASSERT(i == variant_npos); + return absl::OTABSL_OPTION_INLINE_NAMESPACE_NAME::base_internal::Invoke(absl::forward<Op>(op), NPos()); + } + } +}; + +template <std::size_t... EndIndices> +struct VisitIndicesFallback { + template <class Op, class... SizeT> + static VisitIndicesResultT<Op, SizeT...> Run(Op&& op, SizeT... indices) { + return AccessSimpleArray( + MakeVisitationMatrix<VisitIndicesResultT<Op, SizeT...>, Op, + index_sequence<(EndIndices + 1)...>, + index_sequence<>>::Run(), + (indices + 1)...)(absl::forward<Op>(op)); + } +}; + +// Take an N-dimensional series of indices and convert them into a single index +// without loss of information. The purpose of this is to be able to convert an +// N-ary visit operation into a single switch statement. +template <std::size_t...> +struct FlattenIndices; + +template <std::size_t HeadSize, std::size_t... TailSize> +struct FlattenIndices<HeadSize, TailSize...> { + template<class... SizeType> + static constexpr std::size_t Run(std::size_t head, SizeType... tail) { + return head + HeadSize * FlattenIndices<TailSize...>::Run(tail...); + } +}; + +template <> +struct FlattenIndices<> { + static constexpr std::size_t Run() { return 0; } +}; + +// Take a single "flattened" index (flattened by FlattenIndices) and determine +// the value of the index of one of the logically represented dimensions. +template <std::size_t I, std::size_t IndexToGet, std::size_t HeadSize, + std::size_t... TailSize> +struct UnflattenIndex { + static constexpr std::size_t value = + UnflattenIndex<I / HeadSize, IndexToGet - 1, TailSize...>::value; +}; + +template <std::size_t I, std::size_t HeadSize, std::size_t... TailSize> +struct UnflattenIndex<I, 0, HeadSize, TailSize...> { + static constexpr std::size_t value = (I % HeadSize); +}; + +// The backend for converting an N-ary visit operation into a unary visit. +template <class IndexSequence, std::size_t... EndIndices> +struct VisitIndicesVariadicImpl; + +template <std::size_t... N, std::size_t... EndIndices> +struct VisitIndicesVariadicImpl<absl::index_sequence<N...>, EndIndices...> { + // A type that can take an N-ary function object and converts it to a unary + // function object that takes a single, flattened index, and "unflattens" it + // into its individual dimensions when forwarding to the wrapped object. + template <class Op> + struct FlattenedOp { + template <std::size_t I> + VisitIndicesResultT<Op, decltype(EndIndices)...> operator()( + SizeT<I> /*index*/) && { + return OTABSL_OPTION_INLINE_NAMESPACE_NAME::base_internal::Invoke( + absl::forward<Op>(op), + SizeT<UnflattenIndex<I, N, (EndIndices + 1)...>::value - + std::size_t{1}>()...); + } + + Op&& op; + }; + + template <class Op, class... SizeType> + static VisitIndicesResultT<Op, decltype(EndIndices)...> Run( + Op&& op, SizeType... i) { + return VisitIndicesSwitch<NumCasesOfSwitch<EndIndices...>::value>::Run( + FlattenedOp<Op>{absl::forward<Op>(op)}, + FlattenIndices<(EndIndices + std::size_t{1})...>::Run( + (i + std::size_t{1})...)); + } +}; + +template <std::size_t... EndIndices> +struct VisitIndicesVariadic + : VisitIndicesVariadicImpl<absl::make_index_sequence<sizeof...(EndIndices)>, + EndIndices...> {}; + +// This implementation will flatten N-ary visit operations into a single switch +// statement when the number of cases would be less than our maximum specified +// switch-statement size. +// TODO(calabrese) +// Based on benchmarks, determine whether the function table approach actually +// does optimize better than a chain of switch statements and possibly update +// the implementation accordingly. Also consider increasing the maximum switch +// size. +template <std::size_t... EndIndices> +struct VisitIndices + : absl::conditional_t<(NumCasesOfSwitch<EndIndices...>::value <= + MaxUnrolledVisitCases), + VisitIndicesVariadic<EndIndices...>, + VisitIndicesFallback<EndIndices...>> {}; + +template <std::size_t EndIndex> +struct VisitIndices<EndIndex> + : absl::conditional_t<(EndIndex <= MaxUnrolledVisitCases), + VisitIndicesSwitch<EndIndex>, + VisitIndicesFallback<EndIndex>> {}; + +// Suppress bogus warning on MSVC: MSVC complains that the `reinterpret_cast` +// below is returning the address of a temporary or local object. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4172) +#endif // _MSC_VER + +// TODO(calabrese) std::launder +// TODO(calabrese) constexpr +// NOTE: DO NOT REMOVE the `inline` keyword as it is necessary to work around a +// MSVC bug. See https://github.com/abseil/abseil-cpp/issues/129 for details. +template <class Self, std::size_t I> +inline VariantAccessResult<I, Self> AccessUnion(Self&& self, SizeT<I> /*i*/) { + return reinterpret_cast<VariantAccessResult<I, Self>>(self); +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +template <class T> +void DeducedDestroy(T& self) { // NOLINT + self.~T(); +} + +// NOTE: This type exists as a single entity for variant and its bases to +// befriend. It contains helper functionality that manipulates the state of the +// variant, such as the implementation of things like assignment and emplace +// operations. +struct VariantCoreAccess { + template <class VariantType> + static typename VariantType::Variant& Derived(VariantType& self) { // NOLINT + return static_cast<typename VariantType::Variant&>(self); + } + + template <class VariantType> + static const typename VariantType::Variant& Derived( + const VariantType& self) { // NOLINT + return static_cast<const typename VariantType::Variant&>(self); + } + + template <class VariantType> + static void Destroy(VariantType& self) { // NOLINT + Derived(self).destroy(); + self.index_ = absl::variant_npos; + } + + template <class Variant> + static void SetIndex(Variant& self, std::size_t i) { // NOLINT + self.index_ = i; + } + + template <class Variant> + static void InitFrom(Variant& self, Variant&& other) { // NOLINT + VisitIndices<absl::variant_size<Variant>::value>::Run( + InitFromVisitor<Variant, Variant&&>{&self, + std::forward<Variant>(other)}, + other.index()); + self.index_ = other.index(); + } + + // Access a variant alternative, assuming the index is correct. + template <std::size_t I, class Variant> + static VariantAccessResult<I, Variant> Access(Variant&& self) { + // This cast instead of invocation of AccessUnion with an rvalue is a + // workaround for msvc. Without this there is a runtime failure when dealing + // with rvalues. + // TODO(calabrese) Reduce test case and find a simpler workaround. + return static_cast<VariantAccessResult<I, Variant>>( + variant_internal::AccessUnion(self.state_, SizeT<I>())); + } + + // Access a variant alternative, throwing if the index is incorrect. + template <std::size_t I, class Variant> + static VariantAccessResult<I, Variant> CheckedAccess(Variant&& self) { + if (OTABSL_PREDICT_FALSE(self.index_ != I)) { + TypedThrowBadVariantAccess<VariantAccessResult<I, Variant>>(); + } + + return Access<I>(absl::forward<Variant>(self)); + } + + // The implementation of the move-assignment operation for a variant. + template <class VType> + struct MoveAssignVisitor { + using DerivedType = typename VType::Variant; + template <std::size_t NewIndex> + void operator()(SizeT<NewIndex> /*new_i*/) const { + if (left->index_ == NewIndex) { + Access<NewIndex>(*left) = std::move(Access<NewIndex>(*right)); + } else { + Derived(*left).template emplace<NewIndex>( + std::move(Access<NewIndex>(*right))); + } + } + + void operator()(SizeT<absl::variant_npos> /*new_i*/) const { + Destroy(*left); + } + + VType* left; + VType* right; + }; + + template <class VType> + static MoveAssignVisitor<VType> MakeMoveAssignVisitor(VType* left, + VType* other) { + return {left, other}; + } + + // The implementation of the assignment operation for a variant. + template <class VType> + struct CopyAssignVisitor { + using DerivedType = typename VType::Variant; + template <std::size_t NewIndex> + void operator()(SizeT<NewIndex> /*new_i*/) const { + using New = + typename absl::variant_alternative<NewIndex, DerivedType>::type; + + if (left->index_ == NewIndex) { + Access<NewIndex>(*left) = Access<NewIndex>(*right); + } else if (std::is_nothrow_copy_constructible<New>::value || + !std::is_nothrow_move_constructible<New>::value) { + Derived(*left).template emplace<NewIndex>(Access<NewIndex>(*right)); + } else { + Derived(*left) = DerivedType(Derived(*right)); + } + } + + void operator()(SizeT<absl::variant_npos> /*new_i*/) const { + Destroy(*left); + } + + VType* left; + const VType* right; + }; + + template <class VType> + static CopyAssignVisitor<VType> MakeCopyAssignVisitor(VType* left, + const VType& other) { + return {left, &other}; + } + + // The implementation of conversion-assignment operations for variant. + template <class Left, class QualifiedNew> + struct ConversionAssignVisitor { + using NewIndex = + variant_internal::IndexOfConstructedType<Left, QualifiedNew>; + + void operator()(SizeT<NewIndex::value> /*old_i*/ + ) const { + Access<NewIndex::value>(*left) = absl::forward<QualifiedNew>(other); + } + + template <std::size_t OldIndex> + void operator()(SizeT<OldIndex> /*old_i*/ + ) const { + using New = + typename absl::variant_alternative<NewIndex::value, Left>::type; + if (std::is_nothrow_constructible<New, QualifiedNew>::value || + !std::is_nothrow_move_constructible<New>::value) { + left->template emplace<NewIndex::value>( + absl::forward<QualifiedNew>(other)); + } else { + // the standard says "equivalent to + // operator=(variant(std::forward<T>(t)))", but we use `emplace` here + // because the variant's move assignment operator could be deleted. + left->template emplace<NewIndex::value>( + New(absl::forward<QualifiedNew>(other))); + } + } + + Left* left; + QualifiedNew&& other; + }; + + template <class Left, class QualifiedNew> + static ConversionAssignVisitor<Left, QualifiedNew> + MakeConversionAssignVisitor(Left* left, QualifiedNew&& qual) { + return {left, absl::forward<QualifiedNew>(qual)}; + } + + // Backend for operations for `emplace()` which destructs `*self` then + // construct a new alternative with `Args...`. + template <std::size_t NewIndex, class Self, class... Args> + static typename absl::variant_alternative<NewIndex, Self>::type& Replace( + Self* self, Args&&... args) { + Destroy(*self); + using New = typename absl::variant_alternative<NewIndex, Self>::type; + New* const result = ::new (static_cast<void*>(&self->state_)) + New(absl::forward<Args>(args)...); + self->index_ = NewIndex; + return *result; + } + + template <class LeftVariant, class QualifiedRightVariant> + struct InitFromVisitor { + template <std::size_t NewIndex> + void operator()(SizeT<NewIndex> /*new_i*/) const { + using Alternative = + typename variant_alternative<NewIndex, LeftVariant>::type; + ::new (static_cast<void*>(&left->state_)) Alternative( + Access<NewIndex>(std::forward<QualifiedRightVariant>(right))); + } + + void operator()(SizeT<absl::variant_npos> /*new_i*/) const { + // This space intentionally left blank. + } + LeftVariant* left; + QualifiedRightVariant&& right; + }; +}; + +template <class Expected, class... T> +struct IndexOfImpl; + +template <class Expected> +struct IndexOfImpl<Expected> { + using IndexFromEnd = SizeT<0>; + using MatchedIndexFromEnd = IndexFromEnd; + using MultipleMatches = std::false_type; +}; + +template <class Expected, class Head, class... Tail> +struct IndexOfImpl<Expected, Head, Tail...> : IndexOfImpl<Expected, Tail...> { + using IndexFromEnd = + SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>; +}; + +template <class Expected, class... Tail> +struct IndexOfImpl<Expected, Expected, Tail...> + : IndexOfImpl<Expected, Tail...> { + using IndexFromEnd = + SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>; + using MatchedIndexFromEnd = IndexFromEnd; + using MultipleMatches = std::integral_constant< + bool, IndexOfImpl<Expected, Tail...>::MatchedIndexFromEnd::value != 0>; +}; + +template <class Expected, class... Types> +struct IndexOfMeta { + using Results = IndexOfImpl<Expected, Types...>; + static_assert(!Results::MultipleMatches::value, + "Attempted to access a variant by specifying a type that " + "matches more than one alternative."); + static_assert(Results::MatchedIndexFromEnd::value != 0, + "Attempted to access a variant by specifying a type that does " + "not match any alternative."); + using type = SizeT<sizeof...(Types) - Results::MatchedIndexFromEnd::value>; +}; + +template <class Expected, class... Types> +using IndexOf = typename IndexOfMeta<Expected, Types...>::type; + +template <class Variant, class T, std::size_t CurrIndex> +struct UnambiguousIndexOfImpl; + +// Terminating case encountered once we've checked all of the alternatives +template <class T, std::size_t CurrIndex> +struct UnambiguousIndexOfImpl<variant<>, T, CurrIndex> : SizeT<CurrIndex> {}; + +// Case where T is not Head +template <class Head, class... Tail, class T, std::size_t CurrIndex> +struct UnambiguousIndexOfImpl<variant<Head, Tail...>, T, CurrIndex> + : UnambiguousIndexOfImpl<variant<Tail...>, T, CurrIndex + 1>::type {}; + +// Case where T is Head +template <class Head, class... Tail, std::size_t CurrIndex> +struct UnambiguousIndexOfImpl<variant<Head, Tail...>, Head, CurrIndex> + : SizeT<UnambiguousIndexOfImpl<variant<Tail...>, Head, 0>::value == + sizeof...(Tail) + ? CurrIndex + : CurrIndex + sizeof...(Tail) + 1> {}; + +template <class Variant, class T> +struct UnambiguousIndexOf; + +struct NoMatch { + struct type {}; +}; + +template <class... Alts, class T> +struct UnambiguousIndexOf<variant<Alts...>, T> + : std::conditional<UnambiguousIndexOfImpl<variant<Alts...>, T, 0>::value != + sizeof...(Alts), + UnambiguousIndexOfImpl<variant<Alts...>, T, 0>, + NoMatch>::type::type {}; + +template <class T, std::size_t /*Dummy*/> +using UnambiguousTypeOfImpl = T; + +template <class Variant, class T> +using UnambiguousTypeOfT = + UnambiguousTypeOfImpl<T, UnambiguousIndexOf<Variant, T>::value>; + +template <class H, class... T> +class VariantStateBase; + +// This is an implementation of the "imaginary function" that is described in +// [variant.ctor] +// It is used in order to determine which alternative to construct during +// initialization from some type T. +template <class Variant, std::size_t I = 0> +struct ImaginaryFun; + +template <std::size_t I> +struct ImaginaryFun<variant<>, I> { + static void Run() = delete; +}; + +template <class H, class... T, std::size_t I> +struct ImaginaryFun<variant<H, T...>, I> : ImaginaryFun<variant<T...>, I + 1> { + using ImaginaryFun<variant<T...>, I + 1>::Run; + + // NOTE: const& and && are used instead of by-value due to lack of guaranteed + // move elision of C++17. This may have other minor differences, but tests + // pass. + static SizeT<I> Run(const H&, SizeT<I>); + static SizeT<I> Run(H&&, SizeT<I>); +}; + +// The following metafunctions are used in constructor and assignment +// constraints. +template <class Self, class T> +struct IsNeitherSelfNorInPlace : std::true_type {}; + +template <class Self> +struct IsNeitherSelfNorInPlace<Self, Self> : std::false_type {}; + +template <class Self, class T> +struct IsNeitherSelfNorInPlace<Self, in_place_type_t<T>> : std::false_type {}; + +template <class Self, std::size_t I> +struct IsNeitherSelfNorInPlace<Self, in_place_index_t<I>> : std::false_type {}; + +template <class Variant, class T, class = void> +struct ConversionIsPossibleImpl : std::false_type {}; + +template <class Variant, class T> +struct ConversionIsPossibleImpl< + Variant, T, + void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>> + : std::true_type {}; + +template <class Variant, class T> +struct ConversionIsPossible : ConversionIsPossibleImpl<Variant, T>::type {}; + +template <class Variant, class T> +struct IndexOfConstructedType< + Variant, T, + void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>> + : decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {})) {}; + +template <std::size_t... Is> +struct ContainsVariantNPos + : absl::negation<std::is_same< // NOLINT + absl::integer_sequence<bool, 0 <= Is...>, + absl::integer_sequence<bool, Is != absl::variant_npos...>>> {}; + +template <class Op, class... QualifiedVariants> +using RawVisitResult = + absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>; + +// NOTE: The spec requires that all return-paths yield the same type and is not +// SFINAE-friendly, so we can deduce the return type by examining the first +// result. If it's not callable, then we get an error, but are compliant and +// fast to compile. +// TODO(calabrese) Possibly rewrite in a way that yields better compile errors +// at the cost of longer compile-times. +template <class Op, class... QualifiedVariants> +struct VisitResultImpl { + using type = + absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>; +}; + +// Done in two steps intentionally so that we don't cause substitution to fail. +template <class Op, class... QualifiedVariants> +using VisitResult = typename VisitResultImpl<Op, QualifiedVariants...>::type; + +template <class Op, class... QualifiedVariants> +struct PerformVisitation { + using ReturnType = VisitResult<Op, QualifiedVariants...>; + + template <std::size_t... Is> + constexpr ReturnType operator()(SizeT<Is>... indices) const { + return Run(typename ContainsVariantNPos<Is...>::type{}, + absl::index_sequence_for<QualifiedVariants...>(), indices...); + } + + template <std::size_t... TupIs, std::size_t... Is> + constexpr ReturnType Run(std::false_type /*has_valueless*/, + index_sequence<TupIs...>, SizeT<Is>...) const { + static_assert( + std::is_same<ReturnType, + absl::result_of_t<Op(VariantAccessResult< + Is, QualifiedVariants>...)>>::value, + "All visitation overloads must have the same return type."); + return absl::OTABSL_OPTION_INLINE_NAMESPACE_NAME::base_internal::Invoke( + absl::forward<Op>(op), + VariantCoreAccess::Access<Is>( + absl::forward<QualifiedVariants>(std::get<TupIs>(variant_tup)))...); + } + + template <std::size_t... TupIs, std::size_t... Is> + [[noreturn]] ReturnType Run(std::true_type /*has_valueless*/, + index_sequence<TupIs...>, SizeT<Is>...) const { + absl::variant_internal::ThrowBadVariantAccess(); + } + + // TODO(calabrese) Avoid using a tuple, which causes lots of instantiations + // Attempts using lambda variadic captures fail on current GCC. + std::tuple<QualifiedVariants&&...> variant_tup; + Op&& op; +}; + +template <class... T> +union Union; + +// We want to allow for variant<> to be trivial. For that, we need the default +// constructor to be trivial, which means we can't define it ourselves. +// Instead, we use a non-default constructor that takes NoopConstructorTag +// that doesn't affect the triviality of the types. +struct NoopConstructorTag {}; + +template <std::size_t I> +struct EmplaceTag {}; + +template <> +union Union<> { + constexpr explicit Union(NoopConstructorTag) noexcept {} +}; + +// Suppress bogus warning on MSVC: MSVC complains that Union<T...> has a defined +// deleted destructor from the `std::is_destructible` check below. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4624) +#endif // _MSC_VER + +template <class Head, class... Tail> +union Union<Head, Tail...> { + using TailUnion = Union<Tail...>; + + explicit constexpr Union(NoopConstructorTag /*tag*/) noexcept + : tail(NoopConstructorTag()) {} + + template <class... P> + explicit constexpr Union(EmplaceTag<0>, P&&... args) + : head(absl::forward<P>(args)...) {} + + template <std::size_t I, class... P> + explicit constexpr Union(EmplaceTag<I>, P&&... args) + : tail(EmplaceTag<I - 1>{}, absl::forward<P>(args)...) {} + + Head head; + TailUnion tail; +}; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +// TODO(calabrese) Just contain a Union in this union (certain configs fail). +template <class... T> +union DestructibleUnionImpl; + +template <> +union DestructibleUnionImpl<> { + constexpr explicit DestructibleUnionImpl(NoopConstructorTag) noexcept {} +}; + +template <class Head, class... Tail> +union DestructibleUnionImpl<Head, Tail...> { + using TailUnion = DestructibleUnionImpl<Tail...>; + + explicit constexpr DestructibleUnionImpl(NoopConstructorTag /*tag*/) noexcept + : tail(NoopConstructorTag()) {} + + template <class... P> + explicit constexpr DestructibleUnionImpl(EmplaceTag<0>, P&&... args) + : head(absl::forward<P>(args)...) {} + + template <std::size_t I, class... P> + explicit constexpr DestructibleUnionImpl(EmplaceTag<I>, P&&... args) + : tail(EmplaceTag<I - 1>{}, absl::forward<P>(args)...) {} + + ~DestructibleUnionImpl() {} + + Head head; + TailUnion tail; +}; + +// This union type is destructible even if one or more T are not trivially +// destructible. In the case that all T are trivially destructible, then so is +// this resultant type. +template <class... T> +using DestructibleUnion = + absl::conditional_t<std::is_destructible<Union<T...>>::value, Union<T...>, + DestructibleUnionImpl<T...>>; + +// Deepest base, containing the actual union and the discriminator +template <class H, class... T> +class VariantStateBase { + protected: + using Variant = variant<H, T...>; + + template <class LazyH = H, + class ConstructibleH = absl::enable_if_t< + std::is_default_constructible<LazyH>::value, LazyH>> + constexpr VariantStateBase() noexcept( + std::is_nothrow_default_constructible<ConstructibleH>::value) + : state_(EmplaceTag<0>()), index_(0) {} + + template <std::size_t I, class... P> + explicit constexpr VariantStateBase(EmplaceTag<I> tag, P&&... args) + : state_(tag, absl::forward<P>(args)...), index_(I) {} + + explicit constexpr VariantStateBase(NoopConstructorTag) + : state_(NoopConstructorTag()), index_(variant_npos) {} + + void destroy() {} // Does nothing (shadowed in child if non-trivial) + + DestructibleUnion<H, T...> state_; + std::size_t index_; +}; + +using absl::OTABSL_OPTION_INLINE_NAMESPACE_NAME::internal::identity; + +// OverloadSet::Overload() is a unary function which is overloaded to +// take any of the element types of the variant, by reference-to-const. +// The return type of the overload on T is identity<T>, so that you +// can statically determine which overload was called. +// +// Overload() is not defined, so it can only be called in unevaluated +// contexts. +template <typename... Ts> +struct OverloadSet; + +template <typename T, typename... Ts> +struct OverloadSet<T, Ts...> : OverloadSet<Ts...> { + using Base = OverloadSet<Ts...>; + static identity<T> Overload(const T&); + using Base::Overload; +}; + +template <> +struct OverloadSet<> { + // For any case not handled above. + static void Overload(...); +}; + +template <class T> +using LessThanResult = decltype(std::declval<T>() < std::declval<T>()); + +template <class T> +using GreaterThanResult = decltype(std::declval<T>() > std::declval<T>()); + +template <class T> +using LessThanOrEqualResult = decltype(std::declval<T>() <= std::declval<T>()); + +template <class T> +using GreaterThanOrEqualResult = + decltype(std::declval<T>() >= std::declval<T>()); + +template <class T> +using EqualResult = decltype(std::declval<T>() == std::declval<T>()); + +template <class T> +using NotEqualResult = decltype(std::declval<T>() != std::declval<T>()); + +using type_traits_internal::is_detected_convertible; + +template <class... T> +using RequireAllHaveEqualT = absl::enable_if_t< + absl::conjunction<is_detected_convertible<bool, EqualResult, T>...>::value, + bool>; + +template <class... T> +using RequireAllHaveNotEqualT = + absl::enable_if_t<absl::conjunction<is_detected_convertible< + bool, NotEqualResult, T>...>::value, + bool>; + +template <class... T> +using RequireAllHaveLessThanT = + absl::enable_if_t<absl::conjunction<is_detected_convertible< + bool, LessThanResult, T>...>::value, + bool>; + +template <class... T> +using RequireAllHaveLessThanOrEqualT = + absl::enable_if_t<absl::conjunction<is_detected_convertible< + bool, LessThanOrEqualResult, T>...>::value, + bool>; + +template <class... T> +using RequireAllHaveGreaterThanOrEqualT = + absl::enable_if_t<absl::conjunction<is_detected_convertible< + bool, GreaterThanOrEqualResult, T>...>::value, + bool>; + +template <class... T> +using RequireAllHaveGreaterThanT = + absl::enable_if_t<absl::conjunction<is_detected_convertible< + bool, GreaterThanResult, T>...>::value, + bool>; + +// Helper template containing implementations details of variant that can't go +// in the private section. For convenience, this takes the variant type as a +// single template parameter. +template <typename T> +struct VariantHelper; + +template <typename... Ts> +struct VariantHelper<variant<Ts...>> { + // Type metafunction which returns the element type selected if + // OverloadSet::Overload() is well-formed when called with argument type U. + template <typename U> + using BestMatch = decltype( + variant_internal::OverloadSet<Ts...>::Overload(std::declval<U>())); + + // Type metafunction which returns true if OverloadSet::Overload() is + // well-formed when called with argument type U. + // CanAccept can't be just an alias because there is a MSVC bug on parameter + // pack expansion involving decltype. + template <typename U> + struct CanAccept : + std::integral_constant<bool, !std::is_void<BestMatch<U>>::value> {}; + + // Type metafunction which returns true if Other is an instantiation of + // variant, and variants's converting constructor from Other will be + // well-formed. We will use this to remove constructors that would be + // ill-formed from the overload set. + template <typename Other> + struct CanConvertFrom; + + template <typename... Us> + struct CanConvertFrom<variant<Us...>> + : public absl::conjunction<CanAccept<Us>...> {}; +}; + +// A type with nontrivial copy ctor and trivial move ctor. +struct TrivialMoveOnly { + TrivialMoveOnly(TrivialMoveOnly&&) = default; +}; + +// Trait class to detect whether a type is trivially move constructible. +// A union's defaulted copy/move constructor is deleted if any variant member's +// copy/move constructor is nontrivial. +template <typename T> +struct IsTriviallyMoveConstructible: + std::is_move_constructible<Union<T, TrivialMoveOnly>> {}; + +// To guarantee triviality of all special-member functions that can be trivial, +// we use a chain of conditional bases for each one. +// The order of inheritance of bases from child to base are logically: +// +// variant +// VariantCopyAssignBase +// VariantMoveAssignBase +// VariantCopyBase +// VariantMoveBase +// VariantStateBaseDestructor +// VariantStateBase +// +// Note that there is a separate branch at each base that is dependent on +// whether or not that corresponding special-member-function can be trivial in +// the resultant variant type. + +template <class... T> +class VariantStateBaseDestructorNontrivial; + +template <class... T> +class VariantMoveBaseNontrivial; + +template <class... T> +class VariantCopyBaseNontrivial; + +template <class... T> +class VariantMoveAssignBaseNontrivial; + +template <class... T> +class VariantCopyAssignBaseNontrivial; + +// Base that is dependent on whether or not the destructor can be trivial. +template <class... T> +using VariantStateBaseDestructor = + absl::conditional_t<std::is_destructible<Union<T...>>::value, + VariantStateBase<T...>, + VariantStateBaseDestructorNontrivial<T...>>; + +// Base that is dependent on whether or not the move-constructor can be +// implicitly generated by the compiler (trivial or deleted). +// Previously we were using `std::is_move_constructible<Union<T...>>` to check +// whether all Ts have trivial move constructor, but it ran into a GCC bug: +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84866 +// So we have to use a different approach (i.e. `HasTrivialMoveConstructor`) to +// work around the bug. +template <class... T> +using VariantMoveBase = absl::conditional_t< + absl::disjunction< + absl::negation<absl::conjunction<std::is_move_constructible<T>...>>, + absl::conjunction<IsTriviallyMoveConstructible<T>...>>::value, + VariantStateBaseDestructor<T...>, VariantMoveBaseNontrivial<T...>>; + +// Base that is dependent on whether or not the copy-constructor can be trivial. +template <class... T> +using VariantCopyBase = absl::conditional_t< + absl::disjunction< + absl::negation<absl::conjunction<std::is_copy_constructible<T>...>>, + std::is_copy_constructible<Union<T...>>>::value, + VariantMoveBase<T...>, VariantCopyBaseNontrivial<T...>>; + +// Base that is dependent on whether or not the move-assign can be trivial. +template <class... T> +using VariantMoveAssignBase = absl::conditional_t< + absl::disjunction< + absl::conjunction<absl::is_move_assignable<Union<T...>>, + std::is_move_constructible<Union<T...>>, + std::is_destructible<Union<T...>>>, + absl::negation<absl::conjunction<std::is_move_constructible<T>..., + // Note: We're not qualifying this with + // absl:: because it doesn't compile + // under MSVC. + is_move_assignable<T>...>>>::value, + VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>; + +// Base that is dependent on whether or not the copy-assign can be trivial. +template <class... T> +using VariantCopyAssignBase = absl::conditional_t< + absl::disjunction< + absl::conjunction<absl::is_copy_assignable<Union<T...>>, + std::is_copy_constructible<Union<T...>>, + std::is_destructible<Union<T...>>>, + absl::negation<absl::conjunction<std::is_copy_constructible<T>..., + // Note: We're not qualifying this with + // absl:: because it doesn't compile + // under MSVC. + is_copy_assignable<T>...>>>::value, + VariantMoveAssignBase<T...>, VariantCopyAssignBaseNontrivial<T...>>; + +template <class... T> +using VariantBase = VariantCopyAssignBase<T...>; + +template <class... T> +class VariantStateBaseDestructorNontrivial : protected VariantStateBase<T...> { + private: + using Base = VariantStateBase<T...>; + + protected: + using Base::Base; + + VariantStateBaseDestructorNontrivial() = default; + VariantStateBaseDestructorNontrivial(VariantStateBaseDestructorNontrivial&&) = + default; + VariantStateBaseDestructorNontrivial( + const VariantStateBaseDestructorNontrivial&) = default; + VariantStateBaseDestructorNontrivial& operator=( + VariantStateBaseDestructorNontrivial&&) = default; + VariantStateBaseDestructorNontrivial& operator=( + const VariantStateBaseDestructorNontrivial&) = default; + + struct Destroyer { + template <std::size_t I> + void operator()(SizeT<I> i) const { + using Alternative = + typename absl::variant_alternative<I, variant<T...>>::type; + variant_internal::AccessUnion(self->state_, i).~Alternative(); + } + + void operator()(SizeT<absl::variant_npos> /*i*/) const { + // This space intentionally left blank + } + + VariantStateBaseDestructorNontrivial* self; + }; + + void destroy() { VisitIndices<sizeof...(T)>::Run(Destroyer{this}, index_); } + + ~VariantStateBaseDestructorNontrivial() { destroy(); } + + protected: + using Base::index_; + using Base::state_; +}; + +template <class... T> +class VariantMoveBaseNontrivial : protected VariantStateBaseDestructor<T...> { + private: + using Base = VariantStateBaseDestructor<T...>; + + protected: + using Base::Base; + + struct Construct { + template <std::size_t I> + void operator()(SizeT<I> i) const { + using Alternative = + typename absl::variant_alternative<I, variant<T...>>::type; + ::new (static_cast<void*>(&self->state_)) Alternative( + variant_internal::AccessUnion(absl::move(other->state_), i)); + } + + void operator()(SizeT<absl::variant_npos> /*i*/) const {} + + VariantMoveBaseNontrivial* self; + VariantMoveBaseNontrivial* other; + }; + + VariantMoveBaseNontrivial() = default; + VariantMoveBaseNontrivial(VariantMoveBaseNontrivial&& other) noexcept( + absl::conjunction<std::is_nothrow_move_constructible<T>...>::value) + : Base(NoopConstructorTag()) { + VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_); + index_ = other.index_; + } + + VariantMoveBaseNontrivial(VariantMoveBaseNontrivial const&) = default; + + VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial&&) = default; + VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial const&) = + default; + + protected: + using Base::index_; + using Base::state_; +}; + +template <class... T> +class VariantCopyBaseNontrivial : protected VariantMoveBase<T...> { + private: + using Base = VariantMoveBase<T...>; + + protected: + using Base::Base; + + VariantCopyBaseNontrivial() = default; + VariantCopyBaseNontrivial(VariantCopyBaseNontrivial&&) = default; + + struct Construct { + template <std::size_t I> + void operator()(SizeT<I> i) const { + using Alternative = + typename absl::variant_alternative<I, variant<T...>>::type; + ::new (static_cast<void*>(&self->state_)) + Alternative(variant_internal::AccessUnion(other->state_, i)); + } + + void operator()(SizeT<absl::variant_npos> /*i*/) const {} + + VariantCopyBaseNontrivial* self; + const VariantCopyBaseNontrivial* other; + }; + + VariantCopyBaseNontrivial(VariantCopyBaseNontrivial const& other) + : Base(NoopConstructorTag()) { + VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_); + index_ = other.index_; + } + + VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial&&) = default; + VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial const&) = + default; + + protected: + using Base::index_; + using Base::state_; +}; + +template <class... T> +class VariantMoveAssignBaseNontrivial : protected VariantCopyBase<T...> { + friend struct VariantCoreAccess; + + private: + using Base = VariantCopyBase<T...>; + + protected: + using Base::Base; + + VariantMoveAssignBaseNontrivial() = default; + VariantMoveAssignBaseNontrivial(VariantMoveAssignBaseNontrivial&&) = default; + VariantMoveAssignBaseNontrivial(const VariantMoveAssignBaseNontrivial&) = + default; + VariantMoveAssignBaseNontrivial& operator=( + VariantMoveAssignBaseNontrivial const&) = default; + + VariantMoveAssignBaseNontrivial& + operator=(VariantMoveAssignBaseNontrivial&& other) noexcept( + absl::conjunction<std::is_nothrow_move_constructible<T>..., + std::is_nothrow_move_assignable<T>...>::value) { + VisitIndices<sizeof...(T)>::Run( + VariantCoreAccess::MakeMoveAssignVisitor(this, &other), other.index_); + return *this; + } + + protected: + using Base::index_; + using Base::state_; +}; + +template <class... T> +class VariantCopyAssignBaseNontrivial : protected VariantMoveAssignBase<T...> { + friend struct VariantCoreAccess; + + private: + using Base = VariantMoveAssignBase<T...>; + + protected: + using Base::Base; + + VariantCopyAssignBaseNontrivial() = default; + VariantCopyAssignBaseNontrivial(VariantCopyAssignBaseNontrivial&&) = default; + VariantCopyAssignBaseNontrivial(const VariantCopyAssignBaseNontrivial&) = + default; + VariantCopyAssignBaseNontrivial& operator=( + VariantCopyAssignBaseNontrivial&&) = default; + + VariantCopyAssignBaseNontrivial& operator=( + const VariantCopyAssignBaseNontrivial& other) { + VisitIndices<sizeof...(T)>::Run( + VariantCoreAccess::MakeCopyAssignVisitor(this, other), other.index_); + return *this; + } + + protected: + using Base::index_; + using Base::state_; +}; + +//////////////////////////////////////// +// Visitors for Comparison Operations // +//////////////////////////////////////// + +template <class... Types> +struct EqualsOp { + const variant<Types...>* v; + const variant<Types...>* w; + + constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { + return true; + } + + template <std::size_t I> + constexpr bool operator()(SizeT<I> /*v_i*/) const { + return VariantCoreAccess::Access<I>(*v) == VariantCoreAccess::Access<I>(*w); + } +}; + +template <class... Types> +struct NotEqualsOp { + const variant<Types...>* v; + const variant<Types...>* w; + + constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { + return false; + } + + template <std::size_t I> + constexpr bool operator()(SizeT<I> /*v_i*/) const { + return VariantCoreAccess::Access<I>(*v) != VariantCoreAccess::Access<I>(*w); + } +}; + +template <class... Types> +struct LessThanOp { + const variant<Types...>* v; + const variant<Types...>* w; + + constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { + return false; + } + + template <std::size_t I> + constexpr bool operator()(SizeT<I> /*v_i*/) const { + return VariantCoreAccess::Access<I>(*v) < VariantCoreAccess::Access<I>(*w); + } +}; + +template <class... Types> +struct GreaterThanOp { + const variant<Types...>* v; + const variant<Types...>* w; + + constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { + return false; + } + + template <std::size_t I> + constexpr bool operator()(SizeT<I> /*v_i*/) const { + return VariantCoreAccess::Access<I>(*v) > VariantCoreAccess::Access<I>(*w); + } +}; + +template <class... Types> +struct LessThanOrEqualsOp { + const variant<Types...>* v; + const variant<Types...>* w; + + constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { + return true; + } + + template <std::size_t I> + constexpr bool operator()(SizeT<I> /*v_i*/) const { + return VariantCoreAccess::Access<I>(*v) <= VariantCoreAccess::Access<I>(*w); + } +}; + +template <class... Types> +struct GreaterThanOrEqualsOp { + const variant<Types...>* v; + const variant<Types...>* w; + + constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const { + return true; + } + + template <std::size_t I> + constexpr bool operator()(SizeT<I> /*v_i*/) const { + return VariantCoreAccess::Access<I>(*v) >= VariantCoreAccess::Access<I>(*w); + } +}; + +// Precondition: v.index() == w.index(); +template <class... Types> +struct SwapSameIndex { + variant<Types...>* v; + variant<Types...>* w; + template <std::size_t I> + void operator()(SizeT<I>) const { + type_traits_internal::Swap(VariantCoreAccess::Access<I>(*v), + VariantCoreAccess::Access<I>(*w)); + } + + void operator()(SizeT<variant_npos>) const {} +}; + +// TODO(calabrese) do this from a different namespace for proper adl usage +template <class... Types> +struct Swap { + variant<Types...>* v; + variant<Types...>* w; + + void generic_swap() const { + variant<Types...> tmp(std::move(*w)); + VariantCoreAccess::Destroy(*w); + VariantCoreAccess::InitFrom(*w, std::move(*v)); + VariantCoreAccess::Destroy(*v); + VariantCoreAccess::InitFrom(*v, std::move(tmp)); + } + + void operator()(SizeT<absl::variant_npos> /*w_i*/) const { + if (!v->valueless_by_exception()) { + generic_swap(); + } + } + + template <std::size_t Wi> + void operator()(SizeT<Wi> /*w_i*/) { + if (v->index() == Wi) { + VisitIndices<sizeof...(Types)>::Run(SwapSameIndex<Types...>{v, w}, Wi); + } else { + generic_swap(); + } + } +}; + +template <typename Variant, typename = void, typename... Ts> +struct VariantHashBase { + VariantHashBase() = delete; + VariantHashBase(const VariantHashBase&) = delete; + VariantHashBase(VariantHashBase&&) = delete; + VariantHashBase& operator=(const VariantHashBase&) = delete; + VariantHashBase& operator=(VariantHashBase&&) = delete; +}; + +struct VariantHashVisitor { + template <typename T> + size_t operator()(const T& t) { + return std::hash<T>{}(t); + } +}; + +template <typename Variant, typename... Ts> +struct VariantHashBase<Variant, + absl::enable_if_t<absl::conjunction< + type_traits_internal::IsHashable<Ts>...>::value>, + Ts...> { + using argument_type = Variant; + using result_type = size_t; + size_t operator()(const Variant& var) const { + type_traits_internal::AssertHashEnabled<Ts...>(); + if (var.valueless_by_exception()) { + return 239799884; + } + size_t result = VisitIndices<variant_size<Variant>::value>::Run( + PerformVisitation<VariantHashVisitor, const Variant&>{ + std::forward_as_tuple(var), VariantHashVisitor{}}, + var.index()); + // Combine the index and the hash result in order to distinguish + // std::variant<int, int> holding the same value as different alternative. + return result ^ var.index(); + } +}; + +} // namespace variant_internal +OTABSL_NAMESPACE_END +} // namespace absl + +#endif // !defined(OTABSL_USES_STD_VARIANT) +#endif // OTABSL_TYPES_variant_internal_H_ diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/types/variant.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/types/variant.h new file mode 100644 index 000000000..2649a29ce --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/types/variant.h @@ -0,0 +1,866 @@ +// Copyright 2018 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// variant.h +// ----------------------------------------------------------------------------- +// +// This header file defines an `absl::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::variant` type is a form of type-safe union. An `absl::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::variant` will hold the value of its first alternative type, provided +// it is default-constructible. +// +// In exceptional cases due to error, an `absl::variant` can hold no +// value (known as a "valueless by exception" state), though this is not the +// norm. +// +// As with `absl::optional`, an `absl::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::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::variant +// ----------------------------------------------------------------------------- +// +// An `absl::variant` type is a form of type-safe union. An `absl::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::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::variant<int, std::string>(); // Holds an int of value '0'. +// +// // variants are assignable. +// +// // copy assignment +// auto v1 = absl::variant<int, std::string>("abc"); +// auto v2 = absl::variant<int, std::string>(10); +// v2 = v1; // copy assign +// +// // move assignment +// auto v1 = absl::variant<int, std::string>("abc"); +// v1 = absl::variant<int, std::string>(10); +// +// // assignment through type conversion +// a = 128; // variant contains int +// a = "128"; // variant contains std::string +// +// An `absl::variant` holding a value of one of its alternative types `T` holds +// an allocation of `T` directly within the variant itself. An `absl::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::variant` values. This function is equivalent to `v.swap(w)` +// where `v` and `w` are `absl::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::enable_if_t< + absl::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::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::variant` instance. +// +// Example: +// +// auto a = absl::variant<int, std::string>; +// constexpr int num_types = +// absl::variant_size<absl::variant<int, std::string>>(); +// +// // You can also use the member constant `value`. +// constexpr int num_types = +// absl::variant_size<absl::variant<int, std::string>>::value; +// +// // `absl::variant_size` is more valuable for use in generic code: +// template <typename Variant> +// constexpr bool IsVariantMultivalue() { +// return absl::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::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::variant` variable. +// +// Example: +// +// // The type of the 0th alternative is "int". +// using alternative_type_0 +// = absl::variant_alternative<0, absl::variant<int, std::string>>::type; +// +// static_assert(std::is_same<alternative_type_0, int>::value, ""); +// +// // `absl::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::variant_alternative_t<0, absl::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::variant<int, std::string> foo = 42; +// if (absl::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::bad_variant_access`. +// +// Example: +// +// auto a = absl::variant<int, std::string>; +// +// // Get the value by type (if unique). +// int i = absl::get<int>(a); +// +// auto b = absl::variant<int, int>; +// +// // Getting the value by a type that is not unique is ill-formed. +// int j = absl::get<int>(b); // Compile Error! +// +// // Getting value by index not ambiguous and allowed. +// int k = absl::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::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::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::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::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::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::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::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::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::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::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::add_pointer_t<T> get_if(variant<Types...>* v) noexcept { + return absl::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::add_pointer_t<const T> get_if( + const variant<Types...>* v) noexcept { + return absl::get_if<variant_internal::IndexOf<T, Types...>::value>(v); +} + +// visit() +// +// Calls a provided functor on a given set of variants. `absl::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::visit()` on it. +// // Note that `GetVariant()` returns void in either case. +// absl::variant<int, std::string> foo = std::string("foo"); +// GetVariant visitor; +// absl::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::decay_t<Variants> >::value...>::Run( + variant_internal::PerformVisitation<Visitor, Variants...>{ + std::forward_as_tuple(absl::forward<Variants>(vars)...), + absl::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::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::variant` Template Definition +//------------------------------------------------------------------------------ +template <typename T0, typename... Tn> +class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> { + static_assert(absl::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::` to work around a bug + // in MSVC 2015 with inline namespace and variadic template. + static_assert(absl::conjunction<negation<std::is_array<T0> >, + negation<std::is_array<Tn> >...>::value, + "Attempted to instantiate a variant containing an array type."); + static_assert(absl::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::variant`. + template < + class T, + std::size_t I = std::enable_if< + variant_internal::IsNeitherSelfNorInPlace<variant, + absl::decay_t<T>>::value, + variant_internal::IndexOfConstructedType<variant, T>>::type::value, + class Tj = absl::variant_alternative_t<I, variant>, + absl::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::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::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::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::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::forward<Args>(args)...) {} + + // Destructors + + // Destroys the variant's currently contained value, provided that + // `absl::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::variant`. + template < + class T, + std::size_t I = std::enable_if< + !std::is_same<absl::decay_t<T>, variant>::value, + variant_internal::IndexOfConstructedType<variant, T>>::type::value, + class Tj = absl::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::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::valueless_by_exception()` is false). Requires that T is unambiguous + // in the variant. + // + // Example: + // + // absl::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::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::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::valueless_by_exception()` is false). Requires that T + // is unambiguous in the variant. + // + // Example: + // + // absl::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::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::forward<Args>(args)...); + } + + // Destroys the current value of the variant (provided that + // `absl::valueless_by_exception()` is false) and constructs a new value at + // the given index. + // + // Example: + // + // absl::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::variant_alternative_t<I, variant>, + Args...>::value>::type* = nullptr> + absl::variant_alternative_t<I, variant>& emplace(Args&&... args) { + return variant_internal::VariantCoreAccess::Replace<I>( + this, absl::forward<Args>(args)...); + } + + // Destroys the current value of the variant (provided that + // `absl::valueless_by_exception()` is false) and constructs a new value at + // the given index using an initializer list and the provided arguments. + // + // Example: + // + // absl::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::variant_alternative_t<I, variant>, + std::initializer_list<U>&, Args...>::value>::type* = nullptr> + absl::variant_alternative_t<I, variant>& emplace(std::initializer_list<U> il, + Args&&... args) { + return variant_internal::VariantCoreAccess::Replace<I>( + this, il, absl::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::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::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::monostate> { + std::size_t operator()(absl::monostate) const { return 0; } +}; + +template <class... T> // NOLINT +struct hash<absl::variant<T...>> + : absl::variant_internal::VariantHashBase<absl::variant<T...>, void, + absl::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::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::variant<name1, name2, float> InternalReq(const Req&); +// +// // name1 and name2 are convertible to name +// absl::variant<name, float> ExternalReq(const Req& req) { +// return absl::ConvertVariantTo<absl::variant<name, float>>( +// InternalReq(req)); +// } +template <typename To, typename Variant> +To ConvertVariantTo(Variant&& variant) { + return absl::visit(variant_internal::ConversionVisitor<To>{}, + std::forward<Variant>(variant)); +} + +OTABSL_NAMESPACE_END +} // namespace absl + +#endif // OTABSL_TYPES_VARIANT_H_ diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/utility/utility.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/utility/utility.h new file mode 100644 index 000000000..8c15e2b8c --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl/utility/utility.h @@ -0,0 +1,350 @@ +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This header file contains C++11 versions of standard <utility> header +// abstractions available within C++14 and C++17, and are designed to be drop-in +// replacement for code compliant with C++14 and C++17. +// +// The following abstractions are defined: +// +// * integer_sequence<T, Ints...> == std::integer_sequence<T, Ints...> +// * index_sequence<Ints...> == std::index_sequence<Ints...> +// * make_integer_sequence<T, N> == std::make_integer_sequence<T, N> +// * make_index_sequence<N> == std::make_index_sequence<N> +// * index_sequence_for<Ts...> == std::index_sequence_for<Ts...> +// * apply<Functor, Tuple> == std::apply<Functor, Tuple> +// * exchange<T> == std::exchange<T> +// * make_from_tuple<T> == std::make_from_tuple<T> +// +// This header file also provides the tag types `in_place_t`, `in_place_type_t`, +// and `in_place_index_t`, as well as the constant `in_place`, and +// `constexpr` `std::move()` and `std::forward()` implementations in C++11. +// +// References: +// +// https://en.cppreference.com/w/cpp/utility/integer_sequence +// https://en.cppreference.com/w/cpp/utility/apply +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html + +#ifndef OTABSL_UTILITY_UTILITY_H_ +#define OTABSL_UTILITY_UTILITY_H_ + +#include <cstddef> +#include <cstdlib> +#include <tuple> +#include <utility> + +#include "../base/config.h" +#include "../base/internal/inline_variable.h" +#include "../base/internal/invoke.h" +#include "../meta/type_traits.h" + +namespace absl { +OTABSL_NAMESPACE_BEGIN + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::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::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::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::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::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::remove_reference_t<T>&& move(T&& t) noexcept { + return static_cast<absl::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::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_INLINE_NAMESPACE_NAME::base_internal::Invoke( + absl::forward<Functor>(functor), + std::get<Indexes>(absl::forward<Tuple>(t))...)) { + return absl::OTABSL_OPTION_INLINE_NAMESPACE_NAME::base_internal::Invoke( + absl::forward<Functor>(functor), + std::get<Indexes>(absl::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::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::apply(&user_function1, tuple1); +// +// std::tuple<std::unique_ptr<Foo>> tuple2(absl::make_unique<Foo>()); +// // Invokes the user function that takes ownership of the unique +// // pointer. +// absl::apply(&user_function2, std::move(tuple2)); +// +// auto foo = absl::make_unique<Foo>(); +// std::tuple<Foo*, int> tuple3(foo.get(), 42); +// // Invokes the method Bar on foo with one argument, 42. +// absl::apply(&Foo::Bar, tuple3); +// +// std::tuple<int, int> tuple4(8, 9); +// // Invokes a lambda. +// absl::apply(user_lambda, tuple4); +// } +template <typename Functor, typename Tuple> +auto apply(Functor&& functor, Tuple&& t) + -> decltype(utility_internal::apply_helper( + absl::forward<Functor>(functor), absl::forward<Tuple>(t), + absl::make_index_sequence<std::tuple_size< + typename std::remove_reference<Tuple>::type>::value>{})) { + return utility_internal::apply_helper( + absl::forward<Functor>(functor), absl::forward<Tuple>(t), + absl::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::exchange` is designed to be a drop-in replacement for C++14's +// `std::exchange`. +// +// Example: +// +// Foo& operator=(Foo&& other) { +// ptr1_ = absl::exchange(other.ptr1_, nullptr); +// int1_ = absl::exchange(other.int1_, -1); +// return *this; +// } +template <typename T, typename U = T> +T exchange(T& obj, U&& new_value) { + T old_value = absl::move(obj); + obj = absl::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::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::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::make_index_sequence< + std::tuple_size<absl::decay_t<Tuple>>::value>{}); +} + +OTABSL_NAMESPACE_END +} // namespace absl + +#endif // OTABSL_UTILITY_UTILITY_H_ diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/shared_ptr.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/shared_ptr.h new file mode 100644 index 000000000..e1eac6156 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/shared_ptr.h @@ -0,0 +1,190 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef HAVE_CPP_STDLIB +# include "opentelemetry/std/shared_ptr.h" +#else +# include <cstdlib> +# include <memory> +# include <utility> + +# 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 + { + new (buffer.data) 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() { 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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/span.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/span.h new file mode 100644 index 000000000..4334f3caf --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/span.h @@ -0,0 +1,251 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +// Try to use either `std::span` or `gsl::span` +#ifdef HAVE_CPP_STDLIB +# include "opentelemetry/std/span.h" +#endif + +// Fallback to `nostd::span` if necessary +#if !defined(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; + + 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; + + 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: + // Note: matches libstdc++'s layout for std::span + // See + // https://github.com/gcc-mirror/gcc/blob/a60701e05b3878000ff9fdde1aecbc472b9dec5a/libstdc%2B%2B-v3/include/std/span#L402-L403 + size_t extent_; + T *data_; +}; +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/string_view.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/string_view.h new file mode 100644 index 000000000..b5a9e4c52 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/string_view.h @@ -0,0 +1,215 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef HAVE_CPP_STDLIB +# include "opentelemetry/std/string_view.h" +#else +# include <algorithm> +# include <cstddef> +# include <cstring> +# include <ostream> +# include <stdexcept> +# include <string> + +# 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) 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 _MSC_VER == 1900 + // Avoid SCL error in Visual Studio 2015 + (std::memcmp(lhs.data(), rhs.data(), lhs.length()) == 0); +# 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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/type_traits.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/type_traits.h new file mode 100644 index 000000000..3d212ea3e --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/type_traits.h @@ -0,0 +1,157 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef HAVE_CPP_STDLIB +# include "opentelemetry/std/type_traits.h" +#else +# include <array> +# include <type_traits> + +# include "opentelemetry/config.h" +# include "opentelemetry/nostd/detail/void.h" +# include "opentelemetry/version.h" + +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; + +/** + * 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>; + +/** + * 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 +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/unique_ptr.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/unique_ptr.h new file mode 100644 index 000000000..a97111b9d --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/unique_ptr.h @@ -0,0 +1,175 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef HAVE_CPP_STDLIB +# include "opentelemetry/std/unique_ptr.h" +#else +# 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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/utility.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/utility.h new file mode 100644 index 000000000..a22491ce0 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/utility.h @@ -0,0 +1,156 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef HAVE_CPP_STDLIB +# include "opentelemetry/std/utility.h" +#else + +# include <cstddef> +# include <initializer_list> +# include <type_traits> + +# include "opentelemetry/nostd/detail/decay.h" +# include "opentelemetry/nostd/detail/invoke.h" +# 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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/variant.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/variant.h new file mode 100644 index 000000000..b6b232699 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/nostd/variant.h @@ -0,0 +1,76 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/version.h" + +#ifdef HAVE_CPP_STDLIB +# include "opentelemetry/std/variant.h" +#else + +# ifndef HAVE_ABSEIL +// 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 +# 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 + +# ifdef HAVE_ABSEIL +# include "absl/types/variant.h" +# else +# include "./internal/absl/types/variant.h" +# endif + +# ifdef _MSC_VER +# pragma warning(pop) +# endif + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +# ifdef HAVE_ABSEIL +using absl::bad_variant_access; +# endif +using absl::get; +using absl::get_if; +using absl::holds_alternative; +using absl::monostate; +using absl::variant; +using absl::variant_alternative_t; +using absl::variant_size; +using absl::visit; +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE + +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/dynamic_library_handle.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/dynamic_library_handle.h new file mode 100644 index 000000000..9ffe076ad --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/dynamic_library_handle.h @@ -0,0 +1,20 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace plugin +{ +/** + * Manage the ownership of a dynamically loaded library. + */ +class DynamicLibraryHandle +{ +public: + virtual ~DynamicLibraryHandle() = default; +}; +} // namespace plugin +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/dynamic_load_unix.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/dynamic_load_unix.h new file mode 100644 index 000000000..bcc4bd0b8 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/dynamic_load_unix.h @@ -0,0 +1,72 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <algorithm> +#include <memory> + +#include <dlfcn.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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/dynamic_load_windows.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/dynamic_load_windows.h new file mode 100644 index 000000000..7a586b6bc --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/dynamic_load_windows.h @@ -0,0 +1,97 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <memory> + +#include "opentelemetry/plugin/detail/utility.h" +#include "opentelemetry/plugin/factory.h" +#include "opentelemetry/plugin/hook.h" +#include "opentelemetry/version.h" + +#ifndef NOMINMAX +# define NOMINMAX +#endif +#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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/loader_info.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/loader_info.h new file mode 100644 index 000000000..ca8c9f0a1 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/loader_info.h @@ -0,0 +1,24 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace plugin +{ +/** + * LoaderInfo describes the versioning of the loader. + * + * Plugins can check against this information and properly error out if they were built against an + * incompatible OpenTelemetry API. + */ +struct LoaderInfo +{ + nostd::string_view opentelemetry_version = OPENTELEMETRY_VERSION; + nostd::string_view opentelemetry_abi_version = OPENTELEMETRY_ABI_VERSION; +}; +} // namespace plugin +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/tracer_handle.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/tracer_handle.h new file mode 100644 index 000000000..559d7ddf4 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/tracer_handle.h @@ -0,0 +1,23 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/trace/tracer.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/utility.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/utility.h new file mode 100644 index 000000000..6f8dd5d46 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/detail/utility.h @@ -0,0 +1,34 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <memory> +#include <string> + +#include "opentelemetry/nostd/string_view.h" +#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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/dynamic_load.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/dynamic_load.h new file mode 100644 index 000000000..8318d534a --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/dynamic_load.h @@ -0,0 +1,27 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <string> + +#ifdef _WIN32 +# include "opentelemetry/plugin/detail/dynamic_load_windows.h" +#else +# include "opentelemetry/plugin/detail/dynamic_load_unix.h" +#endif + +#include "opentelemetry/version.h" + +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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/factory.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/factory.h new file mode 100644 index 000000000..0a285d65b --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/factory.h @@ -0,0 +1,65 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#include <memory> +#include <string> + +#include "opentelemetry/plugin/detail/utility.h" +#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<opentelemetry::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<opentelemetry::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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/hook.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/hook.h new file mode 100644 index 000000000..c06c0b324 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/hook.h @@ -0,0 +1,48 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/plugin/detail/loader_info.h" +#include "opentelemetry/plugin/factory.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 +{ +using OpenTelemetryHook = + nostd::unique_ptr<Factory::FactoryImpl> (*)(const LoaderInfo &loader_info, + nostd::unique_ptr<char[]> &error_message); +} // namespace plugin +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/tracer.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/tracer.h new file mode 100644 index 000000000..149f2a93b --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/plugin/tracer.h @@ -0,0 +1,103 @@ +// 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/dynamic_library_handle.h" +#include "opentelemetry/plugin/detail/tracer_handle.h" +#include "opentelemetry/trace/tracer.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace plugin +{ +class Span final : public trace::Span +{ +public: + Span(std::shared_ptr<trace::Tracer> &&tracer, 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, + common::SystemTimestamp timestamp, + const common::KeyValueIterable &attributes) noexcept override + { + span_->AddEvent(name, timestamp, attributes); + } + + 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)} + {} + + // 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}}; + } + + void ForceFlushWithMicroseconds(uint64_t timeout) noexcept override + { + tracer_handle_->tracer().ForceFlushWithMicroseconds(timeout); + } + + void CloseWithMicroseconds(uint64_t timeout) noexcept override + { + tracer_handle_->tracer().CloseWithMicroseconds(timeout); + } + +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 diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/shared_ptr.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/shared_ptr.h new file mode 100644 index 000000000..418d4ef71 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/shared_ptr.h @@ -0,0 +1,20 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/version.h" + +#include <memory> + +OPENTELEMETRY_BEGIN_NAMESPACE +// Standard Type aliases in nostd namespace +namespace nostd +{ + +// nostd::shared_ptr<T...> +template <class... _Types> +using shared_ptr = std::shared_ptr<_Types...>; + +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/span.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/span.h new file mode 100644 index 000000000..5fdff57fd --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/span.h @@ -0,0 +1,69 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/version.h" + +// Standard library implementation requires at least C++17 compiler. +// Older C++14 compilers may provide support for __has_include as a +// conforming extension. +#if defined __has_include +# if __has_include(<version>) // Check for __cpp_{feature} +# include <version> +# if defined(__cpp_lib_span) && __cplusplus > 201703L +# define HAVE_SPAN +# endif +# endif +# if !defined(HAVE_SPAN) +# // Check for Visual Studio span +# if defined(_MSVC_LANG) && _HAS_CXX20 +# define HAVE_SPAN +# endif +# // Check for other compiler span implementation +# if !defined(_MSVC_LANG) && __has_include(<span>) && __cplusplus > 201703L +// This works as long as compiler standard is set to C++20 +# define HAVE_SPAN +# endif +# endif +# if !__has_include(<gsl/gsl>) +# undef HAVE_GSL +# endif +#endif + +#if !defined(HAVE_SPAN) +# if defined(HAVE_GSL) +# include <type_traits> +// Guidelines Support Library provides an implementation of std::span +# include <gsl/gsl> +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +using gsl::dynamic_extent; +template <class ElementType, std::size_t Extent = gsl::dynamic_extent> +using span = gsl::span<ElementType, Extent>; +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE +# define HAVE_SPAN +# else +// No `gsl::span`, no `std::span`, fallback to `nostd::span` +# endif + +#else // HAVE_SPAN +// Using std::span (https://wg21.link/P0122R7) from Standard Library available in C++20 : +// - GCC libstdc++ 10+ +// - Clang libc++ 7 +// - MSVC Standard Library 19.26* +// - Apple Clang 10.0.0* +# include <limits> +# include <span> +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +constexpr std::size_t dynamic_extent = (std::numeric_limits<std::size_t>::max()); + +template <class ElementType, std::size_t Extent = nostd::dynamic_extent> +using span = std::span<ElementType, Extent>; +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE +#endif // of HAVE_SPAN diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/string_view.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/string_view.h new file mode 100644 index 000000000..8fd159d3a --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/string_view.h @@ -0,0 +1,25 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/version.h" + +#include "opentelemetry/std/utility.h" + +#include <cstddef> +#include <memory> +#include <string_view> +#include <utility> +#include <variant> + +OPENTELEMETRY_BEGIN_NAMESPACE +// Standard Type aliases in nostd namespace +namespace nostd +{ + +// nostd::string_view +using string_view = std::string_view; + +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/type_traits.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/type_traits.h new file mode 100644 index 000000000..66308a42a --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/type_traits.h @@ -0,0 +1,20 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/version.h" + +#include <type_traits> + +OPENTELEMETRY_BEGIN_NAMESPACE +// Standard Type aliases in nostd namespace +namespace nostd +{ + +// nostd::enable_if_t<...> +template <bool B, class T = void> +using enable_if_t = typename std::enable_if<B, T>::type; + +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/unique_ptr.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/unique_ptr.h new file mode 100644 index 000000000..f15699b67 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/unique_ptr.h @@ -0,0 +1,20 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/version.h" + +#include <memory> + +OPENTELEMETRY_BEGIN_NAMESPACE +// Standard Type aliases in nostd namespace +namespace nostd +{ + +// nostd::unique_ptr<T...> +template <class... _Types> +using unique_ptr = std::unique_ptr<_Types...>; + +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/utility.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/utility.h new file mode 100644 index 000000000..7a8233f67 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/utility.h @@ -0,0 +1,69 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/version.h" + +#include <cstddef> +#include <utility> + +OPENTELEMETRY_BEGIN_NAMESPACE +// Standard Type aliases in nostd namespace +namespace nostd +{ + +// +// Backport 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, std::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(); +} + +// +// Backport 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, std::size_t N> +std::size_t size(T (&array)[N]) noexcept +{ + return N; +} + +template <std::size_t N> +using make_index_sequence = std::make_index_sequence<N>; + +template <std::size_t... Ints> +using index_sequence = std::index_sequence<Ints...>; + +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/variant.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/variant.h new file mode 100644 index 000000000..cb696ab39 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/std/variant.h @@ -0,0 +1,230 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/version.h" + +#include <cstddef> +#include <memory> +#include <utility> +#include <variant> + +OPENTELEMETRY_BEGIN_NAMESPACE +// Standard Type aliases in nostd namespace +namespace nostd +{ +using std::get_if; +using std::monostate; +using std::variant_alternative_t; + +// nostd::variant<...> +template <class... _Types> +using variant = std::variant<_Types...>; + +template <class... _Types> +using variant_size = std::variant_size<_Types...>; + +using monostate = std::monostate; + +#if defined(__APPLE__) && defined(_LIBCPP_USE_AVAILABILITY_APPLE) +// Apple Platforms provide std::bad_variant_access only in newer versions of OS. +// To keep API compatible with any version of OS - we are providing our own +// implementation of nostd::bad_variant_access exception. +# if __EXCEPTIONS + +// nostd::bad_variant_access +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{}; +} +# endif + +# if __EXCEPTIONS +# define THROW_BAD_VARIANT_ACCESS throw_bad_variant_access() +# else +# define THROW_BAD_VARIANT_ACCESS std::terminate() +# endif + +// +// nostd::get<...> for Apple Clang +// +template <typename T, class... Types> +constexpr auto get_type = [](auto &&t) constexpr -> decltype(auto) +{ + auto v = t; + auto result = std::get_if<T>(&v); // TODO: optimize with std::forward(t) if t is not rvalue + if (result) + { + return *result; + } + THROW_BAD_VARIANT_ACCESS; + return *result; +}; + +template <std::size_t I, class... Types> +constexpr auto get_index = [](auto &&t) constexpr -> decltype(auto) +{ + auto v = t; + auto result = std::get_if<I>(&v); // TODO: optimize with std::forward(t) if t is not rvalue + if (result) + { + return *result; + } + THROW_BAD_VARIANT_ACCESS; + return *result; +}; + +template <std::size_t I, class... Types> +constexpr std::variant_alternative_t<I, std::variant<Types...>> &get(std::variant<Types...> &v) +{ + return get_index<I, Types...>(v); +}; + +template <std::size_t I, class... Types> +constexpr std::variant_alternative_t<I, std::variant<Types...>> &&get(std::variant<Types...> &&v) +{ + return get_index<I, Types...>(std::forward<decltype(v)>(v)); +}; + +template <std::size_t I, class... Types> +constexpr const std::variant_alternative_t<I, std::variant<Types...>> &get( + const std::variant<Types...> &v) +{ + return get_index<I, Types...>(v); +}; + +template <std::size_t I, class... Types> +constexpr const std::variant_alternative_t<I, std::variant<Types...>> &&get( + const std::variant<Types...> &&v) +{ + return get_index<I, Types...>(std::forward<decltype(v)>(v)); +}; + +template <class T, class... Types> +constexpr T &get(std::variant<Types...> &v) +{ + return get_type<T, Types...>(v); +}; + +template <class T, class... Types> +constexpr T /*&&*/ get(std::variant<Types...> &&v) +{ + return get_type<T, Types...>(v); +}; + +template <class T, class... Types> +constexpr const T &get(const std::variant<Types...> &v) +{ + return get_type<T, Types...>(v); +}; + +template <class T, class... Types> +constexpr const T &&get(const std::variant<Types...> &&v) +{ + return get_type<T, Types...>(std::forward<decltype(v)>(v)); +}; + +template <class _Callable, class... _Variants> +constexpr auto visit(_Callable &&_Obj, _Variants &&... _Args) +{ + // Ref: + // https://stackoverflow.com/questions/52310835/xcode-10-call-to-unavailable-function-stdvisit + return std::__variant_detail::__visitation::__variant::__visit_value(_Obj, _Args...); +}; + +#else +using std::bad_variant_access; + +template <std::size_t I, class... Types> +constexpr std::variant_alternative_t<I, std::variant<Types...>> &get(std::variant<Types...> &v) +{ + return std::get<I, Types...>(v); +}; + +template <std::size_t I, class... Types> +constexpr std::variant_alternative_t<I, std::variant<Types...>> &&get(std::variant<Types...> &&v) +{ + return std::get<I, Types...>(std::forward<decltype(v)>(v)); +}; + +template <std::size_t I, class... Types> +constexpr const std::variant_alternative_t<I, std::variant<Types...>> &get( + const std::variant<Types...> &v) +{ + return std::get<I, Types...>(v); +}; + +template <std::size_t I, class... Types> +constexpr const std::variant_alternative_t<I, std::variant<Types...>> &&get( + const std::variant<Types...> &&v) +{ + return std::get<I, Types...>(std::forward<decltype(v)>(v)); +}; + +template <class T, class... Types> +constexpr T &get(std::variant<Types...> &v) +{ + return std::get<T, Types...>(v); +}; + +template <class T, class... Types> +constexpr T &&get(std::variant<Types...> &&v) +{ + return std::get<T, Types...>(std::forward<decltype(v)>(v)); +}; + +template <class T, class... Types> +constexpr const T &get(const std::variant<Types...> &v) +{ + return std::get<T, Types...>(v); +}; + +template <class T, class... Types> +constexpr const T &&get(const std::variant<Types...> &&v) +{ + return std::get<T, Types...>(std::forward<decltype(v)>(v)); +}; + +template <class _Callable, class... _Variants> +constexpr auto visit(_Callable &&_Obj, _Variants &&... _Args) +{ + return std::visit<_Callable, _Variants...>(static_cast<_Callable &&>(_Obj), + static_cast<_Variants &&>(_Args)...); +}; + +#endif + +/* +# if _HAS_CXX20 +template <class _Ret, class _Callable, class... _Variants> +constexpr _Ret visit(_Callable &&_Obj, _Variants &&... _Args) +{ + return std::visit<_Ret, _Callable, _Variants...>( + static_cast<_Callable &&>(_Obj), + static_cast<_Variants &&>(_Args)...); +}; +# endif +*/ + +// nostd::holds_alternative +template <std::size_t I, typename... Ts> +inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept +{ + return v.index() == I; +} + +template <typename T, typename... Ts> +inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept +{ + return std::holds_alternative<T, Ts...>(v); +} + +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/canonical_code.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/canonical_code.h new file mode 100644 index 000000000..fd722891d --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/canonical_code.h @@ -0,0 +1,141 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <cstdint> + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +enum class CanonicalCode : uint8_t +{ + /** + * The operation completed successfully. + */ + OK = 0, + + /** + * The operation was cancelled (typically by the caller). + */ + CANCELLED = 1, + + /** + * Unknown error. An example of where this error may be returned is if a Status value received + * from another address space belongs to an error-space that is not known in this address space. + * Also errors raised by APIs that do not return enough error information may be converted to + * this error. + */ + UNKNOWN = 2, + + /** + * Client specified an invalid argument. Note that this differs from FAILED_PRECONDITION. + * INVALID_ARGUMENT indicates arguments that are problematic regardless of the state of the + * system (e.g., a malformed file name). + */ + INVALID_ARGUMENT = 3, + + /** + * Deadline expired before operation could complete. For operations that change the state of the + * system, this error may be returned even if the operation has completed successfully. For + * example, a successful response from a server could have been delayed long enough for the + * deadline to expire. + */ + DEADLINE_EXCEEDED = 4, + + /** + * Some requested entity (e.g., file or directory) was not found. + */ + NOT_FOUND = 5, + + /** + * Some entity that we attempted to create (e.g., file or directory) already exists. + */ + ALREADY_EXISTS = 6, + + /** + * The caller does not have permission to execute the specified operation. PERMISSION_DENIED + * must not be used for rejections caused by exhausting some resource (use RESOURCE_EXHAUSTED + * instead for those errors). PERMISSION_DENIED must not be used if the caller cannot be + * identified (use UNAUTHENTICATED instead for those errors). + */ + PERMISSION_DENIED = 7, + + /** + * Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system + * is out of space. + */ + RESOURCE_EXHAUSTED = 8, + + /** + * Operation was rejected because the system is not in a state required for the operation's + * execution. For example, directory to be deleted may be non-empty, an rmdir operation is + * applied to a non-directory, etc. + * + * A litmus test that may help a service implementor in deciding between FAILED_PRECONDITION, + * ABORTED, and UNAVAILABLE: (a) Use UNAVAILABLE if the client can retry just the failing call. + * (b) Use ABORTED if the client should retry at a higher-level (e.g., restarting a + * read-modify-write sequence). (c) Use FAILED_PRECONDITION if the client should not retry until + * the system state has been explicitly fixed. E.g., if an "rmdir" fails because the directory + * is non-empty, FAILED_PRECONDITION should be returned since the client should not retry unless + * they have first fixed up the directory by deleting files from it. + */ + FAILED_PRECONDITION = 9, + + /** + * The operation was aborted, typically due to a concurrency issue like sequencer check + * failures, transaction aborts, etc. + * + * See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. + */ + ABORTED = 10, + + /** + * Operation was attempted past the valid range. E.g., seeking or reading past end of file. + * + * Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system + * state changes. For example, a 32-bit file system will generate INVALID_ARGUMENT if asked to + * read at an offset that is not in the range [0,2^32-1], but it will generate OUT_OF_RANGE if + * asked to read from an offset past the current file size. + * + * There is a fair bit of overlap between FAILED_PRECONDITION and OUT_OF_RANGE. We recommend + * using OUT_OF_RANGE (the more specific error) when it applies so that callers who are + * iterating through a space can easily look for an OUT_OF_RANGE error to detect when they are + * done. + */ + OUT_OF_RANGE = 11, + + /** + * Operation is not implemented or not supported/enabled in this service. + */ + UNIMPLEMENTED = 12, + + /** + * Internal errors. Means some invariants expected by underlying system has been broken. If you + * see one of these errors, something is very broken. + */ + INTERNAL = 13, + + /** + * The service is currently unavailable. This is a most likely a transient condition and may be + * corrected by retrying with a backoff. + * + * See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. + */ + UNAVAILABLE = 14, + + /** + * Unrecoverable data loss or corruption. + */ + DATA_LOSS = 15, + + /** + * The request does not have valid authentication credentials for the operation. + */ + UNAUTHENTICATED = 16, +}; + +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/context.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/context.h new file mode 100644 index 000000000..963c18717 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/context.h @@ -0,0 +1,33 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/context/context.h" +#include "opentelemetry/trace/default_span.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ + +// Get Span from explicit context +inline nostd::shared_ptr<Span> GetSpan(const opentelemetry::context::Context &context) noexcept +{ + context::ContextValue span = context.GetValue(kSpanKey); + if (nostd::holds_alternative<nostd::shared_ptr<Span>>(span)) + { + return nostd::get<nostd::shared_ptr<Span>>(span); + } + return nostd::shared_ptr<Span>(new DefaultSpan(SpanContext::GetInvalid())); +} + +// Set Span into explicit context +inline context::Context SetSpan(opentelemetry::context::Context &context, + nostd::shared_ptr<Span> span) noexcept +{ + return context.SetValue(kSpanKey, span); +} + +} // namespace trace +OPENTELEMETRY_END_NAMESPACE
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/default_span.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/default_span.h new file mode 100644 index 000000000..fadd92386 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/default_span.h @@ -0,0 +1,66 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#include "opentelemetry/common/attribute_value.h" +#include "opentelemetry/trace/canonical_code.h" +#include "opentelemetry/trace/span.h" +#include "opentelemetry/trace/span_context.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ + +/** + * DefaultSpan provides a non-operational Span that propagates + * the tracer context by wrapping it inside the Span object. + */ + +class DefaultSpan : public Span +{ +public: + // Returns an invalid span. + static DefaultSpan GetInvalid() { return DefaultSpan(SpanContext::GetInvalid()); } + + trace::SpanContext GetContext() const noexcept { return span_context_; } + + bool IsRecording() const noexcept { return false; } + + void SetAttribute(nostd::string_view /* key */, + const common::AttributeValue & /* value */) noexcept + {} + + void AddEvent(nostd::string_view /* name */) noexcept {} + + void AddEvent(nostd::string_view /* name */, common::SystemTimestamp /* timestamp */) noexcept {} + + void AddEvent(nostd::string_view /* name */, + common::SystemTimestamp /* timestamp */, + const common::KeyValueIterable & /* attributes */) noexcept + {} + + void AddEvent(nostd::string_view name, const common::KeyValueIterable &attributes) noexcept + { + this->AddEvent(name, std::chrono::system_clock::now(), attributes); + } + + void SetStatus(StatusCode /* status */, nostd::string_view /* description */) noexcept {} + + void UpdateName(nostd::string_view /* name */) noexcept {} + + void End(const EndSpanOptions & /* options */ = {}) noexcept {} + + nostd::string_view ToString() const noexcept { return "DefaultSpan"; } + + DefaultSpan(SpanContext span_context) noexcept : span_context_(span_context) {} + + // movable and copiable + DefaultSpan(DefaultSpan &&spn) noexcept : span_context_(spn.GetContext()) {} + DefaultSpan(const DefaultSpan &spn) noexcept : span_context_(spn.GetContext()) {} + +private: + SpanContext span_context_; +}; + +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/experimental_semantic_conventions.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/experimental_semantic_conventions.h new file mode 100644 index 000000000..dd320e20d --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/experimental_semantic_conventions.h @@ -0,0 +1,195 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// NOTE: +// This implementation is based on the experimental specs for trace semantic convention as defined +// here: +// https://github.com/open-telemetry/opentelemetry-specification/tree/v1.0.0/specification/trace/semantic_conventions +// and MAY will change in future. + +#pragma once + +#include "opentelemetry/common/string_util.h" +#include "opentelemetry/version.h" + +#define OTEL_GET_TRACE_ATTR(name) opentelemetry::trace::attr(OTEL_CPP_CONST_HASHCODE(name)) + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ + +/** + * Stores the Constants for semantic kAttribute names outlined by the OpenTelemetry specifications. + * <see + * href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/README.md"/>. + */ +static const struct +{ + uint32_t attribute_id; + const char *attribute_key; +} attribute_ids[] = { + // The set of constants matches the specification as of this commit. + // https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/trace/semantic_conventions + // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/exceptions.md + + // General network connection attributes + {OTEL_CPP_CONST_HASHCODE(AttrNetTransport), "net.transport"}, + {OTEL_CPP_CONST_HASHCODE(AttrNetPeerIp), "net.peer.ip"}, + {OTEL_CPP_CONST_HASHCODE(AttrNetPeerPort), "net.peer.port"}, + {OTEL_CPP_CONST_HASHCODE(AttrNetPeerName), "net.peer.name"}, + {OTEL_CPP_CONST_HASHCODE(AttrNetHostIp), "net.host.ip"}, + {OTEL_CPP_CONST_HASHCODE(AttrNetHostPort), "net.host.port"}, + {OTEL_CPP_CONST_HASHCODE(AttrNetHostName), "net.host.name"}, + + // General identity attributes + {OTEL_CPP_CONST_HASHCODE(AttrEnduserId), "enduser.id"}, + {OTEL_CPP_CONST_HASHCODE(AttrEnduserRole), "enduser.role"}, + {OTEL_CPP_CONST_HASHCODE(AttrEnduserScope), "enduser.scope"}, + + // General remote service attributes + {OTEL_CPP_CONST_HASHCODE(AttrPeerService), "peer.service"}, + + // General thread attributes + {OTEL_CPP_CONST_HASHCODE(AttrThreadId), "thread.id"}, + {OTEL_CPP_CONST_HASHCODE(AttrThreadName), "thread.name"}, + + // Source Code Attributes + {OTEL_CPP_CONST_HASHCODE(AttrCodeFunction), "code.function"}, + {OTEL_CPP_CONST_HASHCODE(AttrCodeNamespace), "code.namespace"}, + {OTEL_CPP_CONST_HASHCODE(AttrCodeFilepath), "code.filepath"}, + {OTEL_CPP_CONST_HASHCODE(AttrCodeLineno), "code.lineno"}, + + // Http Span Common Attributes + {OTEL_CPP_CONST_HASHCODE(AttrHttpMethod), "http.method"}, + {OTEL_CPP_CONST_HASHCODE(AttrHttpUrl), "http.url"}, + {OTEL_CPP_CONST_HASHCODE(AttrHttpTarget), "http.target"}, + {OTEL_CPP_CONST_HASHCODE(AttrHttpHost), "http.host"}, + {OTEL_CPP_CONST_HASHCODE(AttrHttpScheme), "http.scheme"}, + {OTEL_CPP_CONST_HASHCODE(AttrHttpStatusCode), "http.status_code"}, + {OTEL_CPP_CONST_HASHCODE(AttrHttpFlavor), "http.flavor"}, + {OTEL_CPP_CONST_HASHCODE(AttrHttpUserAgent), "http.user_agent"}, + {OTEL_CPP_CONST_HASHCODE(AttrHttpRequestContentLength), "http.request_content_length"}, + {OTEL_CPP_CONST_HASHCODE(AttrHttpRequestContentLengthUncompressed), + "http.request_content_length_uncompressed"}, + {OTEL_CPP_CONST_HASHCODE(AttrHttpResponseContentLength), "http.response_content_length"}, + {OTEL_CPP_CONST_HASHCODE(AttrHttpResponseContentLengthUncompressed), + "http.response_content_length_uncompressed"}, + + // HTTP Span Client Attributes + // One of the following combinations: + // - http.url + // - http.scheme, http.host, http.target + // - http.scheme, net.peer.name, net.peer.port, http.target + // - http.scheme, net.peer.ip, net.peer.port, http.target + + // HTTP Span Server Attributes + // One of the following combinations: + // -http.scheme, http.host, http.target + // -http.scheme, http.server_name, net.host.port, http.target + // -http.scheme, net.host.name, net.host.port, http.target + // -http.url + {OTEL_CPP_CONST_HASHCODE(AttrHttpServerName), "http.server_name"}, + {OTEL_CPP_CONST_HASHCODE(AttrHttpRoute), "http.route"}, + {OTEL_CPP_CONST_HASHCODE(AttrHttpClientIp), "http.client_ip"}, + + // DB: Connection-level attributes + {OTEL_CPP_CONST_HASHCODE(AttrDbSystem), "db.system"}, // other_sql, mssql, mysql... + {OTEL_CPP_CONST_HASHCODE(AttrDbConnectionString), "db.connection_string"}, + {OTEL_CPP_CONST_HASHCODE(AttrDbUser), "db.user"}, + // DB: Connection-level attributes for specific technologies + {OTEL_CPP_CONST_HASHCODE(AttrDbMssqlInstanceName), "db.mssql.instance_name"}, + {OTEL_CPP_CONST_HASHCODE(AttrDbJdbcDriverClassname), "db.jdbc.driver_classname"}, + // DB: Call-level attributes + {OTEL_CPP_CONST_HASHCODE(AttrDbName), "db.name"}, + {OTEL_CPP_CONST_HASHCODE(AttrDbStatement), "db.statement"}, + {OTEL_CPP_CONST_HASHCODE(AttrDbOperation), "db.operation"}, + // DB: Call-level attributes for specific technologies + {OTEL_CPP_CONST_HASHCODE(AttrDbHbaseNamespace), "db.hbase.namespace"}, + {OTEL_CPP_CONST_HASHCODE(AttrDbRedisDatabaseIndex), "db.redis.database_index"}, + {OTEL_CPP_CONST_HASHCODE(AttrDbMongodbCollection), "db.mongodb.collection"}, + + // // DB: Call-level attributes for Cassandra for clarity + {OTEL_CPP_CONST_HASHCODE(AttrDbCassandraKeyspace), "db.cassandra.keyspace"}, + {OTEL_CPP_CONST_HASHCODE(AttrDbCassandraPageSize), "db.cassandra.page_size"}, + {OTEL_CPP_CONST_HASHCODE(AttrDbCassandraConsistencyLevel), "db.cassandra.consistency_level"}, + {OTEL_CPP_CONST_HASHCODE(AttrDbCassandraTable), "db.cassandra.table"}, + {OTEL_CPP_CONST_HASHCODE(AttrDbCassandraIdempotence), "db.cassandra.idempotence"}, + {OTEL_CPP_CONST_HASHCODE(AttrDbCassandraSpeculativeExecutionCount), + "db.cassandra.speculative_execution_count"}, + {OTEL_CPP_CONST_HASHCODE(AttrDbCassandraCoordinatorId), "db.cassandra.coordinator.id"}, + {OTEL_CPP_CONST_HASHCODE(AttrDbCassandraCoordinatorDC), "db.cassandra.coordinator.dc"}, + + // Common RPC attributes + {OTEL_CPP_CONST_HASHCODE(AttrRpcSystem), "rpc.system"}, + {OTEL_CPP_CONST_HASHCODE(AttrRpcService), "rpc.service"}, + {OTEL_CPP_CONST_HASHCODE(AttrRpcMethod), "rpc.method"}, + // gRPC attributes + {OTEL_CPP_CONST_HASHCODE(AttrRpcGrpcStatusCode), "rpc.grpc.status_code"}, + // JSON-RPC attributes + {OTEL_CPP_CONST_HASHCODE(AttrRpcJsonrpcVersion), "rpc.jsonrpc.version"}, + {OTEL_CPP_CONST_HASHCODE(AttrRpcJsonrpcRequestId), "rpc.jsonrpc.request_id"}, + {OTEL_CPP_CONST_HASHCODE(AttrRpcJsonrpcErrorCode), "rpc.jsonrpc.error_code"}, + {OTEL_CPP_CONST_HASHCODE(AttrRpcJsonrpcErrorMessage), "rpc.jsonrpc.error_message"}, + + // faas: General Attributes + {OTEL_CPP_CONST_HASHCODE(AttrFaasTrigger), "faas.trigger"}, + {OTEL_CPP_CONST_HASHCODE(AttrFaasExecution), "faas.execution"}, + // faas: incoming invocations + {OTEL_CPP_CONST_HASHCODE(AttrFaasColdStart), "faas.coldstart"}, + // faas: outgoing invocations + {OTEL_CPP_CONST_HASHCODE(AttrFaasInvokedName), "faas.invoked_name"}, + {OTEL_CPP_CONST_HASHCODE(AttrFaasInvokedProvider), "faas.invoked_provider"}, + {OTEL_CPP_CONST_HASHCODE(AttrFaasInvokedRegion), "faas.invoked_region"}, + // faas: datastore trigger + {OTEL_CPP_CONST_HASHCODE(AttrFaasDocumentCollection), "faas.document.collection"}, + {OTEL_CPP_CONST_HASHCODE(AttrFaasDocumentOperation), "faas.document.operation"}, + {OTEL_CPP_CONST_HASHCODE(AttrFaasDocumentTime), "faas.document.time"}, + {OTEL_CPP_CONST_HASHCODE(AttrFaasDocumentName), "faas.document.name"}, + // faas: timer trigger + {OTEL_CPP_CONST_HASHCODE(AttrFaasTime), "faas.time"}, + {OTEL_CPP_CONST_HASHCODE(AttrFaasCron), "faas.cron"}, + + // messaging attributes + {OTEL_CPP_CONST_HASHCODE(AttrMessagingSystem), "messaging.system"}, + {OTEL_CPP_CONST_HASHCODE(AttrMessagingDestination), "messaging.destination"}, + {OTEL_CPP_CONST_HASHCODE(AttrMessagingDestinationKind), "messaging.destination_kind"}, + {OTEL_CPP_CONST_HASHCODE(AttrMessagingTempDestination), "messaging.temp_destination"}, + {OTEL_CPP_CONST_HASHCODE(AttrMessagingProtocol), "messaging.protocol"}, + {OTEL_CPP_CONST_HASHCODE(AttrMessagingProtocolVersion), "messaging.protocol_version"}, + {OTEL_CPP_CONST_HASHCODE(AttrMessagingUrl), "messaging.url"}, + {OTEL_CPP_CONST_HASHCODE(AttrMessagingMessageId), "messaging.message_id"}, + {OTEL_CPP_CONST_HASHCODE(AttrMessagingConversationId), "messaging.conversation_id"}, + {OTEL_CPP_CONST_HASHCODE(AttrMessagingPayloadSize), "messaging.message_payload_size_bytes"}, + {OTEL_CPP_CONST_HASHCODE(AttrMessagingPayloadCompressedSize), + "messaging.message_payload_compressed_size_bytes"}, + {OTEL_CPP_CONST_HASHCODE(AttrMessagingOperation), "messaging.operation"}, + // messaging attributes specific to messaging systems + {OTEL_CPP_CONST_HASHCODE(AttrMessagingRabbitMQRoutingKey), "messaging.rabbitmq.routing_key"}, + {OTEL_CPP_CONST_HASHCODE(AttrMessagingKafkaMessageKey), "messaging.kafka.message_key"}, + {OTEL_CPP_CONST_HASHCODE(AttrMessagingKafkaConsumerGroup), "messaging.kafka.consumer_group"}, + {OTEL_CPP_CONST_HASHCODE(AttrMessagingKafkaClientId), "messaging.kafka.client_id"}, + {OTEL_CPP_CONST_HASHCODE(AttrMessagingKafkaPartition), "messaging.kafka.partition"}, + {OTEL_CPP_CONST_HASHCODE(AttrMessagingKafkaTombstone), "messaging.kafka.tombstone"}, + + // Exceptions attributes + {OTEL_CPP_CONST_HASHCODE(AttrExceptionType), "exception.type"}, + {OTEL_CPP_CONST_HASHCODE(AttrExceptionMessage), "exception.message"}, + {OTEL_CPP_CONST_HASHCODE(AttrExceptionStacktrace), "exception.stacktrace"}, + {OTEL_CPP_CONST_HASHCODE(AttrExceptionEscapted), "exception.escaped"}, +}; +// function to generate hash code for semantic conventions attributes. + +#define OTEL_CPP_TRACE_ATTRIBUTES_MAX (sizeof(attribute_ids) / sizeof(attribute_ids[0])) + +inline const char *attr(uint32_t attr) +{ + for (size_t i = 0; i < OTEL_CPP_TRACE_ATTRIBUTES_MAX; i++) + { + if (attribute_ids[i].attribute_id == attr) + return attribute_ids[i].attribute_key; + } + return ""; +} + +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/noop.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/noop.h new file mode 100644 index 000000000..e7784c4be --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/noop.h @@ -0,0 +1,120 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +// Please refer to provider.h for documentation on how to obtain a Tracer object. +// +// This file is part of the internal implementation of OpenTelemetry. Nothing in this file should be +// used directly. Please refer to span.h and tracer.h for documentation on these interfaces. + +#include "opentelemetry/context/runtime_context.h" +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/nostd/unique_ptr.h" +#include "opentelemetry/trace/span.h" +#include "opentelemetry/trace/span_context.h" +#include "opentelemetry/trace/span_context_kv_iterable.h" +#include "opentelemetry/trace/tracer.h" +#include "opentelemetry/trace/tracer_provider.h" +#include "opentelemetry/version.h" + +#include <memory> + +namespace trace_api = opentelemetry::trace; + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +/** + * No-op implementation of Span. This class should not be used directly. + */ +class NoopSpan final : public Span +{ +public: + explicit NoopSpan(const std::shared_ptr<Tracer> &tracer) noexcept + : tracer_{tracer}, span_context_{new SpanContext(false, false)} + {} + + explicit NoopSpan(const std::shared_ptr<Tracer> &tracer, + nostd::unique_ptr<SpanContext> span_context) noexcept + : tracer_{tracer}, span_context_{std::move(span_context)} + {} + + void SetAttribute(nostd::string_view /*key*/, + const common::AttributeValue & /*value*/) noexcept override + {} + + void AddEvent(nostd::string_view /*name*/) noexcept override {} + + void AddEvent(nostd::string_view /*name*/, + common::SystemTimestamp /*timestamp*/) noexcept override + {} + + void AddEvent(nostd::string_view /*name*/, + common::SystemTimestamp /*timestamp*/, + const common::KeyValueIterable & /*attributes*/) noexcept override + {} + + void SetStatus(StatusCode /*code*/, nostd::string_view /*description*/) noexcept override {} + + void UpdateName(nostd::string_view /*name*/) noexcept override {} + + void End(const EndSpanOptions & /*options*/) noexcept override {} + + bool IsRecording() const noexcept override { return false; } + + SpanContext GetContext() const noexcept override { return *span_context_.get(); } + +private: + std::shared_ptr<Tracer> tracer_; + nostd::unique_ptr<SpanContext> span_context_; +}; + +/** + * No-op implementation of Tracer. + */ +class NoopTracer final : public Tracer, public std::enable_shared_from_this<NoopTracer> +{ +public: + // Tracer + nostd::shared_ptr<Span> StartSpan(nostd::string_view /*name*/, + const common::KeyValueIterable & /*attributes*/, + const SpanContextKeyValueIterable & /*links*/, + const StartSpanOptions & /*options*/) noexcept override + { + // Don't allocate a no-op span for every StartSpan call, but use a static + // singleton for this case. + static nostd::shared_ptr<trace_api::Span> noop_span( + new trace_api::NoopSpan{this->shared_from_this()}); + + return noop_span; + } + + void ForceFlushWithMicroseconds(uint64_t /*timeout*/) noexcept override {} + + void CloseWithMicroseconds(uint64_t /*timeout*/) noexcept override {} +}; + +/** + * No-op implementation of a TracerProvider. + */ +class NoopTracerProvider final : public opentelemetry::trace::TracerProvider +{ +public: + NoopTracerProvider() noexcept + : tracer_{nostd::shared_ptr<opentelemetry::trace::NoopTracer>( + new opentelemetry::trace::NoopTracer)} + {} + + nostd::shared_ptr<opentelemetry::trace::Tracer> GetTracer( + nostd::string_view library_name, + nostd::string_view library_version, + nostd::string_view schema_url) noexcept override + { + return tracer_; + } + +private: + nostd::shared_ptr<opentelemetry::trace::Tracer> tracer_; +}; +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/propagation/b3_propagator.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/propagation/b3_propagator.h new file mode 100644 index 000000000..d5661cb2a --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/propagation/b3_propagator.h @@ -0,0 +1,190 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "detail/hex.h" +#include "detail/string.h" +#include "opentelemetry/context/propagation/text_map_propagator.h" +#include "opentelemetry/trace/context.h" +#include "opentelemetry/trace/default_span.h" + +#include <array> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +namespace propagation +{ + +static const nostd::string_view kB3CombinedHeader = "b3"; + +static const nostd::string_view kB3TraceIdHeader = "X-B3-TraceId"; +static const nostd::string_view kB3SpanIdHeader = "X-B3-SpanId"; +static const nostd::string_view kB3SampledHeader = "X-B3-Sampled"; + +/* + B3, single header: + b3: 80f198ee56343ba864fe8b2a57d3eff7-e457b5a2e4d86bd1-1-05e3ac9a4f6e3b90 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^ + 0 TraceId 31 33 SpanId 48 | 52 ParentSpanId 68 + 50 Debug flag + Multiheader version: X-B3-Sampled + X-B3-TraceId X-B3-SpanId X-B3-ParentSpanId (ignored) +*/ + +static const int kTraceIdHexStrLength = 32; +static const int kSpanIdHexStrLength = 16; + +// The B3PropagatorExtractor class provides an interface that enables extracting context from +// headers of HTTP requests. HTTP frameworks and clients can integrate with B3Propagator by +// providing the object containing the headers, and a getter function for the extraction. Based on: +// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/api-propagators.md#b3-extract + +class B3PropagatorExtractor : public opentelemetry::context::propagation::TextMapPropagator +{ +public: + // Returns the context that is stored in the HTTP header carrier. + context::Context Extract(const opentelemetry::context::propagation::TextMapCarrier &carrier, + context::Context &context) noexcept override + { + SpanContext span_context = ExtractImpl(carrier); + nostd::shared_ptr<Span> sp{new DefaultSpan(span_context)}; + return trace::SetSpan(context, sp); + } + + static TraceId TraceIdFromHex(nostd::string_view trace_id) + { + uint8_t buf[kTraceIdHexStrLength / 2]; + detail::HexToBinary(trace_id, buf, sizeof(buf)); + return TraceId(buf); + } + + static SpanId SpanIdFromHex(nostd::string_view span_id) + { + uint8_t buf[kSpanIdHexStrLength / 2]; + detail::HexToBinary(span_id, buf, sizeof(buf)); + return SpanId(buf); + } + + static TraceFlags TraceFlagsFromHex(nostd::string_view trace_flags) + { + if (trace_flags.length() != 1 || (trace_flags[0] != '1' && trace_flags[0] != 'd')) + { // check for invalid length of flags and treat 'd' as sampled + return TraceFlags(0); + } + return TraceFlags(TraceFlags::kIsSampled); + } + +private: + static SpanContext ExtractImpl(const opentelemetry::context::propagation::TextMapCarrier &carrier) + { + nostd::string_view trace_id_hex; + nostd::string_view span_id_hex; + nostd::string_view trace_flags_hex; + + // first let's try a single-header variant + auto singleB3Header = carrier.Get(kB3CombinedHeader); + if (!singleB3Header.empty()) + { + std::array<nostd::string_view, 3> fields{}; + // https://github.com/openzipkin/b3-propagation/blob/master/RATIONALE.md + if (detail::SplitString(singleB3Header, '-', fields.data(), 3) < 2) + { + return SpanContext::GetInvalid(); + } + + trace_id_hex = fields[0]; + span_id_hex = fields[1]; + trace_flags_hex = fields[2]; + } + else + { + trace_id_hex = carrier.Get(kB3TraceIdHeader); + span_id_hex = carrier.Get(kB3SpanIdHeader); + trace_flags_hex = carrier.Get(kB3SampledHeader); + } + + if (!detail::IsValidHex(trace_id_hex) || !detail::IsValidHex(span_id_hex)) + { + return SpanContext::GetInvalid(); + } + + TraceId trace_id = TraceIdFromHex(trace_id_hex); + SpanId span_id = SpanIdFromHex(span_id_hex); + + if (!trace_id.IsValid() || !span_id.IsValid()) + { + return SpanContext::GetInvalid(); + } + + return SpanContext(trace_id, span_id, TraceFlagsFromHex(trace_flags_hex), true); + } +}; + +// The B3Propagator class provides interface that enables extracting and injecting context into +// single header of HTTP Request. +class B3Propagator : public B3PropagatorExtractor +{ +public: + // Sets the context for a HTTP header carrier with self defined rules. + void Inject(opentelemetry::context::propagation::TextMapCarrier &carrier, + const context::Context &context) noexcept override + { + SpanContext span_context = trace::GetSpan(context)->GetContext(); + if (!span_context.IsValid()) + { + return; + } + + char trace_identity[kTraceIdHexStrLength + kSpanIdHexStrLength + 3]; + static_assert(sizeof(trace_identity) == 51, "b3 trace identity buffer size mismatch"); + span_context.trace_id().ToLowerBase16(nostd::span<char, 2 * TraceId::kSize>{ + &trace_identity[0], static_cast<std::size_t>(kTraceIdHexStrLength)}); + trace_identity[kTraceIdHexStrLength] = '-'; + span_context.span_id().ToLowerBase16(nostd::span<char, 2 * SpanId::kSize>{ + &trace_identity[kTraceIdHexStrLength + 1], static_cast<std::size_t>(kSpanIdHexStrLength)}); + trace_identity[kTraceIdHexStrLength + kSpanIdHexStrLength + 1] = '-'; + trace_identity[kTraceIdHexStrLength + kSpanIdHexStrLength + 2] = + span_context.trace_flags().IsSampled() ? '1' : '0'; + + carrier.Set(kB3CombinedHeader, nostd::string_view(trace_identity, sizeof(trace_identity))); + } + + bool Fields(nostd::function_ref<bool(nostd::string_view)> callback) const noexcept override + { + return callback(kB3CombinedHeader); + } +}; + +class B3PropagatorMultiHeader : public B3PropagatorExtractor +{ +public: + void Inject(opentelemetry::context::propagation::TextMapCarrier &carrier, + const context::Context &context) noexcept override + { + SpanContext span_context = GetSpan(context)->GetContext(); + if (!span_context.IsValid()) + { + return; + } + char trace_id[32]; + TraceId(span_context.trace_id()).ToLowerBase16(trace_id); + char span_id[16]; + SpanId(span_context.span_id()).ToLowerBase16(span_id); + char trace_flags[2]; + TraceFlags(span_context.trace_flags()).ToLowerBase16(trace_flags); + carrier.Set(kB3TraceIdHeader, nostd::string_view(trace_id, sizeof(trace_id))); + carrier.Set(kB3SpanIdHeader, nostd::string_view(span_id, sizeof(span_id))); + carrier.Set(kB3SampledHeader, nostd::string_view(trace_flags + 1, 1)); + } + + bool Fields(nostd::function_ref<bool(nostd::string_view)> callback) const noexcept override + { + return callback(kB3TraceIdHeader) && callback(kB3SpanIdHeader) && callback(kB3SampledHeader); + } +}; + +} // namespace propagation +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/propagation/detail/hex.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/propagation/detail/hex.h new file mode 100644 index 000000000..10a17ff51 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/propagation/detail/hex.h @@ -0,0 +1,79 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/nostd/string_view.h" + +#include <algorithm> +#include <cstring> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +namespace propagation +{ +// NOTE - code within `detail` namespace implements internal details, and not part +// of the public interface. +namespace detail +{ + +constexpr int8_t kHexDigits[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, +}; + +inline int8_t HexToInt(char c) +{ + return kHexDigits[uint8_t(c)]; +} + +inline bool IsValidHex(nostd::string_view s) +{ + return std::all_of(s.begin(), s.end(), [](char c) { return HexToInt(c) != -1; }); +} + +/** + * Converts a hexadecimal to binary format if the hex string will fit the buffer. + * Smaller hex strings are left padded with zeroes. + */ +inline bool HexToBinary(nostd::string_view hex, uint8_t *buffer, size_t buffer_size) +{ + std::memset(buffer, 0, buffer_size); + + if (hex.size() > buffer_size * 2) + { + return false; + } + + int64_t hex_size = int64_t(hex.size()); + int64_t buffer_pos = int64_t(buffer_size) - (hex_size + 1) / 2; + int64_t last_hex_pos = hex_size - 1; + + int64_t i = 0; + for (; i < last_hex_pos; i += 2) + { + buffer[buffer_pos++] = (HexToInt(hex[i]) << 4) | HexToInt(hex[i + 1]); + } + + if (i == last_hex_pos) + { + buffer[buffer_pos] = HexToInt(hex[i]); + } + + return true; +} + +} // namespace detail +} // namespace propagation +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/propagation/detail/string.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/propagation/detail/string.h new file mode 100644 index 000000000..67e934b40 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/propagation/detail/string.h @@ -0,0 +1,62 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/nostd/string_view.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +namespace propagation +{ +// NOTE - code within `detail` namespace implements internal details, and not part +// of the public interface. +namespace detail +{ + +/** + * Splits a string by separator, up to given buffer count words. + * Returns the amount of words the input was split into. + */ +inline size_t SplitString(nostd::string_view s, + char separator, + nostd::string_view *results, + size_t count) +{ + if (count == 0) + { + return count; + } + + size_t filled = 0; + size_t token_start = 0; + for (size_t i = 0; i < s.size(); i++) + { + if (s[i] != separator) + { + continue; + } + + results[filled++] = s.substr(token_start, i - token_start); + + if (filled == count) + { + return count; + } + + token_start = i + 1; + } + + if (filled < count) + { + results[filled++] = s.substr(token_start); + } + + return filled; +} + +} // namespace detail +} // namespace propagation +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/propagation/http_trace_context.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/propagation/http_trace_context.h new file mode 100644 index 000000000..9440960be --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/propagation/http_trace_context.h @@ -0,0 +1,177 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <array> +#include "detail/hex.h" +#include "detail/string.h" +#include "opentelemetry/context/propagation/text_map_propagator.h" +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/trace/context.h" +#include "opentelemetry/trace/default_span.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +namespace propagation +{ +static const nostd::string_view kTraceParent = "traceparent"; +static const nostd::string_view kTraceState = "tracestate"; +static const size_t kVersionSize = 2; +static const size_t kTraceIdSize = 32; +static const size_t kSpanIdSize = 16; +static const size_t kTraceFlagsSize = 2; +static const size_t kTraceParentSize = 55; + +// The HttpTraceContext provides methods to extract and inject +// context into headers of HTTP requests with traces. +// Example: +// HttpTraceContext().Inject(carrier, context); +// HttpTraceContext().Extract(carrier, context); + +class HttpTraceContext : public opentelemetry::context::propagation::TextMapPropagator +{ +public: + void Inject(opentelemetry::context::propagation::TextMapCarrier &carrier, + const context::Context &context) noexcept override + { + SpanContext span_context = trace::GetSpan(context)->GetContext(); + if (!span_context.IsValid()) + { + return; + } + InjectImpl(carrier, span_context); + } + + context::Context Extract(const opentelemetry::context::propagation::TextMapCarrier &carrier, + context::Context &context) noexcept override + { + SpanContext span_context = ExtractImpl(carrier); + nostd::shared_ptr<Span> sp{new DefaultSpan(span_context)}; + return trace::SetSpan(context, sp); + } + + static TraceId TraceIdFromHex(nostd::string_view trace_id) + { + uint8_t buf[kTraceIdSize / 2]; + detail::HexToBinary(trace_id, buf, sizeof(buf)); + return TraceId(buf); + } + + static SpanId SpanIdFromHex(nostd::string_view span_id) + { + uint8_t buf[kSpanIdSize / 2]; + detail::HexToBinary(span_id, buf, sizeof(buf)); + return SpanId(buf); + } + + static TraceFlags TraceFlagsFromHex(nostd::string_view trace_flags) + { + uint8_t flags; + detail::HexToBinary(trace_flags, &flags, sizeof(flags)); + return TraceFlags(flags); + } + +private: + static constexpr uint8_t kInvalidVersion = 0xFF; + + static bool IsValidVersion(nostd::string_view version_hex) + { + uint8_t version; + detail::HexToBinary(version_hex, &version, sizeof(version)); + return version != kInvalidVersion; + } + + static void InjectImpl(opentelemetry::context::propagation::TextMapCarrier &carrier, + const SpanContext &span_context) + { + char trace_parent[kTraceParentSize]; + trace_parent[0] = '0'; + trace_parent[1] = '0'; + trace_parent[2] = '-'; + span_context.trace_id().ToLowerBase16( + nostd::span<char, 2 * TraceId::kSize>{&trace_parent[3], kTraceIdSize}); + trace_parent[kTraceIdSize + 3] = '-'; + span_context.span_id().ToLowerBase16( + nostd::span<char, 2 * SpanId::kSize>{&trace_parent[kTraceIdSize + 4], kSpanIdSize}); + trace_parent[kTraceIdSize + kSpanIdSize + 4] = '-'; + span_context.trace_flags().ToLowerBase16( + nostd::span<char, 2>{&trace_parent[kTraceIdSize + kSpanIdSize + 5], 2}); + + carrier.Set(kTraceParent, nostd::string_view(trace_parent, sizeof(trace_parent))); + const auto trace_state = span_context.trace_state()->ToHeader(); + if (!trace_state.empty()) + { + carrier.Set(kTraceState, trace_state); + } + } + + static SpanContext ExtractContextFromTraceHeaders(nostd::string_view trace_parent, + nostd::string_view trace_state) + { + if (trace_parent.size() != kTraceParentSize) + { + return SpanContext::GetInvalid(); + } + + std::array<nostd::string_view, 4> fields{}; + if (detail::SplitString(trace_parent, '-', fields.data(), 4) != 4) + { + return SpanContext::GetInvalid(); + } + + nostd::string_view version_hex = fields[0]; + nostd::string_view trace_id_hex = fields[1]; + nostd::string_view span_id_hex = fields[2]; + nostd::string_view trace_flags_hex = fields[3]; + + if (version_hex.size() != kVersionSize || trace_id_hex.size() != kTraceIdSize || + span_id_hex.size() != kSpanIdSize || trace_flags_hex.size() != kTraceFlagsSize) + { + return SpanContext::GetInvalid(); + } + + if (!detail::IsValidHex(version_hex) || !detail::IsValidHex(trace_id_hex) || + !detail::IsValidHex(span_id_hex) || !detail::IsValidHex(trace_flags_hex)) + { + return SpanContext::GetInvalid(); + } + + if (!IsValidVersion(version_hex)) + { + return SpanContext::GetInvalid(); + } + + TraceId trace_id = TraceIdFromHex(trace_id_hex); + SpanId span_id = SpanIdFromHex(span_id_hex); + + if (!trace_id.IsValid() || !span_id.IsValid()) + { + return SpanContext::GetInvalid(); + } + + return SpanContext(trace_id, span_id, TraceFlagsFromHex(trace_flags_hex), true, + opentelemetry::trace::TraceState::FromHeader(trace_state)); + } + + static SpanContext ExtractImpl(const opentelemetry::context::propagation::TextMapCarrier &carrier) + { + nostd::string_view trace_parent = carrier.Get(kTraceParent); + nostd::string_view trace_state = carrier.Get(kTraceState); + if (trace_parent == "") + { + return SpanContext::GetInvalid(); + } + + return ExtractContextFromTraceHeaders(trace_parent, trace_state); + } + + bool Fields(nostd::function_ref<bool(nostd::string_view)> callback) const noexcept override + { + return (callback(kTraceParent) && callback(kTraceState)); + } +}; +} // namespace propagation +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/propagation/jaeger.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/propagation/jaeger.h new file mode 100644 index 000000000..78fc9e9c0 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/propagation/jaeger.h @@ -0,0 +1,120 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "detail/hex.h" +#include "detail/string.h" +#include "opentelemetry/context/propagation/text_map_propagator.h" +#include "opentelemetry/trace/context.h" +#include "opentelemetry/trace/default_span.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +namespace propagation +{ + +static const nostd::string_view kJaegerTraceHeader = "uber-trace-id"; + +class JaegerPropagator : public context::propagation::TextMapPropagator +{ +public: + void Inject(context::propagation::TextMapCarrier &carrier, + const context::Context &context) noexcept override + { + SpanContext span_context = trace::GetSpan(context)->GetContext(); + if (!span_context.IsValid()) + { + return; + } + + const size_t trace_id_length = 32; + const size_t span_id_length = 16; + + // trace-id(32):span-id(16):0:debug(2) + char trace_identity[trace_id_length + span_id_length + 6]; + span_context.trace_id().ToLowerBase16( + nostd::span<char, 2 * TraceId::kSize>{&trace_identity[0], trace_id_length}); + trace_identity[trace_id_length] = ':'; + span_context.span_id().ToLowerBase16( + nostd::span<char, 2 * SpanId::kSize>{&trace_identity[trace_id_length + 1], span_id_length}); + trace_identity[trace_id_length + span_id_length + 1] = ':'; + trace_identity[trace_id_length + span_id_length + 2] = '0'; + trace_identity[trace_id_length + span_id_length + 3] = ':'; + trace_identity[trace_id_length + span_id_length + 4] = '0'; + trace_identity[trace_id_length + span_id_length + 5] = span_context.IsSampled() ? '1' : '0'; + + carrier.Set(kJaegerTraceHeader, nostd::string_view(trace_identity, sizeof(trace_identity))); + } + + context::Context Extract(const context::propagation::TextMapCarrier &carrier, + context::Context &context) noexcept override + { + SpanContext span_context = ExtractImpl(carrier); + nostd::shared_ptr<Span> sp{new DefaultSpan(span_context)}; + return trace::SetSpan(context, sp); + } + + bool Fields(nostd::function_ref<bool(nostd::string_view)> callback) const noexcept override + { + return callback(kJaegerTraceHeader); + } + +private: + static constexpr uint8_t kIsSampled = 0x01; + + static TraceFlags GetTraceFlags(uint8_t jaeger_flags) + { + uint8_t sampled = jaeger_flags & kIsSampled; + return TraceFlags(sampled); + } + + static SpanContext ExtractImpl(const context::propagation::TextMapCarrier &carrier) + { + nostd::string_view trace_identity = carrier.Get(kJaegerTraceHeader); + + const size_t trace_field_count = 4; + nostd::string_view trace_fields[trace_field_count]; + + if (detail::SplitString(trace_identity, ':', trace_fields, trace_field_count) != + trace_field_count) + { + return SpanContext::GetInvalid(); + } + + nostd::string_view trace_id_hex = trace_fields[0]; + nostd::string_view span_id_hex = trace_fields[1]; + nostd::string_view flags_hex = trace_fields[3]; + + if (!detail::IsValidHex(trace_id_hex) || !detail::IsValidHex(span_id_hex) || + !detail::IsValidHex(flags_hex)) + { + return SpanContext::GetInvalid(); + } + + uint8_t trace_id[16]; + if (!detail::HexToBinary(trace_id_hex, trace_id, sizeof(trace_id))) + { + return SpanContext::GetInvalid(); + } + + uint8_t span_id[8]; + if (!detail::HexToBinary(span_id_hex, span_id, sizeof(span_id))) + { + return SpanContext::GetInvalid(); + } + + uint8_t flags; + if (!detail::HexToBinary(flags_hex, &flags, sizeof(flags))) + { + return SpanContext::GetInvalid(); + } + + return SpanContext(TraceId(trace_id), SpanId(span_id), GetTraceFlags(flags), true); + } +}; + +} // namespace propagation +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/provider.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/provider.h new file mode 100644 index 000000000..6267cbd4d --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/provider.h @@ -0,0 +1,58 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <mutex> + +#include "opentelemetry/common/spin_lock_mutex.h" +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/trace/noop.h" +#include "opentelemetry/trace/tracer_provider.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +/** + * Stores the singleton global TracerProvider. + */ +class Provider +{ +public: + /** + * Returns the singleton TracerProvider. + * + * By default, a no-op TracerProvider is returned. This will never return a + * nullptr TracerProvider. + */ + static nostd::shared_ptr<TracerProvider> GetTracerProvider() noexcept + { + std::lock_guard<common::SpinLockMutex> guard(GetLock()); + return nostd::shared_ptr<TracerProvider>(GetProvider()); + } + + /** + * Changes the singleton TracerProvider. + */ + static void SetTracerProvider(nostd::shared_ptr<TracerProvider> tp) noexcept + { + std::lock_guard<common::SpinLockMutex> guard(GetLock()); + GetProvider() = tp; + } + +private: + static nostd::shared_ptr<TracerProvider> &GetProvider() noexcept + { + static nostd::shared_ptr<TracerProvider> provider(new NoopTracerProvider); + return provider; + } + + static common::SpinLockMutex &GetLock() noexcept + { + static common::SpinLockMutex lock; + return lock; + } +}; + +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/scope.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/scope.h new file mode 100644 index 000000000..ecceba458 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/scope.h @@ -0,0 +1,37 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/context/runtime_context.h" +#include "opentelemetry/trace/span.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +/** + * Controls how long a span is active. + * + * On creation of the Scope object, the given span is set to the currently + * active span. On destruction, the given span is ended and the previously + * active span will be the currently active span again. + */ +class Scope final +{ +public: + /** + * Initialize a new scope. + * @param span the given span will be set as the currently active span. + */ + Scope(const nostd::shared_ptr<Span> &span) noexcept + : token_(context::RuntimeContext::Attach( + context::RuntimeContext::GetCurrent().SetValue(kSpanKey, span))) + {} + +private: + nostd::unique_ptr<context::Token> token_; +}; + +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span.h new file mode 100644 index 000000000..77de4050d --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span.h @@ -0,0 +1,130 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <cstdint> + +#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/unique_ptr.h" +#include "opentelemetry/trace/canonical_code.h" +#include "opentelemetry/trace/span_context.h" +#include "opentelemetry/trace/span_metadata.h" + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ + +class Tracer; + +/** + * A Span represents a single operation within a Trace. + */ +class Span +{ +public: + // Note that Spans should be created using the Tracer class. Please refer to + // tracer.h for documentation. + Span() = default; + + // The Span destructor End()s the Span, if it hasn't been ended already. + virtual ~Span() = default; + + // Not copiable or movable. + Span(const Span &) = delete; + Span(Span &&) = delete; + Span &operator=(const Span &) = delete; + Span &operator=(Span &&) = delete; + + // Sets an attribute on the Span. If the Span previously contained a mapping + // for + // the key, the old value is replaced. + virtual void SetAttribute(nostd::string_view key, + const common::AttributeValue &value) noexcept = 0; + + // Adds an event to the Span. + virtual void AddEvent(nostd::string_view name) noexcept = 0; + + // Adds an event to the Span, with a custom timestamp. + virtual void AddEvent(nostd::string_view name, common::SystemTimestamp timestamp) noexcept = 0; + + // Adds an event to the Span, with a custom timestamp, and attributes. + virtual void AddEvent(nostd::string_view name, + common::SystemTimestamp timestamp, + const common::KeyValueIterable &attributes) noexcept = 0; + + virtual void AddEvent(nostd::string_view name, + const common::KeyValueIterable &attributes) noexcept + { + this->AddEvent(name, std::chrono::system_clock::now(), attributes); + } + + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void AddEvent(nostd::string_view name, + common::SystemTimestamp timestamp, + const T &attributes) noexcept + { + this->AddEvent(name, timestamp, common::KeyValueIterableView<T>{attributes}); + } + + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + void AddEvent(nostd::string_view name, const T &attributes) noexcept + { + this->AddEvent(name, common::KeyValueIterableView<T>{attributes}); + } + + void AddEvent(nostd::string_view name, + common::SystemTimestamp timestamp, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> + attributes) noexcept + { + this->AddEvent(name, timestamp, + nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{ + attributes.begin(), attributes.end()}); + } + + void AddEvent(nostd::string_view name, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> + attributes) noexcept + { + this->AddEvent(name, std::chrono::system_clock::now(), + nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{ + attributes.begin(), attributes.end()}); + } + + // Sets the status of the span. The default status is Unset. Only the value of + // the last call will be + // recorded, and implementations are free to ignore previous calls. + virtual void SetStatus(StatusCode code, nostd::string_view description = "") noexcept = 0; + + // Updates the name of the Span. If used, this will override the name provided + // during creation. + virtual void UpdateName(nostd::string_view name) noexcept = 0; + + /** + * Mark the end of the Span. + * Only the timing of the first End call for a given Span will be recorded, + * and implementations are free to ignore all further calls. + * @param options can be used to manually define span properties like the end + * timestamp + */ + virtual void End(const trace::EndSpanOptions &options = {}) noexcept = 0; + + virtual trace::SpanContext GetContext() const noexcept = 0; + + // Returns true if this Span is recording tracing events (e.g. SetAttribute, + // AddEvent). + virtual bool IsRecording() const noexcept = 0; +}; + +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_context.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_context.h new file mode 100644 index 000000000..e19bb9900 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_context.h @@ -0,0 +1,96 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/nostd/unique_ptr.h" +#include "opentelemetry/trace/span_id.h" +#include "opentelemetry/trace/trace_flags.h" +#include "opentelemetry/trace/trace_id.h" +#include "opentelemetry/trace/trace_state.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +/* SpanContext contains the state that must propagate to child Spans and across + * process boundaries. It contains TraceId and SpanId, TraceFlags, TraceState + * and whether it was propagated from a remote parent. + */ +class SpanContext final +{ +public: + /* A temporary constructor for an invalid SpanContext. + * Trace id and span id are set to invalid (all zeros). + * + * @param sampled_flag a required parameter specifying if child spans should be + * sampled + * @param is_remote true if this context was propagated from a remote parent. + */ + SpanContext(bool sampled_flag, bool is_remote) noexcept + : trace_id_(), + span_id_(), + trace_flags_(opentelemetry::trace::TraceFlags((uint8_t)sampled_flag)), + is_remote_(is_remote), + trace_state_(TraceState::GetDefault()) + {} + + SpanContext(TraceId trace_id, + SpanId span_id, + TraceFlags trace_flags, + bool is_remote, + nostd::shared_ptr<TraceState> trace_state = TraceState::GetDefault()) noexcept + : trace_id_(trace_id), + span_id_(span_id), + trace_flags_(trace_flags), + is_remote_(is_remote), + trace_state_(trace_state) + {} + + SpanContext(const SpanContext &ctx) = default; + + // @returns whether this context is valid + bool IsValid() const noexcept { return trace_id_.IsValid() && span_id_.IsValid(); } + + // @returns the trace_flags associated with this span_context + const opentelemetry::trace::TraceFlags &trace_flags() const noexcept { return trace_flags_; } + + // @returns the trace_id associated with this span_context + const opentelemetry::trace::TraceId &trace_id() const noexcept { return trace_id_; } + + // @returns the span_id associated with this span_context + const opentelemetry::trace::SpanId &span_id() const noexcept { return span_id_; } + + // @returns the trace_state associated with this span_context + const nostd::shared_ptr<opentelemetry::trace::TraceState> trace_state() const noexcept + { + return trace_state_; + } + + /* + * @param that SpanContext for comparing. + * @return true if `that` equals the current SpanContext. + * N.B. trace_state is ignored for the comparison. + */ + bool operator==(const SpanContext &that) const noexcept + { + return trace_id() == that.trace_id() && span_id() == that.span_id() && + trace_flags() == that.trace_flags(); + } + + SpanContext &operator=(const SpanContext &ctx) = default; + + bool IsRemote() const noexcept { return is_remote_; } + + static SpanContext GetInvalid() noexcept { return SpanContext(false, false); } + + bool IsSampled() const noexcept { return trace_flags_.IsSampled(); } + +private: + opentelemetry::trace::TraceId trace_id_; + opentelemetry::trace::SpanId span_id_; + opentelemetry::trace::TraceFlags trace_flags_; + bool is_remote_; + nostd::shared_ptr<opentelemetry::trace::TraceState> trace_state_; +}; +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_context_kv_iterable.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_context_kv_iterable.h new file mode 100644 index 000000000..2cbff8d65 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_context_kv_iterable.h @@ -0,0 +1,54 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/common/attribute_value.h" +#include "opentelemetry/common/key_value_iterable_view.h" +#include "opentelemetry/nostd/function_ref.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +/** + * Supports internal iteration over a collection of SpanContext/key-value pairs. + */ +class SpanContextKeyValueIterable +{ +public: + virtual ~SpanContextKeyValueIterable() = default; + + /** + * Iterate over SpanContext/key-value pairs + * @param callback a callback to invoke for each key-value for each SpanContext. + * If the callback returns false, the iteration is aborted. + * @return true if every SpanContext/key-value pair was iterated over + */ + virtual bool ForEachKeyValue( + nostd::function_ref<bool(SpanContext, const opentelemetry::common::KeyValueIterable &)> + callback) const noexcept = 0; + /** + * @return the number of key-value pairs + */ + virtual size_t size() const noexcept = 0; +}; + +/** + * @brief Null Span context that does not carry any information. + */ +class NullSpanContext : public SpanContextKeyValueIterable +{ +public: + bool ForEachKeyValue( + nostd::function_ref<bool(SpanContext, const opentelemetry::common::KeyValueIterable &)> + /* callback */) const noexcept override + { + return true; + } + + size_t size() const noexcept override { return 0; }; +}; + +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_context_kv_iterable_view.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_context_kv_iterable_view.h new file mode 100644 index 000000000..252b4cf17 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_context_kv_iterable_view.h @@ -0,0 +1,117 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <iterator> +#include <type_traits> +#include <utility> + +#include "opentelemetry/common/key_value_iterable_view.h" +#include "opentelemetry/nostd/utility.h" +#include "opentelemetry/trace/span_context_kv_iterable.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +// NOTE - code within `detail` namespace implements internal details, and not part +// of the public interface. +namespace detail +{ +template <class T> +inline void take_span_context_kv(SpanContext, common::KeyValueIterableView<T>) +{} + +template <class T, nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> +inline void take_span_context_kv(SpanContext, T &) +{} + +inline void take_span_context_kv( + SpanContext, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>) +{} + +template <class T> +auto is_span_context_kv_iterable_impl(T iterable) + -> decltype(take_span_context_kv(std::begin(iterable)->first, std::begin(iterable)->second), + nostd::size(iterable), + std::true_type{}); + +std::false_type is_span_context_kv_iterable_impl(...); + +template <class T> +struct is_span_context_kv_iterable +{ + static const bool value = + decltype(detail::is_span_context_kv_iterable_impl(std::declval<T>()))::value; +}; +} // namespace detail + +template <class T> +class SpanContextKeyValueIterableView final : public SpanContextKeyValueIterable +{ + static_assert(detail::is_span_context_kv_iterable<T>::value, + "Must be a context/key-value iterable"); + +public: + explicit SpanContextKeyValueIterableView(const T &links) noexcept : container_{&links} {} + + bool ForEachKeyValue( + nostd::function_ref<bool(SpanContext, const opentelemetry::common::KeyValueIterable &)> + callback) const noexcept override + { + auto iter = std::begin(*container_); + auto last = std::end(*container_); + for (; iter != last; ++iter) + { + if (!this->do_callback(iter->first, iter->second, callback)) + { + return false; + } + } + return true; + } + + size_t size() const noexcept override { return nostd::size(*container_); } + +private: + const T *container_; + + bool do_callback( + SpanContext span_context, + const common::KeyValueIterable &attributes, + nostd::function_ref<bool(SpanContext, const opentelemetry::common::KeyValueIterable &)> + callback) const noexcept + { + if (!callback(span_context, attributes)) + { + return false; + } + return true; + } + + template <class U, + nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr> + bool do_callback(SpanContext span_context, + const U &attributes, + nostd::function_ref<bool(SpanContext, const common::KeyValueIterable &)> + callback) const noexcept + { + return do_callback(span_context, common::KeyValueIterableView<U>(attributes), callback); + } + + bool do_callback( + SpanContext span_context, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes, + nostd::function_ref<bool(SpanContext, const common::KeyValueIterable &)> callback) + const noexcept + { + return do_callback(span_context, + nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{ + attributes.begin(), attributes.end()}, + callback); + } +}; +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_id.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_id.h new file mode 100644 index 000000000..63d2f3689 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_id.h @@ -0,0 +1,78 @@ +// Copyright 2019, OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <cstdint> +#include <cstring> + +#include "opentelemetry/nostd/span.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ + +class SpanId final +{ +public: + // The size in bytes of the SpanId. + static constexpr int kSize = 8; + + // An invalid SpanId (all zeros). + SpanId() noexcept : rep_{0} {} + + // Creates a SpanId with the given ID. + explicit SpanId(nostd::span<const uint8_t, kSize> id) noexcept { memcpy(rep_, id.data(), kSize); } + + // Populates the buffer with the lowercase base16 representation of the ID. + void ToLowerBase16(nostd::span<char, 2 * kSize> buffer) const noexcept + { + constexpr char kHex[] = "0123456789abcdef"; + for (int i = 0; i < kSize; ++i) + { + buffer[i * 2 + 0] = kHex[(rep_[i] >> 4) & 0xF]; + buffer[i * 2 + 1] = kHex[(rep_[i] >> 0) & 0xF]; + } + } + + // Returns a nostd::span of the ID. + nostd::span<const uint8_t, kSize> Id() const noexcept + { + return nostd::span<const uint8_t, kSize>(rep_); + } + + bool operator==(const SpanId &that) const noexcept { return memcmp(rep_, that.rep_, kSize) == 0; } + + bool operator!=(const SpanId &that) const noexcept { return !(*this == that); } + + // Returns false if the SpanId is all zeros. + bool IsValid() const noexcept + { + static constexpr uint8_t kEmptyRep[kSize] = {0}; + return memcmp(rep_, kEmptyRep, kSize) != 0; + } + + // Copies the opaque SpanId data to dest. + void CopyBytesTo(nostd::span<uint8_t, kSize> dest) const noexcept + { + memcpy(dest.data(), rep_, kSize); + } + +private: + uint8_t rep_[kSize]; +}; + +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_metadata.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_metadata.h new file mode 100644 index 000000000..977329a15 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_metadata.h @@ -0,0 +1,43 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/common/timestamp.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ + +enum class SpanKind +{ + kInternal, + kServer, + kClient, + kProducer, + kConsumer, +}; + +// The key identifies the active span in the current context. +constexpr char kSpanKey[] = "active_span"; + +// StatusCode - Represents the canonical set of status codes of a finished Span. +enum class StatusCode +{ + kUnset, // default status + kOk, // Operation has completed successfully. + kError // The operation contains an error +}; + +/** + * EndSpanOptions provides options to set properties of a Span when it is + * ended. + */ +struct EndSpanOptions +{ + // Optionally sets the end time of a Span. + common::SteadyTimestamp end_steady_time; +}; + +} // namespace trace +OPENTELEMETRY_END_NAMESPACE
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_startoptions.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_startoptions.h new file mode 100644 index 000000000..688b768bd --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/span_startoptions.h @@ -0,0 +1,45 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/context/context.h" +#include "opentelemetry/trace/span_context.h" +#include "opentelemetry/trace/span_metadata.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ + +/** + * StartSpanOptions provides options to set properties of a Span at the time of + * its creation + */ +struct StartSpanOptions +{ + // Optionally sets the start time of a Span. + // + // If the start time of a Span is set, timestamps from both the system clock + // and steady clock must be provided. + // + // Timestamps from the steady clock can be used to most accurately measure a + // Span's duration, while timestamps from the system clock can be used to most + // accurately place a Span's + // time point relative to other Spans collected across a distributed system. + common::SystemTimestamp start_system_time; + common::SteadyTimestamp start_steady_time; + + // Explicitly set the parent of a Span. + // + // This defaults to an invalid span context. In this case, the Span is + // automatically parented to the currently active span. + nostd::variant<SpanContext, opentelemetry::context::Context> parent = SpanContext::GetInvalid(); + + // TODO: + // SpanContext remote_parent; + // Links + SpanKind kind = SpanKind::kInternal; +}; + +} // namespace trace +OPENTELEMETRY_END_NAMESPACE
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/trace_flags.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/trace_flags.h new file mode 100644 index 000000000..3cfbb022f --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/trace_flags.h @@ -0,0 +1,52 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <cstdint> +#include <cstring> + +#include "opentelemetry/nostd/span.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ + +// TraceFlags represents options for a Trace. These options are propagated to all child Spans +// and determine features such as whether a Span should be traced. TraceFlags +// are implemented as a bitmask. +class TraceFlags final +{ +public: + static constexpr uint8_t kIsSampled = 1; + + TraceFlags() noexcept : rep_{0} {} + + explicit TraceFlags(uint8_t flags) noexcept : rep_(flags) {} + + bool IsSampled() const noexcept { return rep_ & kIsSampled; } + + // Populates the buffer with the lowercase base16 representation of the flags. + void ToLowerBase16(nostd::span<char, 2> buffer) const noexcept + { + constexpr char kHex[] = "0123456789ABCDEF"; + buffer[0] = kHex[(rep_ >> 4) & 0xF]; + buffer[1] = kHex[(rep_ >> 0) & 0xF]; + } + + uint8_t flags() const noexcept { return rep_; } + + bool operator==(const TraceFlags &that) const noexcept { return rep_ == that.rep_; } + + bool operator!=(const TraceFlags &that) const noexcept { return !(*this == that); } + + // Copies the TraceFlags to dest. + void CopyBytesTo(nostd::span<uint8_t, 1> dest) const noexcept { dest[0] = rep_; } + +private: + uint8_t rep_; +}; + +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/trace_id.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/trace_id.h new file mode 100644 index 000000000..3a262c7a6 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/trace_id.h @@ -0,0 +1,72 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <cstdint> +#include <cstring> + +#include "opentelemetry/nostd/span.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ + +// TraceId represents an opaque 128-bit trace identifier. The trace identifier +// remains constant across the trace. A valid trace identifier is a 16-byte array with at +// least one non-zero byte. +class TraceId final +{ +public: + // The size in bytes of the TraceId. + static constexpr int kSize = 16; + + // An invalid TraceId (all zeros). + TraceId() noexcept : rep_{0} {} + + // Creates a TraceId with the given ID. + explicit TraceId(nostd::span<const uint8_t, kSize> id) noexcept + { + memcpy(rep_, id.data(), kSize); + } + + // Populates the buffer with the lowercase base16 representation of the ID. + void ToLowerBase16(nostd::span<char, 2 * kSize> buffer) const noexcept + { + constexpr char kHex[] = "0123456789abcdef"; + for (int i = 0; i < kSize; ++i) + { + buffer[i * 2 + 0] = kHex[(rep_[i] >> 4) & 0xF]; + buffer[i * 2 + 1] = kHex[(rep_[i] >> 0) & 0xF]; + } + } + + // Returns a nostd::span of the ID. + nostd::span<const uint8_t, kSize> Id() const noexcept + { + return nostd::span<const uint8_t, kSize>(rep_); + } + + bool operator==(const TraceId &that) const noexcept + { + return memcmp(rep_, that.rep_, kSize) == 0; + } + + bool operator!=(const TraceId &that) const noexcept { return !(*this == that); } + + // Returns false if the TraceId is all zeros. + bool IsValid() const noexcept { return *this != TraceId(); } + + // Copies the opaque TraceId data to dest. + void CopyBytesTo(nostd::span<uint8_t, kSize> dest) const noexcept + { + memcpy(dest.data(), rep_, kSize); + } + +private: + uint8_t rep_[kSize]; +}; + +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/trace_state.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/trace_state.h new file mode 100644 index 000000000..0343637cf --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/trace_state.h @@ -0,0 +1,320 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <cstdint> +#include <cstring> +#include <string> + +#include <regex> +#if (__GNUC__ == 4 && (__GNUC_MINOR__ == 8 || __GNUC_MINOR__ == 9)) +# define HAVE_WORKING_REGEX 0 +#else +# define HAVE_WORKING_REGEX 1 +#endif + +#include "opentelemetry/common/kv_properties.h" +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/nostd/span.h" +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/nostd/unique_ptr.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ + +/** + * TraceState carries tracing-system specific context in a list of key-value pairs. TraceState + * allows different vendors to propagate additional information and inter-operate with their legacy + * id formats. + * + * For more information, see the W3C Trace Context specification: + * https://www.w3.org/TR/trace-context + */ +class TraceState +{ +public: + static constexpr int kKeyMaxSize = 256; + static constexpr int kValueMaxSize = 256; + static constexpr int kMaxKeyValuePairs = 32; + static constexpr auto kKeyValueSeparator = '='; + static constexpr auto kMembersSeparator = ','; + + static nostd::shared_ptr<TraceState> GetDefault() + { + static nostd::shared_ptr<TraceState> ts{new TraceState()}; + return ts; + } + + /** + * Returns shared_ptr to a newly created TraceState parsed from the header provided. + * @param header Encoding of the tracestate header defined by + * the W3C Trace Context specification https://www.w3.org/TR/trace-context/ + * @return TraceState A new TraceState instance or DEFAULT + */ + static nostd::shared_ptr<TraceState> FromHeader(nostd::string_view header) noexcept + { + + 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<TraceState> ts(new TraceState(cnt)); + bool kv_valid; + nostd::string_view key, value; + while (kv_str_tokenizer.next(kv_valid, key, value) && ts->kv_properties_->Size() < cnt) + { + if (kv_valid == false) + { + return GetDefault(); + } + + if (!IsValidKey(key) || !IsValidValue(value)) + { + // invalid header. return empty TraceState + ts->kv_properties_.reset(new opentelemetry::common::KeyValueProperties()); + break; + } + + ts->kv_properties_->AddEntry(key, value); + } + + return ts; + } + + /** + * Creates a w3c tracestate header from TraceState object + */ + std::string ToHeader() const noexcept + { + std::string header_s; + bool first = true; + kv_properties_->GetAllEntries( + [&header_s, &first](nostd::string_view key, nostd::string_view value) noexcept { + if (!first) + { + header_s.append(","); + } + else + { + first = false; + } + header_s.append(std::string(key.data(), key.size())); + header_s.append(1, kKeyValueSeparator); + header_s.append(std::string(value.data(), value.size())); + return true; + }); + return header_s; + } + + /** + * Returns `value` associated with `key` passed as argument + * Returns empty string if key is invalid or not found + */ + bool Get(nostd::string_view key, std::string &value) const noexcept + { + if (!IsValidKey(key)) + { + return false; + } + + return kv_properties_->GetValue(key, value); + } + + /** + * Returns shared_ptr of `new` TraceState object with following mutations applied to the existing + * instance: Update Key value: The updated value must be moved to beginning of List Add : The new + * key-value pair SHOULD be added to beginning of List + * + * If the provided key-value pair is invalid, or results in transtate that violates the + * tracecontext specification, empty TraceState instance will be returned. + * + * If the existing object has maximum list members, it's copy is returned. + */ + nostd::shared_ptr<TraceState> Set(const nostd::string_view &key, + const nostd::string_view &value) noexcept + { + auto curr_size = kv_properties_->Size(); + if (!IsValidKey(key) || !IsValidValue(value)) + { + // max size reached or invalid key/value. Returning empty TraceState + return TraceState::GetDefault(); + } + auto allocate_size = curr_size; + if (curr_size < kMaxKeyValuePairs) + { + allocate_size += 1; + } + nostd::shared_ptr<TraceState> ts(new TraceState(allocate_size)); + if (curr_size < kMaxKeyValuePairs) + { + // add new field first + ts->kv_properties_->AddEntry(key, value); + } + // add rest of the fields. + kv_properties_->GetAllEntries([&ts](nostd::string_view key, nostd::string_view value) { + ts->kv_properties_->AddEntry(key, value); + return true; + }); + return ts; + } + + /** + * Returns shared_ptr to a `new` TraceState object after removing the attribute with given key ( + * if present ) + * @returns empty TraceState object if key is invalid + * @returns copy of original TraceState object if key is not present (??) + */ + nostd::shared_ptr<TraceState> Delete(const nostd::string_view &key) noexcept + { + if (!IsValidKey(key)) + { + return TraceState::GetDefault(); + } + auto curr_size = kv_properties_->Size(); + auto allocate_size = curr_size; + std::string unused; + if (kv_properties_->GetValue(key, unused)) + { + allocate_size -= 1; + } + nostd::shared_ptr<TraceState> ts(new TraceState(allocate_size)); + kv_properties_->GetAllEntries( + [&ts, &key](nostd::string_view e_key, nostd::string_view e_value) { + if (key != e_key) + ts->kv_properties_->AddEntry(e_key, e_value); + return true; + }); + return ts; + } + + // Returns true if there are no keys, false otherwise. + bool Empty() const noexcept { return kv_properties_->Size() == 0; } + + // @return all key-values entris 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); + } + /** Returns whether key is a valid key. See https://www.w3.org/TR/trace-context/#key + * Identifiers MUST begin with a lowercase letter or a digit, and can only contain + * lowercase letters (a-z), digits (0-9), underscores (_), dashes (-), asterisks (*), + * and forward slashes (/). + * For multi-tenant vendor scenarios, an at sign (@) can be used to prefix the vendor name. + * + */ + static bool IsValidKey(nostd::string_view key) + { +#if HAVE_WORKING_REGEX + return IsValidKeyRegEx(key); +#else + return IsValidKeyNonRegEx(key); +#endif + } + + /** Returns whether value is a valid value. See https://www.w3.org/TR/trace-context/#value + * The value is an opaque string containing up to 256 printable ASCII (RFC0020) + * characters ((i.e., the range 0x20 to 0x7E) except comma , and equal =) + */ + static bool IsValidValue(nostd::string_view value) + { +#if HAVE_WORKING_REGEX + return IsValidValueRegEx(value); +#else + return IsValidValueNonRegEx(value); +#endif + } + +private: + TraceState() : kv_properties_(new opentelemetry::common::KeyValueProperties()){}; + TraceState(size_t size) : kv_properties_(new opentelemetry::common::KeyValueProperties(size)){}; + + static nostd::string_view TrimString(nostd::string_view str, size_t left, size_t right) + { + while (str[static_cast<std::size_t>(right)] == ' ' && left < right) + { + right--; + } + while (str[static_cast<std::size_t>(left)] == ' ' && left < right) + { + left++; + } + return str.substr(left, right - left + 1); + } + + static bool IsValidKeyRegEx(nostd::string_view key) + { + static std::regex reg_key("^[a-z0-9][a-z0-9*_\\-/]{0,255}$"); + static std::regex reg_key_multitenant( + "^[a-z0-9][a-z0-9*_\\-/]{0,240}(@)[a-z0-9][a-z0-9*_\\-/]{0,13}$"); + std::string key_s(key.data(), key.size()); + if (std::regex_match(key_s, reg_key) || std::regex_match(key_s, reg_key_multitenant)) + { + return true; + } + return false; + } + + static bool IsValidValueRegEx(nostd::string_view value) + { + // Hex 0x20 to 0x2B, 0x2D to 0x3C, 0x3E to 0x7E + static std::regex reg_value( + "^[\\x20-\\x2B\\x2D-\\x3C\\x3E-\\x7E]{0,255}[\\x21-\\x2B\\x2D-\\x3C\\x3E-\\x7E]$"); + // Need to benchmark without regex, as a string object is created here. + return std::regex_match(std::string(value.data(), value.size()), reg_value); + } + + static bool IsValidKeyNonRegEx(nostd::string_view key) + { + if (key.empty() || key.size() > kKeyMaxSize || !IsLowerCaseAlphaOrDigit(key[0])) + { + return false; + } + + int ats = 0; + + for (const char c : key) + { + if (!IsLowerCaseAlphaOrDigit(c) && c != '_' && c != '-' && c != '@' && c != '*' && c != '/') + { + return false; + } + if ((c == '@') && (++ats > 1)) + { + return false; + } + } + return true; + } + + static bool IsValidValueNonRegEx(nostd::string_view value) + { + if (value.empty() || value.size() > kValueMaxSize) + { + return false; + } + + for (const char c : value) + { + if (c < ' ' || c > '~' || c == ',' || c == '=') + { + return false; + } + } + return true; + } + + static bool IsLowerCaseAlphaOrDigit(char c) { return isdigit(c) || islower(c); } + +private: + // Store entries in a C-style array to avoid using std::array or std::vector. + nostd::unique_ptr<opentelemetry::common::KeyValueProperties> kv_properties_; +}; +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/tracer.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/tracer.h new file mode 100644 index 000000000..b60336a48 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/tracer.h @@ -0,0 +1,194 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/context/context.h" +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/nostd/unique_ptr.h" +#include "opentelemetry/trace/default_span.h" +#include "opentelemetry/trace/scope.h" +#include "opentelemetry/trace/span.h" +#include "opentelemetry/trace/span_context_kv_iterable_view.h" +#include "opentelemetry/trace/span_startoptions.h" +#include "opentelemetry/version.h" + +#include <chrono> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +/** + * Handles span creation and in-process context propagation. + * + * This class provides methods for manipulating the context, creating spans, and controlling spans' + * lifecycles. + */ +class Tracer +{ +public: + virtual ~Tracer() = default; + /** + * Starts a span. + * + * Optionally sets attributes at Span creation from the given key/value pairs. + * + * Attributes will be processed in order, previous attributes with the same + * key will be overwritten. + */ + virtual nostd::shared_ptr<Span> StartSpan(nostd::string_view name, + const common::KeyValueIterable &attributes, + const SpanContextKeyValueIterable &links, + const StartSpanOptions &options = {}) noexcept = 0; + + nostd::shared_ptr<Span> StartSpan(nostd::string_view name, + const StartSpanOptions &options = {}) noexcept + { + return this->StartSpan(name, {}, {}, options); + } + + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + nostd::shared_ptr<Span> StartSpan(nostd::string_view name, + const T &attributes, + const StartSpanOptions &options = {}) noexcept + { + return this->StartSpan(name, attributes, {}, options); + } + + nostd::shared_ptr<Span> StartSpan(nostd::string_view name, + const common::KeyValueIterable &attributes, + const StartSpanOptions &options = {}) noexcept + { + return this->StartSpan(name, attributes, NullSpanContext(), options); + } + + template <class T, + class U, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr, + nostd::enable_if_t<detail::is_span_context_kv_iterable<U>::value> * = nullptr> + nostd::shared_ptr<Span> StartSpan(nostd::string_view name, + const T &attributes, + const U &links, + const StartSpanOptions &options = {}) noexcept + { + return this->StartSpan(name, common::KeyValueIterableView<T>(attributes), + SpanContextKeyValueIterableView<U>(links), options); + } + + nostd::shared_ptr<Span> StartSpan( + nostd::string_view name, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes, + const StartSpanOptions &options = {}) noexcept + { + + return this->StartSpan(name, attributes, {}, options); + } + + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + nostd::shared_ptr<Span> StartSpan( + nostd::string_view name, + const T &attributes, + std::initializer_list< + std::pair<SpanContext, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>>> + links, + const StartSpanOptions &options = {}) noexcept + { + return this->StartSpan( + name, attributes, + nostd::span<const std::pair<SpanContext, std::initializer_list<std::pair< + nostd::string_view, common::AttributeValue>>>>{ + links.begin(), links.end()}, + options); + } + + template <class T, + nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> + nostd::shared_ptr<Span> StartSpan( + nostd::string_view name, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes, + const T &links, + const StartSpanOptions &options = {}) noexcept + { + return this->StartSpan(name, + nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{ + attributes.begin(), attributes.end()}, + links, options); + } + + nostd::shared_ptr<Span> StartSpan( + nostd::string_view name, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes, + std::initializer_list< + std::pair<SpanContext, + std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>>> + links, + const StartSpanOptions &options = {}) noexcept + { + return this->StartSpan( + name, + nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{attributes.begin(), + attributes.end()}, + nostd::span<const std::pair<SpanContext, std::initializer_list<std::pair< + nostd::string_view, common::AttributeValue>>>>{ + links.begin(), links.end()}, + options); + } + + /** + * Set the active span. The span will remain active until the returned Scope + * object is destroyed. + * @param span the span that should be set as the new active span. + * @return a Scope that controls how long the span will be active. + */ + static Scope WithActiveSpan(nostd::shared_ptr<Span> &span) noexcept { return Scope{span}; } + + /** + * Get the currently active span. + * @return the currently active span, or an invalid default span if no span + * is active. + */ + static nostd::shared_ptr<Span> GetCurrentSpan() noexcept + { + context::ContextValue active_span = context::RuntimeContext::GetValue(kSpanKey); + if (nostd::holds_alternative<nostd::shared_ptr<Span>>(active_span)) + { + return nostd::get<nostd::shared_ptr<Span>>(active_span); + } + else + { + return nostd::shared_ptr<Span>(new DefaultSpan(SpanContext::GetInvalid())); + } + } + + /** + * Force any buffered spans to flush. + * @param timeout to complete the flush + */ + template <class Rep, class Period> + void ForceFlush(std::chrono::duration<Rep, Period> timeout) noexcept + { + this->ForceFlushWithMicroseconds(static_cast<uint64_t>( + std::chrono::duration_cast<std::chrono::microseconds>(timeout).count())); + } + + virtual void ForceFlushWithMicroseconds(uint64_t timeout) noexcept = 0; + + /** + * ForceFlush any buffered spans and stop reporting spans. + * @param timeout to complete the flush + */ + template <class Rep, class Period> + void Close(std::chrono::duration<Rep, Period> timeout) noexcept + { + this->CloseWithMicroseconds(static_cast<uint64_t>( + std::chrono::duration_cast<std::chrono::microseconds>(timeout).count())); + } + + virtual void CloseWithMicroseconds(uint64_t timeout) noexcept = 0; +}; +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/tracer_provider.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/tracer_provider.h new file mode 100644 index 000000000..2dae74ce1 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/trace/tracer_provider.h @@ -0,0 +1,31 @@ +// 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/trace/tracer.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +/** + * Creates new Tracer instances. + */ +class TracerProvider +{ +public: + virtual ~TracerProvider() = default; + /** + * Gets or creates a named tracer instance. + * + * Optionally a version can be passed to create a named and versioned tracer + * instance. + */ + virtual nostd::shared_ptr<Tracer> GetTracer(nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") noexcept = 0; +}; +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/version.h b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/version.h new file mode 100644 index 000000000..849259d3e --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/api/include/opentelemetry/version.h @@ -0,0 +1,21 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/detail/preprocessor.h" + +#define OPENTELEMETRY_ABI_VERSION_NO 1 +#define OPENTELEMETRY_VERSION "1.4.0" +#define OPENTELEMETRY_ABI_VERSION OPENTELEMETRY_STRINGIFY(OPENTELEMETRY_ABI_VERSION_NO) + +// clang-format off +#define OPENTELEMETRY_BEGIN_NAMESPACE \ + namespace opentelemetry { inline namespace OPENTELEMETRY_CONCAT(v, OPENTELEMETRY_ABI_VERSION_NO) { + +#define OPENTELEMETRY_END_NAMESPACE \ + }} + +#define OPENTELEMETRY_NAMESPACE opentelemetry :: OPENTELEMETRY_CONCAT(v, OPENTELEMETRY_ABI_VERSION_NO) + +// clang-format on |