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/sdk/include/opentelemetry | |
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/sdk/include/opentelemetry')
101 files changed, 10563 insertions, 0 deletions
diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/aggregator.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/aggregator.h new file mode 100644 index 000000000..f6821d731 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/aggregator.h @@ -0,0 +1,156 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include <mutex> +# include <vector> +# include "opentelemetry/_metrics/instrument.h" +# include "opentelemetry/common/timestamp.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +enum class AggregatorKind +{ + Counter = 0, + MinMaxSumCount = 1, + Gauge = 2, + Sketch = 3, + Histogram = 4, + Exact = 5, +}; + +/* + * Performs calculations necessary to combine updates from instruments into an + * insightful value. + * Also stores current instrument values and checkpoints collected at intervals + * governing the entire pipeline. + */ +template <typename T> +class Aggregator +{ +public: + Aggregator() = default; + + virtual ~Aggregator() = default; + + /** + * Receives a captured value from the instrument and applies it to the current aggregator value. + * + * @param val, the raw value used in aggregation + * @return none + */ + virtual void update(T val) = 0; + + /** + * Checkpoints the current value. This function will overwrite the current checkpoint with the + * current value. + * + * @param none + * @return none + */ + virtual void checkpoint() = 0; + + /** + * Merges the values of two aggregators in a semantically accurate manner. + * Merging will occur differently for different aggregators depending on the + * way values are tracked. + * + * @param other, the aggregator with merge with + * @return none + */ + void merge(Aggregator *other); + + /** + * Returns the checkpointed value + * + * @param none + * @return the value of the checkpoint + */ + virtual std::vector<T> get_checkpoint() = 0; + + /** + * Returns the current value + * + * @param none + * @return the present aggregator value + */ + virtual std::vector<T> get_values() = 0; + + /** + * Returns the instrument kind which this aggregator is associated with + * + * @param none + * @return the InstrumentKind of the aggregator's owner + */ + virtual opentelemetry::metrics::InstrumentKind get_instrument_kind() final { return kind_; } + + /** + * Returns the type of this aggregator + * + * @param none + * @return the AggregatorKind of this instrument + */ + virtual AggregatorKind get_aggregator_kind() final { return agg_kind_; } + + /** + * Getter function for updated_ protected var + * + * @return A bool indicating wether or not this aggregator has been updated + * in the most recent collection interval. + */ + virtual bool is_updated() final { return updated_; } + + // virtual function to be overridden for the Histogram Aggregator + virtual std::vector<double> get_boundaries() { return std::vector<double>(); } + + // virtual function to be overridden for the Histogram Aggregator + virtual std::vector<int> get_counts() { return std::vector<int>(); } + + // virtual function to be overridden for Exact and Sketch Aggregators + virtual bool get_quant_estimation() { return false; } + + // virtual function to be overridden for Exact and Sketch Aggregators + virtual T get_quantiles(double q) { return values_[0]; } + + // virtual function to be overridden for Sketch Aggregator + virtual double get_error_bound() { return 0; } + + // virtual function to be overridden for Sketch Aggregator + virtual size_t get_max_buckets() { return 0; } + + // virtual function to be overridden for Gauge Aggregator + virtual opentelemetry::common::SystemTimestamp get_checkpoint_timestamp() + { + return opentelemetry::common::SystemTimestamp(); + } + + // Custom copy constructor to handle the mutex + Aggregator(const Aggregator &cp) + { + values_ = cp.values_; + checkpoint_ = cp.checkpoint_; + kind_ = cp.kind_; + agg_kind_ = cp.agg_kind_; + // use default initialized mutex as they cannot be copied + } + +protected: + std::vector<T> values_; + std::vector<T> checkpoint_; + opentelemetry::metrics::InstrumentKind kind_; + std::mutex mu_; + AggregatorKind agg_kind_; + bool updated_; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/counter_aggregator.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/counter_aggregator.h new file mode 100644 index 000000000..b9842e8e0 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/counter_aggregator.h @@ -0,0 +1,108 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include <mutex> +# include <vector> +# include "opentelemetry/_metrics/instrument.h" +# include "opentelemetry/sdk/_metrics/aggregator/aggregator.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +template <class T> +class CounterAggregator final : public Aggregator<T> +{ + +public: + CounterAggregator(opentelemetry::metrics::InstrumentKind kind) + { + this->kind_ = kind; + this->values_ = std::vector<T>(1, 0); + this->checkpoint_ = std::vector<T>(1, 0); + this->agg_kind_ = AggregatorKind::Counter; + } + + /** + * Receives a captured value from the instrument and applies it to the current aggregator value. + * + * @param val, the raw value used in aggregation + * @return none + */ + void update(T val) override + { + this->mu_.lock(); + this->updated_ = true; + this->values_[0] += val; // atomic operation + this->mu_.unlock(); + } + + /** + * Checkpoints the current value. This function will overwrite the current checkpoint with the + * current value. + * + * @param none + * @return none + */ + void checkpoint() override + { + this->mu_.lock(); + this->updated_ = false; + this->checkpoint_ = this->values_; + this->values_[0] = 0; + this->mu_.unlock(); + } + + /** + * Merges the values of two aggregators in a semantically accurate manner. + * In this case, merging only requires the the current values of the two aggregators be summed. + * + * @param other, the aggregator with merge with + * @return none + */ + void merge(CounterAggregator other) + { + if (this->agg_kind_ == other.agg_kind_) + { + this->mu_.lock(); + this->values_[0] += other.values_[0]; + this->checkpoint_[0] += other.checkpoint_[0]; + this->mu_.unlock(); + } + else + { +# if __EXCEPTIONS + throw std::invalid_argument("Aggregators of different types cannot be merged."); +# else + std::terminate(); +# endif + } + } + + /** + * Returns the checkpointed value + * + * @param none + * @return the value of the checkpoint + */ + virtual std::vector<T> get_checkpoint() override { return this->checkpoint_; } + + /** + * Returns the current values + * + * @param none + * @return the present aggregator values + */ + virtual std::vector<T> get_values() override { return this->values_; } +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/exact_aggregator.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/exact_aggregator.h new file mode 100644 index 000000000..44ea717a0 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/exact_aggregator.h @@ -0,0 +1,169 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include "opentelemetry/_metrics/instrument.h" +# include "opentelemetry/sdk/_metrics/aggregator/aggregator.h" +# include "opentelemetry/version.h" + +# include <cmath> +# include <memory> +# include <mutex> +# include <vector> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +/** + * This aggregator has two modes. In-order and quantile estimation. + * + * The first mode simply stores all values sent to the Update() + * function in a vector and maintains the order they were sent in. + * + * The second mode also stores all values sent to the Update() + * function in a vector but sorts this vector when Checkpoint() + * is called. This mode also includes a function, Quantile(), + * that estimates the quantiles of the recorded data. + * + * @tparam T the type of values stored in this aggregator. + */ +template <class T> +class ExactAggregator : public Aggregator<T> +{ +public: + ExactAggregator(opentelemetry::metrics::InstrumentKind kind, bool quant_estimation = false) + { + static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type"); + this->kind_ = kind; + this->checkpoint_ = this->values_; + this->agg_kind_ = AggregatorKind::Exact; + quant_estimation_ = quant_estimation; + } + + ~ExactAggregator() = default; + + ExactAggregator(const ExactAggregator &cp) + { + this->values_ = cp.values_; + this->checkpoint_ = cp.checkpoint_; + this->kind_ = cp.kind_; + this->agg_kind_ = cp.agg_kind_; + quant_estimation_ = cp.quant_estimation_; + // use default initialized mutex as they cannot be copied + } + + /** + * Receives a captured value from the instrument and adds it to the values_ vector. + * + * @param val, the raw value used in aggregation + */ + void update(T val) override + { + this->mu_.lock(); + this->updated_ = true; + this->values_.push_back(val); + this->mu_.unlock(); + } + + /** + * Checkpoints the current values. This function will overwrite the current checkpoint with the + * current value. Sorts the values_ vector if quant_estimation_ == true + * + */ + void checkpoint() override + { + this->mu_.lock(); + this->updated_ = false; + if (quant_estimation_) + { + std::sort(this->values_.begin(), this->values_.end()); + } + this->checkpoint_ = this->values_; + this->values_.clear(); + this->mu_.unlock(); + } + + /** + * Merges two exact aggregators' values_ vectors together. + * + * @param other the aggregator to merge with this aggregator + */ + void merge(const ExactAggregator &other) + { + if (this->kind_ == other.kind_) + { + this->mu_.lock(); + // First merge values + this->values_.insert(this->values_.end(), other.values_.begin(), other.values_.end()); + // Now merge checkpoints + this->checkpoint_.insert(this->checkpoint_.end(), other.checkpoint_.begin(), + other.checkpoint_.end()); + this->mu_.unlock(); + } + else + { + // Log error + return; + } + } + + /** + * Performs quantile estimation on the checkpoint vector in this aggregator. + * This function only works if quant_estimation_ == true. + * @param q the quantile to estimate. 0 <= q <= 1 + * @return the nearest value in the vector to the exact quantile. + */ + T get_quantiles(double q) override + { + if (!quant_estimation_) + { +// Log error +# if __EXCEPTIONS + throw std::domain_error("Exact aggregator is not in quantile estimation mode!"); +# else + std::terminate(); +# endif + } + if (this->checkpoint_.size() == 0 || q < 0 || q > 1) + { +// Log error +# if __EXCEPTIONS + throw std::invalid_argument("Arg 'q' must be between 0 and 1, inclusive"); +# else + std::terminate(); +# endif + } + else if (q == 0 || this->checkpoint_.size() == 1) + { + return this->checkpoint_[0]; + } + else if (q == 1) + { + return this->checkpoint_[this->checkpoint_.size() - 1]; + } + else + { + float position = float(float(this->checkpoint_.size() - 1) * q); + int ceiling = int(ceil(position)); + return this->checkpoint_[ceiling]; + } + } + + //////////////////////////ACCESSOR FUNCTIONS////////////////////////// + std::vector<T> get_checkpoint() override { return this->checkpoint_; } + + std::vector<T> get_values() override { return this->values_; } + + bool get_quant_estimation() override { return quant_estimation_; } + +private: + bool quant_estimation_; // Used to switch between in-order and quantile estimation modes +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/gauge_aggregator.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/gauge_aggregator.h new file mode 100644 index 000000000..96119386d --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/gauge_aggregator.h @@ -0,0 +1,146 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include "opentelemetry/_metrics/instrument.h" +# include "opentelemetry/common/timestamp.h" +# include "opentelemetry/sdk/_metrics/aggregator/aggregator.h" +# include "opentelemetry/version.h" + +# include <memory> +# include <mutex> +# include <vector> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +/** + * This aggregator stores and maintains a vector of + * type T where the contents of the vector simply + * include the last value recorded to the aggregator. + * The aggregator also maintains a timestamp of when + * the last value was recorded. + * + * @tparam T the type of values stored in this aggregator. + */ +template <class T> +class GaugeAggregator : public Aggregator<T> +{ +public: + explicit GaugeAggregator(opentelemetry::metrics::InstrumentKind kind) + { + static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type"); + this->kind_ = kind; + this->values_ = std::vector<T>(1, 0); + this->checkpoint_ = this->values_; + this->agg_kind_ = AggregatorKind::Gauge; + current_timestamp_ = opentelemetry::common::SystemTimestamp(std::chrono::system_clock::now()); + } + + ~GaugeAggregator() = default; + + GaugeAggregator(const GaugeAggregator &cp) + { + this->values_ = cp.values_; + this->checkpoint_ = cp.checkpoint_; + this->kind_ = cp.kind_; + this->agg_kind_ = cp.agg_kind_; + current_timestamp_ = cp.current_timestamp_; + // use default initialized mutex as they cannot be copied + } + + /** + * Receives a captured value from the instrument and applies it to the current aggregator value. + * + * @param val, the raw value used in aggregation + */ + void update(T val) override + { + this->mu_.lock(); + this->updated_ = true; + this->values_[0] = val; + current_timestamp_ = opentelemetry::common::SystemTimestamp(std::chrono::system_clock::now()); + this->mu_.unlock(); + } + + /** + * Checkpoints the current value. This function will overwrite the current checkpoint with the + * current value. + * + * @return none + */ + + void checkpoint() override + { + this->mu_.lock(); + + this->updated_ = false; + this->checkpoint_ = this->values_; + + // Reset the values to default + this->values_[0] = 0; + checkpoint_timestamp_ = current_timestamp_; + current_timestamp_ = opentelemetry::common::SystemTimestamp(std::chrono::system_clock::now()); + + this->mu_.unlock(); + } + + /** + * Merges two Gauge aggregators together + * + * @param other the aggregator to merge with this aggregator + */ + void merge(GaugeAggregator<T> other) + { + if (this->kind_ == other.kind_) + { + this->mu_.lock(); + // First merge values + this->values_[0] = other.values_[0]; + // Now merge checkpoints + this->checkpoint_[0] = other.checkpoint_[0]; + current_timestamp_ = opentelemetry::common::SystemTimestamp(std::chrono::system_clock::now()); + this->mu_.unlock(); + } + else + { + // Log error + return; + } + } + + /** + * @return the value of the latest checkpoint + */ + std::vector<T> get_checkpoint() override { return this->checkpoint_; } + + /** + * @return the latest checkpointed timestamp + */ + opentelemetry::common::SystemTimestamp get_checkpoint_timestamp() override + { + return checkpoint_timestamp_; + } + + /** + * @return the values_ vector stored in this aggregator + */ + std::vector<T> get_values() override { return this->values_; } + + /** + * @return the timestamp of when the last value recorded + */ + opentelemetry::common::SystemTimestamp get_timestamp() { return current_timestamp_; } + +private: + opentelemetry::common::SystemTimestamp current_timestamp_; + opentelemetry::common::SystemTimestamp checkpoint_timestamp_; +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/histogram_aggregator.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/histogram_aggregator.h new file mode 100644 index 000000000..13e1e1244 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/histogram_aggregator.h @@ -0,0 +1,207 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include <algorithm> +# include <mutex> +# include <stdexcept> +# include <vector> +# include "opentelemetry/_metrics/instrument.h" +# include "opentelemetry/sdk/_metrics/aggregator/aggregator.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +template <class T> +class HistogramAggregator final : public Aggregator<T> +{ + +public: + /** + * Constructor for the histogram aggregator. A sorted vector of boundaries is expected and + * boundaries are doubles regardless of the aggregator's templated data type. + * + * Sum is stored in values_[0] + * Count is stored in position_[1] + */ + HistogramAggregator(opentelemetry::metrics::InstrumentKind kind, std::vector<double> boundaries) + { + if (!std::is_sorted(boundaries.begin(), boundaries.end())) + { +# if __EXCEPTIONS + throw std::invalid_argument("Histogram boundaries must be monotonic."); +# else + std::terminate(); +# endif + } + this->kind_ = kind; + this->agg_kind_ = AggregatorKind::Histogram; + boundaries_ = boundaries; + this->values_ = std::vector<T>(2, 0); + this->checkpoint_ = std::vector<T>(2, 0); + bucketCounts_ = std::vector<int>(boundaries_.size() + 1, 0); + bucketCounts_ckpt_ = std::vector<int>(boundaries_.size() + 1, 0); + } + + /** + * Receives a captured value from the instrument and inserts it into the current histogram counts. + * + * Depending on the use case, a linear search or binary search based implementation may be + * preferred. In uniformly distributed datasets, linear search outperforms binary search until 512 + * buckets. However, if the distribution is strongly skewed right (for example server latency + * where most values may be <10ms but the range is from 0 - 1000 ms), a linear search could be + * superior even with more than 500 buckets as almost all values inserted would be at the + * beginning of the boundaries array and thus found more quickly through linear search. + * + * @param val, the raw value used in aggregation + * @return none + */ + void update(T val) override + { + this->mu_.lock(); + this->updated_ = true; + size_t bucketID = boundaries_.size(); + for (size_t i = 0; i < boundaries_.size(); i++) + { + if (val < boundaries_[i]) // concurrent read is thread-safe + { + bucketID = i; + break; + } + } + + // Alternate implementation with binary search + // auto pos = std::lower_bound (boundaries_.begin(), boundaries_.end(), val); + // bucketCounts_[pos-boundaries_.begin()] += 1; + + this->values_[0] += val; + this->values_[1] += 1; + bucketCounts_[bucketID] += 1; + this->mu_.unlock(); + } + + /** + * Checkpoints the current value. This function will overwrite the current checkpoint with the + * current value. + * + * @param none + * @return none + */ + void checkpoint() override + { + this->mu_.lock(); + this->updated_ = false; + this->checkpoint_ = this->values_; + this->values_[0] = 0; + this->values_[1] = 0; + bucketCounts_ckpt_ = bucketCounts_; + std::fill(bucketCounts_.begin(), bucketCounts_.end(), 0); + this->mu_.unlock(); + } + + /** + * Merges the values of two aggregators in a semantically accurate manner. + * A histogram aggregator can only be merged with another histogram aggregator that has the same + * boudnaries. A histogram merge first adds the sum and count values then iterates over the adds + * the bucket counts element by element. + * + * @param other, the aggregator with merge with + * @return none + */ + void merge(HistogramAggregator other) + { + this->mu_.lock(); + + // Ensure that incorrect types are not merged + if (this->agg_kind_ != other.agg_kind_) + { +# if __EXCEPTIONS + throw std::invalid_argument("Aggregators of different types cannot be merged."); +# else + std::terminate(); +# endif + // Reject histogram merges with differing boundary vectors + } + else if (other.boundaries_ != this->boundaries_) + { +# if __EXCEPTIONS + throw std::invalid_argument("Histogram boundaries do not match."); +# else + std::terminate(); +# endif + } + + this->values_[0] += other.values_[0]; + this->values_[1] += other.values_[1]; + + this->checkpoint_[0] += other.checkpoint_[0]; + this->checkpoint_[1] += other.checkpoint_[1]; + + for (size_t i = 0; i < bucketCounts_.size(); i++) + { + bucketCounts_[i] += other.bucketCounts_[i]; + bucketCounts_ckpt_[i] += other.bucketCounts_ckpt_[i]; + } + this->mu_.unlock(); + } + + /** + * Returns the checkpointed value + * + * @param none + * @return the value of the checkpoint + */ + std::vector<T> get_checkpoint() override { return this->checkpoint_; } + + /** + * Returns the current values + * + * @param none + * @return the present aggregator values + */ + std::vector<T> get_values() override { return this->values_; } + + /** + * Returns the bucket boundaries specified at this aggregator's creation. + * + * @param none + * @return the aggregator boundaries + */ + virtual std::vector<double> get_boundaries() override { return boundaries_; } + + /** + * Returns the current counts for each bucket . + * + * @param none + * @return the aggregator bucket counts + */ + virtual std::vector<int> get_counts() override { return bucketCounts_ckpt_; } + + HistogramAggregator(const HistogramAggregator &cp) + { + this->values_ = cp.values_; + this->checkpoint_ = cp.checkpoint_; + this->kind_ = cp.kind_; + this->agg_kind_ = cp.agg_kind_; + boundaries_ = cp.boundaries_; + bucketCounts_ = cp.bucketCounts_; + bucketCounts_ckpt_ = cp.bucketCounts_ckpt_; + // use default initialized mutex as they cannot be copied + } + +private: + std::vector<double> boundaries_; + std::vector<int> bucketCounts_; + std::vector<int> bucketCounts_ckpt_; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/min_max_sum_count_aggregator.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/min_max_sum_count_aggregator.h new file mode 100644 index 000000000..60628b567 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/min_max_sum_count_aggregator.h @@ -0,0 +1,159 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include "opentelemetry/_metrics/instrument.h" +# include "opentelemetry/sdk/_metrics/aggregator/aggregator.h" +# include "opentelemetry/version.h" + +# include <memory> +# include <mutex> +# include <vector> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +const int MinValueIndex = 0; +const int MaxValueIndex = 1; +const int SumValueIndex = 2; +const int CountValueIndex = 3; +/** + * This aggregator stores and maintains a vector of + * type T where the contents in the vector are made + * up of the minimum value recorded to this instrument, + * the maximum value, the sum of all values, and the + * count of all values. + * + * @tparam T the type of values stored in this aggregator. + */ +template <class T> +class MinMaxSumCountAggregator : public Aggregator<T> +{ +public: + explicit MinMaxSumCountAggregator(opentelemetry::metrics::InstrumentKind kind) + { + static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type"); + this->kind_ = kind; + this->values_ = std::vector<T>(4, 0); // {min, max, sum, count} + this->checkpoint_ = this->values_; + this->agg_kind_ = AggregatorKind::MinMaxSumCount; + } + + ~MinMaxSumCountAggregator() = default; + + MinMaxSumCountAggregator(const MinMaxSumCountAggregator &cp) + { + this->values_ = cp.values_; + this->checkpoint_ = cp.checkpoint_; + this->kind_ = cp.kind_; + this->agg_kind_ = cp.agg_kind_; + // use default initialized mutex as they cannot be copied + } + + /** + * Receives a captured value from the instrument and applies it to the current aggregator value. + * + * @param val, the raw value used in aggregation + */ + void update(T val) override + { + this->mu_.lock(); + this->updated_ = true; + + if (this->values_[CountValueIndex] == 0 || val < this->values_[MinValueIndex]) // set min + this->values_[MinValueIndex] = val; + if (this->values_[CountValueIndex] == 0 || val > this->values_[MaxValueIndex]) // set max + this->values_[MaxValueIndex] = val; + + this->values_[SumValueIndex] += val; // compute sum + this->values_[CountValueIndex]++; // increment count + + this->mu_.unlock(); + } + + /** + * Checkpoints the current value. This function will overwrite the current checkpoint with the + * current value. + * + */ + void checkpoint() override + { + this->mu_.lock(); + this->updated_ = false; + this->checkpoint_ = this->values_; + // Reset the values + this->values_[MinValueIndex] = 0; + this->values_[MaxValueIndex] = 0; + this->values_[SumValueIndex] = 0; + this->values_[CountValueIndex] = 0; + this->mu_.unlock(); + } + + /** + * Merges two MinMaxSumCount aggregators together + * + * @param other the aggregator to merge with this aggregator + */ + void merge(const MinMaxSumCountAggregator &other) + { + if (this->kind_ == other.kind_) + { + this->mu_.lock(); + // First merge values + // set min + if (this->values_[CountValueIndex] == 0 || + other.values_[MinValueIndex] < this->values_[MinValueIndex]) + this->values_[MinValueIndex] = other.values_[MinValueIndex]; + // set max + if (this->values_[CountValueIndex] == 0 || + other.values_[MaxValueIndex] > this->values_[MaxValueIndex]) + this->values_[MaxValueIndex] = other.values_[MaxValueIndex]; + // set sum + this->values_[SumValueIndex] += other.values_[SumValueIndex]; + // set count + this->values_[CountValueIndex] += other.values_[CountValueIndex]; + + // Now merge checkpoints + if (this->checkpoint_[CountValueIndex] == 0 || + other.checkpoint_[MinValueIndex] < this->checkpoint_[MinValueIndex]) + this->checkpoint_[MinValueIndex] = other.checkpoint_[MinValueIndex]; + // set max + if (this->checkpoint_[CountValueIndex] == 0 || + other.checkpoint_[MaxValueIndex] > this->checkpoint_[MaxValueIndex]) + this->checkpoint_[MaxValueIndex] = other.checkpoint_[MaxValueIndex]; + // set sum + this->checkpoint_[SumValueIndex] += other.checkpoint_[SumValueIndex]; + // set count + this->checkpoint_[CountValueIndex] += other.checkpoint_[CountValueIndex]; + + this->mu_.unlock(); + } + else + { + // Log error + return; + } + } + + /** + * Returns the checkpointed value + * + * @return the value of the checkpoint + */ + std::vector<T> get_checkpoint() override { return this->checkpoint_; } + + /** + * Returns the values currently held by the aggregator + * + * @return the values held by the aggregator + */ + std::vector<T> get_values() override { return this->values_; } +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/sketch_aggregator.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/sketch_aggregator.h new file mode 100644 index 000000000..3942c9550 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/sketch_aggregator.h @@ -0,0 +1,282 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include <algorithm> +# include <cmath> +# include <limits> +# include <map> +# include <mutex> +# include <stdexcept> +# include <vector> +# include "opentelemetry/_metrics/instrument.h" +# include "opentelemetry/sdk/_metrics/aggregator/aggregator.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +/** Sketch Aggregators implement the DDSketch data type. Note that data is compressed + * by the DDSketch algorithm and users should be informed about its behavior before + * selecting it as the aggregation type. NOTE: The current implementation can only support + * non-negative values. + * + * Detailed information about the algorithm can be found in the following paper + * published by Datadog: http://www.vldb.org/pvldb/vol12/p2195-masson.pdf + */ + +template <class T> +class SketchAggregator final : public Aggregator<T> +{ + +public: + /** + * Given the distribution of data this aggregator is designed for and its usage, the raw updates + *are stored in a map rather than a vector. + * + *@param kind, the instrument kind creating this aggregator + *@param error_bound, what is referred to as "alpha" in the DDSketch algorithm + *@param max_buckets, the maximum number of indices in the raw value map + */ + SketchAggregator(opentelemetry::metrics::InstrumentKind kind, + double error_bound, + size_t max_buckets = 2048) + { + + this->kind_ = kind; + this->agg_kind_ = AggregatorKind::Sketch; + this->values_ = std::vector<T>(2, 0); // Sum in [0], Count in [1] + this->checkpoint_ = std::vector<T>(2, 0); + max_buckets_ = max_buckets; + error_bound_ = error_bound; + gamma = (1 + error_bound) / (1 - error_bound); + } + + /** + * Update the aggregator with the new value. For a DDSketch aggregator, if the addition of this + * value creates a new bucket which is in excess of the maximum allowed size, the lowest indexes + * buckets are merged. + * + * @param val, the raw value used in aggregation + * @return none + */ + void update(T val) override + { + this->mu_.lock(); + this->updated_ = true; + int idx; + if (val == 0) + { + idx = (std::numeric_limits<int>::min()); + } + else + { + idx = static_cast<int>(ceil(log(val) / log(gamma))); + } + if (raw_.find(idx) != raw_.end()) + { + raw_[idx] += 1; + } + else + { + raw_[idx] = 1; + } + this->values_[1] += 1; + this->values_[0] += val; + if (raw_.size() > max_buckets_) + { + int minidx = raw_.begin()->first, minidxval = raw_.begin()->second; + raw_.erase(minidx); + raw_[raw_.begin()->first] += minidxval; + } + this->mu_.unlock(); + } + + /** + * Calculate and return the value of a user specified quantile. + * + * @param q, the quantile to calculate (for example 0.5 is equivalent to the 50th percentile) + */ + virtual T get_quantiles(double q) override + { + if (q < 0 || q > 1) + { +# if __EXCEPTIONS + throw std::invalid_argument("Quantile values must fall between 0 and 1"); +# else + std::terminate(); +# endif + } + auto iter = checkpoint_raw_.begin(); + int idx = iter->first; + int count = iter->second; + + while (count < (q * (this->checkpoint_[1] - 1)) && iter != checkpoint_raw_.end()) + { + iter++; + idx = iter->first; + count += iter->second; + } + return static_cast<T>(round(2 * pow(gamma, idx) / (gamma + 1))); + } + + /** + * Checkpoints the current value. This function will overwrite the current checkpoint with the + * current value. + * + * @param none + * @return none + */ + void checkpoint() override + { + this->mu_.lock(); + this->updated_ = false; + this->checkpoint_ = this->values_; + checkpoint_raw_ = raw_; + this->values_[0] = 0; + this->values_[1] = 0; + raw_.clear(); + this->mu_.unlock(); + } + + /** + * Merges this sketch aggregator with another. The same bucket compression used when + * updating values is employed here to manage bucket size if the merging of aggregators + * results in more buckets than allowed. + * + * @param other, the aggregator with merge with + * @return none + */ + void merge(SketchAggregator other) + { + if (gamma != other.gamma) + { +# if __EXCEPTIONS + throw std::invalid_argument("Aggregators must have identical error tolerance"); +# else + std::terminate(); +# endif + } + else if (max_buckets_ != other.max_buckets_) + { +# if __EXCEPTIONS + throw std::invalid_argument("Aggregators must have the same maximum bucket allowance"); +# else + std::terminate(); +# endif + } + + this->mu_.lock(); + this->values_[0] += other.values_[0]; + this->values_[1] += other.values_[1]; + this->checkpoint_[0] += other.checkpoint_[0]; + this->checkpoint_[1] += other.checkpoint_[1]; + auto other_iter = other.raw_.begin(); + while (other_iter != other.raw_.end()) + { + raw_[other_iter->first] += other_iter->second; + if (raw_.size() > max_buckets_) + { + int minidx = raw_.begin()->first, minidxval = raw_.begin()->second; + raw_.erase(minidx); + raw_[raw_.begin()->first] += minidxval; + } + other_iter++; + } + auto other_ckpt_iter = other.checkpoint_raw_.begin(); + while (other_ckpt_iter != other.checkpoint_raw_.end()) + { + checkpoint_raw_[other_ckpt_iter->first] += other_ckpt_iter->second; + if (checkpoint_raw_.size() > max_buckets_) + { + int minidx = checkpoint_raw_.begin()->first, minidxval = checkpoint_raw_.begin()->second; + checkpoint_raw_.erase(minidx); + checkpoint_raw_[checkpoint_raw_.begin()->first] += minidxval; + } + other_ckpt_iter++; + } + this->mu_.unlock(); + } + + /** + * Returns the checkpointed value + * + * @param none + * @return the value of the checkpoint + */ + std::vector<T> get_checkpoint() override { return this->checkpoint_; } + + /** + * Returns the current values + * + * @param none + * @return the present aggregator values + */ + std::vector<T> get_values() override { return this->values_; } + + /** + * Returns the indices (or values) stored by this sketch aggregator. + * + * @param none + * @return a vector of all values the aggregator is currently tracking + */ + virtual std::vector<double> get_boundaries() override + { + std::vector<double> ret; + for (auto const &x : checkpoint_raw_) + { + ret.push_back(2 * pow(gamma, x.first) / (gamma + 1)); + } + return ret; + } + + /** + * Returns the error bound + * + * @param none + * @return the error bound specified during construction + */ + virtual double get_error_bound() override { return error_bound_; } + + /** + * Returns the maximum allowed buckets + * + * @param none + * @return the maximum allowed buckets + */ + virtual size_t get_max_buckets() override { return max_buckets_; } + + /** + * Returns the count of each value tracked by this sketch aggregator. These are returned + * in the same order as the indices returned by the get_boundaries function. + * + * @param none + * @return a vector of all counts for values tracked by the aggregator + */ + virtual std::vector<int> get_counts() override + { + std::vector<int> ret; + for (auto const &x : checkpoint_raw_) + { + ret.push_back(x.second); + } + return ret; + } + +private: + double gamma; + double error_bound_; + size_t max_buckets_; + std::map<int, int> raw_; + std::map<int, int> checkpoint_raw_; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/async_instruments.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/async_instruments.h new file mode 100644 index 000000000..5213a4e2e --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/async_instruments.h @@ -0,0 +1,286 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include <map> +# include <memory> +# include <sstream> +# include <stdexcept> +# include <vector> +# include "opentelemetry/_metrics/async_instruments.h" +# include "opentelemetry/sdk/_metrics/aggregator/counter_aggregator.h" +# include "opentelemetry/sdk/_metrics/aggregator/min_max_sum_count_aggregator.h" +# include "opentelemetry/sdk/_metrics/instrument.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +# if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable : 4250) // inheriting methods via dominance +# endif + +template <class T> +class ValueObserver : public AsynchronousInstrument<T>, + virtual public opentelemetry::metrics::ValueObserver<T> +{ + +public: + ValueObserver() = default; + + ValueObserver(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled, + void (*callback)(opentelemetry::metrics::ObserverResult<T>)) + : AsynchronousInstrument<T>(name, + description, + unit, + enabled, + callback, + opentelemetry::metrics::InstrumentKind::ValueObserver) + {} + + /* + * 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 opentelemetry::common::KeyValueIterable &labels) override + { + this->mu_.lock(); + std::string labelset = KvToString(labels); + if (boundAggregators_.find(labelset) == boundAggregators_.end()) + { + auto sp1 = std::shared_ptr<Aggregator<T>>(new MinMaxSumCountAggregator<T>(this->kind_)); + boundAggregators_.insert(std::make_pair(labelset, sp1)); + sp1->update(value); + } + else + { + boundAggregators_[labelset]->update(value); + } + this->mu_.unlock(); + } + + /* + * Activate the instrument's callback function to record a measurement. This + * function will be called by the specified controller at a regular interval. + * + * @param none + * @return none + */ + virtual void run() override + { + opentelemetry::metrics::ObserverResult<T> res(this); + this->callback_(res); + } + + virtual std::vector<Record> GetRecords() override + { + this->mu_.lock(); + std::vector<Record> ret; + for (auto x : boundAggregators_) + { + x.second->checkpoint(); + ret.push_back(Record(this->GetName(), this->GetDescription(), x.first, x.second)); + } + boundAggregators_.clear(); + this->mu_.unlock(); + return ret; + } + + // Public mapping from labels (stored as strings) to their respective aggregators + std::unordered_map<std::string, std::shared_ptr<Aggregator<T>>> boundAggregators_; +}; + +template <class T> +class SumObserver : public AsynchronousInstrument<T>, + virtual public opentelemetry::metrics::SumObserver<T> +{ + +public: + SumObserver() = default; + + SumObserver(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled, + void (*callback)(opentelemetry::metrics::ObserverResult<T>)) + : AsynchronousInstrument<T>(name, + description, + unit, + enabled, + callback, + opentelemetry::metrics::InstrumentKind::SumObserver) + {} + + /* + * 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 opentelemetry::common::KeyValueIterable &labels) override + { + this->mu_.lock(); + std::string labelset = KvToString(labels); + if (boundAggregators_.find(labelset) == boundAggregators_.end()) + { + auto sp1 = std::shared_ptr<Aggregator<T>>(new CounterAggregator<T>(this->kind_)); + boundAggregators_.insert(std::make_pair(labelset, sp1)); + if (value < 0) + { +# if __EXCEPTIONS + throw std::invalid_argument("Counter instrument updates must be non-negative."); +# else + std::terminate(); +# endif + } + else + { + sp1->update(value); + } + } + else + { + if (value < 0) + { +# if __EXCEPTIONS + throw std::invalid_argument("Counter instrument updates must be non-negative."); +# else + std::terminate(); +# endif + } + else + { + boundAggregators_[labelset]->update(value); + } + } + this->mu_.unlock(); + } + + /* + * Activate the intsrument's callback function to record a measurement. This + * function will be called by the specified controller at a regular interval. + * + * @param none + * @return none + */ + virtual void run() override + { + opentelemetry::metrics::ObserverResult<T> res(this); + this->callback_(res); + } + + virtual std::vector<Record> GetRecords() override + { + this->mu_.lock(); + std::vector<Record> ret; + for (auto x : boundAggregators_) + { + x.second->checkpoint(); + ret.push_back(Record(this->GetName(), this->GetDescription(), x.first, x.second)); + } + boundAggregators_.clear(); + this->mu_.unlock(); + return ret; + } + + // Public mapping from labels (stored as strings) to their respective aggregators + std::unordered_map<std::string, std::shared_ptr<Aggregator<T>>> boundAggregators_; +}; + +template <class T> +class UpDownSumObserver : public AsynchronousInstrument<T>, + virtual public opentelemetry::metrics::UpDownSumObserver<T> +{ + +public: + UpDownSumObserver() = default; + + UpDownSumObserver(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled, + void (*callback)(opentelemetry::metrics::ObserverResult<T>)) + : AsynchronousInstrument<T>(name, + description, + unit, + enabled, + callback, + opentelemetry::metrics::InstrumentKind::UpDownSumObserver) + {} + + /* + * 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 opentelemetry::common::KeyValueIterable &labels) override + { + this->mu_.lock(); + std::string labelset = KvToString(labels); + if (boundAggregators_.find(labelset) == boundAggregators_.end()) + { + auto sp1 = std::shared_ptr<Aggregator<T>>(new CounterAggregator<T>(this->kind_)); + boundAggregators_.insert(std::make_pair(labelset, sp1)); + sp1->update(value); + } + else + { + boundAggregators_[labelset]->update(value); + } + this->mu_.unlock(); + } + + /* + * Activate the intsrument's callback function to record a measurement. This + * function will be called by the specified controller at a regular interval. + * + * @param none + * @return none + */ + virtual void run() override + { + opentelemetry::metrics::ObserverResult<T> res(this); + this->callback_(res); + } + + virtual std::vector<Record> GetRecords() override + { + this->mu_.lock(); + std::vector<Record> ret; + for (auto x : boundAggregators_) + { + x.second->checkpoint(); + ret.push_back(Record(this->GetName(), this->GetDescription(), x.first, x.second)); + } + boundAggregators_.clear(); + this->mu_.unlock(); + return ret; + } + + // Public mapping from labels (stored as strings) to their respective aggregators + std::unordered_map<std::string, std::shared_ptr<Aggregator<T>>> boundAggregators_; +}; + +# if defined(_MSC_VER) +# pragma warning(pop) +# endif + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/controller.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/controller.h new file mode 100644 index 000000000..66a57a2ef --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/controller.h @@ -0,0 +1,154 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include <atomic> +# include <iostream> +# include <sstream> +# include <thread> +# include <vector> + +# include "opentelemetry/_metrics/instrument.h" +# include "opentelemetry/common/macros.h" +# include "opentelemetry/nostd/unique_ptr.h" +# include "opentelemetry/sdk/_metrics/exporter.h" +# include "opentelemetry/sdk/_metrics/meter.h" +# include "opentelemetry/sdk/_metrics/processor.h" +# include "opentelemetry/sdk/_metrics/record.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +class PushController +{ + +public: + PushController(nostd::shared_ptr<opentelemetry::metrics::Meter> meter, + nostd::unique_ptr<MetricsExporter> exporter, + nostd::shared_ptr<MetricsProcessor> processor, + double period, + int timeout = 30) + { + meter_ = meter; + exporter_ = std::move(exporter); + processor_ = processor; + timeout_ = (unsigned int)(timeout * 1000000); // convert seconds to microseconds + period_ = (unsigned int)(period * 1000000); + } + + /* + * Used to check if the metrics pipeline is currently active + * + * @param none + * @return true when active, false when on standby. This is a best guess estimate + * and the boolean from start() should be used to determine wheher the pipeline + * was initiated successfully. + */ + bool isActive() { return active_.load(); } + + /* + * Begins the data processing and export pipeline. The function first ensures that the pipeline + * is not already running. If not, it begins and detaches a new thread for the Controller's run + * function which periodically polls the instruments for their data. + * + * @param none + * @return a boolean which is true when the pipeline is successfully started and false when + * already active + */ + bool start() + { + if (!active_.exchange(true)) + { + runner_ = std::thread(&PushController::run, this); + return true; + } + return false; + } + + /* + * Ends the processing and export pipeline then exports metrics one last time + * before returning. + * + * @param none + * @return none + */ + void stop() + { + if (active_.exchange(false)) + { + if (runner_.joinable()) + { + runner_.join(); + } + tick(); // flush metrics sitting in the processor + } + } + +private: + /* + * Run the tick function at a regular interval. This function + * should be run in its own thread. + * + * Used to wait between collection intervals. + */ + void run() + { + if (!running_.exchange(true)) + { + while (active_.load()) + { + tick(); + std::this_thread::sleep_for(std::chrono::microseconds(period_)); + } + running_.exchange(false); + } + } + + /* + * Tick + * + * Called at regular intervals, this function collects all values from the + * member variable meter_, then sends them to the processor_ for + * processing. After the records have been processed they are sent to the + * exporter_ to be exported. + * + */ + void tick() + { + this->mu_.lock(); +# ifdef OPENTELEMETRY_RTTI_ENABLED + std::vector<Record> collected = dynamic_cast<Meter *>(meter_.get())->Collect(); +# else + std::vector<Record> collected = static_cast<Meter *>(meter_.get())->Collect(); +# endif + for (const auto &rec : collected) + { + processor_->process(rec); + } + collected = processor_->CheckpointSelf(); + processor_->FinishedCollection(); + exporter_->Export(collected); + this->mu_.unlock(); + } + + nostd::shared_ptr<opentelemetry::metrics::Meter> meter_; + nostd::unique_ptr<MetricsExporter> exporter_; + nostd::shared_ptr<MetricsProcessor> processor_; + std::thread runner_; + std::mutex mu_; + std::atomic<bool> active_ = ATOMIC_VAR_INIT(false); + std::atomic<bool> running_ = ATOMIC_VAR_INIT(false); + unsigned int period_; + unsigned int timeout_; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/exporter.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/exporter.h new file mode 100644 index 000000000..aae416527 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/exporter.h @@ -0,0 +1,35 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include <memory> +# include "opentelemetry/sdk/_metrics/record.h" +# include "opentelemetry/sdk/common/exporter_utils.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +/** + * MetricsExporter defines the interface that protocol-specific span exporters must + * implement. + */ +class MetricsExporter +{ +public: + virtual ~MetricsExporter() = default; + + /** + * Exports a vector of Records. This method must not be called + * concurrently for the same exporter instance. + * @param records a vector of unique pointers to metric records + */ + virtual sdk::common::ExportResult Export(const std::vector<Record> &records) noexcept = 0; +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/instrument.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/instrument.h new file mode 100644 index 000000000..51111be5e --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/instrument.h @@ -0,0 +1,312 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include <iostream> +# include <map> +# include <memory> +# include <sstream> +# include <string> +# include <unordered_map> +# include <vector> +# include "opentelemetry/_metrics/instrument.h" +# include "opentelemetry/sdk/_metrics/aggregator/aggregator.h" +# include "opentelemetry/sdk/_metrics/record.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +# if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable : 4250) // inheriting methods via dominance +# endif + +class Instrument : virtual public opentelemetry::metrics::Instrument +{ + +public: + Instrument() = default; + + Instrument(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled, + opentelemetry::metrics::InstrumentKind kind) + : name_(name), description_(description), unit_(unit), enabled_(enabled), kind_(kind) + {} + + // Returns true if the instrument is enabled and collecting data + virtual bool IsEnabled() override { return enabled_; } + + // Return the instrument name + virtual nostd::string_view GetName() override { return name_; } + + // Return the instrument description + virtual nostd::string_view GetDescription() override { return description_; } + + // Return the insrument's units of measurement + virtual nostd::string_view GetUnits() override { return unit_; } + + virtual opentelemetry::metrics::InstrumentKind GetKind() override { return this->kind_; } + +protected: + std::string name_; + std::string description_; + std::string unit_; + bool enabled_; + std::mutex mu_; + opentelemetry::metrics::InstrumentKind kind_; +}; + +template <class T> +class BoundSynchronousInstrument + : public Instrument, + virtual public opentelemetry::metrics::BoundSynchronousInstrument<T> +{ + +public: + BoundSynchronousInstrument() = default; + + BoundSynchronousInstrument(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled, + opentelemetry::metrics::InstrumentKind kind, + std::shared_ptr<Aggregator<T>> agg) + : Instrument(name, description, unit, enabled, kind), agg_(agg) + { + this->inc_ref(); // increase reference count when instantiated + } + + /** + * 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() override + { + this->mu_.lock(); + ref_ -= 1; + this->mu_.unlock(); + } + + /** + * Increments the reference count. This function is used when binding or instantiating. + * + * @param none + * @return void + */ + virtual void inc_ref() override + { + this->mu_.lock(); + ref_ += 1; + this->mu_.unlock(); + } + + /** + * Returns the current reference count of the instrument. This value is used to + * later in the pipeline remove stale instruments. + * + * @param none + * @return current ref count of the instrument + */ + virtual int get_ref() override + { + this->mu_.lock(); + auto ret = ref_; + this->mu_.unlock(); + return ret; + } + + /** + * Records a single synchronous metric event via 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) override + { + this->mu_.lock(); + agg_->update(value); + this->mu_.unlock(); + } + + /** + * Returns the aggregator responsible for meaningfully combining update values. + * + * @param none + * @return the aggregator assigned to this instrument + */ + virtual std::shared_ptr<Aggregator<T>> GetAggregator() final { return agg_; } + +private: + std::shared_ptr<Aggregator<T>> agg_; + int ref_ = 0; +}; + +template <class T> +class SynchronousInstrument : public Instrument, + virtual public opentelemetry::metrics::SynchronousInstrument<T> +{ + +public: + SynchronousInstrument() = default; + + SynchronousInstrument(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled, + opentelemetry::metrics::InstrumentKind kind) + : Instrument(name, description, unit, enabled, kind) + {} + + /** + * 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<opentelemetry::metrics::BoundSynchronousInstrument<T>> bind( + const opentelemetry::common::KeyValueIterable &labels) override + { + return nostd::shared_ptr<BoundSynchronousInstrument<T>>(); + } + + // This function is necessary for batch recording and should NOT be called by the user + virtual void update(T value, const opentelemetry::common::KeyValueIterable &labels) override = 0; + + /** + * Checkpoints instruments and returns a set of records which are ready for processing. + * This method should ONLY be called by the Meter Class as part of the export pipeline + * as it also prunes bound instruments with no active references. + * + * @param none + * @return vector of Records which hold the data attached to this synchronous instrument + */ + virtual std::vector<Record> GetRecords() = 0; +}; + +template <class T> +class AsynchronousInstrument : public Instrument, + virtual public opentelemetry::metrics::AsynchronousInstrument<T> +{ + +public: + AsynchronousInstrument() = default; + + AsynchronousInstrument(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled, + void (*callback)(opentelemetry::metrics::ObserverResult<T>), + opentelemetry::metrics::InstrumentKind kind) + : Instrument(name, description, unit, enabled, kind) + { + this->callback_ = callback; + } + + /** + * 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 opentelemetry::common::KeyValueIterable &labels) override = 0; + + virtual std::vector<Record> GetRecords() = 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; +}; + +// Helper functions for turning a common::KeyValueIterable into a string +inline void print_value(std::stringstream &ss, + opentelemetry::common::AttributeValue &value, + bool jsonTypes = false) +{ + switch (value.index()) + { + case opentelemetry::common::AttributeType::kTypeString: + + ss << nostd::get<nostd::string_view>(value); + + break; + default: +# if __EXCEPTIONS + throw std::invalid_argument("Labels must be strings"); +# else + std::terminate(); +# endif + break; + } +}; + +// Utility function which converts maps to strings for better performance +inline std::string mapToString(const std::map<std::string, std::string> &conv) +{ + std::stringstream ss; + ss << "{"; + for (auto i : conv) + { + ss << i.first << ':' << i.second << ','; + } + ss << "}"; + return ss.str(); +} + +inline std::string KvToString(const opentelemetry::common::KeyValueIterable &kv) noexcept +{ + std::stringstream ss; + ss << "{"; + size_t size = kv.size(); + if (size) + { + size_t i = 1; + kv.ForEachKeyValue( + [&](nostd::string_view key, opentelemetry::common::AttributeValue value) noexcept { + ss << key << ":"; + print_value(ss, value, true); + if (size != i) + { + ss << ","; + } + i++; + return true; + }); + }; + ss << "}"; + return ss.str(); +} + +# if defined(_MSC_VER) +# pragma warning(pop) +# endif + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/meter.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/meter.h new file mode 100644 index 000000000..a91a3ed2b --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/meter.h @@ -0,0 +1,392 @@ +// 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/sdk/_metrics/async_instruments.h" +# include "opentelemetry/sdk/_metrics/instrument.h" +# include "opentelemetry/sdk/_metrics/record.h" +# include "opentelemetry/sdk/_metrics/sync_instruments.h" + +# include <unordered_set> +# include <vector> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +class Meter : public opentelemetry::metrics::Meter +{ +public: + explicit Meter(std::string library_name, std::string library_version = "") + { + library_name_ = library_name; + library_version_ = library_version; + } + + /** + * 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 invalid_argument exception if name is null or does not conform to OTel syntax. + */ + nostd::shared_ptr<opentelemetry::metrics::Counter<short>> NewShortCounter( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override; + + nostd::shared_ptr<opentelemetry::metrics::Counter<int>> NewIntCounter( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override; + + nostd::shared_ptr<opentelemetry::metrics::Counter<float>> NewFloatCounter( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override; + + nostd::shared_ptr<opentelemetry::metrics::Counter<double>> NewDoubleCounter( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override; + + /** + * 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 invalid_argument exception if name is null or does not conform to OTel syntax. + */ + nostd::shared_ptr<opentelemetry::metrics::UpDownCounter<short>> NewShortUpDownCounter( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override; + + nostd::shared_ptr<opentelemetry::metrics::UpDownCounter<int>> NewIntUpDownCounter( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override; + + nostd::shared_ptr<opentelemetry::metrics::UpDownCounter<float>> NewFloatUpDownCounter( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override; + + nostd::shared_ptr<opentelemetry::metrics::UpDownCounter<double>> NewDoubleUpDownCounter( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override; + + /** + * 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 invalid_argument exception if name is null or does not conform to OTel syntax. + */ + nostd::shared_ptr<opentelemetry::metrics::ValueRecorder<short>> NewShortValueRecorder( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override; + + nostd::shared_ptr<opentelemetry::metrics::ValueRecorder<int>> NewIntValueRecorder( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override; + + nostd::shared_ptr<opentelemetry::metrics::ValueRecorder<float>> NewFloatValueRecorder( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override; + + nostd::shared_ptr<opentelemetry::metrics::ValueRecorder<double>> NewDoubleValueRecorder( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled) override; + + /** + * 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 invalid_argument exception if name is null or does not conform to OTel syntax. + */ + nostd::shared_ptr<opentelemetry::metrics::SumObserver<short>> NewShortSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(opentelemetry::metrics::ObserverResult<short>)) override; + + nostd::shared_ptr<opentelemetry::metrics::SumObserver<int>> NewIntSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(opentelemetry::metrics::ObserverResult<int>)) override; + + nostd::shared_ptr<opentelemetry::metrics::SumObserver<float>> NewFloatSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(opentelemetry::metrics::ObserverResult<float>)) override; + + nostd::shared_ptr<opentelemetry::metrics::SumObserver<double>> NewDoubleSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(opentelemetry::metrics::ObserverResult<double>)) override; + + /** + * 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 invalid_argument exception if name is null or does not conform to OTel syntax. + */ + nostd::shared_ptr<opentelemetry::metrics::UpDownSumObserver<short>> NewShortUpDownSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(opentelemetry::metrics::ObserverResult<short>)) override; + + nostd::shared_ptr<opentelemetry::metrics::UpDownSumObserver<int>> NewIntUpDownSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(opentelemetry::metrics::ObserverResult<int>)) override; + + nostd::shared_ptr<opentelemetry::metrics::UpDownSumObserver<float>> NewFloatUpDownSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(opentelemetry::metrics::ObserverResult<float>)) override; + + nostd::shared_ptr<opentelemetry::metrics::UpDownSumObserver<double>> NewDoubleUpDownSumObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(opentelemetry::metrics::ObserverResult<double>)) override; + + /** + * 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 invalid_argument exception if name is null or does not conform to OTel syntax. + */ + nostd::shared_ptr<opentelemetry::metrics::ValueObserver<short>> NewShortValueObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(opentelemetry::metrics::ObserverResult<short>)) override; + + nostd::shared_ptr<opentelemetry::metrics::ValueObserver<int>> NewIntValueObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(opentelemetry::metrics::ObserverResult<int>)) override; + + nostd::shared_ptr<opentelemetry::metrics::ValueObserver<float>> NewFloatValueObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(opentelemetry::metrics::ObserverResult<float>)) override; + + nostd::shared_ptr<opentelemetry::metrics::ValueObserver<double>> NewDoubleValueObserver( + nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + const bool enabled, + void (*callback)(opentelemetry::metrics::ObserverResult<double>)) override; + + /** + * 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 values a span of pairs where the first element of the pair is a metric instrument + * to record to, and the second element is the value to update that instrument with. + */ + void RecordShortBatch( + const opentelemetry::common::KeyValueIterable &labels, + nostd::span<opentelemetry::metrics::SynchronousInstrument<short> *> instruments, + nostd::span<const short> values) noexcept override; + + void RecordIntBatch(const opentelemetry::common::KeyValueIterable &labels, + nostd::span<opentelemetry::metrics::SynchronousInstrument<int> *> instruments, + nostd::span<const int> values) noexcept override; + + void RecordFloatBatch( + const opentelemetry::common::KeyValueIterable &labels, + nostd::span<opentelemetry::metrics::SynchronousInstrument<float> *> instruments, + nostd::span<const float> values) noexcept override; + + void RecordDoubleBatch( + const opentelemetry::common::KeyValueIterable &labels, + nostd::span<opentelemetry::metrics::SynchronousInstrument<double> *> instruments, + nostd::span<const double> values) noexcept override; + + /** + * An SDK-only function that checkpoints the aggregators of all instruments created from + * this meter, creates a {@code Record} out of them, and sends them for export. + * + * @return A vector of {@code Records} to be sent to the processor. + */ + std::vector<Record> Collect() noexcept; + +private: + /** + * A private function that creates records from all synchronous instruments created from + * this meter. + * + * @param records A reference to the vector to push the new records to. + */ + void CollectMetrics(std::vector<Record> &records); + + /** + * Helper function to collect Records from a single synchronous instrument + * + * @tparam T The integral type of the instrument to collect from. + * @param i A map iterator pointing to the instrument to collect from + * @param records The vector to add the new records to. + */ + template <typename T> + void CollectSingleSyncInstrument( + typename std::map<std::string, + std::shared_ptr<opentelemetry::metrics::SynchronousInstrument<T>>>::iterator + i, + std::vector<Record> &records); + + /** + * A private function that creates records from all asynchronous instruments created from + * this meter. + * + * @param records A reference to the vector to push the new records to. + */ + void CollectObservers(std::vector<Record> &records); + + /** + * Helper function to collect Records from a single asynchronous instrument + * + * @tparam T The integral type of the instrument to collect from. + * @param i A map iterator pointing to the instrument to collect from + * @param records The vector to add the new records to. + */ + template <typename T> + void CollectSingleAsyncInstrument( + typename std::map< + std::string, + std::shared_ptr<opentelemetry::metrics::AsynchronousInstrument<T>>>::iterator i, + std::vector<Record> &records); + + /** + * Utility function used by the meter that checks if a user-passed name abides by OpenTelemetry + * naming rules. The rules are as follows: + * 1. The name must not be empty. + * 2. The name must not start with a digit, a space, or any punctuation. + * 3. The name must only have the following chaacters: + * All alphanumeric characters, '.', '_' and '-'. + * + * @param name The name to be examined for legality. + * @return A bool representing whether the name is valid by the OpenTelemetry syntax rules. + */ + bool IsValidName(nostd::string_view name); + + /** + * A utility function used by the meter to determine whether an instrument of a specified + * name already exists in this meter. + * + * @param name The name to examine. + * @return A boolean representing whether the name has already been used by this meter. + */ + bool NameAlreadyUsed(nostd::string_view name); + + /* + * All instruments must be stored in a map so the meter can collect on these instruments. + * Additionally, when creating a new instrument, the meter must check if an instrument of the same + * name already exists. + */ + std::map<std::string, std::shared_ptr<opentelemetry::metrics::SynchronousInstrument<short>>> + short_metrics_; + std::map<std::string, std::shared_ptr<opentelemetry::metrics::SynchronousInstrument<int>>> + int_metrics_; + std::map<std::string, std::shared_ptr<opentelemetry::metrics::SynchronousInstrument<float>>> + float_metrics_; + std::map<std::string, std::shared_ptr<opentelemetry::metrics::SynchronousInstrument<double>>> + double_metrics_; + + std::map<std::string, std::shared_ptr<opentelemetry::metrics::AsynchronousInstrument<short>>> + short_observers_; + std::map<std::string, std::shared_ptr<opentelemetry::metrics::AsynchronousInstrument<int>>> + int_observers_; + std::map<std::string, std::shared_ptr<opentelemetry::metrics::AsynchronousInstrument<float>>> + float_observers_; + std::map<std::string, std::shared_ptr<opentelemetry::metrics::AsynchronousInstrument<double>>> + double_observers_; + + std::unordered_set<std::string> names_; + + std::string library_name_; + std::string library_version_; + + std::mutex metrics_lock_; + std::mutex observers_lock_; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/meter_provider.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/meter_provider.h new file mode 100644 index 000000000..da218ceac --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/meter_provider.h @@ -0,0 +1,37 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include "opentelemetry/_metrics/meter_provider.h" +# include "opentelemetry/nostd/shared_ptr.h" +# include "opentelemetry/sdk/_metrics/meter.h" + +# include <memory> +# include <string> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +class MeterProvider final : public opentelemetry::metrics::MeterProvider +{ +public: + /** + * Initialize a new meter provider + */ + explicit MeterProvider(std::string library_name = "", std::string library_version = "") noexcept; + + opentelemetry::nostd::shared_ptr<opentelemetry::metrics::Meter> GetMeter( + nostd::string_view library_name, + nostd::string_view library_version = "") noexcept override; + +private: + std::shared_ptr<opentelemetry::metrics::Meter> meter_; +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/processor.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/processor.h new file mode 100644 index 000000000..dd6c421fb --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/processor.h @@ -0,0 +1,38 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW +# include "opentelemetry/_metrics/instrument.h" +# include "opentelemetry/nostd/string_view.h" +# include "opentelemetry/sdk/_metrics/record.h" +# include "opentelemetry/version.h" + +# include <iostream> +# include <string> +# include <unordered_map> + +OPENTELEMETRY_BEGIN_NAMESPACE + +namespace sdk +{ +namespace metrics +{ + +class MetricsProcessor +{ +public: + virtual ~MetricsProcessor() = default; + + virtual std::vector<opentelemetry::sdk::metrics::Record> CheckpointSelf() noexcept = 0; + + virtual void FinishedCollection() noexcept = 0; + + virtual void process(opentelemetry::sdk::metrics::Record record) noexcept = 0; +}; + +} // namespace metrics +} // namespace sdk + +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/record.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/record.h new file mode 100644 index 000000000..a07c1595c --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/record.h @@ -0,0 +1,50 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include <memory> +# include "opentelemetry/_metrics/instrument.h" +# include "opentelemetry/nostd/variant.h" +# include "opentelemetry/sdk/_metrics/aggregator/aggregator.h" + +OPENTELEMETRY_BEGIN_NAMESPACE + +namespace sdk +{ +namespace metrics +{ +using AggregatorVariant = nostd::variant<std::shared_ptr<Aggregator<short>>, + std::shared_ptr<Aggregator<int>>, + std::shared_ptr<Aggregator<float>>, + std::shared_ptr<Aggregator<double>>>; +class Record +{ +public: + explicit Record(nostd::string_view name, + nostd::string_view description, + std::string labels, + AggregatorVariant aggregator) + { + name_ = std::string(name); + description_ = std::string(description); + labels_ = labels; + aggregator_ = aggregator; + } + + std::string GetName() { return name_; } + std::string GetDescription() { return description_; } + std::string GetLabels() { return labels_; } + AggregatorVariant GetAggregator() { return aggregator_; } + +private: + std::string name_; + std::string description_; + std::string labels_; + AggregatorVariant aggregator_; +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/sync_instruments.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/sync_instruments.h new file mode 100644 index 000000000..80d9b6092 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/sync_instruments.h @@ -0,0 +1,465 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include <map> +# include <memory> +# include <sstream> +# include <stdexcept> +# include <vector> + +# include "opentelemetry/_metrics/sync_instruments.h" +# include "opentelemetry/common/macros.h" +# include "opentelemetry/sdk/_metrics/aggregator/counter_aggregator.h" +# include "opentelemetry/sdk/_metrics/aggregator/min_max_sum_count_aggregator.h" +# include "opentelemetry/sdk/_metrics/instrument.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +# if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable : 4250) // inheriting methods via dominance +# endif + +template <class T> +class BoundCounter final : public BoundSynchronousInstrument<T>, + public opentelemetry::metrics::BoundCounter<T> +{ + +public: + BoundCounter() = default; + + BoundCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled) + : BoundSynchronousInstrument<T>( + name, + description, + unit, + enabled, + opentelemetry::metrics::InstrumentKind::Counter, + std::shared_ptr<Aggregator<T>>(new CounterAggregator<T>( + opentelemetry::metrics::InstrumentKind::Counter))) // Aggregator is chosen here + {} + + /* + * 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) override + { + if (value < 0) + { +# if __EXCEPTIONS + throw std::invalid_argument("Counter instrument updates must be non-negative."); +# else + std::terminate(); +# endif + } + else + { + this->update(value); + } + } +}; + +template <class T> +class Counter final : public SynchronousInstrument<T>, public opentelemetry::metrics::Counter<T> +{ + +public: + Counter() = default; + + Counter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled) + : SynchronousInstrument<T>(name, + description, + unit, + enabled, + opentelemetry::metrics::InstrumentKind::Counter) + {} + + /* + * 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 BoundCounter tied to the specified labels + */ + + virtual nostd::shared_ptr<opentelemetry::metrics::BoundCounter<T>> bindCounter( + const opentelemetry::common::KeyValueIterable &labels) override + { + this->mu_.lock(); + std::string labelset = KvToString(labels); + if (boundInstruments_.find(labelset) == boundInstruments_.end()) + { + auto sp1 = nostd::shared_ptr<opentelemetry::metrics::BoundCounter<T>>( + new BoundCounter<T>(this->name_, this->description_, this->unit_, this->enabled_)); + boundInstruments_[labelset] = sp1; + this->mu_.unlock(); + return sp1; + } + else + { + boundInstruments_[labelset]->inc_ref(); + auto ret = boundInstruments_[labelset]; + this->mu_.unlock(); + return ret; + } + } + + /* + * 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 opentelemetry::common::KeyValueIterable &labels) override + { + if (value < 0) + { +# if __EXCEPTIONS + throw std::invalid_argument("Counter instrument updates must be non-negative."); +# else + std::terminate(); +# endif + } + else + { + auto sp = bindCounter(labels); + sp->update(value); + sp->unbind(); + } + } + + virtual std::vector<Record> GetRecords() override + { + this->mu_.lock(); + std::vector<Record> ret; + std::vector<std::string> toDelete; + for (const auto &x : boundInstruments_) + { + if (x.second->get_ref() == 0) + { + toDelete.push_back(x.first); + } +# ifdef OPENTELEMETRY_RTTI_ENABLED + auto agg_ptr = dynamic_cast<BoundCounter<T> *>(x.second.get())->GetAggregator(); +# else + auto agg_ptr = static_cast<BoundCounter<T> *>(x.second.get())->GetAggregator(); +# endif + if (agg_ptr->is_updated()) + { + agg_ptr->checkpoint(); + ret.push_back(Record(x.second->GetName(), x.second->GetDescription(), x.first, agg_ptr)); + } + } + for (const auto &x : toDelete) + { + boundInstruments_.erase(x); + } + this->mu_.unlock(); + return ret; + } + + virtual void update(T val, const opentelemetry::common::KeyValueIterable &labels) override + { + add(val, labels); + } + + // A collection of the bound instruments created by this unbound instrument identified by their + // labels. + std::unordered_map<std::string, nostd::shared_ptr<opentelemetry::metrics::BoundCounter<T>>> + boundInstruments_; +}; + +template <class T> +class BoundUpDownCounter final : public BoundSynchronousInstrument<T>, + virtual public opentelemetry::metrics::BoundUpDownCounter<T> +{ + +public: + BoundUpDownCounter() = default; + + BoundUpDownCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled) + : BoundSynchronousInstrument<T>(name, + description, + unit, + enabled, + opentelemetry::metrics::InstrumentKind::UpDownCounter, + std::shared_ptr<Aggregator<T>>(new CounterAggregator<T>( + opentelemetry::metrics::InstrumentKind::UpDownCounter))) + {} + + /* + * 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) override { this->update(value); } +}; + +template <class T> +class UpDownCounter final : public SynchronousInstrument<T>, + public opentelemetry::metrics::UpDownCounter<T> +{ + +public: + UpDownCounter() = default; + + UpDownCounter(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled) + : SynchronousInstrument<T>(name, + description, + unit, + enabled, + opentelemetry::metrics::InstrumentKind::UpDownCounter) + {} + + /* + * 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 + */ + nostd::shared_ptr<opentelemetry::metrics::BoundUpDownCounter<T>> bindUpDownCounter( + const opentelemetry::common::KeyValueIterable &labels) override + { + this->mu_.lock(); + std::string labelset = KvToString(labels); + if (boundInstruments_.find(labelset) == boundInstruments_.end()) + { + auto sp1 = nostd::shared_ptr<opentelemetry::metrics::BoundUpDownCounter<T>>( + new BoundUpDownCounter<T>(this->name_, this->description_, this->unit_, this->enabled_)); + boundInstruments_[labelset] = sp1; + this->mu_.unlock(); + return sp1; + } + else + { + boundInstruments_[labelset]->inc_ref(); + auto ret = boundInstruments_[labelset]; + this->mu_.unlock(); + return ret; + } + } + + /* + * 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 + */ + void add(T value, const opentelemetry::common::KeyValueIterable &labels) override + { + auto sp = bindUpDownCounter(labels); + sp->update(value); + sp->unbind(); + } + + virtual std::vector<Record> GetRecords() override + { + this->mu_.lock(); + std::vector<Record> ret; + std::vector<std::string> toDelete; + for (const auto &x : boundInstruments_) + { + if (x.second->get_ref() == 0) + { + toDelete.push_back(x.first); + } +# ifdef OPENTELEMETRY_RTTI_ENABLED + auto agg_ptr = dynamic_cast<BoundUpDownCounter<T> *>(x.second.get())->GetAggregator(); +# else + auto agg_ptr = static_cast<BoundUpDownCounter<T> *>(x.second.get())->GetAggregator(); +# endif + if (agg_ptr->is_updated()) + { + agg_ptr->checkpoint(); + ret.push_back(Record(x.second->GetName(), x.second->GetDescription(), x.first, agg_ptr)); + } + } + for (const auto &x : toDelete) + { + boundInstruments_.erase(x); + } + this->mu_.unlock(); + return ret; + } + + virtual void update(T val, const opentelemetry::common::KeyValueIterable &labels) override + { + add(val, labels); + } + + std::unordered_map<std::string, nostd::shared_ptr<opentelemetry::metrics::BoundUpDownCounter<T>>> + boundInstruments_; +}; + +template <class T> +class BoundValueRecorder final : public BoundSynchronousInstrument<T>, + public opentelemetry::metrics::BoundValueRecorder<T> +{ + +public: + BoundValueRecorder() = default; + + BoundValueRecorder(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled) + : BoundSynchronousInstrument<T>( + name, + description, + unit, + enabled, + opentelemetry::metrics::InstrumentKind::ValueRecorder, + std::shared_ptr<Aggregator<T>>(new MinMaxSumCountAggregator<T>( + opentelemetry::metrics::InstrumentKind::ValueRecorder))) + {} + + /* + * 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 + */ + void record(T value) { this->update(value); } +}; + +template <class T> +class ValueRecorder final : public SynchronousInstrument<T>, + public opentelemetry::metrics::ValueRecorder<T> +{ + +public: + ValueRecorder() = default; + + ValueRecorder(nostd::string_view name, + nostd::string_view description, + nostd::string_view unit, + bool enabled) + : SynchronousInstrument<T>(name, + description, + unit, + enabled, + opentelemetry::metrics::InstrumentKind::ValueRecorder) + {} + + /* + * 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 + */ + nostd::shared_ptr<opentelemetry::metrics::BoundValueRecorder<T>> bindValueRecorder( + const opentelemetry::common::KeyValueIterable &labels) override + { + this->mu_.lock(); + std::string labelset = KvToString(labels); + if (boundInstruments_.find(labelset) == boundInstruments_.end()) + { + auto sp1 = nostd::shared_ptr<opentelemetry::metrics::BoundValueRecorder<T>>( + new BoundValueRecorder<T>(this->name_, this->description_, this->unit_, this->enabled_)); + boundInstruments_[labelset] = sp1; + this->mu_.unlock(); + return sp1; + } + else + { + boundInstruments_[labelset]->inc_ref(); + auto ret = boundInstruments_[labelset]; + this->mu_.unlock(); + return ret; + } + } + + /* + * 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 + */ + void record(T value, const opentelemetry::common::KeyValueIterable &labels) override + { + auto sp = bindValueRecorder(labels); + sp->update(value); + sp->unbind(); + } + + virtual std::vector<Record> GetRecords() override + { + this->mu_.lock(); + std::vector<Record> ret; + std::vector<std::string> toDelete; + for (const auto &x : boundInstruments_) + { + if (x.second->get_ref() == 0) + { + toDelete.push_back(x.first); + } +# ifdef OPENTELEMETRY_RTTI_ENABLED + auto agg_ptr = dynamic_cast<BoundValueRecorder<T> *>(x.second.get())->GetAggregator(); +# else + auto agg_ptr = static_cast<BoundValueRecorder<T> *>(x.second.get())->GetAggregator(); +# endif + if (agg_ptr->is_updated()) + { + agg_ptr->checkpoint(); + ret.push_back(Record(x.second->GetName(), x.second->GetDescription(), x.first, agg_ptr)); + } + } + for (const auto &x : toDelete) + { + boundInstruments_.erase(x); + } + this->mu_.unlock(); + return ret; + } + + virtual void update(T value, const opentelemetry::common::KeyValueIterable &labels) override + { + record(value, labels); + } + + std::unordered_map<std::string, nostd::shared_ptr<opentelemetry::metrics::BoundValueRecorder<T>>> + boundInstruments_; +}; + +# if defined(_MSC_VER) +# pragma warning(pop) +# endif + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/ungrouped_processor.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/ungrouped_processor.h new file mode 100644 index 000000000..cc13ae52b --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/ungrouped_processor.h @@ -0,0 +1,365 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_METRICS_PREVIEW + +# include <map> + +# include "opentelemetry/common/macros.h" +# include "opentelemetry/sdk/_metrics/aggregator/counter_aggregator.h" +# include "opentelemetry/sdk/_metrics/aggregator/exact_aggregator.h" +# include "opentelemetry/sdk/_metrics/aggregator/gauge_aggregator.h" +# include "opentelemetry/sdk/_metrics/aggregator/histogram_aggregator.h" +# include "opentelemetry/sdk/_metrics/aggregator/min_max_sum_count_aggregator.h" +# include "opentelemetry/sdk/_metrics/aggregator/sketch_aggregator.h" +# include "opentelemetry/sdk/_metrics/processor.h" +# include "opentelemetry/sdk/_metrics/record.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE + +namespace sdk +{ + +namespace metrics +{ + +struct KeyStruct +{ + std::string name; + std::string description; + std::string labels; + opentelemetry::metrics::InstrumentKind ins_kind; + + // constructor + KeyStruct(std::string name, + std::string description, + std::string labels, + opentelemetry::metrics::InstrumentKind ins_kind) + { + this->name = name; + this->description = description; + this->labels = labels; + this->ins_kind = ins_kind; + } + + // operator== is required to compare keys in case of hash collision + bool operator==(const KeyStruct &p) const + { + return name == p.name && description == p.description && labels == p.labels && + ins_kind == p.ins_kind; + } +}; + +struct KeyStruct_Hash +{ + std::size_t operator()(const KeyStruct &keystruct) const + { + std::size_t name_size = keystruct.name.length(); + std::size_t desc_size = keystruct.description.length(); + std::size_t labels_size = keystruct.labels.length(); + std::size_t ins_size = (int)keystruct.ins_kind; + + return (name_size ^ desc_size ^ labels_size) + ins_size; + } +}; + +class UngroupedMetricsProcessor : public MetricsProcessor +{ +public: + explicit UngroupedMetricsProcessor(bool stateful); + + std::vector<opentelemetry::sdk::metrics::Record> CheckpointSelf() noexcept override; + + virtual void FinishedCollection() noexcept override; + + virtual void process(opentelemetry::sdk::metrics::Record record) noexcept override; + +private: + bool stateful_; + std::unordered_map<KeyStruct, opentelemetry::sdk::metrics::AggregatorVariant, KeyStruct_Hash> + batch_map_; + + /** + * get_instrument returns the instrument from the passed in AggregatorVariant. We have to + * unpack the variant then get the instrument from the Aggreagtor. + */ + opentelemetry::metrics::InstrumentKind get_instrument( + opentelemetry::sdk::metrics::AggregatorVariant aggregator) + { + if (nostd::holds_alternative<std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<short>>>( + aggregator)) + { + return nostd::get<std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<short>>>(aggregator) + ->get_instrument_kind(); + } + else if (nostd::holds_alternative< + std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<int>>>(aggregator)) + { + return nostd::get<std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<int>>>(aggregator) + ->get_instrument_kind(); + } + else if (nostd::holds_alternative< + std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<float>>>(aggregator)) + { + return nostd::get<std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<float>>>(aggregator) + ->get_instrument_kind(); + } + else if (nostd::holds_alternative< + std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<double>>>(aggregator)) + { + return nostd::get<std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<double>>>( + aggregator) + ->get_instrument_kind(); + } + + return opentelemetry::metrics::InstrumentKind::Counter; + } + + /** + * aggregator_copy creates a copy of the aggregtor passed through process() for a + * stateful processor. For Sketch, Histogram and Exact we also need to pass in + * additional constructor values + */ + template <typename T> + std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>> aggregator_copy( + std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>> aggregator) + { + auto ins_kind = aggregator->get_instrument_kind(); + auto agg_kind = aggregator->get_aggregator_kind(); + + switch (agg_kind) + { + case opentelemetry::sdk::metrics::AggregatorKind::Counter: + return std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>>( + new opentelemetry::sdk::metrics::CounterAggregator<T>(ins_kind)); + + case opentelemetry::sdk::metrics::AggregatorKind::MinMaxSumCount: + return std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>>( + new opentelemetry::sdk::metrics::MinMaxSumCountAggregator<T>(ins_kind)); + + case opentelemetry::sdk::metrics::AggregatorKind::Gauge: + return std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>>( + new opentelemetry::sdk::metrics::GaugeAggregator<T>(ins_kind)); + + case opentelemetry::sdk::metrics::AggregatorKind::Sketch: + return std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>>( + new opentelemetry::sdk::metrics::SketchAggregator<T>( + ins_kind, aggregator->get_error_bound(), aggregator->get_max_buckets())); + + case opentelemetry::sdk::metrics::AggregatorKind::Histogram: + return std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>>( + new opentelemetry::sdk::metrics::HistogramAggregator<T>(ins_kind, + aggregator->get_boundaries())); + + case opentelemetry::sdk::metrics::AggregatorKind::Exact: + return std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>>( + new opentelemetry::sdk::metrics::ExactAggregator<T>( + ins_kind, aggregator->get_quant_estimation())); + + default: + return std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>>( + new opentelemetry::sdk::metrics::CounterAggregator<T>(ins_kind)); + } + }; + + /** + * aggregator_for will return an Aggregator based off the instrument passed in. This should be + * the function that we assign Aggreagtors for instruments, but is currently unused in our + * pipeline. + */ + template <typename T> + std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>> aggregator_for( + opentelemetry::metrics::InstrumentKind ins_kind) + { + switch (ins_kind) + { + case opentelemetry::metrics::InstrumentKind::Counter: + return std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>>( + new opentelemetry::sdk::metrics::CounterAggregator<T>(ins_kind)); + + case opentelemetry::metrics::InstrumentKind::UpDownCounter: + return std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>>( + new opentelemetry::sdk::metrics::CounterAggregator<T>(ins_kind)); + + case opentelemetry::metrics::InstrumentKind::ValueRecorder: + return std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>>( + new opentelemetry::sdk::metrics::MinMaxSumCountAggregator<T>(ins_kind)); + + case opentelemetry::metrics::InstrumentKind::SumObserver: + return std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>>( + new opentelemetry::sdk::metrics::CounterAggregator<T>(ins_kind)); + + case opentelemetry::metrics::InstrumentKind::UpDownSumObserver: + return std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>>( + new opentelemetry::sdk::metrics::CounterAggregator<T>(ins_kind)); + + case opentelemetry::metrics::InstrumentKind::ValueObserver: + return std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>>( + new opentelemetry::sdk::metrics::MinMaxSumCountAggregator<T>(ins_kind)); + + default: + return std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>>( + new opentelemetry::sdk::metrics::CounterAggregator<T>(ins_kind)); + } + }; + + /** + * merge_aggreagtors takes in two shared pointers to aggregators of the same kind. + * We first need to dynamically cast to the actual Aggregator that is held in the + * Aggregator<T> wrapper. Then we must get the underlying pointer from the shared + * pointer and merge them together. + */ + template <typename T> + void merge_aggregators(std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>> batch_agg, + std::shared_ptr<opentelemetry::sdk::metrics::Aggregator<T>> record_agg) + { + auto agg_kind = batch_agg->get_aggregator_kind(); + if (agg_kind == opentelemetry::sdk::metrics::AggregatorKind::Counter) + { +# ifdef OPENTELEMETRY_RTTI_ENABLED + std::shared_ptr<opentelemetry::sdk::metrics::CounterAggregator<T>> temp_batch_agg_counter = + std::dynamic_pointer_cast<opentelemetry::sdk::metrics::CounterAggregator<T>>(batch_agg); + + std::shared_ptr<opentelemetry::sdk::metrics::CounterAggregator<T>> temp_record_agg_counter = + std::dynamic_pointer_cast<opentelemetry::sdk::metrics::CounterAggregator<T>>(record_agg); +# else + std::shared_ptr<opentelemetry::sdk::metrics::CounterAggregator<T>> temp_batch_agg_counter = + std::static_pointer_cast<opentelemetry::sdk::metrics::CounterAggregator<T>>(batch_agg); + + std::shared_ptr<opentelemetry::sdk::metrics::CounterAggregator<T>> temp_record_agg_counter = + std::static_pointer_cast<opentelemetry::sdk::metrics::CounterAggregator<T>>(record_agg); +# endif + auto temp_batch_agg_raw_counter = temp_batch_agg_counter.get(); + auto temp_record_agg_raw_counter = temp_record_agg_counter.get(); + + temp_batch_agg_raw_counter->merge(*temp_record_agg_raw_counter); + } + else if (agg_kind == opentelemetry::sdk::metrics::AggregatorKind::MinMaxSumCount) + { +# ifdef OPENTELEMETRY_RTTI_ENABLED + std::shared_ptr<opentelemetry::sdk::metrics::MinMaxSumCountAggregator<T>> + temp_batch_agg_mmsc = + std::dynamic_pointer_cast<opentelemetry::sdk::metrics::MinMaxSumCountAggregator<T>>( + batch_agg); + + std::shared_ptr<opentelemetry::sdk::metrics::MinMaxSumCountAggregator<T>> + temp_record_agg_mmsc = + std::dynamic_pointer_cast<opentelemetry::sdk::metrics::MinMaxSumCountAggregator<T>>( + record_agg); +# else + std::shared_ptr<opentelemetry::sdk::metrics::MinMaxSumCountAggregator<T>> + temp_batch_agg_mmsc = + std::static_pointer_cast<opentelemetry::sdk::metrics::MinMaxSumCountAggregator<T>>( + batch_agg); + + std::shared_ptr<opentelemetry::sdk::metrics::MinMaxSumCountAggregator<T>> + temp_record_agg_mmsc = + std::static_pointer_cast<opentelemetry::sdk::metrics::MinMaxSumCountAggregator<T>>( + record_agg); +# endif + + auto temp_batch_agg_raw_mmsc = temp_batch_agg_mmsc.get(); + auto temp_record_agg_raw_mmsc = temp_record_agg_mmsc.get(); + + temp_batch_agg_raw_mmsc->merge(*temp_record_agg_raw_mmsc); + } + else if (agg_kind == opentelemetry::sdk::metrics::AggregatorKind::Gauge) + { +# ifdef OPENTELEMETRY_RTTI_ENABLED + std::shared_ptr<opentelemetry::sdk::metrics::GaugeAggregator<T>> temp_batch_agg_gauge = + std::dynamic_pointer_cast<opentelemetry::sdk::metrics::GaugeAggregator<T>>(batch_agg); + + std::shared_ptr<opentelemetry::sdk::metrics::GaugeAggregator<T>> temp_record_agg_gauge = + std::dynamic_pointer_cast<opentelemetry::sdk::metrics::GaugeAggregator<T>>(record_agg); +# else + std::shared_ptr<opentelemetry::sdk::metrics::GaugeAggregator<T>> temp_batch_agg_gauge = + std::static_pointer_cast<opentelemetry::sdk::metrics::GaugeAggregator<T>>(batch_agg); + + std::shared_ptr<opentelemetry::sdk::metrics::GaugeAggregator<T>> temp_record_agg_gauge = + std::static_pointer_cast<opentelemetry::sdk::metrics::GaugeAggregator<T>>(record_agg); +# endif + + auto temp_batch_agg_raw_gauge = temp_batch_agg_gauge.get(); + auto temp_record_agg_raw_gauge = temp_record_agg_gauge.get(); + + temp_batch_agg_raw_gauge->merge(*temp_record_agg_raw_gauge); + } + else if (agg_kind == opentelemetry::sdk::metrics::AggregatorKind::Sketch) + { +# ifdef OPENTELEMETRY_RTTI_ENABLED + std::shared_ptr<opentelemetry::sdk::metrics::SketchAggregator<T>> temp_batch_agg_sketch = + std::dynamic_pointer_cast<opentelemetry::sdk::metrics::SketchAggregator<T>>(batch_agg); + + std::shared_ptr<opentelemetry::sdk::metrics::SketchAggregator<T>> temp_record_agg_sketch = + std::dynamic_pointer_cast<opentelemetry::sdk::metrics::SketchAggregator<T>>(record_agg); +# else + std::shared_ptr<opentelemetry::sdk::metrics::SketchAggregator<T>> temp_batch_agg_sketch = + std::static_pointer_cast<opentelemetry::sdk::metrics::SketchAggregator<T>>(batch_agg); + + std::shared_ptr<opentelemetry::sdk::metrics::SketchAggregator<T>> temp_record_agg_sketch = + std::static_pointer_cast<opentelemetry::sdk::metrics::SketchAggregator<T>>(record_agg); +# endif + auto temp_batch_agg_raw_sketch = temp_batch_agg_sketch.get(); + auto temp_record_agg_raw_sketch = temp_record_agg_sketch.get(); + + temp_batch_agg_raw_sketch->merge(*temp_record_agg_raw_sketch); + } + else if (agg_kind == opentelemetry::sdk::metrics::AggregatorKind::Histogram) + { +# ifdef OPENTELEMETRY_RTTI_ENABLED + std::shared_ptr<opentelemetry::sdk::metrics::HistogramAggregator<T>> + temp_batch_agg_histogram = + std::dynamic_pointer_cast<opentelemetry::sdk::metrics::HistogramAggregator<T>>( + batch_agg); + + std::shared_ptr<opentelemetry::sdk::metrics::HistogramAggregator<T>> + temp_record_agg_histogram = + std::dynamic_pointer_cast<opentelemetry::sdk::metrics::HistogramAggregator<T>>( + record_agg); +# else + std::shared_ptr<opentelemetry::sdk::metrics::HistogramAggregator<T>> + temp_batch_agg_histogram = + std::static_pointer_cast<opentelemetry::sdk::metrics::HistogramAggregator<T>>( + batch_agg); + + std::shared_ptr<opentelemetry::sdk::metrics::HistogramAggregator<T>> + temp_record_agg_histogram = + std::static_pointer_cast<opentelemetry::sdk::metrics::HistogramAggregator<T>>( + record_agg); +# endif + + auto temp_batch_agg_raw_histogram = temp_batch_agg_histogram.get(); + auto temp_record_agg_raw_histogram = temp_record_agg_histogram.get(); + + temp_batch_agg_raw_histogram->merge(*temp_record_agg_raw_histogram); + } + else if (agg_kind == opentelemetry::sdk::metrics::AggregatorKind::Exact) + { +# ifdef OPENTELEMETRY_RTTI_ENABLED + std::shared_ptr<opentelemetry::sdk::metrics::ExactAggregator<T>> temp_batch_agg_exact = + std::dynamic_pointer_cast<opentelemetry::sdk::metrics::ExactAggregator<T>>(batch_agg); + + std::shared_ptr<opentelemetry::sdk::metrics::ExactAggregator<T>> temp_record_agg_exact = + std::dynamic_pointer_cast<opentelemetry::sdk::metrics::ExactAggregator<T>>(record_agg); +# else + std::shared_ptr<opentelemetry::sdk::metrics::ExactAggregator<T>> temp_batch_agg_exact = + std::static_pointer_cast<opentelemetry::sdk::metrics::ExactAggregator<T>>(batch_agg); + + std::shared_ptr<opentelemetry::sdk::metrics::ExactAggregator<T>> temp_record_agg_exact = + std::static_pointer_cast<opentelemetry::sdk::metrics::ExactAggregator<T>>(record_agg); +# endif + + auto temp_batch_agg_raw_exact = temp_batch_agg_exact.get(); + auto temp_record_agg_raw_exact = temp_record_agg_exact.get(); + + temp_batch_agg_raw_exact->merge(*temp_record_agg_raw_exact); + } + } +}; +} // namespace metrics +} // namespace sdk + +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/atomic_shared_ptr.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/atomic_shared_ptr.h new file mode 100644 index 000000000..07e19ac0f --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/atomic_shared_ptr.h @@ -0,0 +1,62 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <atomic> +#include <memory> +#include <mutex> +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace common +{ +/** + * A wrapper to provide atomic shared pointers. + * + * This wrapper relies on a mutex for gcc 4.8, and specializations of + * std::atomic_store and std::atomic_load for all other instances. + */ +#if (__GNUC__ == 4 && (__GNUC_MINOR__ >= 8)) +template <class T> +class AtomicSharedPtr +{ +public: + explicit AtomicSharedPtr(std::shared_ptr<T> ptr) noexcept : ptr_{std::move(ptr)} {} + + void store(const std::shared_ptr<T> &other) noexcept + { + std::lock_guard<std::mutex> lock_guard{mu_}; + ptr_ = other; + } + + std::shared_ptr<T> load() const noexcept + { + std::lock_guard<std::mutex> lock_guard{mu_}; + return ptr_; + } + +private: + std::shared_ptr<T> ptr_; + mutable std::mutex mu_; +}; +#else +template <class T> +class AtomicSharedPtr +{ +public: + explicit AtomicSharedPtr(std::shared_ptr<T> ptr) noexcept : ptr_{std::move(ptr)} {} + + void store(const std::shared_ptr<T> &other) noexcept { std::atomic_store(&ptr_, other); } + + std::shared_ptr<T> load() const noexcept { return std::atomic_load(&ptr_); } + +private: + std::shared_ptr<T> ptr_; +}; +#endif +} // namespace common +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/atomic_unique_ptr.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/atomic_unique_ptr.h new file mode 100644 index 000000000..5945df98c --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/atomic_unique_ptr.h @@ -0,0 +1,87 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <atomic> +#include <memory> + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace common +{ +/** + * An owning pointer similar to std::unique_ptr but with methods for atomic + * operations. + */ +template <class T> +class AtomicUniquePtr +{ +public: + AtomicUniquePtr() noexcept {} + + explicit AtomicUniquePtr(std::unique_ptr<T> &&other) noexcept : ptr_(other.release()) {} + + ~AtomicUniquePtr() noexcept { Reset(); } + + T &operator*() const noexcept { return *Get(); } + + T *operator->() const noexcept { return Get(); } + + /** + * @return the underly pointer managed. + */ + T *Get() const noexcept { return ptr_; } + + /** + * @return true if the pointer is null + */ + bool IsNull() const noexcept { return ptr_.load() == nullptr; } + + /** + * Atomically swap the pointer only if it's null. + * @param owner the pointer to swap with + * @return true if the swap was successful + */ + bool SwapIfNull(std::unique_ptr<T> &owner) noexcept + { + auto ptr = owner.get(); + T *expected = nullptr; + auto was_successful = ptr_.compare_exchange_weak(expected, ptr, std::memory_order_release, + std::memory_order_relaxed); + if (was_successful) + { + owner.release(); + return true; + } + return false; + } + + /** + * Atomically swap the pointer with another. + * @param ptr the pointer to swap with + */ + void Swap(std::unique_ptr<T> &other) noexcept { other.reset(ptr_.exchange(other.release())); } + + /** + * Set the pointer to a new value and delete the current value if non-null. + * @param ptr the new pointer value to set + */ + void Reset(T *ptr = nullptr) noexcept + { + ptr = ptr_.exchange(ptr); + if (ptr != nullptr) + { + delete ptr; + } + } + +private: + std::atomic<T *> ptr_{nullptr}; +}; +} // namespace common +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/attribute_utils.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/attribute_utils.h new file mode 100644 index 000000000..68b09f044 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/attribute_utils.h @@ -0,0 +1,199 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <map> +#include <string> +#include <unordered_map> +#include <vector> +#include "opentelemetry/common/attribute_value.h" +#include "opentelemetry/common/key_value_iterable_view.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace common +{ +/** + * A counterpart to AttributeValue that makes sure a value is owned. This + * replaces all non-owning references with owned copies. + * + * The following types are not currently supported by the OpenTelemetry + * specification, but reserved for future use: + * - uint64_t + * - std::vector<uint64_t> + * - std::vector<uint8_t> + */ +using OwnedAttributeValue = nostd::variant<bool, + int32_t, + uint32_t, + int64_t, + double, + std::string, + std::vector<bool>, + std::vector<int32_t>, + std::vector<uint32_t>, + std::vector<int64_t>, + std::vector<double>, + std::vector<std::string>, + uint64_t, + std::vector<uint64_t>, + std::vector<uint8_t>>; + +enum OwnedAttributeType +{ + kTypeBool, + kTypeInt, + kTypeUInt, + kTypeInt64, + kTypeDouble, + kTypeString, + kTypeSpanBool, + kTypeSpanInt, + kTypeSpanUInt, + kTypeSpanInt64, + kTypeSpanDouble, + kTypeSpanString, + kTypeUInt64, + kTypeSpanUInt64, + kTypeSpanByte +}; + +/** + * Creates an owned copy (OwnedAttributeValue) of a non-owning AttributeValue. + */ +struct AttributeConverter +{ + OwnedAttributeValue operator()(bool v) { return OwnedAttributeValue(v); } + OwnedAttributeValue operator()(int32_t v) { return OwnedAttributeValue(v); } + OwnedAttributeValue operator()(uint32_t v) { return OwnedAttributeValue(v); } + OwnedAttributeValue operator()(int64_t v) { return OwnedAttributeValue(v); } + OwnedAttributeValue operator()(uint64_t v) { return OwnedAttributeValue(v); } + OwnedAttributeValue operator()(double v) { return OwnedAttributeValue(v); } + OwnedAttributeValue operator()(nostd::string_view v) + { + return OwnedAttributeValue(std::string(v)); + } + OwnedAttributeValue operator()(std::string v) { return OwnedAttributeValue(v); } + OwnedAttributeValue operator()(const char *v) { return OwnedAttributeValue(std::string(v)); } + OwnedAttributeValue operator()(nostd::span<const uint8_t> v) { return convertSpan<uint8_t>(v); } + OwnedAttributeValue operator()(nostd::span<const bool> v) { return convertSpan<bool>(v); } + OwnedAttributeValue operator()(nostd::span<const int32_t> v) { return convertSpan<int32_t>(v); } + OwnedAttributeValue operator()(nostd::span<const uint32_t> v) { return convertSpan<uint32_t>(v); } + OwnedAttributeValue operator()(nostd::span<const int64_t> v) { return convertSpan<int64_t>(v); } + OwnedAttributeValue operator()(nostd::span<const uint64_t> v) { return convertSpan<uint64_t>(v); } + OwnedAttributeValue operator()(nostd::span<const double> v) { return convertSpan<double>(v); } + OwnedAttributeValue operator()(nostd::span<const nostd::string_view> v) + { + return convertSpan<std::string>(v); + } + + template <typename T, typename U = T> + OwnedAttributeValue convertSpan(nostd::span<const U> vals) + { + const std::vector<T> copy(vals.begin(), vals.end()); + return OwnedAttributeValue(std::move(copy)); + } +}; + +/** + * Class for storing attributes. + */ +class AttributeMap : public std::unordered_map<std::string, OwnedAttributeValue> +{ +public: + // Contruct empty attribute map + AttributeMap() : std::unordered_map<std::string, OwnedAttributeValue>(){}; + + // Contruct attribute map and populate with attributes + AttributeMap(const opentelemetry::common::KeyValueIterable &attributes) : AttributeMap() + { + attributes.ForEachKeyValue( + [&](nostd::string_view key, opentelemetry::common::AttributeValue value) noexcept { + SetAttribute(key, value); + return true; + }); + } + + // Construct map from initializer list by applying `SetAttribute` transform for every attribute + AttributeMap( + std::initializer_list<std::pair<nostd::string_view, opentelemetry::common::AttributeValue>> + attributes) + : AttributeMap() + { + for (auto &kv : attributes) + { + SetAttribute(kv.first, kv.second); + } + } + + // Returns a reference to this map + const std::unordered_map<std::string, OwnedAttributeValue> &GetAttributes() const noexcept + { + return (*this); + } + + // Convert non-owning key-value to owning std::string(key) and OwnedAttributeValue(value) + void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept + { + (*this)[std::string(key)] = nostd::visit(converter_, value); + } + +private: + AttributeConverter converter_; +}; + +/** + * Class for storing attributes. + */ +class OrderedAttributeMap : public std::map<std::string, OwnedAttributeValue> +{ +public: + // Contruct empty attribute map + OrderedAttributeMap() : std::map<std::string, OwnedAttributeValue>(){}; + + // Contruct attribute map and populate with attributes + OrderedAttributeMap(const opentelemetry::common::KeyValueIterable &attributes) + : OrderedAttributeMap() + { + attributes.ForEachKeyValue( + [&](nostd::string_view key, opentelemetry::common::AttributeValue value) noexcept { + SetAttribute(key, value); + return true; + }); + } + + // Construct map from initializer list by applying `SetAttribute` transform for every attribute + OrderedAttributeMap( + std::initializer_list<std::pair<nostd::string_view, opentelemetry::common::AttributeValue>> + attributes) + : OrderedAttributeMap() + { + for (auto &kv : attributes) + { + SetAttribute(kv.first, kv.second); + } + } + + // Returns a reference to this map + const std::map<std::string, OwnedAttributeValue> &GetAttributes() const noexcept + { + return (*this); + } + + // Convert non-owning key-value to owning std::string(key) and OwnedAttributeValue(value) + void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept + { + (*this)[std::string(key)] = nostd::visit(converter_, value); + } + +private: + AttributeConverter converter_; +}; + +} // namespace common +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/attributemap_hash.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/attributemap_hash.h new file mode 100644 index 000000000..573f57eb1 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/attributemap_hash.h @@ -0,0 +1,62 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <iostream> +#include <string> +#include "opentelemetry/sdk/common/attribute_utils.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace common +{ + +template <class T> +inline void GetHashForAttributeValue(size_t &seed, const T arg) +{ + std::hash<T> hasher; + // reference - + // https://www.boost.org/doc/libs/1_37_0/doc/html/hash/reference.html#boost.hash_combine + seed ^= hasher(arg) + 0x9e3779b9 + (seed << 6) + (seed >> 2); +} + +template <class T> +inline void GetHashForAttributeValue(size_t &seed, const std::vector<T> &arg) +{ + for (auto v : arg) + { + GetHashForAttributeValue<T>(seed, v); + } +} + +struct GetHashForAttributeValueVisitor +{ + GetHashForAttributeValueVisitor(size_t &seed) : seed_(seed) {} + template <class T> + void operator()(T &v) + { + GetHashForAttributeValue(seed_, v); + } + size_t &seed_; +}; + +// Calculate hash of keys and values of attribute map +inline size_t GetHashForAttributeMap(const OrderedAttributeMap &attribute_map) +{ + size_t seed = 0UL; + for (auto &kv : attribute_map) + { + std::hash<std::string> hasher; + // reference - + // https://www.boost.org/doc/libs/1_37_0/doc/html/hash/reference.html#boost.hash_combine + seed ^= hasher(kv.first) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + nostd::visit(GetHashForAttributeValueVisitor(seed), kv.second); + } + return seed; +} + +} // namespace common +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/circular_buffer.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/circular_buffer.h new file mode 100644 index 000000000..6af900183 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/circular_buffer.h @@ -0,0 +1,186 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <atomic> +#include <cstdint> +#include <memory> + +#include "opentelemetry/sdk/common/atomic_unique_ptr.h" +#include "opentelemetry/sdk/common/circular_buffer_range.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace common +{ +/* + * A lock-free circular buffer that supports multiple concurrent producers + * and a single consumer. + */ +template <class T> +class CircularBuffer +{ +public: + explicit CircularBuffer(size_t max_size) + : data_{new AtomicUniquePtr<T>[max_size + 1]}, capacity_{max_size + 1} + {} + + /** + * @return a range of the elements in the circular buffer + * + * Note: This method must only be called from the consumer thread. + */ + CircularBufferRange<const AtomicUniquePtr<T>> Peek() const noexcept + { + return const_cast<CircularBuffer *>(this)->PeekImpl(); + } + + /** + * Consume elements from the circular buffer's tail. + * @param n the number of elements to consume + * @param callback the callback to invoke with an AtomicUniquePtr to each + * consumed element. + * + * Note: The callback must set the passed AtomicUniquePtr to null. + * + * Note: This method must only be called from the consumer thread. + */ + template <class Callback> + void Consume(size_t n, Callback callback) noexcept + { + assert(n <= static_cast<size_t>(head_ - tail_)); + auto range = PeekImpl().Take(n); + static_assert(noexcept(callback(range)), "callback not allowed to throw"); + tail_ += n; + callback(range); + } + + /** + * Consume elements from the circular buffer's tail. + * @param n the number of elements to consume + * + * Note: This method must only be called from the consumer thread. + */ + void Consume(size_t n) noexcept + { + Consume(n, [](CircularBufferRange<AtomicUniquePtr<T>> &range) noexcept { + range.ForEach([](AtomicUniquePtr<T> &ptr) noexcept { + ptr.Reset(); + return true; + }); + }); + } + + /** + * Adds an element into the circular buffer. + * @param ptr a pointer to the element to add + * @return true if the element was successfully added; false, otherwise. + */ + bool Add(std::unique_ptr<T> &ptr) noexcept + { + while (true) + { + uint64_t tail = tail_; + uint64_t head = head_; + + // The circular buffer is full, so return false. + if (head - tail >= capacity_ - 1) + { + return false; + } + + uint64_t head_index = head % capacity_; + if (data_[head_index].SwapIfNull(ptr)) + { + auto new_head = head + 1; + auto expected_head = head; + if (head_.compare_exchange_weak(expected_head, new_head, std::memory_order_release, + std::memory_order_relaxed)) + { + // free the swapped out value + ptr.reset(); + + return true; + } + + // If we reached this point (unlikely), it means that between the last + // iteration elements were added and then consumed from the circular + // buffer, so we undo the swap and attempt to add again. + data_[head_index].Swap(ptr); + } + } + return true; + } + + /** + * Clear the circular buffer. + * + * Note: This method must only be called from the consumer thread. + */ + void Clear() noexcept { Consume(size()); } + + /** + * @return the maximum number of bytes that can be stored in the buffer. + */ + size_t max_size() const noexcept { return capacity_ - 1; } + + /** + * @return true if the buffer is empty. + */ + bool empty() const noexcept { return head_ == tail_; } + + /** + * @return the number of bytes stored in the circular buffer. + * + * Note: this method will only return a correct snapshot of the size if called + * from the consumer thread. + */ + size_t size() const noexcept + { + uint64_t tail = tail_; + uint64_t head = head_; + assert(tail <= head); + return head - tail; + } + + /** + * @return the number of elements consumed from the circular buffer. + */ + uint64_t consumption_count() const noexcept { return tail_; } + + /** + * @return the number of elements added to the circular buffer. + */ + uint64_t production_count() const noexcept { return head_; } + +private: + std::unique_ptr<AtomicUniquePtr<T>[]> data_; + size_t capacity_; + std::atomic<uint64_t> head_{0}; + std::atomic<uint64_t> tail_{0}; + + CircularBufferRange<AtomicUniquePtr<T>> PeekImpl() noexcept + { + uint64_t tail_index = tail_ % capacity_; + uint64_t head_index = head_ % capacity_; + if (head_index == tail_index) + { + return {}; + } + auto data = data_.get(); + if (tail_index < head_index) + { + return CircularBufferRange<AtomicUniquePtr<T>>{nostd::span<AtomicUniquePtr<T>>{ + data + tail_index, static_cast<std::size_t>(head_index - tail_index)}}; + } + return {nostd::span<AtomicUniquePtr<T>>{data + tail_index, + static_cast<std::size_t>(capacity_ - tail_index)}, + nostd::span<AtomicUniquePtr<T>>{data, static_cast<std::size_t>(head_index)}}; + } +}; +} // namespace common +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/circular_buffer_range.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/circular_buffer_range.h new file mode 100644 index 000000000..9ef3b66be --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/circular_buffer_range.h @@ -0,0 +1,93 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <cassert> +#include <iterator> +#include <type_traits> +#include <utility> + +#include "opentelemetry/nostd/span.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace common +{ +/** + * A non-owning view into a range of elements in a circular buffer. + */ +template <class T> +class CircularBufferRange +{ +public: + CircularBufferRange() noexcept = default; + + explicit CircularBufferRange(nostd::span<T> first) noexcept : first_{first} {} + + CircularBufferRange(nostd::span<T> first, nostd::span<T> second) noexcept + : first_{first}, second_{second} + {} + + operator CircularBufferRange<const T>() const noexcept { return {first_, second_}; } + + /** + * Iterate over the elements in the range. + * @param callback the callback to call for each element + * @return true if we iterated over all elements + */ + template <class Callback> + bool ForEach(Callback callback) const + noexcept(noexcept(std::declval<Callback>()(std::declval<T &>()))) + { + for (auto &value : first_) + { + if (!callback(value)) + { + return false; + } + } + for (auto &value : second_) + { + if (!callback(value)) + { + return false; + } + } + return true; + } + + /** + * @return the number of elements in the range + */ + size_t size() const noexcept { return first_.size() + second_.size(); } + + /** + * @return true if the range is empty + */ + bool empty() const noexcept { return first_.empty(); } + + /** + * Return a subrange taken from the start of this range. + * @param n the number of element to take in the subrange + * @return a subrange of the first n elements in this range + */ + CircularBufferRange Take(size_t n) const noexcept + { + assert(n <= size()); + if (first_.size() >= n) + { + return CircularBufferRange{nostd::span<T>{first_.data(), n}}; + } + return {first_, nostd::span<T>{second_.data(), n - first_.size()}}; + } + +private: + nostd::span<T> first_; + nostd::span<T> second_; +}; +} // namespace common +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/empty_attributes.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/empty_attributes.h new file mode 100644 index 000000000..4f740bf10 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/empty_attributes.h @@ -0,0 +1,34 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/common/key_value_iterable_view.h" +#include "opentelemetry/common/macros.h" + +#include <array> +#include <map> +#include <string> +#include <utility> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +/** + * Maintain a static empty array of pairs that represents empty (default) attributes. + * This helps to avoid constructing a new empty container every time a call is made + * with default attributes. + */ +OPENTELEMETRY_MAYBE_UNUSED static const opentelemetry::common::KeyValueIterableView< + std::array<std::pair<std::string, int>, 0>> + &GetEmptyAttributes() noexcept +{ + static const std::array<std::pair<std::string, int>, 0> array{}; + static const opentelemetry::common::KeyValueIterableView< + std::array<std::pair<std::string, int>, 0>> + kEmptyAttributes(array); + + return kEmptyAttributes; +} +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/env_variables.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/env_variables.h new file mode 100644 index 000000000..be955ee86 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/env_variables.h @@ -0,0 +1,53 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <string> +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace common +{ + +#if defined(_MSC_VER) +inline int setenv(const char *name, const char *value, int) +{ + return _putenv_s(name, value); +} + +inline int unsetenv(const char *name) +{ + return setenv(name, "", 1); +} +#endif + +// Returns the env variable set. +inline const std::string GetEnvironmentVariable(const char *env_var_name) +{ +#if !defined(NO_GETENV) + const char *endpoint_from_env = nullptr; +# if defined(_MSC_VER) + // avoid calling std::getenv which is deprecated in MSVC. + size_t required_size = 0; + getenv_s(&required_size, nullptr, 0, env_var_name); + std::unique_ptr<char> endpoint_buffer; + if (required_size > 0) + { + endpoint_buffer = std::unique_ptr<char>{new char[required_size]}; + getenv_s(&required_size, endpoint_buffer.get(), required_size, env_var_name); + endpoint_from_env = endpoint_buffer.get(); + } +# else + endpoint_from_env = std::getenv(env_var_name); +# endif // defined(_MSC_VER) + return endpoint_from_env == nullptr ? std::string{} : std::string{endpoint_from_env}; +#else + return std::string{}; +#endif // !defined(NO_GETENV) +} +} // namespace common +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/exporter_utils.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/exporter_utils.h new file mode 100644 index 000000000..091f481f9 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/exporter_utils.h @@ -0,0 +1,34 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace common +{ +/** + * ExportResult is returned as result of exporting a batch of Records. + */ +enum class ExportResult +{ + // Batch was exported successfully. + kSuccess = 0, + + // Batch exporting failed, caller must not retry exporting the same batch + // and the batch must be dropped. + kFailure = 1, + + // The collection does not have enough space to receive the export batch. + kFailureFull = 2, + + // The export() function was passed an invalid argument. + kFailureInvalidArgument = 3 +}; + +} // namespace common +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/global_log_handler.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/global_log_handler.h new file mode 100644 index 000000000..99cf48b82 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/common/global_log_handler.h @@ -0,0 +1,222 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <iostream> +#include <sstream> +#include <utility> + +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/sdk/common/attribute_utils.h" +#include "opentelemetry/version.h" + +#define OTEL_INTERNAL_LOG_LEVEL_ERROR 0 +#define OTEL_INTERNAL_LOG_LEVEL_WARN 1 +#define OTEL_INTERNAL_LOG_LEVEL_INFO 2 +#define OTEL_INTERNAL_LOG_LEVEL_DEBUG 3 +#ifndef OTEL_INTERNAL_LOG_LEVEL +// DEBUG by default, we can change log level on runtime +# define OTEL_INTERNAL_LOG_LEVEL OTEL_INTERNAL_LOG_LEVEL_DEBUG +#endif + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace common +{ +namespace internal_log +{ + +enum class LogLevel +{ + Error = 0, + Warning, + Info, + Debug +}; + +inline std::string LevelToString(LogLevel level) +{ + switch (level) + { + case LogLevel::Error: + return "Error"; + case LogLevel::Warning: + return "Warning"; + case LogLevel::Info: + return "Info"; + case LogLevel::Debug: + return "Debug"; + } + return {}; +} + +class LogHandler +{ +public: + virtual ~LogHandler(); + + virtual void Handle(LogLevel level, + const char *file, + int line, + const char *msg, + const sdk::common::AttributeMap &attributes) noexcept = 0; +}; + +class DefaultLogHandler : public LogHandler +{ +public: + void Handle(LogLevel level, + const char *file, + int line, + const char *msg, + const sdk::common::AttributeMap &attributes) noexcept override; +}; + +class NoopLogHandler : public LogHandler +{ +public: + void Handle(LogLevel level, + const char *file, + int line, + const char *msg, + const sdk::common::AttributeMap &error_attributes) noexcept override; +}; + +/** + * Stores the singleton global LogHandler. + */ +class GlobalLogHandler +{ +public: + /** + * Returns the singleton LogHandler. + * + * By default, a default LogHandler is returned. + */ + static inline const nostd::shared_ptr<LogHandler> &GetLogHandler() noexcept + { + return GetHandlerAndLevel().first; + } + + /** + * Changes the singleton LogHandler. + * This should be called once at the start of application before creating any Provider + * instance. + */ + static inline void SetLogHandler(nostd::shared_ptr<LogHandler> eh) noexcept + { + GetHandlerAndLevel().first = eh; + } + + /** + * Returns the singleton log level. + * + * By default, a default log level is returned. + */ + static inline LogLevel GetLogLevel() noexcept { return GetHandlerAndLevel().second; } + + /** + * Changes the singleton Log level. + * This should be called once at the start of application before creating any Provider + * instance. + */ + static inline void SetLogLevel(LogLevel level) noexcept { GetHandlerAndLevel().second = level; } + +private: + static std::pair<nostd::shared_ptr<LogHandler>, LogLevel> &GetHandlerAndLevel() noexcept; +}; + +} // namespace internal_log +} // namespace common +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE + +/** + * We can not decide the destroying order of signaltons. + * Which means, the destructors of other singletons (GlobalLogHandler,TracerProvider and etc.) + * may be called after destroying of global LogHandler and use OTEL_INTERNAL_LOG_* in it.We can do + * nothing but ignore the log in this situation. + */ +#define OTEL_INTERNAL_LOG_DISPATCH(level, message, attributes) \ + do \ + { \ + using opentelemetry::sdk::common::internal_log::GlobalLogHandler; \ + using opentelemetry::sdk::common::internal_log::LogHandler; \ + if (level > GlobalLogHandler::GetLogLevel()) \ + { \ + break; \ + } \ + const opentelemetry::nostd::shared_ptr<LogHandler> &log_handler = \ + GlobalLogHandler::GetLogHandler(); \ + if (!log_handler) \ + { \ + break; \ + } \ + std::stringstream tmp_stream; \ + tmp_stream << message; \ + log_handler->Handle(level, __FILE__, __LINE__, tmp_stream.str().c_str(), attributes); \ + } while (false); + +#define OTEL_INTERNAL_LOG_GET_3RD_ARG(arg1, arg2, arg3, ...) arg3 + +#if OTEL_INTERNAL_LOG_LEVEL >= OTEL_INTERNAL_LOG_LEVEL_ERROR +# define OTEL_INTERNAL_LOG_ERROR_1_ARGS(message) \ + OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Error, message, \ + {}) +# define OTEL_INTERNAL_LOG_ERROR_2_ARGS(message, attributes) \ + OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Error, message, \ + attributes) +# define OTEL_INTERNAL_LOG_ERROR_MACRO(...) \ + OTEL_INTERNAL_LOG_GET_3RD_ARG(__VA_ARGS__, OTEL_INTERNAL_LOG_ERROR_2_ARGS, \ + OTEL_INTERNAL_LOG_ERROR_1_ARGS) +# define OTEL_INTERNAL_LOG_ERROR(...) OTEL_INTERNAL_LOG_ERROR_MACRO(__VA_ARGS__)(__VA_ARGS__) +#else +# define OTEL_INTERNAL_LOG_ERROR(...) +#endif + +#if OTEL_INTERNAL_LOG_LEVEL >= OTEL_INTERNAL_LOG_LEVEL_WARN +# define OTEL_INTERNAL_LOG_WARN_1_ARGS(message) \ + OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Warning, \ + message, {}) +# define OTEL_INTERNAL_LOG_WARN_2_ARGS(message, attributes) \ + OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Warning, \ + message, attributes) +# define OTEL_INTERNAL_LOG_WARN_MACRO(...) \ + OTEL_INTERNAL_LOG_GET_3RD_ARG(__VA_ARGS__, OTEL_INTERNAL_LOG_WARN_2_ARGS, \ + OTEL_INTERNAL_LOG_WARN_1_ARGS) +# define OTEL_INTERNAL_LOG_WARN(...) OTEL_INTERNAL_LOG_WARN_MACRO(__VA_ARGS__)(__VA_ARGS__) +#else +# define OTEL_INTERNAL_LOG_ERROR(...) +#endif + +#if OTEL_INTERNAL_LOG_LEVEL >= OTEL_INTERNAL_LOG_LEVEL_DEBUG +# define OTEL_INTERNAL_LOG_DEBUG_1_ARGS(message) \ + OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Debug, message, \ + {}) +# define OTEL_INTERNAL_LOG_DEBUG_2_ARGS(message, attributes) \ + OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Debug, message, \ + attributes) +# define OTEL_INTERNAL_LOG_DEBUG_MACRO(...) \ + OTEL_INTERNAL_LOG_GET_3RD_ARG(__VA_ARGS__, OTEL_INTERNAL_LOG_DEBUG_2_ARGS, \ + OTEL_INTERNAL_LOG_DEBUG_1_ARGS) +# define OTEL_INTERNAL_LOG_DEBUG(...) OTEL_INTERNAL_LOG_DEBUG_MACRO(__VA_ARGS__)(__VA_ARGS__) +#else +# define OTEL_INTERNAL_LOG_DEBUG(...) +#endif + +#if OTEL_INTERNAL_LOG_LEVEL >= OTEL_INTERNAL_LOG_LEVEL_INFO +# define OTEL_INTERNAL_LOG_INFO_1_ARGS(message) \ + OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Info, message, \ + {}) +# define OTEL_INTERNAL_LOG_INFO_2_ARGS(message, attributes) \ + OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Info, message, \ + attributes) +# define OTEL_INTERNAL_LOG_INFO_MACRO(...) \ + OTEL_INTERNAL_LOG_GET_3RD_ARG(__VA_ARGS__, OTEL_INTERNAL_LOG_INFO_2_ARGS, \ + OTEL_INTERNAL_LOG_INFO_1_ARGS) +# define OTEL_INTERNAL_LOG_INFO(...) OTEL_INTERNAL_LOG_INFO_MACRO(__VA_ARGS__)(__VA_ARGS__) +#else +# define OTEL_INTERNAL_LOG_INFO(...) +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h new file mode 100644 index 000000000..20f82a5d1 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h @@ -0,0 +1,96 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/nostd/unique_ptr.h" +#include "opentelemetry/version.h" + +#include <functional> +#include <string> + +OPENTELEMETRY_BEGIN_NAMESPACE + +namespace sdk +{ +namespace instrumentationlibrary +{ + +class InstrumentationLibrary +{ +public: + InstrumentationLibrary(const InstrumentationLibrary &) = default; + + /** + * Returns a newly created InstrumentationLibrary with the specified library name and version. + * @param name name of the instrumentation library. + * @param version version of the instrumentation library. + * @param schema_url schema url of the telemetry emitted by the library. + * @returns the newly created InstrumentationLibrary. + */ + static nostd::unique_ptr<InstrumentationLibrary> Create(nostd::string_view name, + nostd::string_view version = "", + nostd::string_view schema_url = "") + { + return nostd::unique_ptr<InstrumentationLibrary>( + new InstrumentationLibrary{name, version, schema_url}); + } + + std::size_t HashCode() const noexcept { return hash_code_; } + + /** + * Compare 2 instrumentation libraries. + * @param other the instrumentation library to compare to. + * @returns true if the 2 instrumentation libraries are equal, false otherwise. + */ + bool operator==(const InstrumentationLibrary &other) const + { + return equal(other.name_, other.version_, other.schema_url_); + } + + /** + * Check whether the instrumentation library has given name and version. + * This could be used to check version equality and avoid heap allocation. + * @param name name of the instrumentation library to compare. + * @param version version of the instrumentatoin library to compare. + * @param schema_url schema url of the telemetry emitted by the library. + * @returns true if name and version in this instrumentation library are equal with the given name + * and version. + */ + bool equal(const nostd::string_view name, + const nostd::string_view version, + const nostd::string_view schema_url = "") const + { + return this->name_ == name && this->version_ == version && this->schema_url_ == schema_url; + } + + const std::string &GetName() const { return name_; } + const std::string &GetVersion() const { return version_; } + const std::string &GetSchemaURL() const { return schema_url_; } + +private: + InstrumentationLibrary(nostd::string_view name, + nostd::string_view version, + nostd::string_view schema_url = "") + : name_(name), version_(version), schema_url_(schema_url) + { + std::string hash_data; + hash_data.reserve(name_.size() + version_.size() + schema_url_.size()); + hash_data += name_; + hash_data += version_; + hash_data += schema_url_; + hash_code_ = std::hash<std::string>{}(hash_data); + } + +private: + std::string name_; + std::string version_; + std::string schema_url_; + std::size_t hash_code_; +}; + +} // namespace instrumentationlibrary +} // namespace sdk + +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/batch_log_processor.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/batch_log_processor.h new file mode 100644 index 000000000..1b6d443c8 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/batch_log_processor.h @@ -0,0 +1,128 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include "opentelemetry/sdk/common/circular_buffer.h" +# include "opentelemetry/sdk/logs/exporter.h" +# include "opentelemetry/sdk/logs/processor.h" + +# include <atomic> +# include <condition_variable> +# include <thread> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ + +namespace logs +{ + +/** + * This is an implementation of the LogProcessor which creates batches of finished logs and passes + * the export-friendly log data representations to the configured LogExporter. + */ +class BatchLogProcessor : public LogProcessor +{ +public: + /** + * Creates a batch log processor by configuring the specified exporter and other parameters + * as per the official, language-agnostic opentelemetry specs. + * + * @param exporter - The backend exporter to pass the logs to + * @param max_queue_size - The maximum buffer/queue size. After the size is reached, logs are + * dropped. + * @param scheduled_delay_millis - The time interval between two consecutive exports. + * @param max_export_batch_size - The maximum batch size of every export. It must be smaller or + * equal to max_queue_size + */ + explicit BatchLogProcessor( + std::unique_ptr<LogExporter> &&exporter, + const size_t max_queue_size = 2048, + const std::chrono::milliseconds scheduled_delay_millis = std::chrono::milliseconds(5000), + const size_t max_export_batch_size = 512); + + /** Makes a new recordable **/ + std::unique_ptr<Recordable> MakeRecordable() noexcept override; + + /** + * Called when the Logger's log method creates a log record + * @param record the log record + */ + + void OnReceive(std::unique_ptr<Recordable> &&record) noexcept override; + + /** + * Export all log records that have not been exported yet. + * + * NOTE: Timeout functionality not supported yet. + */ + bool ForceFlush( + std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + + /** + * Shuts down the processor and does any cleanup required. Completely drains the buffer/queue of + * all its logs and passes them to the exporter. Any subsequent calls to + * ForceFlush or Shutdown will return immediately without doing anything. + * + * NOTE: Timeout functionality not supported yet. + */ + bool Shutdown( + std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + + /** + * Class destructor which invokes the Shutdown() method. + */ + virtual ~BatchLogProcessor() override; + +private: + /** + * The background routine performed by the worker thread. + */ + void DoBackgroundWork(); + + /** + * Exports all logs to the configured exporter. + * + * @param was_force_flush_called - A flag to check if the current export is the result + * of a call to ForceFlush method. If true, then we have to + * notify the main thread to wake it up in the ForceFlush + * method. + */ + void Export(const bool was_for_flush_called); + + /** + * Called when Shutdown() is invoked. Completely drains the queue of all log records and + * passes them to the exporter. + */ + void DrainQueue(); + + /* The configured backend log exporter */ + std::unique_ptr<LogExporter> exporter_; + + /* Configurable parameters as per the official *trace* specs */ + const size_t max_queue_size_; + const std::chrono::milliseconds scheduled_delay_millis_; + const size_t max_export_batch_size_; + + /* Synchronization primitives */ + std::condition_variable cv_, force_flush_cv_; + std::mutex cv_m_, force_flush_cv_m_, shutdown_m_; + + /* The buffer/queue to which the ended logs are added */ + common::CircularBuffer<Recordable> buffer_; + + /* Important boolean flags to handle the workflow of the processor */ + std::atomic<bool> is_shutdown_{false}; + std::atomic<bool> is_force_flush_{false}; + std::atomic<bool> is_force_flush_notified_{false}; + + /* The background worker thread */ + std::thread worker_thread_; +}; + +} // namespace logs +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/exporter.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/exporter.h new file mode 100644 index 000000000..85c58e9f1 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/exporter.h @@ -0,0 +1,62 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include <memory> +# include <vector> +# include "opentelemetry/nostd/span.h" +# include "opentelemetry/sdk/common/exporter_utils.h" +# include "opentelemetry/sdk/logs/processor.h" +# include "opentelemetry/sdk/logs/recordable.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ +/** + * LogExporter defines the interface that log exporters must implement. + */ +class LogExporter +{ +public: + virtual ~LogExporter() = default; + + /** + * Create a log recordable. This object will be used to record log data and + * will subsequently be passed to LogExporter::Export. Vendors can implement + * custom recordables or use the default LogRecord recordable provided by the + * SDK. + * @return a newly initialized Recordable object + * + * Note: This method must be callable from multiple threads. + */ + virtual std::unique_ptr<Recordable> MakeRecordable() noexcept = 0; + + /** + * Exports the batch of log records to their export destination. + * This method must not be called concurrently for the same exporter instance. + * The exporter may attempt to retry sending the batch, but should drop + * and return kFailure after a certain timeout. + * @param records a span of unique pointers to log records + * @returns an ExportResult code (whether export was success or failure) + */ + virtual sdk::common::ExportResult Export( + const nostd::span<std::unique_ptr<Recordable>> &records) noexcept = 0; + + /** + * Marks the exporter as ShutDown and cleans up any resources as required. + * Shutdown should be called only once for each Exporter instance. + * @param timeout minimum amount of microseconds to wait for shutdown before giving up and + * returning failure. + * @return true if the exporter shutdown succeeded, false otherwise + */ + virtual bool Shutdown( + std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept = 0; +}; +} // namespace logs +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/log_record.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/log_record.h new file mode 100644 index 000000000..2a3a78289 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/log_record.h @@ -0,0 +1,193 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include <map> +# include <unordered_map> +# include "opentelemetry/sdk/common/attribute_utils.h" +# include "opentelemetry/sdk/logs/recordable.h" +# include "opentelemetry/sdk/resource/resource.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ + +/** + * A default Recordable implemenation to be passed in log statements, + * matching the 10 fields of the Log Data Model. + * (https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#log-and-event-record-definition) + * + */ +class LogRecord final : public Recordable +{ +private: + // Default values are set by the respective data structures' constructors for all fields, + // except the severity field, which must be set manually (an enum with no default value). + opentelemetry::logs::Severity severity_ = opentelemetry::logs::Severity::kInvalid; + const opentelemetry::sdk::resource::Resource *resource_ = nullptr; + common::AttributeMap attributes_map_; + std::string body_; // Currently a simple string, but should be changed to "Any" type + opentelemetry::trace::TraceId trace_id_; + opentelemetry::trace::SpanId span_id_; + opentelemetry::trace::TraceFlags trace_flags_; + opentelemetry::common::SystemTimestamp timestamp_; // uint64 nanoseconds since Unix epoch + +public: + /********** Setters for each field (overrides methods from the Recordable interface) ************/ + + /** + * Set the severity for this log. + * @param severity the severity of the event + */ + void SetSeverity(opentelemetry::logs::Severity severity) noexcept override + { + severity_ = severity; + } + + /** + * Set body field for this log. + * @param message the body to set + */ + void SetBody(nostd::string_view message) noexcept override { body_ = std::string(message); } + + /** + * Set Resource of this log + * @param Resource the resource to set + */ + void SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept override + { + resource_ = &resource; + } + + /** + * Set an attribute of a log. + * @param name the name of the attribute + * @param value the attribute value + */ + + void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept override + { + attributes_map_.SetAttribute(key, value); + } + + /** + * Set trace id for this log. + * @param trace_id the trace id to set + */ + void SetTraceId(opentelemetry::trace::TraceId trace_id) noexcept override + { + trace_id_ = trace_id; + } + + /** + * Set span id for this log. + * @param span_id the span id to set + */ + virtual void SetSpanId(opentelemetry::trace::SpanId span_id) noexcept override + { + span_id_ = span_id; + } + + /** + * Inject a trace_flags for this log. + * @param trace_flags the span id to set + */ + void SetTraceFlags(opentelemetry::trace::TraceFlags trace_flags) noexcept override + { + trace_flags_ = trace_flags; + } + + /** + * Set the timestamp for this log. + * @param timestamp the timestamp of the event + */ + void SetTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept override + { + timestamp_ = timestamp; + } + + /************************** Getters for each field ****************************/ + + /** + * Get the severity for this log + * @return the severity for this log + */ + opentelemetry::logs::Severity GetSeverity() const noexcept { return severity_; } + + /** + * Get the body of this log + * @return the body of this log + */ + std::string GetBody() const noexcept { return body_; } + + /** + * Get the resource for this log + * @return the resource for this log + */ + const opentelemetry::sdk::resource::Resource &GetResource() const noexcept + { + if (nullptr == resource_) + { + return sdk::resource::Resource::GetDefault(); + } + return *resource_; + } + + /** + * Get the attributes for this log + * @return the attributes for this log + */ + const std::unordered_map<std::string, common::OwnedAttributeValue> &GetAttributes() const noexcept + { + return attributes_map_.GetAttributes(); + } + + /** + * Get the trace id for this log + * @return the trace id for this log + */ + opentelemetry::trace::TraceId GetTraceId() const noexcept { return trace_id_; } + + /** + * Get the span id for this log + * @return the span id for this log + */ + opentelemetry::trace::SpanId GetSpanId() const noexcept { return span_id_; } + + /** + * Get the trace flags for this log + * @return the trace flags for this log + */ + opentelemetry::trace::TraceFlags GetTraceFlags() const noexcept { return trace_flags_; } + + /** + * Get the timestamp for this log + * @return the timestamp for this log + */ + opentelemetry::common::SystemTimestamp GetTimestamp() const noexcept { return timestamp_; } + + /** + * Set instrumentation_library for this log. + * @param instrumentation_library the instrumentation library to set + */ + void SetInstrumentationLibrary( + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + &instrumentation_library) noexcept + { + instrumentation_library_ = &instrumentation_library; + } + +private: + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + *instrumentation_library_ = nullptr; +}; +} // namespace logs +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/logger.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/logger.h new file mode 100644 index 000000000..4eeca2da1 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/logger.h @@ -0,0 +1,77 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include "opentelemetry/logs/logger.h" +# include "opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h" +# include "opentelemetry/sdk/logs/logger_context.h" +# include "opentelemetry/sdk/logs/logger_provider.h" + +# include <vector> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ +class LoggerProvider; + +class Logger final : public opentelemetry::logs::Logger +{ +public: + /** + * Initialize a new logger. + * @param name The name of this logger instance + * @param context The logger provider that owns this logger. + */ + explicit Logger( + opentelemetry::nostd::string_view name, + std::shared_ptr<LoggerContext> context, + std::unique_ptr<instrumentationlibrary::InstrumentationLibrary> instrumentation_library = + instrumentationlibrary::InstrumentationLibrary::Create("")) noexcept; + + /** + * Returns the name of this logger. + */ + const opentelemetry::nostd::string_view GetName() noexcept override; + + /** + * Writes a log record into the processor. + * @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). + * with the log event. + * @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. */ + void Log(opentelemetry::logs::Severity severity, + nostd::string_view body, + const opentelemetry::common::KeyValueIterable &attributes, + opentelemetry::trace::TraceId trace_id, + opentelemetry::trace::SpanId span_id, + opentelemetry::trace::TraceFlags trace_flags, + opentelemetry::common::SystemTimestamp timestamp) noexcept override; + + /** Returns the associated instruementation library */ + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary & + GetInstrumentationLibrary() const noexcept; + +private: + // The name of this logger + std::string logger_name_; + + // order of declaration is important here - instrumentation library should destroy after + // logger-context. + std::unique_ptr<instrumentationlibrary::InstrumentationLibrary> instrumentation_library_; + std::shared_ptr<LoggerContext> context_; +}; + +} // namespace logs +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/logger_context.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/logger_context.h new file mode 100644 index 000000000..01c2f7dd8 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/logger_context.h @@ -0,0 +1,81 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef ENABLE_LOGS_PREVIEW + +# include "opentelemetry/sdk/logs/processor.h" +# include "opentelemetry/sdk/resource/resource.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ +/** + * A class which stores the LoggerContext context. + * + * This class meets the following design criteria: + * - A shared reference between LoggerProvider and Logger instantiated. + * - A thread-safe class that allows updating/altering processor/exporter pipelines + * and sampling config. + * - The owner/destroyer of Processors/Exporters. These will remain active until + * this class is destroyed. I.e. Sampling, Exporting, flushing, Custom Iterator etc. are all ok + * if this object is alive, and they will work together. If this object is destroyed, then no shared + * references to Processor, Exporter, Recordable, Custom Iterator etc. should exist, and all + * associated pipelines will have been flushed. + */ +class LoggerContext +{ +public: + explicit LoggerContext(std::vector<std::unique_ptr<LogProcessor>> &&processors, + opentelemetry::sdk::resource::Resource resource = + opentelemetry::sdk::resource::Resource::Create({})) noexcept; + + /** + * Attaches a log processor to list of configured processors to this tracer context. + * Processor once attached can't be removed. + * @param processor The new log processor for this tracer. This must not be + * a nullptr. Ownership is given to the `TracerContext`. + * + * Note: This method is not thread safe. + */ + void AddProcessor(std::unique_ptr<LogProcessor> processor) noexcept; + + /** + * Obtain the configured (composite) processor. + * + * Note: When more than one processor is active, this will + * return an "aggregate" processor + */ + LogProcessor &GetProcessor() const noexcept; + + /** + * Obtain the resource associated with this tracer context. + * @return The resource for this tracer context. + */ + const opentelemetry::sdk::resource::Resource &GetResource() const noexcept; + + /** + * Force all active LogProcessors to flush any buffered logs + * within the given timeout. + */ + bool ForceFlush(std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept; + + /** + * Shutdown the log processor associated with this tracer provider. + */ + bool Shutdown(std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept; + +private: + // order of declaration is important here - resource object should be destroyed after processor. + opentelemetry::sdk::resource::Resource resource_; + std::unique_ptr<LogProcessor> processor_; +}; +} // namespace logs +} // namespace sdk + +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/logger_provider.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/logger_provider.h new file mode 100755 index 000000000..9afb67ba0 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/logger_provider.h @@ -0,0 +1,131 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0/ + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include <memory> +# include <mutex> +# include <string> +# include <vector> + +# include "opentelemetry/logs/logger_provider.h" +# include "opentelemetry/logs/noop.h" +# include "opentelemetry/nostd/shared_ptr.h" +# include "opentelemetry/sdk/common/atomic_shared_ptr.h" +# include "opentelemetry/sdk/logs/logger.h" +# include "opentelemetry/sdk/logs/logger_context.h" +# include "opentelemetry/sdk/logs/processor.h" + +// Define the maximum number of loggers that are allowed to be registered to the loggerprovider. +// TODO: Add link to logging spec once this is added to it +# define MAX_LOGGER_COUNT 100 + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ +class Logger; + +class LoggerProvider final : public opentelemetry::logs::LoggerProvider +{ +public: + /** + * Initialize a new logger provider + * @param processor The span processor for this logger provider. This must + * not be a nullptr. + * @param resource The resources for this logger provider. + * @param sampler The sampler for this logger provider. This must + * not be a nullptr. + * @param id_generator The custom id generator for this logger provider. This must + * not be a nullptr + */ + explicit LoggerProvider(std::unique_ptr<LogProcessor> &&processor, + opentelemetry::sdk::resource::Resource resource = + opentelemetry::sdk::resource::Resource::Create({})) noexcept; + + explicit LoggerProvider(std::vector<std::unique_ptr<LogProcessor>> &&processors, + opentelemetry::sdk::resource::Resource resource = + opentelemetry::sdk::resource::Resource::Create({})) noexcept; + + /** + * Initialize a new logger provider. A processor must later be assigned + * to this logger provider via the AddProcessor() method. + */ + explicit LoggerProvider() noexcept; + + /** + * Initialize a new logger provider with a specified context + * @param context The shared logger configuration/pipeline for this provider. + */ + explicit LoggerProvider(std::shared_ptr<sdk::logs::LoggerContext> context) noexcept; + + ~LoggerProvider(); + + /** + * Creates a logger with the given name, and returns a shared pointer to it. + * If a logger with that name already exists, return a shared pointer to it + * @param logger_name The name of the logger to be created. + * @param options The options for the logger. TODO: Once the logging spec defines it, + * give a list of options that the logger supports. + * @param library_name The version of the library. + * @param library_version The version of the library. + * @param schema_url The schema URL. + */ + nostd::shared_ptr<opentelemetry::logs::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 = "") noexcept override; + /** + * Creates a logger with the given name, and returns a shared pointer to it. + * If a logger with that name already exists, return a shared pointer to it + * @param name The name of the logger to be created. + * @param args The arguments for the logger. TODO: Once the logging spec defines it, + * give a list of arguments that the logger supports. + * @param library_name The version of the library. + * @param library_version The version of the library. + * @param schema_url The schema URL. + */ + nostd::shared_ptr<opentelemetry::logs::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 = "") noexcept override; + + /** + * Add the processor that is stored internally in the logger provider. + * @param processor The processor to be stored inside the logger provider. + * This must not be a nullptr. + */ + void AddProcessor(std::unique_ptr<LogProcessor> processor) noexcept; + + /** + * Obtain the resource associated with this logger provider. + * @return The resource for this logger provider. + */ + const opentelemetry::sdk::resource::Resource &GetResource() const noexcept; + + /** + * Shutdown the log processor associated with this log provider. + */ + bool Shutdown() noexcept; + + /** + * Force flush the log processor associated with this log provider. + */ + bool ForceFlush(std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept; + +private: + // order of declaration is important here - loggers should destroy only after context. + std::vector<std::shared_ptr<opentelemetry::sdk::logs::Logger>> loggers_; + std::shared_ptr<sdk::logs::LoggerContext> context_; + std::mutex lock_; +}; +} // namespace logs +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/multi_log_processor.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/multi_log_processor.h new file mode 100644 index 000000000..c1bda24a0 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/multi_log_processor.h @@ -0,0 +1,69 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef ENABLE_LOGS_PREVIEW + +# include <memory> +# include <vector> + +# include "opentelemetry/sdk/logs/multi_recordable.h" +# include "opentelemetry/sdk/logs/processor.h" +# include "opentelemetry/sdk/resource/resource.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ + +/** + * Log processor allow hooks for receive method invocations. + * + * Built-in log processors are responsible for batching and conversion of + * logs to exportable representation and passing batches to exporters. + */ +class MultiLogProcessor : public LogProcessor +{ +public: + MultiLogProcessor(std::vector<std::unique_ptr<LogProcessor>> &&processors); + ~MultiLogProcessor(); + + void AddProcessor(std::unique_ptr<LogProcessor> &&processor); + + std::unique_ptr<Recordable> MakeRecordable() noexcept override; + + /** + * OnReceive is called by the SDK once a log record has been successfully created. + * @param record the log record + */ + void OnReceive(std::unique_ptr<Recordable> &&record) noexcept override; + + /** + * Exports all log records that have not yet been exported to the configured Exporter. + * @param timeout that the forceflush is required to finish within. + * @return a result code indicating whether it succeeded, failed or timed out + */ + bool ForceFlush( + std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + + /** + * Shuts down the processor and does any cleanup required. + * ShutDown should only be called once for each processor. + * @param timeout minimum amount of microseconds to wait for + * shutdown before giving up and returning failure. + * @return true if the shutdown succeeded, false otherwise + */ + bool Shutdown( + std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + +private: + std::vector<std::unique_ptr<LogProcessor>> processors_; +}; +} // namespace logs +} // namespace sdk + +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/multi_recordable.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/multi_recordable.h new file mode 100644 index 000000000..db3df9622 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/multi_recordable.h @@ -0,0 +1,104 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef ENABLE_LOGS_PREVIEW + +# include <cstddef> +# include <memory> +# include <unordered_map> + +# include "opentelemetry/sdk/logs/processor.h" +# include "opentelemetry/sdk/logs/recordable.h" +# include "opentelemetry/sdk/resource/resource.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ +class MultiRecordable final : public Recordable +{ +public: + void AddRecordable(const LogProcessor &processor, + std::unique_ptr<Recordable> recordable) noexcept; + + const std::unique_ptr<Recordable> &GetRecordable(const LogProcessor &processor) const noexcept; + + std::unique_ptr<Recordable> ReleaseRecordable(const LogProcessor &processor) noexcept; + + /** + * Set the timestamp for this log. + * @param timestamp the timestamp to set + */ + void SetTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept override; + + /** + * Set the severity for this log. + * @param severity the severity of the event + */ + void SetSeverity(opentelemetry::logs::Severity severity) noexcept override; + + /** + * Set body field for this log. + * @param message the body to set + */ + void SetBody(nostd::string_view message) noexcept override; + + /** + * Set Resource of this log + * @param Resource the resource to set + */ + void SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept override; + + /** + * Set an attribute of a log. + * @param key the name of the attribute + * @param value the attribute value + */ + void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept override; + + /** + * Set the trace id for this log. + * @param trace_id the trace id to set + */ + void SetTraceId(opentelemetry::trace::TraceId trace_id) noexcept override; + + /** + * Set the span id for this log. + * @param span_id the span id to set + */ + void SetSpanId(opentelemetry::trace::SpanId span_id) noexcept override; + + /** + * Inject trace_flags for this log. + * @param trace_flags the trace flags to set + */ + void SetTraceFlags(opentelemetry::trace::TraceFlags trace_flags) noexcept override; + + /** + * Set instrumentation_library for this log. + * @param instrumentation_library the instrumentation library to set + */ + void SetInstrumentationLibrary( + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + &instrumentation_library) noexcept override; + + /** Returns the associated instruementation library */ + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary & + GetInstrumentationLibrary() const noexcept; + +private: + std::unordered_map<std::size_t, std::unique_ptr<Recordable>> recordables_; + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + *instrumentation_library_ = nullptr; +}; +} // namespace logs +} // namespace sdk + +OPENTELEMETRY_END_NAMESPACE + +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/processor.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/processor.h new file mode 100644 index 000000000..36da036f3 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/processor.h @@ -0,0 +1,61 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include <chrono> +# include <memory> +# include "opentelemetry/sdk/logs/recordable.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ +/** + * The Log Processor is responsible for passing log records + * to the configured exporter. + */ +class LogProcessor +{ +public: + virtual ~LogProcessor() = default; + + /** + * Create a log recordable. This requests a new log recordable from the + * associated exporter. + * @return a newly initialized recordable + * + * Note: This method must be callable from multiple threads. + */ + virtual std::unique_ptr<Recordable> MakeRecordable() noexcept = 0; + + /** + * OnReceive is called by the SDK once a log record has been successfully created. + * @param record the log record + */ + virtual void OnReceive(std::unique_ptr<Recordable> &&record) noexcept = 0; + + /** + * Exports all log records that have not yet been exported to the configured Exporter. + * @param timeout that the forceflush is required to finish within. + * @return a result code indicating whether it succeeded, failed or timed out + */ + virtual bool ForceFlush( + std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept = 0; + + /** + * Shuts down the processor and does any cleanup required. + * ShutDown should only be called once for each processor. + * @param timeout minimum amount of microseconds to wait for + * shutdown before giving up and returning failure. + * @return true if the shutdown succeeded, false otherwise + */ + virtual bool Shutdown( + std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept = 0; +}; +} // namespace logs +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/recordable.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/recordable.h new file mode 100644 index 000000000..4a3227373 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/recordable.h @@ -0,0 +1,97 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include "opentelemetry/common/attribute_value.h" +# include "opentelemetry/common/key_value_iterable.h" +# include "opentelemetry/common/timestamp.h" +# include "opentelemetry/logs/severity.h" +# include "opentelemetry/sdk/common/empty_attributes.h" +# include "opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h" +# include "opentelemetry/sdk/resource/resource.h" +# include "opentelemetry/trace/span.h" +# include "opentelemetry/trace/span_context.h" +# include "opentelemetry/trace/span_id.h" +# include "opentelemetry/trace/trace_flags.h" +# include "opentelemetry/trace/trace_id.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ +/** + * Maintains a representation of a log in a format that can be processed by a recorder. + * + * This class is thread-compatible. + */ +class Recordable +{ +public: + virtual ~Recordable() = default; + + /** + * Set the timestamp for this log. + * @param timestamp the timestamp to set + */ + virtual void SetTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept = 0; + + /** + * Set the severity for this log. + * @param severity the severity of the event + */ + virtual void SetSeverity(opentelemetry::logs::Severity severity) noexcept = 0; + + /** + * Set body field for this log. + * @param message the body to set + */ + virtual void SetBody(nostd::string_view message) noexcept = 0; + + /** + * Set Resource of this log + * @param Resource the resource to set + */ + virtual void SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept = 0; + + /** + * Set an attribute of a log. + * @param key the name of the attribute + * @param value the attribute value + */ + virtual void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept = 0; + + /** + * Set the trace id for this log. + * @param trace_id the trace id to set + */ + virtual void SetTraceId(opentelemetry::trace::TraceId trace_id) noexcept = 0; + + /** + * Set the span id for this log. + * @param span_id the span id to set + */ + virtual void SetSpanId(opentelemetry::trace::SpanId span_id) noexcept = 0; + + /** + * Inject trace_flags for this log. + * @param trace_flags the trace flags to set + */ + virtual void SetTraceFlags(opentelemetry::trace::TraceFlags trace_flags) noexcept = 0; + + /** + * Set instrumentation_library for this log. + * @param instrumentation_library the instrumentation library to set + */ + virtual void SetInstrumentationLibrary( + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + &instrumentation_library) noexcept = 0; +}; +} // namespace logs +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/simple_log_processor.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/simple_log_processor.h new file mode 100644 index 000000000..cc3aec47b --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/logs/simple_log_processor.h @@ -0,0 +1,55 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include <atomic> +# include <mutex> + +# include "opentelemetry/common/spin_lock_mutex.h" +# include "opentelemetry/sdk/logs/exporter.h" +# include "opentelemetry/sdk/logs/processor.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ +/** + * The simple log processor passes all log records + * in a batch of 1 to the configured + * LogExporter. + * + * All calls to the configured LogExporter are synchronized using a + * spin-lock on an atomic_flag. + */ +class SimpleLogProcessor : public LogProcessor +{ + +public: + explicit SimpleLogProcessor(std::unique_ptr<LogExporter> &&exporter); + virtual ~SimpleLogProcessor() = default; + + std::unique_ptr<Recordable> MakeRecordable() noexcept override; + + void OnReceive(std::unique_ptr<Recordable> &&record) noexcept override; + + bool ForceFlush( + std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + + bool Shutdown( + std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + +private: + // The configured exporter + std::unique_ptr<LogExporter> exporter_; + // The lock used to ensure the exporter is not called concurrently + opentelemetry::common::SpinLockMutex lock_; + // The atomic boolean flag to ensure the ShutDown() function is only called once + std::atomic_flag shutdown_latch_ = ATOMIC_FLAG_INIT; +}; +} // namespace logs +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/aggregation.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/aggregation.h new file mode 100644 index 000000000..7ec9a6ea2 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/aggregation.h @@ -0,0 +1,55 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/nostd/string_view.h" +# include "opentelemetry/sdk/metrics/data/metric_data.h" +# include "opentelemetry/sdk/metrics/data/point_data.h" +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +class Aggregation +{ +public: + virtual void Aggregate(long value, const PointAttributes &attributes = {}) noexcept = 0; + + virtual void Aggregate(double value, const PointAttributes &attributes = {}) noexcept = 0; + + /** + * Returns the result of the merge of the two aggregations. + * + * This should always assume that the aggregations do not overlap and merge together for a new + * cumulative report. + * + * @param delta the newly captured (delta) aggregation + * @return the result of the merge of the given aggregation. + */ + + virtual std::unique_ptr<Aggregation> Merge(const Aggregation &delta) const noexcept = 0; + + /** + * Returns a new delta aggregation by comparing two cumulative measurements. + * + * @param next the newly captured (cumulative) aggregation. + * @return The resulting delta aggregation. + */ + virtual std::unique_ptr<Aggregation> Diff(const Aggregation &next) const noexcept = 0; + + /** + * Returns the point data that the aggregation will produce. + * + * @return PointType + */ + + virtual PointType ToPoint() const noexcept = 0; + + virtual ~Aggregation() = default; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/default_aggregation.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/default_aggregation.h new file mode 100644 index 000000000..887e1beb9 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/default_aggregation.h @@ -0,0 +1,146 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/common/spin_lock_mutex.h" +# include "opentelemetry/sdk/metrics/aggregation/aggregation.h" +# include "opentelemetry/sdk/metrics/aggregation/drop_aggregation.h" +# include "opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h" +# include "opentelemetry/sdk/metrics/aggregation/lastvalue_aggregation.h" +# include "opentelemetry/sdk/metrics/aggregation/sum_aggregation.h" +# include "opentelemetry/sdk/metrics/instruments.h" + +# include <mutex> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +class DefaultAggregation +{ +public: + static std::unique_ptr<Aggregation> CreateAggregation( + const opentelemetry::sdk::metrics::InstrumentDescriptor &instrument_descriptor) + { + switch (instrument_descriptor.type_) + { + case InstrumentType::kCounter: + case InstrumentType::kUpDownCounter: + case InstrumentType::kObservableCounter: + case InstrumentType::kObservableUpDownCounter: + return (instrument_descriptor.value_type_ == InstrumentValueType::kLong) + ? std::move(std::unique_ptr<Aggregation>(new LongSumAggregation())) + : std::move(std::unique_ptr<Aggregation>(new DoubleSumAggregation())); + break; + case InstrumentType::kHistogram: + return (instrument_descriptor.value_type_ == InstrumentValueType::kLong) + ? std::move(std::unique_ptr<Aggregation>(new LongHistogramAggregation())) + : std::move(std::unique_ptr<Aggregation>(new DoubleHistogramAggregation())); + break; + case InstrumentType::kObservableGauge: + return (instrument_descriptor.value_type_ == InstrumentValueType::kLong) + ? std::move(std::unique_ptr<Aggregation>(new LongLastValueAggregation())) + : std::move(std::unique_ptr<Aggregation>(new DoubleLastValueAggregation())); + break; + default: + return std::move(std::unique_ptr<Aggregation>(new DropAggregation())); + }; + } + + static std::unique_ptr<Aggregation> CreateAggregation(AggregationType aggregation_type, + InstrumentDescriptor instrument_descriptor) + { + switch (aggregation_type) + { + case AggregationType::kDrop: + return std::unique_ptr<Aggregation>(new DropAggregation()); + break; + case AggregationType::kHistogram: + if (instrument_descriptor.value_type_ == InstrumentValueType::kLong) + { + return std::unique_ptr<Aggregation>(new LongHistogramAggregation()); + } + else + { + return std::unique_ptr<Aggregation>(new DoubleHistogramAggregation()); + } + break; + case AggregationType::kLastValue: + if (instrument_descriptor.value_type_ == InstrumentValueType::kLong) + { + return std::unique_ptr<Aggregation>(new LongLastValueAggregation()); + } + else + { + return std::unique_ptr<Aggregation>(new DoubleLastValueAggregation()); + } + break; + case AggregationType::kSum: + if (instrument_descriptor.value_type_ == InstrumentValueType::kLong) + { + return std::unique_ptr<Aggregation>(new LongSumAggregation()); + } + else + { + return std::unique_ptr<Aggregation>(new DoubleSumAggregation()); + } + break; + default: + return DefaultAggregation::CreateAggregation(instrument_descriptor); + } + } + + static std::unique_ptr<Aggregation> CloneAggregation(AggregationType aggregation_type, + InstrumentDescriptor instrument_descriptor, + const Aggregation &to_copy) + { + const PointType point_data = to_copy.ToPoint(); + switch (aggregation_type) + { + case AggregationType::kDrop: + return std::unique_ptr<Aggregation>(new DropAggregation()); + case AggregationType::kHistogram: + if (instrument_descriptor.value_type_ == InstrumentValueType::kLong) + { + return std::unique_ptr<Aggregation>( + new LongHistogramAggregation(nostd::get<HistogramPointData>(point_data))); + } + else + { + return std::unique_ptr<Aggregation>( + new DoubleHistogramAggregation(nostd::get<HistogramPointData>(point_data))); + } + case AggregationType::kLastValue: + if (instrument_descriptor.value_type_ == InstrumentValueType::kLong) + { + return std::unique_ptr<Aggregation>( + new LongLastValueAggregation(nostd::get<LastValuePointData>(point_data))); + } + else + { + return std::unique_ptr<Aggregation>( + new DoubleLastValueAggregation(nostd::get<LastValuePointData>(point_data))); + } + case AggregationType::kSum: + if (instrument_descriptor.value_type_ == InstrumentValueType::kLong) + { + return std::unique_ptr<Aggregation>( + new LongSumAggregation(nostd::get<SumPointData>(point_data))); + } + else + { + return std::unique_ptr<Aggregation>( + new DoubleSumAggregation(nostd::get<SumPointData>(point_data))); + } + default: + return DefaultAggregation::CreateAggregation(instrument_descriptor); + } + } +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/drop_aggregation.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/drop_aggregation.h new file mode 100644 index 000000000..6c3d89d24 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/drop_aggregation.h @@ -0,0 +1,51 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/common/spin_lock_mutex.h" +# include "opentelemetry/sdk/metrics/aggregation/aggregation.h" + +# include <mutex> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +/** + * A null Aggregation which denotes no aggregation should occur. + */ + +class DropAggregation : public Aggregation +{ +public: + DropAggregation() = default; + + DropAggregation(const DropPointData &) {} + + void Aggregate(long value, const PointAttributes &attributes = {}) noexcept override {} + + void Aggregate(double value, const PointAttributes &attributes = {}) noexcept override {} + + std::unique_ptr<Aggregation> Merge(const Aggregation &) const noexcept override + { + return std::unique_ptr<Aggregation>(new DropAggregation()); + } + + std::unique_ptr<Aggregation> Diff(const Aggregation &) const noexcept override + { + return std::unique_ptr<Aggregation>(new DropAggregation()); + } + + PointType ToPoint() const noexcept override + { + static DropPointData point_data; + return point_data; + } +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h new file mode 100644 index 000000000..e2a55fba5 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h @@ -0,0 +1,103 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/common/spin_lock_mutex.h" +# include "opentelemetry/sdk/metrics/aggregation/aggregation.h" + +# include <mutex> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +class LongHistogramAggregation : public Aggregation +{ +public: + LongHistogramAggregation(); + LongHistogramAggregation(HistogramPointData &&); + LongHistogramAggregation(const HistogramPointData &); + + void Aggregate(long value, const PointAttributes &attributes = {}) noexcept override; + + void Aggregate(double value, const PointAttributes &attributes = {}) noexcept override {} + + /* Returns the result of merge of the existing aggregation with delta aggregation with same + * boundaries */ + std::unique_ptr<Aggregation> Merge(const Aggregation &delta) const noexcept override; + + /* Returns the new delta aggregation by comparing existing aggregation with next aggregation with + * same boundaries. Data points for `next` aggregation (sum , bucket-counts) should be more than + * the current aggregation - which is the normal scenario as measurements values are monotonic + * increasing. + */ + std::unique_ptr<Aggregation> Diff(const Aggregation &next) const noexcept override; + + PointType ToPoint() const noexcept override; + +private: + opentelemetry::common::SpinLockMutex lock_; + HistogramPointData point_data_; +}; + +class DoubleHistogramAggregation : public Aggregation +{ +public: + DoubleHistogramAggregation(); + DoubleHistogramAggregation(HistogramPointData &&); + DoubleHistogramAggregation(const HistogramPointData &); + + void Aggregate(long value, const PointAttributes &attributes = {}) noexcept override {} + + void Aggregate(double value, const PointAttributes &attributes = {}) noexcept override; + + /* Returns the result of merge of the existing aggregation with delta aggregation with same + * boundaries */ + std::unique_ptr<Aggregation> Merge(const Aggregation &delta) const noexcept override; + + /* Returns the new delta aggregation by comparing existing aggregation with next aggregation with + * same boundaries. Data points for `next` aggregation (sum , bucket-counts) should be more than + * the current aggregation - which is the normal scenario as measurements values are monotonic + * increasing. + */ + std::unique_ptr<Aggregation> Diff(const Aggregation &next) const noexcept override; + + PointType ToPoint() const noexcept override; + +private: + mutable opentelemetry::common::SpinLockMutex lock_; + mutable HistogramPointData point_data_; +}; + +template <class T> +void HistogramMerge(HistogramPointData ¤t, + HistogramPointData &delta, + HistogramPointData &merge) +{ + for (size_t i = 0; i < current.counts_.size(); i++) + { + merge.counts_[i] = current.counts_[i] + delta.counts_[i]; + } + merge.boundaries_ = current.boundaries_; + merge.sum_ = nostd::get<T>(current.sum_) + nostd::get<T>(delta.sum_); + merge.count_ = current.count_ + delta.count_; +} + +template <class T> +void HistogramDiff(HistogramPointData ¤t, HistogramPointData &next, HistogramPointData &diff) +{ + for (size_t i = 0; i < current.counts_.size(); i++) + { + diff.counts_[i] = next.counts_[i] - current.counts_[i]; + } + diff.boundaries_ = current.boundaries_; + diff.count_ = next.count_ - current.count_; +} + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/lastvalue_aggregation.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/lastvalue_aggregation.h new file mode 100644 index 000000000..3b2c08f8c --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/lastvalue_aggregation.h @@ -0,0 +1,63 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/common/spin_lock_mutex.h" +# include "opentelemetry/sdk/metrics/aggregation/aggregation.h" + +# include <mutex> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +class LongLastValueAggregation : public Aggregation +{ +public: + LongLastValueAggregation(); + LongLastValueAggregation(LastValuePointData &&); + LongLastValueAggregation(const LastValuePointData &); + + void Aggregate(long value, const PointAttributes &attributes = {}) noexcept override; + + void Aggregate(double value, const PointAttributes &attributes = {}) noexcept override {} + + std::unique_ptr<Aggregation> Merge(const Aggregation &delta) const noexcept override; + + std::unique_ptr<Aggregation> Diff(const Aggregation &next) const noexcept override; + + PointType ToPoint() const noexcept override; + +private: + opentelemetry::common::SpinLockMutex lock_; + LastValuePointData point_data_; +}; + +class DoubleLastValueAggregation : public Aggregation +{ +public: + DoubleLastValueAggregation(); + DoubleLastValueAggregation(LastValuePointData &&); + DoubleLastValueAggregation(const LastValuePointData &); + + void Aggregate(long value, const PointAttributes &attributes = {}) noexcept override {} + + void Aggregate(double value, const PointAttributes &attributes = {}) noexcept override; + + virtual std::unique_ptr<Aggregation> Merge(const Aggregation &delta) const noexcept override; + + virtual std::unique_ptr<Aggregation> Diff(const Aggregation &next) const noexcept override; + + PointType ToPoint() const noexcept override; + +private: + mutable opentelemetry::common::SpinLockMutex lock_; + mutable LastValuePointData point_data_; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/sum_aggregation.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/sum_aggregation.h new file mode 100644 index 000000000..14f13bd72 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/aggregation/sum_aggregation.h @@ -0,0 +1,64 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/common/spin_lock_mutex.h" +# include "opentelemetry/sdk/metrics/aggregation/aggregation.h" + +# include <mutex> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +class LongSumAggregation : public Aggregation +{ +public: + LongSumAggregation(); + LongSumAggregation(SumPointData &&); + LongSumAggregation(const SumPointData &); + + void Aggregate(long value, const PointAttributes &attributes = {}) noexcept override; + + void Aggregate(double value, const PointAttributes &attributes = {}) noexcept override {} + + std::unique_ptr<Aggregation> Merge(const Aggregation &delta) const noexcept override; + + std::unique_ptr<Aggregation> Diff(const Aggregation &next) const noexcept override; + + PointType ToPoint() const noexcept override; + +private: + opentelemetry::common::SpinLockMutex lock_; + SumPointData point_data_; +}; + +class DoubleSumAggregation : public Aggregation +{ +public: + DoubleSumAggregation(); + DoubleSumAggregation(SumPointData &&); + DoubleSumAggregation(const SumPointData &); + + void Aggregate(long value, const PointAttributes &attributes = {}) noexcept override {} + + void Aggregate(double value, const PointAttributes &attributes = {}) noexcept override; + + std::unique_ptr<Aggregation> Merge(const Aggregation &delta) const noexcept override; + + std::unique_ptr<Aggregation> Diff(const Aggregation &next) const noexcept override; + + PointType ToPoint() const noexcept override; + +private: + mutable opentelemetry::common::SpinLockMutex lock_; + SumPointData point_data_; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/async_instruments.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/async_instruments.h new file mode 100644 index 000000000..8b1f76377 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/async_instruments.h @@ -0,0 +1,115 @@ +// 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/observer_result.h" +# include "opentelemetry/nostd/string_view.h" +# include "opentelemetry/sdk/metrics/instruments.h" +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +template <class T> +class Asynchronous +{ +public: + Asynchronous(nostd::string_view name, + void (*callback)(opentelemetry::metrics::ObserverResult<T> &), + nostd::string_view description = "", + nostd::string_view unit = "") + : name_(name), callback_(callback), description_(description), unit_(unit) + {} + +protected: + std::string name_; + void (*callback_)(opentelemetry::metrics::ObserverResult<T> &); + std::string description_; + std::string unit_; +}; + +class LongObservableCounter : public opentelemetry::metrics::ObservableCounter<long>, + public Asynchronous<long> +{ +public: + LongObservableCounter(nostd::string_view name, + void (*callback)(opentelemetry::metrics::ObserverResult<long> &), + nostd::string_view description = "", + nostd::string_view unit = "") + : Asynchronous(name, callback, description, unit) + + {} +}; + +class DoubleObservableCounter : public opentelemetry::metrics::ObservableCounter<double>, + public Asynchronous<double> +{ +public: + DoubleObservableCounter(nostd::string_view name, + void (*callback)(opentelemetry::metrics::ObserverResult<double> &), + nostd::string_view description = "", + nostd::string_view unit = "") + : Asynchronous(name, callback, description, unit) + + {} +}; + +class LongObservableGauge : public opentelemetry::metrics::ObservableGauge<long>, + public Asynchronous<long> +{ +public: + LongObservableGauge(nostd::string_view name, + void (*callback)(opentelemetry::metrics::ObserverResult<long> &), + nostd::string_view description = "", + nostd::string_view unit = "") + : Asynchronous(name, callback, description, unit) + + {} +}; + +class DoubleObservableGauge : public opentelemetry::metrics::ObservableGauge<double>, + public Asynchronous<double> +{ +public: + DoubleObservableGauge(nostd::string_view name, + void (*callback)(opentelemetry::metrics::ObserverResult<double> &), + nostd::string_view description = "", + nostd::string_view unit = "") + : Asynchronous(name, callback, description, unit) + + {} +}; + +class LongObservableUpDownCounter : public opentelemetry::metrics::ObservableUpDownCounter<long>, + public Asynchronous<long> +{ +public: + LongObservableUpDownCounter(nostd::string_view name, + void (*callback)(opentelemetry::metrics::ObserverResult<long> &), + nostd::string_view description = "", + nostd::string_view unit = "") + : Asynchronous(name, callback, description, unit) + + {} +}; + +class DoubleObservableUpDownCounter + : public opentelemetry::metrics::ObservableUpDownCounter<double>, + public Asynchronous<double> +{ +public: + DoubleObservableUpDownCounter(nostd::string_view name, + void (*callback)(opentelemetry::metrics::ObserverResult<double> &), + nostd::string_view description = "", + nostd::string_view unit = "") + : Asynchronous(name, callback, description, unit) + {} +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/data/metric_data.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/data/metric_data.h new file mode 100644 index 000000000..738d4540f --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/data/metric_data.h @@ -0,0 +1,42 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/nostd/variant.h" +# include "opentelemetry/sdk/common/attribute_utils.h" +# include "opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h" +# include "opentelemetry/sdk/metrics/data/point_data.h" +# include "opentelemetry/sdk/metrics/instruments.h" +# include "opentelemetry/sdk/resource/resource.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +using PointAttributes = opentelemetry::sdk::common::OrderedAttributeMap; +using PointType = opentelemetry::nostd:: + variant<SumPointData, HistogramPointData, LastValuePointData, DropPointData>; + +struct PointDataAttributes +{ + PointAttributes attributes; + PointType point_data; +}; + +class MetricData +{ +public: + InstrumentDescriptor instrument_descriptor; + opentelemetry::common::SystemTimestamp start_ts; + opentelemetry::common::SystemTimestamp end_ts; + std::vector<PointDataAttributes> point_data_attr_; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/data/point_data.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/data/point_data.h new file mode 100644 index 000000000..714f96c9a --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/data/point_data.h @@ -0,0 +1,78 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/common/timestamp.h" +# include "opentelemetry/nostd/variant.h" +# include "opentelemetry/sdk/metrics/instruments.h" +# include "opentelemetry/version.h" + +# include <list> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +using ValueType = nostd::variant<long, double>; +using ListType = nostd::variant<std::list<long>, std::list<double>>; + +// TODO: remove ctors and initializers from below classes when GCC<5 stops shipping on Ubuntu + +class SumPointData +{ +public: + // TODO: remove ctors and initializers when GCC<5 stops shipping on Ubuntu + SumPointData(SumPointData &&) = default; + SumPointData(const SumPointData &) = default; + SumPointData &operator=(SumPointData &&) = default; + SumPointData() = default; + + ValueType value_ = {}; +}; + +class LastValuePointData +{ +public: + // TODO: remove ctors and initializers when GCC<5 stops shipping on Ubuntu + LastValuePointData(LastValuePointData &&) = default; + LastValuePointData(const LastValuePointData &) = default; + LastValuePointData &operator=(LastValuePointData &&) = default; + LastValuePointData() = default; + + ValueType value_ = {}; + bool is_lastvalue_valid_ = {}; + opentelemetry::common::SystemTimestamp sample_ts_ = {}; +}; + +class HistogramPointData +{ +public: + // TODO: remove ctors and initializers when GCC<5 stops shipping on Ubuntu + HistogramPointData(HistogramPointData &&) = default; + HistogramPointData &operator=(HistogramPointData &&) = default; + HistogramPointData(const HistogramPointData &) = default; + HistogramPointData() = default; + + ListType boundaries_ = {}; + ValueType sum_ = {}; + std::vector<uint64_t> counts_ = {}; + uint64_t count_ = {}; +}; + +class DropPointData +{ +public: + // TODO: remove ctors and initializers when GCC<5 stops shipping on Ubuntu + DropPointData(DropPointData &&) = default; + DropPointData(const DropPointData &) = default; + DropPointData() = default; + DropPointData &operator=(DropPointData &&) = default; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/always_sample_filter.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/always_sample_filter.h new file mode 100644 index 000000000..5e7f0436e --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/always_sample_filter.h @@ -0,0 +1,43 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/sdk/metrics/exemplar/filter.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +class AlwaysSampleFilter final : public ExemplarFilter +{ +public: + static nostd::shared_ptr<ExemplarFilter> GetAlwaysSampleFilter() + { + static nostd::shared_ptr<ExemplarFilter> alwaysSampleFilter{new AlwaysSampleFilter{}}; + return alwaysSampleFilter; + } + + bool ShouldSampleMeasurement(long value, + const MetricAttributes &attributes, + const opentelemetry::context::Context &context) noexcept override + { + return true; + } + + bool ShouldSampleMeasurement(double value, + const MetricAttributes &attributes, + const opentelemetry::context::Context &context) noexcept override + { + return true; + } + +private: + explicit AlwaysSampleFilter() = default; +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/data.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/data.h new file mode 100644 index 000000000..14eac6249 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/data.h @@ -0,0 +1,45 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/common/timestamp.h" +# include "opentelemetry/context/context.h" +# include "opentelemetry/sdk/common/attribute_utils.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +using MetricAttributes = opentelemetry::sdk::common::OrderedAttributeMap; +/** + * A sample input measurement. + * + * Exemplars also hold information about the environment when the measurement was recorded, for + * example the span and trace ID of the active span when the exemplar was recorded. + */ +class ExemplarData +{ +public: + /** + * The set of key/value pairs that were filtered out by the aggregator, but recorded alongside the + * original measurement. Only key/value pairs that were filtered out by the aggregator should be + * included + */ + MetricAttributes GetFilteredAttributes(); + + /** Returns the timestamp in nanos when measurement was collected. */ + opentelemetry::common::SystemTimestamp GetEpochNanos(); + + /** + * Returns the SpanContext associated with this exemplar. If the exemplar was not recorded + * inside a sampled trace, the Context will be invalid. + */ + opentelemetry::context::Context GetSpanContext(); +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/filter.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/filter.h new file mode 100644 index 000000000..4b512e131 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/filter.h @@ -0,0 +1,39 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/context/context.h" +# include "opentelemetry/sdk/common/attribute_utils.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +using MetricAttributes = opentelemetry::sdk::common::OrderedAttributeMap; + +/** + * Exemplar filters are used to pre-filter measurements before attempting to store them in a + * reservoir. + */ +class ExemplarFilter +{ +public: + // Returns whether or not a reservoir should attempt to filter a measurement. + virtual bool ShouldSampleMeasurement(long value, + const MetricAttributes &attributes, + const opentelemetry::context::Context &context) noexcept = 0; + + // Returns whether or not a reservoir should attempt to filter a measurement. + virtual bool ShouldSampleMeasurement(double value, + const MetricAttributes &attributes, + const opentelemetry::context::Context &context) noexcept = 0; + + virtual ~ExemplarFilter() = default; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/never_sample_filter.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/never_sample_filter.h new file mode 100644 index 000000000..38f51778c --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/never_sample_filter.h @@ -0,0 +1,43 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/sdk/metrics/exemplar/filter.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +class NeverSampleFilter final : public ExemplarFilter +{ +public: + static nostd::shared_ptr<ExemplarFilter> GetNeverSampleFilter() + { + nostd::shared_ptr<ExemplarFilter> neverSampleFilter{new NeverSampleFilter{}}; + return neverSampleFilter; + } + + bool ShouldSampleMeasurement(long value, + const MetricAttributes &attributes, + const opentelemetry::context::Context &context) noexcept override + { + return false; + } + + bool ShouldSampleMeasurement(double value, + const MetricAttributes &attributes, + const opentelemetry::context::Context &context) noexcept override + { + return false; + } + +private: + explicit NeverSampleFilter() = default; +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/no_exemplar_reservoir.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/no_exemplar_reservoir.h new file mode 100644 index 000000000..1fe0586d2 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/no_exemplar_reservoir.h @@ -0,0 +1,55 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include <vector> +# include "opentelemetry/context/context.h" +# include "opentelemetry/nostd/shared_ptr.h" +# include "opentelemetry/sdk/common/attribute_utils.h" +# include "opentelemetry/sdk/metrics/exemplar/reservoir.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +class NoExemplarReservoir final : public ExemplarReservoir +{ + +public: + static nostd::shared_ptr<ExemplarReservoir> GetNoExemplarReservoir() + { + return nostd::shared_ptr<ExemplarReservoir>{new NoExemplarReservoir{}}; + } + + void OfferMeasurement(long value, + const MetricAttributes &attributes, + const opentelemetry::context::Context &context, + const opentelemetry::common::SystemTimestamp ×tamp) noexcept override + { + // Stores nothing + } + + void OfferMeasurement(double value, + const MetricAttributes &attributes, + const opentelemetry::context::Context &context, + const opentelemetry::common::SystemTimestamp ×tamp) noexcept override + { + // Stores nothing. + } + + std::vector<ExemplarData> CollectAndReset( + const MetricAttributes &pointAttributes) noexcept override + { + return std::vector<ExemplarData>{}; + } + +private: + explicit NoExemplarReservoir() = default; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/reservoir.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/reservoir.h new file mode 100644 index 000000000..25e8421d6 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/exemplar/reservoir.h @@ -0,0 +1,55 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include <vector> +# include "opentelemetry/sdk/metrics/exemplar/data.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +/** + * An interface for an exemplar reservoir of samples. + * + * <p>This represents a reservoir for a specific "point" of metric data. + */ +class ExemplarReservoir +{ +public: + virtual ~ExemplarReservoir() = default; + + /** Offers a long measurement to be sampled. */ + virtual void OfferMeasurement( + long value, + const MetricAttributes &attributes, + const opentelemetry::context::Context &context, + const opentelemetry::common::SystemTimestamp ×tamp) noexcept = 0; + + /** Offers a double measurement to be sampled. */ + virtual void OfferMeasurement( + double value, + const MetricAttributes &attributes, + const opentelemetry::context::Context &context, + const opentelemetry::common::SystemTimestamp ×tamp) noexcept = 0; + + /** + * Builds vector of Exemplars for exporting from the current reservoir. + * + * <p>Additionally, clears the reservoir for the next sampling period. + * + * @param pointAttributes the Attributes associated with the metric point. + * ExemplarDatas should filter these out of their final data state. + * @return A vector of sampled exemplars for this point. Implementers are expected to + * filter out pointAttributes from the original recorded attributes. + */ + virtual std::vector<ExemplarData> CollectAndReset( + const MetricAttributes &pointAttributes) noexcept = 0; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h new file mode 100644 index 000000000..d3b38759a --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/export/metric_producer.h @@ -0,0 +1,57 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h" +# include "opentelemetry/sdk/metrics/data/metric_data.h" +# include "opentelemetry/sdk/resource/resource.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +/** + * Metric Data to be exported along with resources and + * Instrumentation library. + */ +struct InstrumentationInfoMetrics +{ + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + *instrumentation_library_; + std::vector<MetricData> metric_data_; +}; + +struct ResourceMetrics +{ + const opentelemetry::sdk::resource::Resource *resource_; + std::vector<InstrumentationInfoMetrics> instrumentation_info_metric_data_; +}; + +/** + * MetricProducer is the interface that is used to make metric data available to the + * OpenTelemetry exporters. Implementations should be stateful, in that each call to + * `Collect` will return any metric generated since the last call was made. + * + * <p>Implementations must be thread-safe. + */ + +class MetricProducer +{ +public: + /** + * The callback to be called for each metric exporter. This will only be those + * metrics that have been produced since the last time this method was called. + * + * @return a status of completion of method. + */ + virtual bool Collect( + nostd::function_ref<bool(ResourceMetrics &metric_data)> callback) noexcept = 0; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader.h new file mode 100644 index 000000000..29125a6ea --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader.h @@ -0,0 +1,72 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW + +# include "opentelemetry/sdk/metrics/metric_reader.h" +# include "opentelemetry/version.h" + +# include <atomic> +# include <chrono> +# include <condition_variable> +# include <thread> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +class MetricExporter; +/** + * Struct to hold PeriodicExortingMetricReader options. + */ + +constexpr std::chrono::milliseconds kExportIntervalMillis = std::chrono::milliseconds(60000); +constexpr std::chrono::milliseconds kExportTimeOutMillis = std::chrono::milliseconds(30000); +struct PeriodicExportingMetricReaderOptions +{ + + /* The time interval between two consecutive exports. */ + std::chrono::milliseconds export_interval_millis = + std::chrono::milliseconds(kExportIntervalMillis); + + /* how long the export can run before it is cancelled. */ + std::chrono::milliseconds export_timeout_millis = std::chrono::milliseconds(kExportTimeOutMillis); +}; + +class PeriodicExportingMetricReader : public MetricReader +{ + +public: + PeriodicExportingMetricReader( + std::unique_ptr<MetricExporter> exporter, + const PeriodicExportingMetricReaderOptions &option, + AggregationTemporality aggregation_temporality = AggregationTemporality::kCumulative); + +private: + bool OnForceFlush(std::chrono::microseconds timeout) noexcept override; + + bool OnShutDown(std::chrono::microseconds timeout) noexcept override; + + void OnInitialized() noexcept override; + + std::unique_ptr<MetricExporter> exporter_; + std::chrono::milliseconds export_interval_millis_; + std::chrono::milliseconds export_timeout_millis_; + + void DoBackgroundWork(); + + /* The background worker thread */ + std::thread worker_thread_; + + /* Synchronization primitives */ + std::condition_variable cv_; + std::mutex cv_m_; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/instruments.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/instruments.h new file mode 100644 index 000000000..5d8535714 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/instruments.h @@ -0,0 +1,70 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/sdk/common/attribute_utils.h" +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +enum class InstrumentType +{ + kCounter, + kHistogram, + kUpDownCounter, + kObservableCounter, + kObservableGauge, + kObservableUpDownCounter +}; + +enum class InstrumentValueType +{ + kInt, + kLong, + kFloat, + kDouble +}; + +enum class AggregationType +{ + kDrop, + kHistogram, + kLastValue, + kSum, + kDefault +}; + +enum class AggregationTemporality +{ + kUnspecified, + kDelta, + kCumulative +}; + +struct InstrumentDescriptor +{ + std::string name_; + std::string description_; + std::string unit_; + InstrumentType type_; + InstrumentValueType value_type_; +}; + +using MetricAttributes = opentelemetry::sdk::common::OrderedAttributeMap; + +/*class InstrumentSelector { +public: +InstrumentSelector(opentelemetry::nostd::string_view name, +opentelemetry::sdk::metrics::InstrumentType type): name_(name.data()), type_(type) {} InstrumentType +GetType(){return type_;} std::string GetNameFilter() { return name_;} + +private: +std::string name_; +InstrumentType type_; +};*/ +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/meter.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/meter.h new file mode 100644 index 000000000..44e54adf1 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/meter.h @@ -0,0 +1,156 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include <chrono> +# include "opentelemetry/metrics/meter.h" +# include "opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h" +# include "opentelemetry/sdk/metrics/instruments.h" +# include "opentelemetry/sdk/metrics/meter_context.h" +# include "opentelemetry/sdk/metrics/state/async_metric_storage.h" + +# include "opentelemetry/sdk/resource/resource.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +class MetricStorage; +class WritableMetricStorage; + +class Meter final : public opentelemetry::metrics::Meter +{ +public: + /** Construct a new Meter with the given pipeline. */ + explicit Meter(std::shared_ptr<sdk::metrics::MeterContext> meter_context, + std::unique_ptr<opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary> + instrumentation_library = + opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary::Create( + "")) noexcept; + + nostd::shared_ptr<opentelemetry::metrics::Counter<long>> CreateLongCounter( + nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept override; + + nostd::shared_ptr<opentelemetry::metrics::Counter<double>> CreateDoubleCounter( + nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept override; + + void CreateLongObservableCounter(nostd::string_view name, + void (*callback)(opentelemetry::metrics::ObserverResult<long> &, + void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept override; + + void CreateDoubleObservableCounter( + nostd::string_view name, + void (*callback)(opentelemetry::metrics::ObserverResult<double> &, void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept override; + + nostd::shared_ptr<opentelemetry::metrics::Histogram<long>> CreateLongHistogram( + nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept override; + + nostd::shared_ptr<opentelemetry::metrics::Histogram<double>> CreateDoubleHistogram( + nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept override; + + void CreateLongObservableGauge(nostd::string_view name, + void (*callback)(opentelemetry::metrics::ObserverResult<long> &, + void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept override; + + void CreateDoubleObservableGauge( + nostd::string_view name, + void (*callback)(opentelemetry::metrics::ObserverResult<double> &, void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept override; + + nostd::shared_ptr<opentelemetry::metrics::UpDownCounter<long>> CreateLongUpDownCounter( + nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept override; + + nostd::shared_ptr<opentelemetry::metrics::UpDownCounter<double>> CreateDoubleUpDownCounter( + nostd::string_view name, + nostd::string_view description = "", + nostd::string_view unit = "") noexcept override; + + void CreateLongObservableUpDownCounter( + nostd::string_view name, + void (*callback)(opentelemetry::metrics::ObserverResult<long> &, void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept override; + + void CreateDoubleObservableUpDownCounter( + nostd::string_view name, + void (*callback)(opentelemetry::metrics::ObserverResult<double> &, void *), + nostd::string_view description = "", + nostd::string_view unit = "", + void *state = nullptr) noexcept override; + + /** Returns the associated instruementation library */ + const sdk::instrumentationlibrary::InstrumentationLibrary *GetInstrumentationLibrary() + const noexcept; + + /** collect metrics across all the instruments configured for the meter **/ + std::vector<MetricData> Collect(CollectorHandle *collector, + opentelemetry::common::SystemTimestamp collect_ts) noexcept; + +private: + // order of declaration is important here - instrumentation library should destroy after + // meter-context. + std::unique_ptr<sdk::instrumentationlibrary::InstrumentationLibrary> instrumentation_library_; + std::shared_ptr<sdk::metrics::MeterContext> meter_context_; + // Mapping between instrument-name and Aggregation Storage. + std::unordered_map<std::string, std::shared_ptr<MetricStorage>> storage_registry_; + + std::unique_ptr<WritableMetricStorage> RegisterMetricStorage( + InstrumentDescriptor &instrument_descriptor); + + template <class T> + void RegisterAsyncMetricStorage(InstrumentDescriptor &instrument_descriptor, + void (*callback)(opentelemetry::metrics::ObserverResult<T> &, + void *), + void *state = nullptr) + { + auto view_registry = meter_context_->GetViewRegistry(); + auto success = view_registry->FindViews( + instrument_descriptor, *instrumentation_library_, + [this, &instrument_descriptor, callback, state](const View &view) { + auto view_instr_desc = instrument_descriptor; + if (!view.GetName().empty()) + { + view_instr_desc.name_ = view.GetName(); + } + if (!view.GetDescription().empty()) + { + view_instr_desc.description_ = view.GetDescription(); + } + auto storage = std::shared_ptr<AsyncMetricStorage<T>>( + new AsyncMetricStorage<T>(view_instr_desc, view.GetAggregationType(), callback, + &view.GetAttributesProcessor(), state)); + storage_registry_[instrument_descriptor.name_] = storage; + return true; + }); + } +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/meter_context.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/meter_context.h new file mode 100644 index 000000000..e35700175 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/meter_context.h @@ -0,0 +1,133 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW + +# include "opentelemetry/common/spin_lock_mutex.h" +# include "opentelemetry/sdk/metrics/state/metric_collector.h" +# include "opentelemetry/sdk/metrics/view/instrument_selector.h" +# include "opentelemetry/sdk/metrics/view/meter_selector.h" +# include "opentelemetry/sdk/metrics/view/view_registry.h" +# include "opentelemetry/sdk/resource/resource.h" +# include "opentelemetry/version.h" + +# include <chrono> +# include <memory> +# include <vector> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +// forward declaration +class Meter; +class MetricReader; + +/** + * A class which stores the MeterProvider context. + + */ +class MeterContext : public std::enable_shared_from_this<MeterContext> +{ +public: + /** + * Initialize a new meter provider + * @param readers The readers to be configured with meter context. + * @param views The views to be configured with meter context. + * @param resource The resource for this meter context. + */ + MeterContext( + std::unique_ptr<ViewRegistry> views = std::unique_ptr<ViewRegistry>(new ViewRegistry()), + opentelemetry::sdk::resource::Resource resource = + opentelemetry::sdk::resource::Resource::Create({})) noexcept; + + /** + * Obtain the resource associated with this meter context. + * @return The resource for this meter context + */ + const opentelemetry::sdk::resource::Resource &GetResource() const noexcept; + + /** + * Obtain the View Registry configured + * @return The reference to view registry + */ + ViewRegistry *GetViewRegistry() const noexcept; + + /** + * Obtain the configured meters. + * + */ + nostd::span<std::shared_ptr<Meter>> GetMeters() noexcept; + + /** + * Obtain the configured collectors. + * + */ + nostd::span<std::shared_ptr<CollectorHandle>> GetCollectors() noexcept; + + /** + * GET SDK Start time + * + */ + opentelemetry::common::SystemTimestamp GetSDKStartTime() noexcept; + + /** + * Attaches a metric reader to list of configured readers for this Meter context. + * @param reader The metric reader for this meter context. This + * must not be a nullptr. + * + * Note: This reader may not receive any in-flight meter data, but will get newly created meter + * data. Note: This method is not thread safe, and should ideally be called from main thread. + */ + void AddMetricReader(std::unique_ptr<MetricReader> reader) noexcept; + + /** + * Attaches a View to list of configured Views for this Meter context. + * @param view The Views for this meter context. This + * must not be a nullptr. + * + * Note: This view may not receive any in-flight meter data, but will get newly created meter + * data. Note: This method is not thread safe, and should ideally be called from main thread. + */ + void AddView(std::unique_ptr<InstrumentSelector> instrument_selector, + std::unique_ptr<MeterSelector> meter_selector, + std::unique_ptr<View> view) noexcept; + + /** + * Adds a meter to the list of configured meters. + * Note: This method is INTERNAL to sdk not thread safe. + * + * @param meter + */ + void AddMeter(std::shared_ptr<Meter> meter); + + /** + * Force all active Collectors to flush any buffered meter data + * within the given timeout. + */ + + bool ForceFlush(std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept; + + /** + * Shutdown the Collectors associated with this meter provider. + */ + bool Shutdown() noexcept; + +private: + opentelemetry::sdk::resource::Resource resource_; + std::vector<std::shared_ptr<CollectorHandle>> collectors_; + std::unique_ptr<ViewRegistry> views_; + opentelemetry::common::SystemTimestamp sdk_start_ts_; + std::vector<std::shared_ptr<Meter>> meters_; + + std::atomic_flag shutdown_latch_ = ATOMIC_FLAG_INIT; + opentelemetry::common::SpinLockMutex forceflush_lock_; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/meter_provider.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/meter_provider.h new file mode 100644 index 000000000..685f43e74 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/meter_provider.h @@ -0,0 +1,95 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include <memory> +# include <mutex> +# include <vector> +# include "opentelemetry/metrics/meter.h" +# include "opentelemetry/metrics/meter_provider.h" +# include "opentelemetry/nostd/shared_ptr.h" +# include "opentelemetry/sdk/metrics/meter.h" +# include "opentelemetry/sdk/metrics/meter_context.h" +# include "opentelemetry/sdk/resource/resource.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +// forward declaration +class MetricCollector; +class MetricReader; + +class MeterProvider final : public opentelemetry::metrics::MeterProvider +{ +public: + /** + * Initialize a new meter provider + * @param views The views for this meter provider + * @param resource The resources for this meter provider. + */ + MeterProvider( + std::unique_ptr<ViewRegistry> views = std::unique_ptr<ViewRegistry>(new ViewRegistry()), + sdk::resource::Resource resource = sdk::resource::Resource::Create({})) noexcept; + + /** + * Initialize a new meter provider with a specified context + * @param context The shared meter configuration/pipeline for this provider. + */ + explicit MeterProvider(std::shared_ptr<sdk::metrics::MeterContext> context) noexcept; + + nostd::shared_ptr<opentelemetry::metrics::Meter> GetMeter( + nostd::string_view name, + nostd::string_view version = "", + nostd::string_view schema_url = "") noexcept override; + + /** + * Obtain the resource associated with this meter provider. + * @return The resource for this meter provider. + */ + const sdk::resource::Resource &GetResource() const noexcept; + + /** + * Attaches a metric reader to list of configured readers for this Meter providers. + * @param reader The metric reader for this meter provider. This + * must not be a nullptr. + * + * Note: This reader may not receive any in-flight meter data, but will get newly created meter + * data. Note: This method is not thread safe, and should ideally be called from main thread. + */ + void AddMetricReader(std::unique_ptr<MetricReader> reader) noexcept; + + /** + * Attaches a View to list of configured Views for this Meter provider. + * @param view The Views for this meter provider. This + * must not be a nullptr. + * + * Note: This view may not receive any in-flight meter data, but will get newly created meter + * data. Note: This method is not thread safe, and should ideally be called from main thread. + */ + void AddView(std::unique_ptr<InstrumentSelector> instrument_selector, + std::unique_ptr<MeterSelector> meter_selector, + std::unique_ptr<View> view) noexcept; + + /** + * Shutdown the meter provider. + */ + bool Shutdown() noexcept; + + /** + * Force flush the meter provider. + */ + bool ForceFlush(std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept; + +private: + std::shared_ptr<sdk::metrics::MeterContext> context_; + std::mutex lock_; +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/metric_exporter.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/metric_exporter.h new file mode 100644 index 000000000..3217b83df --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/metric_exporter.h @@ -0,0 +1,55 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW + +# include "opentelemetry/nostd/span.h" +# include "opentelemetry/sdk/common/exporter_utils.h" +# include "opentelemetry/sdk/metrics/export/metric_producer.h" +# include "opentelemetry/version.h" + +# include <chrono> +# include <memory> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +class MetricData; +/** + * MetricExporter defines the interface to be used by metrics libraries to + * push metrics data to the OpenTelemetry exporters. + */ +class MetricExporter +{ +public: + virtual ~MetricExporter() = default; + + /** + * Exports a batch of metrics data. This method must not be called + * concurrently for the same exporter instance. + * @param data metrics data + */ + virtual opentelemetry::sdk::common::ExportResult Export(const ResourceMetrics &data) noexcept = 0; + + /** + * Force flush the exporter. + */ + virtual bool ForceFlush( + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept = 0; + + /** + * Shut down the metric exporter. + * @param timeout an optional timeout. + * @return return the status of the operation. + */ + virtual bool Shutdown( + std::chrono::microseconds timeout = std::chrono::microseconds(0)) noexcept = 0; +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/metric_reader.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/metric_reader.h new file mode 100644 index 000000000..94924315f --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/metric_reader.h @@ -0,0 +1,72 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/common/spin_lock_mutex.h" +# include "opentelemetry/sdk/common/global_log_handler.h" +# include "opentelemetry/sdk/metrics/data/metric_data.h" +# include "opentelemetry/sdk/metrics/export/metric_producer.h" +# include "opentelemetry/sdk/metrics/instruments.h" +# include "opentelemetry/version.h" + +# include <chrono> +# include <memory> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +/** + * MetricReader defines the interface to collect metrics from SDK + */ +class MetricReader +{ +public: + MetricReader( + AggregationTemporality aggregation_temporality = AggregationTemporality::kCumulative); + + void SetMetricProducer(MetricProducer *metric_producer); + + /** + * Collect the metrics from SDK. + * @return return the status of the operation. + */ + bool Collect(nostd::function_ref<bool(ResourceMetrics &metric_data)> callback) noexcept; + + AggregationTemporality GetAggregationTemporality() const noexcept; + + /** + * Shutdown the meter reader. + */ + bool Shutdown(std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept; + + /** + * Force flush the metric read by the reader. + */ + bool ForceFlush(std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept; + + virtual ~MetricReader() = default; + +private: + virtual bool OnForceFlush(std::chrono::microseconds timeout) noexcept = 0; + + virtual bool OnShutDown(std::chrono::microseconds timeout) noexcept = 0; + + virtual void OnInitialized() noexcept {} + +protected: + bool IsShutdown() const noexcept; + +private: + MetricProducer *metric_producer_; + AggregationTemporality aggregation_temporality_; + mutable opentelemetry::common::SpinLockMutex lock_; + bool shutdown_; +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/observer_result.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/observer_result.h new file mode 100644 index 000000000..ca7227bc5 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/observer_result.h @@ -0,0 +1,48 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/common/key_value_iterable.h" +# include "opentelemetry/metrics/observer_result.h" +# include "opentelemetry/sdk/metrics/state/attributes_hashmap.h" +# include "opentelemetry/sdk/metrics/view/attributes_processor.h" + +# include <map> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +template <class T> +class ObserverResult final : public opentelemetry::metrics::ObserverResult<T> +{ +public: + ObserverResult(const AttributesProcessor *attributes_processor) + : attributes_processor_(attributes_processor) + {} + + void Observe(T value) noexcept override { data_.insert({{}, value}); } + + void Observe(T value, const opentelemetry::common::KeyValueIterable &attributes) noexcept override + { + auto attr = attributes_processor_->process(attributes); + data_.insert({attr, value}); + } + + const std::unordered_map<MetricAttributes, T, AttributeHashGenerator> &GetMeasurements() + { + return data_; + } + +private: + std::unordered_map<MetricAttributes, T, AttributeHashGenerator> data_; + + const AttributesProcessor *attributes_processor_; +}; +} // namespace metrics +} // namespace sdk + +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/async_metric_storage.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/async_metric_storage.h new file mode 100644 index 000000000..e5dcbc273 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/async_metric_storage.h @@ -0,0 +1,95 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/sdk/common/attributemap_hash.h" +# include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h" +# include "opentelemetry/sdk/metrics/instruments.h" +# include "opentelemetry/sdk/metrics/observer_result.h" +# include "opentelemetry/sdk/metrics/state/attributes_hashmap.h" +# include "opentelemetry/sdk/metrics/state/metric_collector.h" +# include "opentelemetry/sdk/metrics/state/metric_storage.h" +# include "opentelemetry/sdk/metrics/state/temporal_metric_storage.h" +# include "opentelemetry/sdk/metrics/view/attributes_processor.h" + +# include <memory> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +template <class T> +class AsyncMetricStorage : public MetricStorage +{ +public: + AsyncMetricStorage(InstrumentDescriptor instrument_descriptor, + const AggregationType aggregation_type, + void (*measurement_callback)(opentelemetry::metrics::ObserverResult<T> &, + void *), + const AttributesProcessor *attributes_processor, + void *state = nullptr) + : instrument_descriptor_(instrument_descriptor), + aggregation_type_{aggregation_type}, + measurement_collection_callback_{measurement_callback}, + attributes_processor_{attributes_processor}, + state_{state}, + cumulative_hash_map_(new AttributesHashMap()), + temporal_metric_storage_(instrument_descriptor) + {} + + bool Collect(CollectorHandle *collector, + nostd::span<std::shared_ptr<CollectorHandle>> collectors, + opentelemetry::common::SystemTimestamp sdk_start_ts, + opentelemetry::common::SystemTimestamp collection_ts, + nostd::function_ref<bool(MetricData)> metric_collection_callback) noexcept override + { + opentelemetry::sdk::metrics::ObserverResult<T> ob_res(attributes_processor_); + + // read the measurement using configured callback + measurement_collection_callback_(ob_res, state_); + std::shared_ptr<AttributesHashMap> delta_hash_map(new AttributesHashMap()); + // process the read measurements - aggregate and store in hashmap + for (auto &measurement : ob_res.GetMeasurements()) + { + auto aggr = DefaultAggregation::CreateAggregation(aggregation_type_, instrument_descriptor_); + aggr->Aggregate(measurement.second); + auto prev = cumulative_hash_map_->Get(measurement.first); + if (prev) + { + auto delta = prev->Diff(*aggr); + cumulative_hash_map_->Set(measurement.first, + DefaultAggregation::CloneAggregation( + aggregation_type_, instrument_descriptor_, *delta)); + delta_hash_map->Set(measurement.first, std::move(delta)); + } + else + { + cumulative_hash_map_->Set( + measurement.first, + DefaultAggregation::CloneAggregation(aggregation_type_, instrument_descriptor_, *aggr)); + delta_hash_map->Set(measurement.first, std::move(aggr)); + } + } + + return temporal_metric_storage_.buildMetrics(collector, collectors, sdk_start_ts, collection_ts, + std::move(delta_hash_map), + metric_collection_callback); + } + +private: + InstrumentDescriptor instrument_descriptor_; + AggregationType aggregation_type_; + void (*measurement_collection_callback_)(opentelemetry::metrics::ObserverResult<T> &, void *); + const AttributesProcessor *attributes_processor_; + void *state_; + std::unique_ptr<AttributesHashMap> cumulative_hash_map_; + TemporalMetricStorage temporal_metric_storage_; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/attributes_hashmap.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/attributes_hashmap.h new file mode 100644 index 000000000..50d40e0ae --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/attributes_hashmap.h @@ -0,0 +1,124 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/common/spin_lock_mutex.h" +# include "opentelemetry/nostd/function_ref.h" +# include "opentelemetry/sdk/common/attribute_utils.h" +# include "opentelemetry/sdk/common/attributemap_hash.h" +# include "opentelemetry/sdk/metrics/aggregation/aggregation.h" +# include "opentelemetry/sdk/metrics/instruments.h" +# include "opentelemetry/version.h" + +# include <functional> +# include <memory> +# include <mutex> +# include <unordered_map> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +using opentelemetry::sdk::common::OrderedAttributeMap; + +class AttributeHashGenerator +{ +public: + size_t operator()(const MetricAttributes &attributes) const + { + return opentelemetry::sdk::common::GetHashForAttributeMap(attributes); + } +}; + +class AttributesHashMap +{ +public: + Aggregation *Get(const MetricAttributes &attributes) const + { + std::lock_guard<opentelemetry::common::SpinLockMutex> guard(lock_); + auto it = hash_map_.find(attributes); + if (it != hash_map_.end()) + { + return it->second.get(); + } + return nullptr; + } + + /** + * @return check if key is present in hash + * + */ + bool Has(const MetricAttributes &attributes) const + { + std::lock_guard<opentelemetry::common::SpinLockMutex> guard(lock_); + return (hash_map_.find(attributes) == hash_map_.end()) ? false : true; + } + + /** + * @return the pointer to value for given key if present. + * If not present, it uses the provided callback to generate + * value and store in the hash + */ + Aggregation *GetOrSetDefault(const MetricAttributes &attributes, + std::function<std::unique_ptr<Aggregation>()> aggregation_callback) + { + std::lock_guard<opentelemetry::common::SpinLockMutex> guard(lock_); + + auto it = hash_map_.find(attributes); + if (it != hash_map_.end()) + { + return it->second.get(); + } + + hash_map_[attributes] = std::move(aggregation_callback()); + return hash_map_[attributes].get(); + } + + /** + * Set the value for given key, overwriting the value if already present + */ + void Set(const MetricAttributes &attributes, std::unique_ptr<Aggregation> value) + { + std::lock_guard<opentelemetry::common::SpinLockMutex> guard(lock_); + hash_map_[attributes] = std::move(value); + } + + /** + * Iterate the hash to yield key and value stored in hash. + */ + bool GetAllEnteries( + nostd::function_ref<bool(const MetricAttributes &, Aggregation &)> callback) const + { + std::lock_guard<opentelemetry::common::SpinLockMutex> guard(lock_); + for (auto &kv : hash_map_) + { + if (!callback(kv.first, *(kv.second.get()))) + { + return false; // callback is not prepared to consume data + } + } + return true; + } + + /** + * Return the size of hash. + */ + size_t Size() + { + std::lock_guard<opentelemetry::common::SpinLockMutex> guard(lock_); + return hash_map_.size(); + } + +private: + std::unordered_map<MetricAttributes, std::unique_ptr<Aggregation>, AttributeHashGenerator> + hash_map_; + + mutable opentelemetry::common::SpinLockMutex lock_; +}; +} // namespace metrics + +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/metric_collector.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/metric_collector.h new file mode 100644 index 000000000..20372f520 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/metric_collector.h @@ -0,0 +1,57 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/sdk/metrics/data/metric_data.h" +# include "opentelemetry/sdk/metrics/export/metric_producer.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +class MetricReader; +class MeterContext; + +class CollectorHandle +{ +public: + virtual AggregationTemporality GetAggregationTemporality() noexcept = 0; +}; + +/** + * An internal opaque interface that the MetricReader receives as + * MetricProducer. It acts as the storage key to the internal metric stream + * state for each MetricReader. + */ + +class MetricCollector : public MetricProducer, public CollectorHandle +{ +public: + MetricCollector(std::shared_ptr<MeterContext> &&context, + std::unique_ptr<MetricReader> metric_reader); + + AggregationTemporality GetAggregationTemporality() noexcept override; + + /** + * The callback to be called for each metric exporter. This will only be those + * metrics that have been produced since the last time this method was called. + * + * @return a status of completion of method. + */ + bool Collect(nostd::function_ref<bool(ResourceMetrics &metric_data)> callback) noexcept override; + + bool ForceFlush(std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept; + + bool Shutdown(std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept; + +private: + std::shared_ptr<MeterContext> meter_context_; + std::shared_ptr<MetricReader> metric_reader_; +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/metric_storage.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/metric_storage.h new file mode 100644 index 000000000..e0ba55cbf --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/metric_storage.h @@ -0,0 +1,86 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/common/key_value_iterable_view.h" +# include "opentelemetry/common/timestamp.h" +# include "opentelemetry/context/context.h" +# include "opentelemetry/sdk/metrics/data/metric_data.h" +# include "opentelemetry/sdk/metrics/instruments.h" +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +/* Represent the storage from which to collect the metrics */ +class CollectorHandle; + +class MetricStorage +{ +public: + /* collect the metrics from this storage */ + virtual bool Collect(CollectorHandle *collector, + nostd::span<std::shared_ptr<CollectorHandle>> collectors, + opentelemetry::common::SystemTimestamp sdk_start_ts, + opentelemetry::common::SystemTimestamp collection_ts, + nostd::function_ref<bool(MetricData)> callback) noexcept = 0; +}; + +class WritableMetricStorage +{ +public: + virtual void RecordLong(long value, const opentelemetry::context::Context &context) noexcept = 0; + + virtual void RecordLong(long value, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept = 0; + + virtual void RecordDouble(double value, + const opentelemetry::context::Context &context) noexcept = 0; + + virtual void RecordDouble(double value, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept = 0; + + virtual ~WritableMetricStorage() = default; +}; + +class NoopMetricStorage : public MetricStorage +{ +public: + bool Collect(CollectorHandle *collector, + nostd::span<std::shared_ptr<CollectorHandle>> collectors, + opentelemetry::common::SystemTimestamp sdk_start_ts, + opentelemetry::common::SystemTimestamp collection_ts, + nostd::function_ref<bool(MetricData)> callback) noexcept override + { + MetricData metric_data; + return callback(std::move(metric_data)); + } +}; + +class NoopWritableMetricStorage : public WritableMetricStorage +{ +public: + void RecordLong(long value, const opentelemetry::context::Context &context) noexcept = 0; + + void RecordLong(long value, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept override + {} + + void RecordDouble(double value, const opentelemetry::context::Context &context) noexcept override + {} + + void RecordDouble(double value, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept override + {} +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/multi_metric_storage.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/multi_metric_storage.h new file mode 100644 index 000000000..ceeafa040 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/multi_metric_storage.h @@ -0,0 +1,68 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/common/key_value_iterable_view.h" +# include "opentelemetry/sdk/metrics/instruments.h" +# include "opentelemetry/sdk/metrics/state/metric_storage.h" + +# include <memory> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +class MultiMetricStorage : public WritableMetricStorage +{ +public: + void AddStorage(std::shared_ptr<WritableMetricStorage> storage) { storages_.push_back(storage); } + + virtual void RecordLong(long value, + const opentelemetry::context::Context &context) noexcept override + { + for (auto &s : storages_) + { + s->RecordLong(value, context); + } + } + + virtual void RecordLong(long value, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept override + { + for (auto &s : storages_) + { + s->RecordLong(value, attributes, context); + } + } + + virtual void RecordDouble(double value, + const opentelemetry::context::Context &context) noexcept override + { + for (auto &s : storages_) + { + s->RecordDouble(value, context); + } + } + + virtual void RecordDouble(double value, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept override + { + for (auto &s : storages_) + { + s->RecordDouble(value, attributes, context); + } + } + +private: + std::vector<std::shared_ptr<WritableMetricStorage>> storages_; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/sync_metric_storage.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/sync_metric_storage.h new file mode 100644 index 000000000..278f7dbe3 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/sync_metric_storage.h @@ -0,0 +1,119 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/common/key_value_iterable_view.h" +# include "opentelemetry/sdk/common/attributemap_hash.h" +# include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h" +# include "opentelemetry/sdk/metrics/exemplar/reservoir.h" +# include "opentelemetry/sdk/metrics/state/attributes_hashmap.h" +# include "opentelemetry/sdk/metrics/state/metric_collector.h" +# include "opentelemetry/sdk/metrics/state/metric_storage.h" + +# include "opentelemetry/sdk/metrics/state/temporal_metric_storage.h" +# include "opentelemetry/sdk/metrics/view/attributes_processor.h" + +# include <list> +# include <memory> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +class SyncMetricStorage : public MetricStorage, public WritableMetricStorage +{ + +public: + SyncMetricStorage(InstrumentDescriptor instrument_descriptor, + const AggregationType aggregation_type, + const AttributesProcessor *attributes_processor, + nostd::shared_ptr<ExemplarReservoir> &&exemplar_reservoir) + : instrument_descriptor_(instrument_descriptor), + aggregation_type_{aggregation_type}, + attributes_hashmap_(new AttributesHashMap()), + attributes_processor_{attributes_processor}, + exemplar_reservoir_(exemplar_reservoir), + temporal_metric_storage_(instrument_descriptor) + + { + create_default_aggregation_ = [&]() -> std::unique_ptr<Aggregation> { + return std::move( + DefaultAggregation::CreateAggregation(aggregation_type_, instrument_descriptor_)); + }; + } + + void RecordLong(long value, const opentelemetry::context::Context &context) noexcept override + { + if (instrument_descriptor_.value_type_ != InstrumentValueType::kLong) + { + return; + } + exemplar_reservoir_->OfferMeasurement(value, {}, context, std::chrono::system_clock::now()); + attributes_hashmap_->GetOrSetDefault({}, create_default_aggregation_)->Aggregate(value); + } + + void RecordLong(long value, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept override + { + if (instrument_descriptor_.value_type_ != InstrumentValueType::kLong) + { + return; + } + + exemplar_reservoir_->OfferMeasurement(value, attributes, context, + std::chrono::system_clock::now()); + auto attr = attributes_processor_->process(attributes); + attributes_hashmap_->GetOrSetDefault(attr, create_default_aggregation_)->Aggregate(value); + } + + void RecordDouble(double value, const opentelemetry::context::Context &context) noexcept override + { + if (instrument_descriptor_.value_type_ != InstrumentValueType::kDouble) + { + return; + } + exemplar_reservoir_->OfferMeasurement(value, {}, context, std::chrono::system_clock::now()); + attributes_hashmap_->GetOrSetDefault({}, create_default_aggregation_)->Aggregate(value); + } + + void RecordDouble(double value, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept override + { + exemplar_reservoir_->OfferMeasurement(value, attributes, context, + std::chrono::system_clock::now()); + if (instrument_descriptor_.value_type_ != InstrumentValueType::kDouble) + { + return; + } + exemplar_reservoir_->OfferMeasurement(value, attributes, context, + std::chrono::system_clock::now()); + auto attr = attributes_processor_->process(attributes); + attributes_hashmap_->GetOrSetDefault(attr, create_default_aggregation_)->Aggregate(value); + } + + bool Collect(CollectorHandle *collector, + nostd::span<std::shared_ptr<CollectorHandle>> collectors, + opentelemetry::common::SystemTimestamp sdk_start_ts, + opentelemetry::common::SystemTimestamp collection_ts, + nostd::function_ref<bool(MetricData)> callback) noexcept override; + +private: + InstrumentDescriptor instrument_descriptor_; + AggregationType aggregation_type_; + + // hashmap to maintain the metrics for delta collection (i.e, collection since last Collect call) + std::unique_ptr<AttributesHashMap> attributes_hashmap_; + const AttributesProcessor *attributes_processor_; + std::function<std::unique_ptr<Aggregation>()> create_default_aggregation_; + nostd::shared_ptr<ExemplarReservoir> exemplar_reservoir_; + TemporalMetricStorage temporal_metric_storage_; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/temporal_metric_storage.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/temporal_metric_storage.h new file mode 100644 index 000000000..16659c14f --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/state/temporal_metric_storage.h @@ -0,0 +1,50 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/sdk/metrics/state/attributes_hashmap.h" +# include "opentelemetry/sdk/metrics/state/metric_collector.h" + +# include <memory> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +struct LastReportedMetrics +{ + std::unique_ptr<AttributesHashMap> attributes_map; + opentelemetry::common::SystemTimestamp collection_ts; +}; + +class TemporalMetricStorage +{ +public: + TemporalMetricStorage(InstrumentDescriptor instrument_descriptor); + + bool buildMetrics(CollectorHandle *collector, + nostd::span<std::shared_ptr<CollectorHandle>> collectors, + opentelemetry::common::SystemTimestamp sdk_start_ts, + opentelemetry::common::SystemTimestamp collection_ts, + std::shared_ptr<AttributesHashMap> delta_metrics, + nostd::function_ref<bool(MetricData)> callback) noexcept; + +private: + InstrumentDescriptor instrument_descriptor_; + + // unreported metrics stash for all the collectors + std::unordered_map<CollectorHandle *, std::list<std::shared_ptr<AttributesHashMap>>> + unreported_metrics_; + // last reported metrics stash for all the collectors. + std::unordered_map<CollectorHandle *, LastReportedMetrics> last_reported_metrics_; + + // Lock while building metrics + mutable opentelemetry::common::SpinLockMutex lock_; +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/sync_instruments.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/sync_instruments.h new file mode 100644 index 000000000..f4c9bae32 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/sync_instruments.h @@ -0,0 +1,127 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/common/key_value_iterable.h" +# include "opentelemetry/metrics/sync_instruments.h" +# include "opentelemetry/nostd/string_view.h" +# include "opentelemetry/sdk/metrics/instruments.h" + +# include "opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +// forward declaration +class WritableMetricStorage; + +class Synchronous +{ +public: + Synchronous(InstrumentDescriptor instrument_descriptor, + std::unique_ptr<WritableMetricStorage> storage) + : instrument_descriptor_(instrument_descriptor), storage_(std::move(storage)) + {} + +protected: + InstrumentDescriptor instrument_descriptor_; + std::unique_ptr<WritableMetricStorage> storage_; +}; + +class LongCounter : public Synchronous, public opentelemetry::metrics::Counter<long> +{ +public: + LongCounter(InstrumentDescriptor instrument_descriptor, + std::unique_ptr<WritableMetricStorage> storage); + + void Add(long value, const opentelemetry::common::KeyValueIterable &attributes) noexcept override; + void Add(long value, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept override; + + void Add(long value) noexcept override; + void Add(long value, const opentelemetry::context::Context &context) noexcept override; +}; + +class DoubleCounter : public Synchronous, public opentelemetry::metrics::Counter<double> +{ + +public: + DoubleCounter(InstrumentDescriptor instrument_descriptor, + std::unique_ptr<WritableMetricStorage> storage); + + void Add(double value, + const opentelemetry::common::KeyValueIterable &attributes) noexcept override; + void Add(double value, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept override; + + void Add(double value) noexcept override; + void Add(double value, const opentelemetry::context::Context &context) noexcept override; +}; + +class LongUpDownCounter : public Synchronous, public opentelemetry::metrics::UpDownCounter<long> +{ +public: + LongUpDownCounter(InstrumentDescriptor instrument_descriptor, + std::unique_ptr<WritableMetricStorage> storage); + + void Add(long value, const opentelemetry::common::KeyValueIterable &attributes) noexcept override; + void Add(long value, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept override; + + void Add(long value) noexcept override; + void Add(long value, const opentelemetry::context::Context &context) noexcept override; +}; + +class DoubleUpDownCounter : public Synchronous, public opentelemetry::metrics::UpDownCounter<double> +{ +public: + DoubleUpDownCounter(InstrumentDescriptor instrument_descriptor, + std::unique_ptr<WritableMetricStorage> storage); + + void Add(double value, + const opentelemetry::common::KeyValueIterable &attributes) noexcept override; + void Add(double value, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept override; + + void Add(double value) noexcept override; + void Add(double value, const opentelemetry::context::Context &context) noexcept override; +}; + +class LongHistogram : public Synchronous, public opentelemetry::metrics::Histogram<long> +{ +public: + LongHistogram(InstrumentDescriptor instrument_descriptor, + std::unique_ptr<WritableMetricStorage> storage); + + void Record(long value, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept override; + + void Record(long value, const opentelemetry::context::Context &context) noexcept override; +}; + +class DoubleHistogram : public Synchronous, public opentelemetry::metrics::Histogram<double> +{ +public: + DoubleHistogram(InstrumentDescriptor instrument_descriptor, + std::unique_ptr<WritableMetricStorage> storage); + + void Record(double value, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept override; + + void Record(double value, const opentelemetry::context::Context &context) noexcept override; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/attributes_processor.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/attributes_processor.h new file mode 100644 index 000000000..d82607357 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/attributes_processor.h @@ -0,0 +1,81 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/sdk/common/attribute_utils.h" +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +using MetricAttributes = opentelemetry::sdk::common::OrderedAttributeMap; + +/** + * The AttributesProcessor is responsible for customizing which + * attribute(s) are to be reported as metrics dimension(s). + */ + +class AttributesProcessor +{ +public: + // Process the metric instrument attributes. + // @returns The processed attributes + virtual MetricAttributes process( + const opentelemetry::common::KeyValueIterable &attributes) const noexcept = 0; + + virtual ~AttributesProcessor() = default; +}; + +/** + * DefaultAttributesProcessor returns copy of input instrument attributes without + * any modification. + */ + +class DefaultAttributesProcessor : public AttributesProcessor +{ + MetricAttributes process( + const opentelemetry::common::KeyValueIterable &attributes) const noexcept override + { + MetricAttributes result(attributes); + return result; + } +}; + +/** + * FilteringAttributesProcessor filters by allowed attribute names and drops any names + * that are not in the allow list. + */ + +class FilteringAttributesProcessor : public AttributesProcessor +{ +public: + FilteringAttributesProcessor( + const std::unordered_map<std::string, bool> allowed_attribute_keys = {}) + : allowed_attribute_keys_(std::move(allowed_attribute_keys)) + {} + + MetricAttributes process( + const opentelemetry::common::KeyValueIterable &attributes) const noexcept override + { + MetricAttributes result; + attributes.ForEachKeyValue( + [&](nostd::string_view key, opentelemetry::common::AttributeValue value) noexcept { + if (allowed_attribute_keys_.find(key.data()) != allowed_attribute_keys_.end()) + { + result.SetAttribute(key, value); + return true; + } + return true; + }); + return result; + } + +private: + std::unordered_map<std::string, bool> allowed_attribute_keys_; +}; + +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/instrument_selector.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/instrument_selector.h new file mode 100644 index 000000000..e79a292c0 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/instrument_selector.h @@ -0,0 +1,36 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/nostd/string_view.h" +# include "opentelemetry/sdk/metrics/instruments.h" +# include "opentelemetry/sdk/metrics/view/predicate_factory.h" +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +class InstrumentSelector +{ +public: + InstrumentSelector(opentelemetry::sdk::metrics::InstrumentType instrument_type, + opentelemetry::nostd::string_view name) + : name_filter_{std::move(PredicateFactory::GetPredicate(name, PredicateType::kPattern))}, + instrument_type_{instrument_type} + {} + + // Returns name filter predicate. This shouldn't be deleted + const opentelemetry::sdk::metrics::Predicate *const GetNameFilter() { return name_filter_.get(); } + + // Returns instrument filter. + InstrumentType GetInstrumentType() { return instrument_type_; } + +private: + std::unique_ptr<opentelemetry::sdk::metrics::Predicate> name_filter_; + opentelemetry::sdk::metrics::InstrumentType instrument_type_; +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/meter_selector.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/meter_selector.h new file mode 100644 index 000000000..d0bc07ccb --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/meter_selector.h @@ -0,0 +1,47 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/sdk/metrics/view/predicate_factory.h" +#ifndef ENABLE_METRICS_PREVIEW +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +class MeterSelector +{ +public: + MeterSelector(opentelemetry::nostd::string_view name, + opentelemetry::nostd::string_view version, + opentelemetry::nostd::string_view schema) + : name_filter_{std::move(PredicateFactory::GetPredicate(name, PredicateType::kExact))}, + version_filter_{std::move(PredicateFactory::GetPredicate(version, PredicateType::kExact))}, + schema_filter_{std::move(PredicateFactory::GetPredicate(schema, PredicateType::kExact))} + {} + + // Returns name filter predicate. This shouldn't be deleted + const opentelemetry::sdk::metrics::Predicate *const GetNameFilter() { return name_filter_.get(); } + + // Returns version filter predicate. This shouldn't be deleted + const opentelemetry::sdk::metrics::Predicate *const GetVersionFilter() + { + return version_filter_.get(); + } + + // Returns schema filter predicate. This shouldn't be deleted + const opentelemetry::sdk::metrics::Predicate *const GetSchemaFilter() + { + return schema_filter_.get(); + } + +private: + std::unique_ptr<opentelemetry::sdk::metrics::Predicate> name_filter_; + std::unique_ptr<opentelemetry::sdk::metrics::Predicate> version_filter_; + std::unique_ptr<opentelemetry::sdk::metrics::Predicate> schema_filter_; +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/predicate.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/predicate.h new file mode 100644 index 000000000..72de2979a --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/predicate.h @@ -0,0 +1,82 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include <vector> +# if (__GNUC__ == 4 && (__GNUC_MINOR__ == 8 || __GNUC_MINOR__ == 9)) +# define HAVE_WORKING_REGEX 0 +# include "opentelemetry/sdk/common/global_log_handler.h" +# else +# include <regex> +# define HAVE_WORKING_REGEX 1 +# endif + +# include "opentelemetry/nostd/string_view.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +class Predicate +{ +public: + virtual ~Predicate() = default; + virtual bool Match(opentelemetry::nostd::string_view string) const noexcept = 0; +}; + +class PatternPredicate : public Predicate +{ +public: + PatternPredicate(opentelemetry::nostd::string_view pattern) : reg_key_{pattern.data()} {} + bool Match(opentelemetry::nostd::string_view str) const noexcept override + { +# if HAVE_WORKING_REGEX + return std::regex_match(str.data(), reg_key_); +# else + // TBD - Support regex match for GCC4.8 + OTEL_INTERNAL_LOG_ERROR( + "PatternPredicate::Match - failed. std::regex not fully supported for this compiler."); + return false; // not supported +# endif + } + +private: +# if HAVE_WORKING_REGEX + std::regex reg_key_; +# else + std::string reg_key_; +# endif +}; + +class ExactPredicate : public Predicate +{ +public: + ExactPredicate(opentelemetry::nostd::string_view pattern) : pattern_{pattern} {} + bool Match(opentelemetry::nostd::string_view str) const noexcept override + { + if (pattern_ == str) + { + return true; + } + return false; + } + +private: + std::string pattern_; +}; + +class MatchEverythingPattern : public Predicate +{ + bool Match(opentelemetry::nostd::string_view str) const noexcept override { return true; } +}; + +class MatchNothingPattern : public Predicate +{ + bool Match(opentelemetry::nostd::string_view str) const noexcept override { return false; } +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/predicate_factory.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/predicate_factory.h new file mode 100644 index 000000000..466fa76d5 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/predicate_factory.h @@ -0,0 +1,45 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/sdk/metrics/view/predicate.h" +#ifndef ENABLE_METRICS_PREVIEW +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ + +enum class PredicateType : uint8_t +{ + kPattern, + kExact +}; + +class PredicateFactory +{ +public: + static std::unique_ptr<Predicate> GetPredicate(opentelemetry::nostd::string_view pattern, + PredicateType type) + { + if ((type == PredicateType::kPattern && pattern == "*") || + (type == PredicateType::kExact && pattern == "")) + { + return std::move(std::unique_ptr<Predicate>(new MatchEverythingPattern())); + } + if (type == PredicateType::kPattern) + { + return std::move(std::unique_ptr<Predicate>(new PatternPredicate(pattern))); + } + if (type == PredicateType::kExact) + { + return std::move(std::unique_ptr<Predicate>(new ExactPredicate(pattern))); + } + return std::move(std::unique_ptr<Predicate>(new MatchNothingPattern())); + } +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/view.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/view.h new file mode 100644 index 000000000..3cd9f850e --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/view.h @@ -0,0 +1,57 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include "opentelemetry/nostd/string_view.h" +# include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h" +# include "opentelemetry/sdk/metrics/instruments.h" +# include "opentelemetry/sdk/metrics/view/attributes_processor.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +/** + * View defines the interface to allow SDK user to + * customize the metrics before exported. + */ + +class View +{ +public: + View(const std::string &name, + const std::string &description = "", + AggregationType aggregation_type = AggregationType::kDefault, + std::unique_ptr<opentelemetry::sdk::metrics::AttributesProcessor> attributes_processor = + std::unique_ptr<opentelemetry::sdk::metrics::AttributesProcessor>( + new opentelemetry::sdk::metrics::DefaultAttributesProcessor())) + : name_(name), + description_(description), + aggregation_type_{aggregation_type}, + attributes_processor_{std::move(attributes_processor)} + {} + + virtual std::string GetName() const noexcept { return name_; } + + virtual std::string GetDescription() const noexcept { return description_; } + + virtual AggregationType GetAggregationType() const noexcept { return aggregation_type_; } + + virtual const opentelemetry::sdk::metrics::AttributesProcessor &GetAttributesProcessor() + const noexcept + { + return *attributes_processor_.get(); + } + +private: + std::string name_; + std::string description_; + AggregationType aggregation_type_; + std::unique_ptr<opentelemetry::sdk::metrics::AttributesProcessor> attributes_processor_; +}; +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/view_registry.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/view_registry.h new file mode 100644 index 000000000..795049dd9 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/metrics/view/view_registry.h @@ -0,0 +1,102 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +# include <unordered_map> +# include "opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h" +# include "opentelemetry/sdk/metrics/view/instrument_selector.h" +# include "opentelemetry/sdk/metrics/view/meter_selector.h" +# include "opentelemetry/sdk/metrics/view/view.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace metrics +{ +struct RegisteredView +{ + RegisteredView( + std::unique_ptr<opentelemetry::sdk::metrics::InstrumentSelector> instrument_selector, + std::unique_ptr<opentelemetry::sdk::metrics::MeterSelector> meter_selector, + std::unique_ptr<opentelemetry::sdk::metrics::View> view) + : instrument_selector_{std::move(instrument_selector)}, + meter_selector_{std::move(meter_selector)}, + view_{std::move(view)} + {} + std::unique_ptr<opentelemetry::sdk::metrics::InstrumentSelector> instrument_selector_; + std::unique_ptr<opentelemetry::sdk::metrics::MeterSelector> meter_selector_; + std::unique_ptr<opentelemetry::sdk::metrics::View> view_; +}; + +class ViewRegistry +{ +public: + void AddView(std::unique_ptr<opentelemetry::sdk::metrics::InstrumentSelector> instrument_selector, + std::unique_ptr<opentelemetry::sdk::metrics::MeterSelector> meter_selector, + std::unique_ptr<opentelemetry::sdk::metrics::View> view) + { + // TBD - thread-safe ? + + auto registered_view = std::unique_ptr<RegisteredView>(new RegisteredView{ + std::move(instrument_selector), std::move(meter_selector), std::move(view)}); + registered_views_.push_back(std::move(registered_view)); + } + + bool FindViews(const opentelemetry::sdk::metrics::InstrumentDescriptor &instrument_descriptor, + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + &instrumentation_library, + nostd::function_ref<bool(const View &)> callback) const + { + bool found = false; + for (auto const ®istered_view : registered_views_) + { + if (MatchMeter(registered_view->meter_selector_.get(), instrumentation_library) && + MatchInstrument(registered_view->instrument_selector_.get(), instrument_descriptor)) + { + found = true; + if (!callback(*(registered_view->view_.get()))) + { + return false; + } + } + } + // return default view if none found; + if (!found) + { + static View view("otel-default-view"); + if (!callback(view)) + { + return false; + } + } + return true; + } + + ~ViewRegistry() = default; + +private: + std::vector<std::unique_ptr<RegisteredView>> registered_views_; + static bool MatchMeter(opentelemetry::sdk::metrics::MeterSelector *selector, + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + &instrumentation_library) + { + return selector->GetNameFilter()->Match(instrumentation_library.GetName()) && + (instrumentation_library.GetVersion().size() == 0 || + selector->GetVersionFilter()->Match(instrumentation_library.GetVersion())) && + (instrumentation_library.GetSchemaURL().size() == 0 || + selector->GetSchemaFilter()->Match(instrumentation_library.GetSchemaURL())); + } + + static bool MatchInstrument( + opentelemetry::sdk::metrics::InstrumentSelector *selector, + const opentelemetry::sdk::metrics::InstrumentDescriptor &instrument_descriptor) + { + return selector->GetNameFilter()->Match(instrument_descriptor.name_) && + (selector->GetInstrumentType() == instrument_descriptor.type_); + } +}; +}; // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/resource/experimental_semantic_conventions.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/resource/experimental_semantic_conventions.h new file mode 100644 index 000000000..d9dc3630f --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/resource/experimental_semantic_conventions.h @@ -0,0 +1,141 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// NOTE: +// This implementation is based on the experimental specs for resource semantic convention as +// defined here: +// https://github.com/open-telemetry/opentelemetry-specification/tree/v1.0.0/specification/resource/semantic_conventions +// and MAY will change in future. + +#pragma once + +#include <type_traits> +#include <unordered_map> + +#include "opentelemetry/common/string_util.h" +#include "opentelemetry/version.h" + +#define OTEL_GET_RESOURCE_ATTR(name) \ + opentelemetry::sdk::resource::attr(OTEL_CPP_CONST_HASHCODE(name)) + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace resource +{ + +static const std::unordered_map<uint32_t, const char *> attribute_ids = { + {OTEL_CPP_CONST_HASHCODE(AttrServiceName), "service.name"}, + {OTEL_CPP_CONST_HASHCODE(AttrServiceNamespace), "service.namespace"}, + {OTEL_CPP_CONST_HASHCODE(AttrServiceInstance), "service.instance.id"}, + {OTEL_CPP_CONST_HASHCODE(AttrServiceVersion), "service.version"}, + + // telemetry attributes + {OTEL_CPP_CONST_HASHCODE(AttrTelemetrySdkName), "telemetry.sdk.name"}, + {OTEL_CPP_CONST_HASHCODE(AttrTelemetrySdkLanguage), "telemetry.sdk.language"}, + {OTEL_CPP_CONST_HASHCODE(AttrTelemetrySdkVersion), "telemetry.sdk.version"}, + {OTEL_CPP_CONST_HASHCODE(AttrTelemetryAutoVersion), "telemetry.auto.version"}, + + // compute unit: container attributes + {OTEL_CPP_CONST_HASHCODE(AttrContainerName), "container.name"}, + {OTEL_CPP_CONST_HASHCODE(AttrContainerId), "container.id"}, + {OTEL_CPP_CONST_HASHCODE(AttrContainerRuntime), "container.runtime"}, + {OTEL_CPP_CONST_HASHCODE(AttrContainerImageName), "container.image.name"}, + {OTEL_CPP_CONST_HASHCODE(AttrContainerImageTag), "container.image.tag"}, + + // compute unit: faas attributes + {OTEL_CPP_CONST_HASHCODE(AttrFaasName), "faas.name"}, + {OTEL_CPP_CONST_HASHCODE(AttrFaasId), "faas.id"}, + {OTEL_CPP_CONST_HASHCODE(AttrFaasVersion), "faas.version"}, + {OTEL_CPP_CONST_HASHCODE(AttrFaasInstance), "faas.instance"}, + {OTEL_CPP_CONST_HASHCODE(AttrFaasMaxMemory), "faas.max_memory"}, + + // compute unit : process attributes + {OTEL_CPP_CONST_HASHCODE(AttrProcessId), "process.pid"}, + {OTEL_CPP_CONST_HASHCODE(AttrProcessExecutableName), "process.executable.name"}, + {OTEL_CPP_CONST_HASHCODE(AttrProcessExecutablePath), "process.executable.path"}, + {OTEL_CPP_CONST_HASHCODE(AttrProcessCommand), "process.command"}, + {OTEL_CPP_CONST_HASHCODE(AttrProcessCommandLine), "process.command_line"}, + {OTEL_CPP_CONST_HASHCODE(AttrProcessCommandArgs), "process.command_args"}, + {OTEL_CPP_CONST_HASHCODE(AttrProcessOwner), "process.owner"}, + + // compute : process runtimes + {OTEL_CPP_CONST_HASHCODE(AttrProcessRuntimeName), "process.runtime.name"}, + {OTEL_CPP_CONST_HASHCODE(AttrProcessRuntimeVersion), "process.runtime.version"}, + {OTEL_CPP_CONST_HASHCODE(AttrProcessRuntimeDescription), "process.runtime.description"}, + + // compute unit : WebEngine + {OTEL_CPP_CONST_HASHCODE(AttrWebEngineName), "webengine.name"}, + {OTEL_CPP_CONST_HASHCODE(AttrWebEngineVersion), "webengine.version"}, + {OTEL_CPP_CONST_HASHCODE(AttrWebEngineDescription), "webengine.description"}, + + // compute instance : host + {OTEL_CPP_CONST_HASHCODE(AttrHostId), "host.id"}, + {OTEL_CPP_CONST_HASHCODE(AttrHostName), "host.name"}, + {OTEL_CPP_CONST_HASHCODE(AttrHostType), "host.type"}, + {OTEL_CPP_CONST_HASHCODE(AttrHostArch), "host.arch"}, + {OTEL_CPP_CONST_HASHCODE(AttrHostImageName), "host.image.name"}, + {OTEL_CPP_CONST_HASHCODE(AttrHostImageId), "host.image.id"}, + {OTEL_CPP_CONST_HASHCODE(AttrHostImageVersion), "host.image.version"}, + + // env os attributes + {OTEL_CPP_CONST_HASHCODE(AttrOsType), "os.type"}, + {OTEL_CPP_CONST_HASHCODE(AttrOsDescription), "os.description"}, + {OTEL_CPP_CONST_HASHCODE(AttrOsName), "os.name"}, + {OTEL_CPP_CONST_HASHCODE(AttrOsVersion), "os.version"}, + + // env device attributes + {OTEL_CPP_CONST_HASHCODE(AttrDeviceId), "device.id"}, + {OTEL_CPP_CONST_HASHCODE(AttrDeviceModelIdentifier), "device.model.identifier"}, + {OTEL_CPP_CONST_HASHCODE(AttrDeviceModelName), "device.model.name"}, + + // env cloud + {OTEL_CPP_CONST_HASHCODE(AttrCloudProvider), "cloud.provider"}, + {OTEL_CPP_CONST_HASHCODE(AttrCloudAccountId), "cloud.account.id"}, + {OTEL_CPP_CONST_HASHCODE(AttrCloudRegion), "cloud.region"}, + {OTEL_CPP_CONST_HASHCODE(AttrCloudAvailabilityZone), "cloud.availability_zone"}, + {OTEL_CPP_CONST_HASHCODE(AttrCloudPlatform), "cloud.platform"}, + + // env deployment + {OTEL_CPP_CONST_HASHCODE(AttrDeploymentEnvironment), "deployment.environment"}, + + // env kubernetes + // - cluster + {OTEL_CPP_CONST_HASHCODE(AttrK8sClusterName), "k8s.cluster.name"}, + // - node + {OTEL_CPP_CONST_HASHCODE(AttrK8sNodeName), "k8s.node.name"}, + {OTEL_CPP_CONST_HASHCODE(AttrK8sNodeUid), "k8s.node.uid"}, + // - namespace + {OTEL_CPP_CONST_HASHCODE(AttrK8sNamespaceName), "k8s.namespace.name"}, + // - pod + {OTEL_CPP_CONST_HASHCODE(AttrK8sPodUid), "k8s.pod.uid"}, + {OTEL_CPP_CONST_HASHCODE(AttrK8sPodName), "k8s.pod.name"}, + // - container + {OTEL_CPP_CONST_HASHCODE(AttrK8sContainerName), "k8s.container.name"}, + // - replicaset + {OTEL_CPP_CONST_HASHCODE(AttrK8sReplicaSetUid), "k8s.replicaset.uid"}, + {OTEL_CPP_CONST_HASHCODE(AttrK8sReplicaSetName), "k8s.replicaset.name"}, + // - deployment + {OTEL_CPP_CONST_HASHCODE(AttrK8sDeploymentUid), "k8s.deployment.uid"}, + {OTEL_CPP_CONST_HASHCODE(AttrK8sDeploymentName), "k8s.deployment.name"}, + // - stateful-set + {OTEL_CPP_CONST_HASHCODE(AttrK8sStatefulSetUid), "k8s.statefulset.uid"}, + {OTEL_CPP_CONST_HASHCODE(AttrK8sStatefulSetName), "k8s.statefulset.name"}, + // - daemon set + {OTEL_CPP_CONST_HASHCODE(AttrK8sDaemonSetUid), "k8s.daemonset.uid"}, + {OTEL_CPP_CONST_HASHCODE(AttrK8sDaemonSetName), "k8s.daemonset.name"}, + // - job + {OTEL_CPP_CONST_HASHCODE(AttrK8sJobUid), "k8s.job.uid"}, + {OTEL_CPP_CONST_HASHCODE(AttrK8sJobName), "k8s.job.name"}, + // - cronjob + {OTEL_CPP_CONST_HASHCODE(AttrCronjobUid), "k8s.cronjob.id"}, + {OTEL_CPP_CONST_HASHCODE(AttrCronjobName), "k8s.cronjob.name"}}; + +// function to generate hash code for semantic conventions attributes. +inline const char *attr(uint32_t attr) +{ + return (attribute_ids.find(attr) != attribute_ids.end()) ? attribute_ids.at(attr) : ""; +} +} // namespace resource +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/resource/resource.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/resource/resource.h new file mode 100644 index 000000000..120e871ab --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/resource/resource.h @@ -0,0 +1,86 @@ +// 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/sdk/common/attribute_utils.h" +#include "opentelemetry/sdk/resource/resource_detector.h" +#include "opentelemetry/sdk/version/version.h" +#include "opentelemetry/version.h" + +#include <memory> +#include <sstream> +#include <unordered_map> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace resource +{ + +using ResourceAttributes = opentelemetry::sdk::common::AttributeMap; + +class Resource +{ +public: + Resource(const Resource &) = default; + + const ResourceAttributes &GetAttributes() const noexcept; + const std::string &GetSchemaURL() const noexcept; + + /** + * Returns a new, merged {@link Resource} by merging the current Resource + * with the other Resource. In case of a collision, current Resource takes + * precedence. + * + * @param other the Resource that will be merged with this. + * @returns the newly merged Resource. + */ + + Resource Merge(const Resource &other) noexcept; + + /** + * Returns a newly created Resource with the specified attributes. + * It adds (merge) SDK attributes and OTEL attributes before returning. + * @param attributes for this resource + * @returns the newly created Resource. + */ + + static Resource Create(const ResourceAttributes &attributes, + const std::string &schema_url = std::string{}); + + /** + * Returns an Empty resource. + */ + + static Resource &GetEmpty(); + + /** + * Returns a Resource that indentifies the SDK in use. + */ + + static Resource &GetDefault(); + +protected: + /** + * The constructor is protected and only for use internally by the class and + * inside ResourceDetector class. + * Users should use the Create factory method to obtain a Resource + * instance. + */ + Resource(const ResourceAttributes &attributes = ResourceAttributes(), + const std::string &schema_url = std::string{}) noexcept; + +private: + ResourceAttributes attributes_; + std::string schema_url_; + + friend class OTELResourceDetector; +}; + +} // namespace resource +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/resource/resource_detector.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/resource/resource_detector.h new file mode 100644 index 000000000..5f9d904af --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/resource/resource_detector.h @@ -0,0 +1,38 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/nostd/unique_ptr.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace resource +{ + +class Resource; + +/** + * Interface for a Resource Detector + */ +class ResourceDetector +{ +public: + virtual Resource Detect() = 0; +}; + +/** + * OTelResourceDetector to detect the presence of and create a Resource + * from the OTEL_RESOURCE_ATTRIBUTES environment variable. + */ +class OTELResourceDetector : public ResourceDetector +{ +public: + Resource Detect() noexcept override; +}; + +} // namespace resource +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/batch_span_processor.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/batch_span_processor.h new file mode 100644 index 000000000..d25ff2d95 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/batch_span_processor.h @@ -0,0 +1,158 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/sdk/common/circular_buffer.h" +#include "opentelemetry/sdk/trace/exporter.h" +#include "opentelemetry/sdk/trace/processor.h" + +#include <atomic> +#include <condition_variable> +#include <thread> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ + +namespace trace +{ + +/** + * Struct to hold batch SpanProcessor options. + */ +struct BatchSpanProcessorOptions +{ + /** + * The maximum buffer/queue size. After the size is reached, spans are + * dropped. + */ + size_t max_queue_size = 2048; + + /* The time interval between two consecutive exports. */ + std::chrono::milliseconds schedule_delay_millis = std::chrono::milliseconds(5000); + + /** + * The maximum batch size of every export. It must be smaller or + * equal to max_queue_size. + */ + size_t max_export_batch_size = 512; +}; + +/** + * This is an implementation of the SpanProcessor which creates batches of finished spans and passes + * the export-friendly span data representations to the configured SpanExporter. + */ +class BatchSpanProcessor : public SpanProcessor +{ +public: + /** + * Creates a batch span processor by configuring the specified exporter and other parameters + * as per the official, language-agnostic opentelemetry specs. + * + * @param exporter - The backend exporter to pass the ended spans to. + * @param options - The batch SpanProcessor options. + */ + BatchSpanProcessor(std::unique_ptr<SpanExporter> &&exporter, + const BatchSpanProcessorOptions &options); + + /** + * Requests a Recordable(Span) from the configured exporter. + * + * @return A recordable generated by the backend exporter + */ + std::unique_ptr<Recordable> MakeRecordable() noexcept override; + + /** + * Called when a span is started. + * + * NOTE: This method is a no-op. + * + * @param span - The span that just started + * @param parent_context - The parent context of the span that just started + */ + void OnStart(Recordable &span, + const opentelemetry::trace::SpanContext &parent_context) noexcept override; + + /** + * Called when a span ends. + * + * @param span - A recordable for a span that just ended + */ + void OnEnd(std::unique_ptr<Recordable> &&span) noexcept override; + + /** + * Export all ended spans that have not been exported yet. + * + * NOTE: Timeout functionality not supported yet. + */ + bool ForceFlush( + std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + + /** + * Shuts down the processor and does any cleanup required. Completely drains the buffer/queue of + * all its ended spans and passes them to the exporter. Any subsequent calls to OnStart, OnEnd, + * ForceFlush or Shutdown will return immediately without doing anything. + * + * NOTE: Timeout functionality not supported yet. + */ + bool Shutdown( + std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + + /** + * Class destructor which invokes the Shutdown() method. The Shutdown() method is supposed to be + * invoked when the Tracer is shutdown (as per other languages), but the C++ Tracer only takes + * shared ownership of the processor, and thus doesn't call Shutdown (as the processor might be + * shared with other Tracers). + */ + ~BatchSpanProcessor(); + +private: + /** + * The background routine performed by the worker thread. + */ + void DoBackgroundWork(); + + /** + * Exports all ended spans to the configured exporter. + * + * @param was_force_flush_called - A flag to check if the current export is the result + * of a call to ForceFlush method. If true, then we have to + * notify the main thread to wake it up in the ForceFlush + * method. + */ + void Export(const bool was_for_flush_called); + + /** + * Called when Shutdown() is invoked. Completely drains the queue of all its ended spans and + * passes them to the exporter. + */ + void DrainQueue(); + + /* The configured backend exporter */ + std::unique_ptr<SpanExporter> exporter_; + + /* Configurable parameters as per the official specs */ + const size_t max_queue_size_; + const std::chrono::milliseconds schedule_delay_millis_; + const size_t max_export_batch_size_; + + /* Synchronization primitives */ + std::condition_variable cv_, force_flush_cv_; + std::mutex cv_m_, force_flush_cv_m_, shutdown_m_; + + /* The buffer/queue to which the ended spans are added */ + common::CircularBuffer<Recordable> buffer_; + + /* Important boolean flags to handle the workflow of the processor */ + std::atomic<bool> is_shutdown_{false}; + std::atomic<bool> is_force_flush_{false}; + std::atomic<bool> is_force_flush_notified_{false}; + + /* The background worker thread */ + std::thread worker_thread_; +}; + +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/exporter.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/exporter.h new file mode 100644 index 000000000..5826b5f45 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/exporter.h @@ -0,0 +1,55 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <memory> +#include "opentelemetry/nostd/span.h" +#include "opentelemetry/sdk/common/exporter_utils.h" +#include "opentelemetry/sdk/trace/recordable.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ +/** + * SpanExporter defines the interface that protocol-specific span exporters must + * implement. + */ +class SpanExporter +{ +public: + virtual ~SpanExporter() = default; + + /** + * Create a span recordable. This object will be used to record span data and + * will subsequently be passed to SpanExporter::Export. Vendors can implement + * custom recordables or use the default SpanData recordable provided by the + * SDK. + * @return a newly initialized Recordable object + * + * Note: This method must be callable from multiple threads. + */ + virtual std::unique_ptr<Recordable> MakeRecordable() noexcept = 0; + + /** + * Exports a batch of span recordables. This method must not be called + * concurrently for the same exporter instance. + * @param spans a span of unique pointers to span recordables + */ + virtual sdk::common::ExportResult Export( + const nostd::span<std::unique_ptr<opentelemetry::sdk::trace::Recordable>> + &spans) noexcept = 0; + + /** + * Shut down the exporter. + * @param timeout an optional timeout. + * @return return the status of the operation. + */ + virtual bool Shutdown( + std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept = 0; +}; +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/id_generator.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/id_generator.h new file mode 100644 index 000000000..da17effae --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/id_generator.h @@ -0,0 +1,31 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#include "opentelemetry/trace/span_id.h" +#include "opentelemetry/trace/trace_id.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ + +/** IdGenerator provides an interface for generating Trace Id and Span Id */ +class IdGenerator +{ + +public: + virtual ~IdGenerator() = default; + + /** Returns a SpanId represented by opaque 128-bit trace identifier */ + virtual opentelemetry::trace::SpanId GenerateSpanId() noexcept = 0; + + /** Returns a TraceId represented by opaque 64-bit trace identifier */ + virtual opentelemetry::trace::TraceId GenerateTraceId() noexcept = 0; +}; +} // namespace trace + +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/multi_recordable.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/multi_recordable.h new file mode 100644 index 000000000..be97dddc9 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/multi_recordable.h @@ -0,0 +1,161 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/common/timestamp.h" +#include "opentelemetry/sdk/trace/processor.h" +#include "opentelemetry/sdk/trace/recordable.h" +#include "opentelemetry/version.h" + +#include <map> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ +namespace +{ +std::size_t MakeKey(const SpanProcessor &processor) +{ + return reinterpret_cast<std::size_t>(&processor); +} + +} // namespace + +class MultiRecordable : public Recordable +{ +public: + void AddRecordable(const SpanProcessor &processor, + std::unique_ptr<Recordable> recordable) noexcept + { + recordables_[MakeKey(processor)] = std::move(recordable); + } + + const std::unique_ptr<Recordable> &GetRecordable(const SpanProcessor &processor) const noexcept + { + // TODO - return nullptr ref on failed lookup? + auto i = recordables_.find(MakeKey(processor)); + if (i != recordables_.end()) + { + return i->second; + } + static std::unique_ptr<Recordable> empty(nullptr); + return empty; + } + + std::unique_ptr<Recordable> ReleaseRecordable(const SpanProcessor &processor) noexcept + { + auto i = recordables_.find(MakeKey(processor)); + if (i != recordables_.end()) + { + std::unique_ptr<Recordable> result(i->second.release()); + recordables_.erase(MakeKey(processor)); + return result; + } + return std::unique_ptr<Recordable>(nullptr); + } + + void SetIdentity(const opentelemetry::trace::SpanContext &span_context, + opentelemetry::trace::SpanId parent_span_id) noexcept override + { + for (auto &recordable : recordables_) + { + recordable.second->SetIdentity(span_context, parent_span_id); + } + } + + void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept override + { + for (auto &recordable : recordables_) + { + recordable.second->SetAttribute(key, value); + } + } + + void AddEvent(nostd::string_view name, + opentelemetry::common::SystemTimestamp timestamp, + const opentelemetry::common::KeyValueIterable &attributes) noexcept override + { + + for (auto &recordable : recordables_) + { + recordable.second->AddEvent(name, timestamp, attributes); + } + } + + void AddLink(const opentelemetry::trace::SpanContext &span_context, + const opentelemetry::common::KeyValueIterable &attributes) noexcept override + { + for (auto &recordable : recordables_) + { + recordable.second->AddLink(span_context, attributes); + } + } + + void SetStatus(opentelemetry::trace::StatusCode code, + nostd::string_view description) noexcept override + { + for (auto &recordable : recordables_) + { + recordable.second->SetStatus(code, description); + } + } + + void SetName(nostd::string_view name) noexcept override + { + for (auto &recordable : recordables_) + { + recordable.second->SetName(name); + } + } + + void SetSpanKind(opentelemetry::trace::SpanKind span_kind) noexcept override + { + for (auto &recordable : recordables_) + { + recordable.second->SetSpanKind(span_kind); + } + } + + void SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept override + { + for (auto &recordable : recordables_) + { + recordable.second->SetResource(resource); + } + } + + void SetStartTime(opentelemetry::common::SystemTimestamp start_time) noexcept override + { + for (auto &recordable : recordables_) + { + recordable.second->SetStartTime(start_time); + } + } + + void SetDuration(std::chrono::nanoseconds duration) noexcept override + { + for (auto &recordable : recordables_) + { + recordable.second->SetDuration(duration); + } + } + + void SetInstrumentationLibrary( + const InstrumentationLibrary &instrumentation_library) noexcept override + { + for (auto &recordable : recordables_) + { + recordable.second->SetInstrumentationLibrary(instrumentation_library); + } + } + +private: + std::map<std::size_t, std::unique_ptr<Recordable>> recordables_; +}; +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/multi_span_processor.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/multi_span_processor.h new file mode 100644 index 000000000..8463ad520 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/multi_span_processor.h @@ -0,0 +1,187 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <mutex> +#include <vector> + +#include "opentelemetry/sdk/trace/multi_recordable.h" +#include "opentelemetry/sdk/trace/processor.h" + +#include <iostream> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ + +/** Instantiation options. */ +struct MultiSpanProcessorOptions +{}; + +/** + * Span processor allow hooks for span start and end method invocations. + * + * Built-in span processors are responsible for batching and conversion of + * spans to exportable representation and passing batches to exporters. + */ +class MultiSpanProcessor : public SpanProcessor +{ +public: + MultiSpanProcessor(std::vector<std::unique_ptr<SpanProcessor>> &&processors) + : head_(nullptr), tail_(nullptr), count_(0) + { + for (auto &processor : processors) + { + AddProcessor(std::move(processor)); + } + } + + void AddProcessor(std::unique_ptr<SpanProcessor> &&processor) + { + // Add preocessor to end of the list. + if (processor) + { + ProcessorNode *pNode = new ProcessorNode(std::move(processor), tail_); + if (count_ > 0) + { + tail_->next_ = pNode; + tail_ = pNode; + } + else + { + head_ = tail_ = pNode; + } + count_++; + } + } + + std::unique_ptr<Recordable> MakeRecordable() noexcept override + { + auto recordable = std::unique_ptr<Recordable>(new MultiRecordable); + auto multi_recordable = static_cast<MultiRecordable *>(recordable.get()); + ProcessorNode *node = head_; + while (node != nullptr) + { + auto processor = node->value_.get(); + multi_recordable->AddRecordable(*processor, processor->MakeRecordable()); + node = node->next_; + } + return recordable; + } + + virtual void OnStart(Recordable &span, + const opentelemetry::trace::SpanContext &parent_context) noexcept override + { + auto multi_recordable = static_cast<MultiRecordable *>(&span); + ProcessorNode *node = head_; + while (node != nullptr) + { + auto processor = node->value_.get(); + auto &recordable = multi_recordable->GetRecordable(*processor); + if (recordable != nullptr) + { + processor->OnStart(*recordable, parent_context); + } + node = node->next_; + } + } + + virtual void OnEnd(std::unique_ptr<Recordable> &&span) noexcept override + { + auto multi_recordable = static_cast<MultiRecordable *>(span.release()); + ProcessorNode *node = head_; + while (node != nullptr) + { + auto processor = node->value_.get(); + auto recordable = multi_recordable->ReleaseRecordable(*processor); + if (recordable != nullptr) + { + processor->OnEnd(std::move(recordable)); + } + node = node->next_; + } + delete multi_recordable; + } + + bool ForceFlush( + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept override + { + bool result = true; + ProcessorNode *node = head_; + while (node != nullptr) + { + auto processor = node->value_.get(); + result |= processor->ForceFlush(timeout); + node = node->next_; + } + return result; + } + + bool Shutdown( + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept override + { + bool result = true; + ProcessorNode *node = head_; + while (node != nullptr) + { + auto processor = node->value_.get(); + result |= processor->Shutdown(timeout); + node = node->next_; + } + return result; + } + + ~MultiSpanProcessor() + { + Shutdown(); + Cleanup(); + } + +private: + struct ProcessorNode + { + std::unique_ptr<SpanProcessor> value_; + ProcessorNode *next_, *prev_; + ProcessorNode(std::unique_ptr<SpanProcessor> &&value, + ProcessorNode *prev = nullptr, + ProcessorNode *next = nullptr) + : value_(std::move(value)), next_(next), prev_(prev) + {} + }; + + void Cleanup() + { + if (count_) + { + ProcessorNode *node = tail_; + while (node != nullptr) + { + if (node->next_ != nullptr) + { + delete node->next_; + node->next_ = nullptr; + } + if (node->prev_ != nullptr) + { + node = node->prev_; + } + else + { + delete node; + node = nullptr; + } + } + head_ = tail_ = nullptr; + count_ = 0; + } + } + + ProcessorNode *head_, *tail_; + size_t count_; +}; +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/processor.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/processor.h new file mode 100644 index 000000000..17ac0e59a --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/processor.h @@ -0,0 +1,70 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <chrono> +#include <memory> +#include "opentelemetry/sdk/trace/recordable.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ +/** + * Span processor allow hooks for span start and end method invocations. + * + * Built-in span processors are responsible for batching and conversion of + * spans to exportable representation and passing batches to exporters. + */ +class SpanProcessor +{ +public: + virtual ~SpanProcessor() = default; + + /** + * Create a span recordable. This requests a new span recordable from the + * associated exporter. + * @return a newly initialized recordable + * + * Note: This method must be callable from multiple threads. + */ + virtual std::unique_ptr<Recordable> MakeRecordable() noexcept = 0; + + /** + * OnStart is called when a span is started. + * @param span a recordable for a span that was just started + * @param parent_context The parent context of the span that just started + */ + virtual void OnStart(Recordable &span, + const opentelemetry::trace::SpanContext &parent_context) noexcept = 0; + + /** + * OnEnd is called when a span is ended. + * @param span a recordable for a span that was ended + */ + virtual void OnEnd(std::unique_ptr<Recordable> &&span) noexcept = 0; + + /** + * Export all ended spans that have not yet been exported. + * @param timeout an optional timeout, the default timeout of 0 means that no + * timeout is applied. + */ + virtual bool ForceFlush( + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept = 0; + + /** + * Shut down the processor and do any cleanup required. Ended spans are + * exported before shutdown. After the call to Shutdown, subsequent calls to + * OnStart, OnEnd, ForceFlush or Shutdown will return immediately without + * doing anything. + * @param timeout an optional timeout, the default timeout of 0 means that no + * timeout is applied. + */ + virtual bool Shutdown( + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept = 0; +}; +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/random_id_generator.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/random_id_generator.h new file mode 100644 index 000000000..908f1b850 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/random_id_generator.h @@ -0,0 +1,24 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#include "opentelemetry/sdk/trace/id_generator.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ + +class RandomIdGenerator : public IdGenerator +{ +public: + opentelemetry::trace::SpanId GenerateSpanId() noexcept override; + + opentelemetry::trace::TraceId GenerateTraceId() noexcept override; +}; + +} // namespace trace + +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE
\ No newline at end of file diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/recordable.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/recordable.h new file mode 100644 index 000000000..b92a3ff06 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/recordable.h @@ -0,0 +1,152 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/common/attribute_value.h" +#include "opentelemetry/common/key_value_iterable.h" +#include "opentelemetry/common/timestamp.h" +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/sdk/common/empty_attributes.h" +#include "opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h" +#include "opentelemetry/sdk/resource/resource.h" +#include "opentelemetry/trace/canonical_code.h" +#include "opentelemetry/trace/span.h" +#include "opentelemetry/trace/span_context.h" +#include "opentelemetry/trace/span_id.h" +#include "opentelemetry/trace/trace_id.h" +#include "opentelemetry/version.h" + +#include <map> + +// TODO: Create generic short pattern for opentelemetry::common and opentelemetry::trace + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ + +using namespace opentelemetry::sdk::instrumentationlibrary; + +/** + * Maintains a representation of a span in a format that can be processed by a recorder. + * + * This class is thread-compatible. + */ +class Recordable +{ +public: + virtual ~Recordable() = default; + + /** + * Set the span context and parent span id + * @param span_context the span context to set + * @param parent_span_id the parent span id to set + */ + virtual void SetIdentity(const opentelemetry::trace::SpanContext &span_context, + opentelemetry::trace::SpanId parent_span_id) noexcept = 0; + + /** + * Set an attribute of a span. + * @param name the name of the attribute + * @param value the attribute value + */ + virtual void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept = 0; + + /** + * Add an event to a span. + * @param name the name of the event + * @param timestamp the timestamp of the event + * @param attributes the attributes associated with the event + */ + virtual void AddEvent(nostd::string_view name, + opentelemetry::common::SystemTimestamp timestamp, + const opentelemetry::common::KeyValueIterable &attributes) noexcept = 0; + + /** + * Add an event to a span with default timestamp and attributes. + * @param name the name of the event + */ + void AddEvent(nostd::string_view name) + { + AddEvent(name, opentelemetry::common::SystemTimestamp(std::chrono::system_clock::now()), + opentelemetry::sdk::GetEmptyAttributes()); + } + + /** + * Add an event to a span with default (empty) attributes. + * @param name the name of the event + * @param timestamp the timestamp of the event + */ + void AddEvent(nostd::string_view name, opentelemetry::common::SystemTimestamp timestamp) + { + AddEvent(name, timestamp, opentelemetry::sdk::GetEmptyAttributes()); + } + + /** + * Add a link to a span. + * @param span_context the span context of the linked span + * @param attributes the attributes associated with the link + */ + virtual void AddLink(const opentelemetry::trace::SpanContext &span_context, + const opentelemetry::common::KeyValueIterable &attributes) noexcept = 0; + + /** + * Add a link to a span with default (empty) attributes. + * @param span_context the span context of the linked span + */ + void AddLink(opentelemetry::trace::SpanContext span_context) + { + AddLink(span_context, opentelemetry::sdk::GetEmptyAttributes()); + } + + /** + * Set the status of the span. + * @param code the status code + * @param description a description of the status + */ + virtual void SetStatus(opentelemetry::trace::StatusCode code, + nostd::string_view description) noexcept = 0; + + /** + * Set the name of the span. + * @param name the name to set + */ + virtual void SetName(nostd::string_view name) noexcept = 0; + + /** + * Set the spankind of the span. + * @param span_kind the spankind to set + */ + virtual void SetSpanKind(opentelemetry::trace::SpanKind span_kind) noexcept = 0; + + /** + * Set Resource of the span + * @param Resource the resource to set + */ + virtual void SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept = 0; + + /** + * Set the start time of the span. + * @param start_time the start time to set + */ + virtual void SetStartTime(opentelemetry::common::SystemTimestamp start_time) noexcept = 0; + + /** + * Set the duration of the span. + * @param duration the duration to set + */ + virtual void SetDuration(std::chrono::nanoseconds duration) noexcept = 0; + + /** + * Set the instrumentation library of the span. + * @param instrumentation_library the instrumentation library to set + */ + virtual void SetInstrumentationLibrary( + const InstrumentationLibrary &instrumentation_library) noexcept = 0; +}; +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/sampler.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/sampler.h new file mode 100644 index 000000000..452ba924b --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/sampler.h @@ -0,0 +1,91 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/common/attribute_value.h" +#include "opentelemetry/trace/span.h" +#include "opentelemetry/trace/span_context.h" +#include "opentelemetry/trace/span_context_kv_iterable.h" +#include "opentelemetry/trace/trace_id.h" +#include "opentelemetry/trace/trace_state.h" +#include "opentelemetry/version.h" + +#include <map> +#include <memory> +#include <string> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ +/** + * A sampling Decision for a Span to be created. + */ +enum class Decision +{ + // IsRecording() == false, span will not be recorded and all events and attributes will be + // dropped. + DROP, + // IsRecording() == true, but Sampled flag MUST NOT be set. + RECORD_ONLY, + // IsRecording() == true AND Sampled flag` MUST be set. + RECORD_AND_SAMPLE +}; + +/** + * The output of ShouldSample. + * It contains a sampling Decision and a set of Span Attributes. + */ +struct SamplingResult +{ + Decision decision; + // A set of span Attributes that will also be added to the Span. Can be nullptr. + std::unique_ptr<const std::map<std::string, opentelemetry::common::AttributeValue>> attributes; + // The tracestate used by the span. + nostd::shared_ptr<opentelemetry::trace::TraceState> trace_state; +}; + +/** + * The Sampler interface allows users to create custom samplers which will return a + * SamplingResult based on information that is typically available just before the Span was created. + */ +class Sampler +{ +public: + virtual ~Sampler() = default; + /** + * Called during Span creation to make a sampling decision. + * + * @param parent_context a const reference to the SpanContext of a parent Span. + * An invalid SpanContext if this is a root span. + * @param trace_id the TraceId for the new Span. This will be identical to that in + * the parentContext, unless this is a root span. + * @param name the name of the new Span. + * @param spanKind the opentelemetry::trace::SpanKind of the Span. + * @param attributes list of AttributeValue with their keys. + * @param links Collection of links that will be associated with the Span to be created. + * @return sampling result whether span should be sampled or not. + * @since 0.1.0 + */ + + virtual SamplingResult ShouldSample( + const opentelemetry::trace::SpanContext &parent_context, + opentelemetry::trace::TraceId trace_id, + nostd::string_view name, + opentelemetry::trace::SpanKind span_kind, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::trace::SpanContextKeyValueIterable &links) noexcept = 0; + + /** + * Returns the sampler name or short description with the configuration. + * This may be displayed on debug pages or in the logs. + * + * @return the description of this Sampler. + */ + virtual nostd::string_view GetDescription() const noexcept = 0; +}; +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/samplers/always_off.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/samplers/always_off.h new file mode 100644 index 000000000..2392b9b2f --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/samplers/always_off.h @@ -0,0 +1,48 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/sdk/trace/sampler.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ +/** + * The always off sampler always returns DROP, effectively disabling + * tracing functionality. + */ +class AlwaysOffSampler : public Sampler +{ +public: + /** + * @return Returns DROP always + */ + SamplingResult ShouldSample( + const opentelemetry::trace::SpanContext &parent_context, + opentelemetry::trace::TraceId /*trace_id*/, + nostd::string_view /*name*/, + opentelemetry::trace::SpanKind /*span_kind*/, + const opentelemetry::common::KeyValueIterable & /*attributes*/, + const opentelemetry::trace::SpanContextKeyValueIterable & /*links*/) noexcept override + { + if (!parent_context.IsValid()) + { + return {Decision::DROP, nullptr, opentelemetry::trace::TraceState::GetDefault()}; + } + else + { + return {Decision::DROP, nullptr, parent_context.trace_state()}; + } + } + + /** + * @return Description MUST be AlwaysOffSampler + */ + nostd::string_view GetDescription() const noexcept override { return "AlwaysOffSampler"; } +}; +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/samplers/always_on.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/samplers/always_on.h new file mode 100644 index 000000000..6c8583599 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/samplers/always_on.h @@ -0,0 +1,47 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/sdk/trace/sampler.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ +/** + * The always on sampler is a default sampler which always return Decision::RECORD_AND_SAMPLE + */ +class AlwaysOnSampler : public Sampler +{ +public: + /** + * @return Always return Decision RECORD_AND_SAMPLE + */ + inline SamplingResult ShouldSample( + const opentelemetry::trace::SpanContext &parent_context, + opentelemetry::trace::TraceId /*trace_id*/, + nostd::string_view /*name*/, + opentelemetry::trace::SpanKind /*span_kind*/, + const opentelemetry::common::KeyValueIterable & /*attributes*/, + const opentelemetry::trace::SpanContextKeyValueIterable & /*links*/) noexcept override + { + if (!parent_context.IsValid()) + { + return {Decision::RECORD_AND_SAMPLE, nullptr, opentelemetry::trace::TraceState::GetDefault()}; + } + else + { + return {Decision::RECORD_AND_SAMPLE, nullptr, parent_context.trace_state()}; + } + } + + /** + * @return Description MUST be AlwaysOnSampler + */ + inline nostd::string_view GetDescription() const noexcept override { return "AlwaysOnSampler"; } +}; +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/samplers/parent.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/samplers/parent.h new file mode 100644 index 000000000..c76a6c2a5 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/samplers/parent.h @@ -0,0 +1,45 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/sdk/common/atomic_shared_ptr.h" +#include "opentelemetry/sdk/trace/sampler.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ +/** + * The ParentBased sampler is a composite sampler. ParentBased(delegateSampler) either respects + * the parent span's sampling decision or delegates to delegateSampler for root spans. + */ +class ParentBasedSampler : public Sampler +{ +public: + explicit ParentBasedSampler(std::shared_ptr<Sampler> delegate_sampler) noexcept; + /** The decision either respects the parent span's sampling decision or delegates to + * delegateSampler for root spans + * @return Returns DROP always + */ + SamplingResult ShouldSample( + const opentelemetry::trace::SpanContext &parent_context, + opentelemetry::trace::TraceId trace_id, + nostd::string_view name, + opentelemetry::trace::SpanKind span_kind, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::trace::SpanContextKeyValueIterable &links) noexcept override; + + /** + * @return Description MUST be ParentBased{delegate_sampler_.getDescription()} + */ + nostd::string_view GetDescription() const noexcept override; + +private: + const std::shared_ptr<Sampler> delegate_sampler_; + const std::string description_; +}; +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/samplers/trace_id_ratio.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/samplers/trace_id_ratio.h new file mode 100644 index 000000000..407b480d6 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/samplers/trace_id_ratio.h @@ -0,0 +1,53 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/sdk/trace/sampler.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ +/** + * The TraceIdRatioBased sampler computes and returns a decision based on the + * provided trace_id and the configured ratio. + */ +class TraceIdRatioBasedSampler : public Sampler +{ +public: + /** + * @param ratio a required value, 1.0 >= ratio >= 0.0. If the given trace_id + * falls into a given ratio of all possible trace_id values, ShouldSample will + * return RECORD_AND_SAMPLE. + * @throws invalid_argument if ratio is out of bounds [0.0, 1.0] + */ + explicit TraceIdRatioBasedSampler(double ratio); + + /** + * @return Returns either RECORD_AND_SAMPLE or DROP based on current + * sampler configuration and provided trace_id and ratio. trace_id + * is used as a pseudorandom value in conjunction with the predefined + * ratio to determine whether this trace should be sampled + */ + SamplingResult ShouldSample( + const opentelemetry::trace::SpanContext & /*parent_context*/, + opentelemetry::trace::TraceId trace_id, + nostd::string_view /*name*/, + opentelemetry::trace::SpanKind /*span_kind*/, + const opentelemetry::common::KeyValueIterable & /*attributes*/, + const opentelemetry::trace::SpanContextKeyValueIterable & /*links*/) noexcept override; + + /** + * @return Description MUST be TraceIdRatioBasedSampler{0.000100} + */ + nostd::string_view GetDescription() const noexcept override; + +private: + std::string description_; + const uint64_t threshold_; +}; +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/simple_processor.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/simple_processor.h new file mode 100644 index 000000000..accc68596 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/simple_processor.h @@ -0,0 +1,84 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <atomic> +#include <mutex> + +#include "opentelemetry/common/spin_lock_mutex.h" +#include "opentelemetry/sdk/trace/exporter.h" +#include "opentelemetry/sdk/trace/processor.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ +/** + * The simple span processor passes finished recordables to the configured + * SpanExporter, as soon as they are finished. + * + * OnEnd and ForceFlush are no-ops. + * + * All calls to the configured SpanExporter are synchronized using a + * spin-lock on an atomic_flag. + */ +class SimpleSpanProcessor : public SpanProcessor +{ +public: + /** + * Initialize a simple span processor. + * @param exporter the exporter used by the span processor + */ + explicit SimpleSpanProcessor(std::unique_ptr<SpanExporter> &&exporter) noexcept + : exporter_(std::move(exporter)) + {} + + std::unique_ptr<Recordable> MakeRecordable() noexcept override + { + return exporter_->MakeRecordable(); + } + + void OnStart(Recordable &span, + const opentelemetry::trace::SpanContext &parent_context) noexcept override + {} + + void OnEnd(std::unique_ptr<Recordable> &&span) noexcept override + { + nostd::span<std::unique_ptr<Recordable>> batch(&span, 1); + const std::lock_guard<opentelemetry::common::SpinLockMutex> locked(lock_); + if (exporter_->Export(batch) == sdk::common::ExportResult::kFailure) + { + /* Once it is defined how the SDK does logging, an error should be + * logged in this case. */ + } + } + + bool ForceFlush( + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept override + { + return true; + } + + bool Shutdown( + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept override + { + // We only call shutdown ONCE. + if (exporter_ != nullptr && !shutdown_latch_.test_and_set(std::memory_order_acquire)) + { + return exporter_->Shutdown(timeout); + } + return true; + } + + ~SimpleSpanProcessor() { Shutdown(); } + +private: + std::unique_ptr<SpanExporter> exporter_; + opentelemetry::common::SpinLockMutex lock_; + std::atomic_flag shutdown_latch_ = ATOMIC_FLAG_INIT; +}; +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/span_data.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/span_data.h new file mode 100644 index 000000000..0fb09f328 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/span_data.h @@ -0,0 +1,304 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <chrono> +#include <unordered_map> +#include <vector> +#include "opentelemetry/common/attribute_value.h" +#include "opentelemetry/common/timestamp.h" +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/sdk/common/attribute_utils.h" +#include "opentelemetry/sdk/trace/recordable.h" +#include "opentelemetry/trace/canonical_code.h" +#include "opentelemetry/trace/span.h" +#include "opentelemetry/trace/span_id.h" +#include "opentelemetry/trace/trace_id.h" + +#include <string> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ +/** + * Class for storing events in SpanData. + */ +class SpanDataEvent +{ +public: + SpanDataEvent(std::string name, + opentelemetry::common::SystemTimestamp timestamp, + const opentelemetry::common::KeyValueIterable &attributes) + : name_(name), timestamp_(timestamp), attribute_map_(attributes) + {} + + /** + * Get the name for this event + * @return the name for this event + */ + std::string GetName() const noexcept { return name_; } + + /** + * Get the timestamp for this event + * @return the timestamp for this event + */ + opentelemetry::common::SystemTimestamp GetTimestamp() const noexcept { return timestamp_; } + + /** + * Get the attributes for this event + * @return the attributes for this event + */ + const std::unordered_map<std::string, common::OwnedAttributeValue> &GetAttributes() const noexcept + { + return attribute_map_.GetAttributes(); + } + +private: + std::string name_; + opentelemetry::common::SystemTimestamp timestamp_; + common::AttributeMap attribute_map_; +}; + +/** + * Class for storing links in SpanData. + */ +class SpanDataLink +{ +public: + SpanDataLink(opentelemetry::trace::SpanContext span_context, + const opentelemetry::common::KeyValueIterable &attributes) + : span_context_(span_context), attribute_map_(attributes) + {} + + /** + * Get the attributes for this link + * @return the attributes for this link + */ + const std::unordered_map<std::string, common::OwnedAttributeValue> &GetAttributes() const noexcept + { + return attribute_map_.GetAttributes(); + } + + /** + * Get the span context for this link + * @return the span context for this link + */ + const opentelemetry::trace::SpanContext &GetSpanContext() const noexcept { return span_context_; } + +private: + opentelemetry::trace::SpanContext span_context_; + common::AttributeMap attribute_map_; +}; + +/** + * SpanData is a representation of all data collected by a span. + */ +class SpanData final : public Recordable +{ +public: + SpanData() : resource_{nullptr}, instrumentation_library_{nullptr} {} + /** + * Get the trace id for this span + * @return the trace id for this span + */ + opentelemetry::trace::TraceId GetTraceId() const noexcept { return span_context_.trace_id(); } + + /** + * Get the span id for this span + * @return the span id for this span + */ + opentelemetry::trace::SpanId GetSpanId() const noexcept { return span_context_.span_id(); } + + /** + * Get the span context for this span + * @return the span context for this span + */ + const opentelemetry::trace::SpanContext &GetSpanContext() const noexcept { return span_context_; } + + /** + * Get the parent span id for this span + * @return the span id for this span's parent + */ + opentelemetry::trace::SpanId GetParentSpanId() const noexcept { return parent_span_id_; } + + /** + * Get the name for this span + * @return the name for this span + */ + opentelemetry::nostd::string_view GetName() const noexcept { return name_; } + + /** + * Get the kind of this span + * @return the kind of this span + */ + opentelemetry::trace::SpanKind GetSpanKind() const noexcept { return span_kind_; } + + /** + * Get the status for this span + * @return the status for this span + */ + opentelemetry::trace::StatusCode GetStatus() const noexcept { return status_code_; } + + /** + * Get the status description for this span + * @return the description of the the status of this span + */ + opentelemetry::nostd::string_view GetDescription() const noexcept { return status_desc_; } + + /** + * Get the attributes associated with the resource + * @returns the attributes associated with the resource configured for TracerProvider + */ + + const opentelemetry::sdk::resource::Resource &GetResource() const noexcept + { + if (resource_ == nullptr) + { + // this shouldn't happen as TraceProvider provides default resources + static opentelemetry::sdk::resource::Resource resource = + opentelemetry::sdk::resource::Resource::GetEmpty(); + return resource; + } + return *resource_; + } + + /** + * Get the attributes associated with the resource + * @returns the attributes associated with the resource configured for TracerProvider + */ + + const opentelemetry::sdk::trace::InstrumentationLibrary &GetInstrumentationLibrary() + const noexcept + { + if (instrumentation_library_ == nullptr) + { + // this shouldn't happen as Tracer ensures there is valid default instrumentation library. + static std::unique_ptr<opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary> + instrumentation_library = + opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary::Create( + "unknown_service"); + return *instrumentation_library; + } + return *instrumentation_library_; + } + + /** + * Get the start time for this span + * @return the start time for this span + */ + opentelemetry::common::SystemTimestamp GetStartTime() const noexcept { return start_time_; } + + /** + * Get the duration for this span + * @return the duration for this span + */ + std::chrono::nanoseconds GetDuration() const noexcept { return duration_; } + + /** + * Get the attributes for this span + * @return the attributes for this span + */ + const std::unordered_map<std::string, common::OwnedAttributeValue> &GetAttributes() const noexcept + { + return attribute_map_.GetAttributes(); + } + + /** + * Get the events associated with this span + * @return the events associated with this span + */ + const std::vector<SpanDataEvent> &GetEvents() const noexcept { return events_; } + + /** + * Get the links associated with this span + * @return the links associated with this span + */ + const std::vector<SpanDataLink> &GetLinks() const noexcept { return links_; } + + void SetIdentity(const opentelemetry::trace::SpanContext &span_context, + opentelemetry::trace::SpanId parent_span_id) noexcept override + { + span_context_ = span_context; + parent_span_id_ = parent_span_id; + } + + void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept override + { + attribute_map_.SetAttribute(key, value); + } + + void AddEvent(nostd::string_view name, + opentelemetry::common::SystemTimestamp timestamp = + opentelemetry::common::SystemTimestamp(std::chrono::system_clock::now()), + const opentelemetry::common::KeyValueIterable &attributes = + opentelemetry::common::KeyValueIterableView<std::map<std::string, int>>( + {})) noexcept override + { + SpanDataEvent event(std::string(name), timestamp, attributes); + events_.push_back(event); + } + + void AddLink(const opentelemetry::trace::SpanContext &span_context, + const opentelemetry::common::KeyValueIterable &attributes) noexcept override + { + SpanDataLink link(span_context, attributes); + links_.push_back(link); + } + + void SetStatus(opentelemetry::trace::StatusCode code, + nostd::string_view description) noexcept override + { + status_code_ = code; + status_desc_ = std::string(description); + } + + void SetName(nostd::string_view name) noexcept override + { + name_ = std::string(name.data(), name.length()); + } + + void SetSpanKind(opentelemetry::trace::SpanKind span_kind) noexcept override + { + span_kind_ = span_kind; + } + + void SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept override + { + resource_ = &resource; + } + + void SetStartTime(opentelemetry::common::SystemTimestamp start_time) noexcept override + { + start_time_ = start_time; + } + + void SetDuration(std::chrono::nanoseconds duration) noexcept override { duration_ = duration; } + + void SetInstrumentationLibrary( + const InstrumentationLibrary &instrumentation_library) noexcept override + { + instrumentation_library_ = &instrumentation_library; + } + +private: + opentelemetry::trace::SpanContext span_context_{false, false}; + opentelemetry::trace::SpanId parent_span_id_; + opentelemetry::common::SystemTimestamp start_time_; + std::chrono::nanoseconds duration_{0}; + std::string name_; + opentelemetry::trace::StatusCode status_code_{opentelemetry::trace::StatusCode::kUnset}; + std::string status_desc_; + common::AttributeMap attribute_map_; + std::vector<SpanDataEvent> events_; + std::vector<SpanDataLink> links_; + opentelemetry::trace::SpanKind span_kind_{opentelemetry::trace::SpanKind::kInternal}; + const opentelemetry::sdk::resource::Resource *resource_; + const InstrumentationLibrary *instrumentation_library_; +}; +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/tracer.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/tracer.h new file mode 100644 index 000000000..fd9f2c8e8 --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/tracer.h @@ -0,0 +1,70 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/sdk/common/atomic_shared_ptr.h" +#include "opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h" +#include "opentelemetry/sdk/resource/resource.h" +#include "opentelemetry/sdk/trace/processor.h" +#include "opentelemetry/sdk/trace/samplers/always_on.h" +#include "opentelemetry/sdk/trace/tracer_context.h" +#include "opentelemetry/trace/noop.h" +#include "opentelemetry/trace/tracer.h" +#include "opentelemetry/version.h" + +#include <memory> + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ + +using namespace opentelemetry::sdk::instrumentationlibrary; + +class Tracer final : public trace_api::Tracer, public std::enable_shared_from_this<Tracer> +{ +public: + /** Construct a new Tracer with the given context pipeline. */ + explicit Tracer(std::shared_ptr<sdk::trace::TracerContext> context, + std::unique_ptr<InstrumentationLibrary> instrumentation_library = + InstrumentationLibrary::Create("")) noexcept; + + nostd::shared_ptr<trace_api::Span> StartSpan( + nostd::string_view name, + const opentelemetry::common::KeyValueIterable &attributes, + const trace_api::SpanContextKeyValueIterable &links, + const trace_api::StartSpanOptions &options = {}) noexcept override; + + void ForceFlushWithMicroseconds(uint64_t timeout) noexcept override; + + void CloseWithMicroseconds(uint64_t timeout) noexcept override; + + /** Returns the configured span processor. */ + SpanProcessor &GetProcessor() noexcept { return context_->GetProcessor(); } + + /** Returns the configured Id generator */ + IdGenerator &GetIdGenerator() const noexcept { return context_->GetIdGenerator(); } + + /** Returns the associated instruementation library */ + const InstrumentationLibrary &GetInstrumentationLibrary() const noexcept + { + return *instrumentation_library_; + } + + /** Returns the currently configured resource **/ + const opentelemetry::sdk::resource::Resource &GetResource() { return context_->GetResource(); } + + // Note: Test only + Sampler &GetSampler() { return context_->GetSampler(); } + +private: + // order of declaration is important here - instrumentation library should destroy after + // tracer-context. + std::shared_ptr<InstrumentationLibrary> instrumentation_library_; + std::shared_ptr<sdk::trace::TracerContext> context_; +}; +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/tracer_context.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/tracer_context.h new file mode 100644 index 000000000..572f60caf --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/tracer_context.h @@ -0,0 +1,100 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/sdk/common/atomic_unique_ptr.h" +#include "opentelemetry/sdk/resource/resource.h" +#include "opentelemetry/sdk/trace/processor.h" +#include "opentelemetry/sdk/trace/random_id_generator.h" +#include "opentelemetry/sdk/trace/samplers/always_on.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ + +/** + * A class which stores the TracerProvider context. + * + * This class meets the following design criteria: + * - A shared reference between TracerProvider and Tracers instantiated. + * - A thread-safe class that allows updating/altering processor/exporter pipelines + * and sampling config. + * - The owner/destroyer of Processors/Exporters. These will remain active until + * this class is destroyed. I.e. Sampling, Exporting, flushing, Custom Iterator etc. are all ok + * if this object is alive, and they will work together. If this object is destroyed, then no shared + * references to Processor, Exporter, Recordable, Custom Iterator etc. should exist, and all + * associated pipelines will have been flushed. + */ +class TracerContext +{ +public: + explicit TracerContext( + std::vector<std::unique_ptr<SpanProcessor>> &&processor, + opentelemetry::sdk::resource::Resource resource = + opentelemetry::sdk::resource::Resource::Create({}), + std::unique_ptr<Sampler> sampler = std::unique_ptr<AlwaysOnSampler>(new AlwaysOnSampler), + std::unique_ptr<IdGenerator> id_generator = + std::unique_ptr<IdGenerator>(new RandomIdGenerator())) noexcept; + + /** + * Attaches a span processor to list of configured processors to this tracer context. + * Processor once attached can't be removed. + * @param processor The new span processor for this tracer. This must not be + * a nullptr. Ownership is given to the `TracerContext`. + * + * Note: This method is not thread safe. + */ + void AddProcessor(std::unique_ptr<SpanProcessor> processor) noexcept; + + /** + * Obtain the sampler associated with this tracer. + * @return The sampler for this tracer. + */ + Sampler &GetSampler() const noexcept; + + /** + * Obtain the configured (composite) processor. + * + * Note: When more than one processor is active, this will + * return an "aggregate" processor + */ + SpanProcessor &GetProcessor() const noexcept; + + /** + * Obtain the resource associated with this tracer context. + * @return The resource for this tracer context. + */ + const opentelemetry::sdk::resource::Resource &GetResource() const noexcept; + + /** + * Obtain the Id Generator associated with this tracer context. + * @return The ID Generator for this tracer context. + */ + opentelemetry::sdk::trace::IdGenerator &GetIdGenerator() const noexcept; + + /** + * Force all active SpanProcessors to flush any buffered spans + * within the given timeout. + */ + bool ForceFlush(std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept; + + /** + * Shutdown the span processor associated with this tracer provider. + */ + bool Shutdown() noexcept; + +private: + // order of declaration is important here - resource object should be destroyed after processor. + opentelemetry::sdk::resource::Resource resource_; + std::unique_ptr<Sampler> sampler_; + std::unique_ptr<IdGenerator> id_generator_; + std::unique_ptr<SpanProcessor> processor_; +}; + +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/tracer_provider.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/tracer_provider.h new file mode 100644 index 000000000..aa0f69a2b --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/trace/tracer_provider.h @@ -0,0 +1,103 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include <map> +#include <memory> +#include <mutex> +#include <string> +#include <vector> + +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/sdk/resource/resource.h" +#include "opentelemetry/sdk/trace/processor.h" +#include "opentelemetry/sdk/trace/samplers/always_on.h" +#include "opentelemetry/sdk/trace/tracer.h" +#include "opentelemetry/sdk/trace/tracer_context.h" +#include "opentelemetry/trace/tracer_provider.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ +class TracerProvider final : public opentelemetry::trace::TracerProvider +{ +public: + /** + * Initialize a new tracer provider with a specified sampler + * @param processor The span processor for this tracer provider. This must + * not be a nullptr. + * @param resource The resources for this tracer provider. + * @param sampler The sampler for this tracer provider. This must + * not be a nullptr. + * @param id_generator The custom id generator for this tracer provider. This must + * not be a nullptr + */ + explicit TracerProvider( + std::unique_ptr<SpanProcessor> processor, + opentelemetry::sdk::resource::Resource resource = + opentelemetry::sdk::resource::Resource::Create({}), + std::unique_ptr<Sampler> sampler = std::unique_ptr<AlwaysOnSampler>(new AlwaysOnSampler), + std::unique_ptr<opentelemetry::sdk::trace::IdGenerator> id_generator = + std::unique_ptr<opentelemetry::sdk::trace::IdGenerator>( + new RandomIdGenerator())) noexcept; + + explicit TracerProvider( + std::vector<std::unique_ptr<SpanProcessor>> &&processors, + opentelemetry::sdk::resource::Resource resource = + opentelemetry::sdk::resource::Resource::Create({}), + std::unique_ptr<Sampler> sampler = std::unique_ptr<AlwaysOnSampler>(new AlwaysOnSampler), + std::unique_ptr<opentelemetry::sdk::trace::IdGenerator> id_generator = + std::unique_ptr<opentelemetry::sdk::trace::IdGenerator>( + new RandomIdGenerator())) noexcept; + + /** + * Initialize a new tracer provider with a specified context + * @param context The shared tracer configuration/pipeline for this provider. + */ + explicit TracerProvider(std::shared_ptr<sdk::trace::TracerContext> context) noexcept; + + ~TracerProvider(); + + opentelemetry::nostd::shared_ptr<opentelemetry::trace::Tracer> GetTracer( + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") noexcept override; + + /** + * Attaches a span processor to list of configured processors for this tracer provider. + * @param processor The new span processor for this tracer provider. This + * must not be a nullptr. + * + * Note: This process may not receive any in-flight spans, but will get newly created spans. + * Note: This method is not thread safe, and should ideally be called from main thread. + */ + void AddProcessor(std::unique_ptr<SpanProcessor> processor) noexcept; + + /** + * Obtain the resource associated with this tracer provider. + * @return The resource for this tracer provider. + */ + const opentelemetry::sdk::resource::Resource &GetResource() const noexcept; + + /** + * Shutdown the span processor associated with this tracer provider. + */ + bool Shutdown() noexcept; + + /** + * Force flush the span processor associated with this tracer provider. + */ + bool ForceFlush(std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept; + +private: + // order of declaration is important here - tracers should destroy only after context. + std::vector<std::shared_ptr<opentelemetry::sdk::trace::Tracer>> tracers_; + std::shared_ptr<sdk::trace::TracerContext> context_; + std::mutex lock_; +}; +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/version/version.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/version/version.h new file mode 100644 index 000000000..65c3c826c --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/version/version.h @@ -0,0 +1,30 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/detail/preprocessor.h" + +#define OPENTELEMETRY_SDK_VERSION "1.4.0" + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace version +{ +extern const int MAJOR_VERSION; +extern const int MINOR_VERSION; +extern const int PATCH_VERSION; +extern const char *PRE_RELEASE; +extern const char *BUILD_METADATA; +extern const int COUNT_NEW_COMMITS; +extern const char *BRANCH; +extern const char *COMMIT_HASH; +extern const char *FULL_VERSION; +extern const char *FULL_VERSION_WITH_BRANCH_COMMITHASH; +extern const char *BUILD_DATE; +} // namespace version +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk_config.h b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk_config.h new file mode 100644 index 000000000..8ac72a10d --- /dev/null +++ b/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk_config.h @@ -0,0 +1,7 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/config.h" +#include "opentelemetry/sdk/common/global_log_handler.h"
\ No newline at end of file |