]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/opentelemetry-cpp/sdk/include/opentelemetry/sdk/_metrics/aggregator/exact_aggregator.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / jaegertracing / opentelemetry-cpp / sdk / include / opentelemetry / sdk / _metrics / aggregator / exact_aggregator.h
1 // Copyright The OpenTelemetry Authors
2 // SPDX-License-Identifier: Apache-2.0
3
4 #pragma once
5 #ifdef ENABLE_METRICS_PREVIEW
6
7 # include "opentelemetry/_metrics/instrument.h"
8 # include "opentelemetry/sdk/_metrics/aggregator/aggregator.h"
9 # include "opentelemetry/version.h"
10
11 # include <cmath>
12 # include <memory>
13 # include <mutex>
14 # include <vector>
15
16 OPENTELEMETRY_BEGIN_NAMESPACE
17 namespace sdk
18 {
19 namespace metrics
20 {
21 /**
22 * This aggregator has two modes. In-order and quantile estimation.
23 *
24 * The first mode simply stores all values sent to the Update()
25 * function in a vector and maintains the order they were sent in.
26 *
27 * The second mode also stores all values sent to the Update()
28 * function in a vector but sorts this vector when Checkpoint()
29 * is called. This mode also includes a function, Quantile(),
30 * that estimates the quantiles of the recorded data.
31 *
32 * @tparam T the type of values stored in this aggregator.
33 */
34 template <class T>
35 class ExactAggregator : public Aggregator<T>
36 {
37 public:
38 ExactAggregator(opentelemetry::metrics::InstrumentKind kind, bool quant_estimation = false)
39 {
40 static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
41 this->kind_ = kind;
42 this->checkpoint_ = this->values_;
43 this->agg_kind_ = AggregatorKind::Exact;
44 quant_estimation_ = quant_estimation;
45 }
46
47 ~ExactAggregator() = default;
48
49 ExactAggregator(const ExactAggregator &cp)
50 {
51 this->values_ = cp.values_;
52 this->checkpoint_ = cp.checkpoint_;
53 this->kind_ = cp.kind_;
54 this->agg_kind_ = cp.agg_kind_;
55 quant_estimation_ = cp.quant_estimation_;
56 // use default initialized mutex as they cannot be copied
57 }
58
59 /**
60 * Receives a captured value from the instrument and adds it to the values_ vector.
61 *
62 * @param val, the raw value used in aggregation
63 */
64 void update(T val) override
65 {
66 this->mu_.lock();
67 this->updated_ = true;
68 this->values_.push_back(val);
69 this->mu_.unlock();
70 }
71
72 /**
73 * Checkpoints the current values. This function will overwrite the current checkpoint with the
74 * current value. Sorts the values_ vector if quant_estimation_ == true
75 *
76 */
77 void checkpoint() override
78 {
79 this->mu_.lock();
80 this->updated_ = false;
81 if (quant_estimation_)
82 {
83 std::sort(this->values_.begin(), this->values_.end());
84 }
85 this->checkpoint_ = this->values_;
86 this->values_.clear();
87 this->mu_.unlock();
88 }
89
90 /**
91 * Merges two exact aggregators' values_ vectors together.
92 *
93 * @param other the aggregator to merge with this aggregator
94 */
95 void merge(const ExactAggregator &other)
96 {
97 if (this->kind_ == other.kind_)
98 {
99 this->mu_.lock();
100 // First merge values
101 this->values_.insert(this->values_.end(), other.values_.begin(), other.values_.end());
102 // Now merge checkpoints
103 this->checkpoint_.insert(this->checkpoint_.end(), other.checkpoint_.begin(),
104 other.checkpoint_.end());
105 this->mu_.unlock();
106 }
107 else
108 {
109 // Log error
110 return;
111 }
112 }
113
114 /**
115 * Performs quantile estimation on the checkpoint vector in this aggregator.
116 * This function only works if quant_estimation_ == true.
117 * @param q the quantile to estimate. 0 <= q <= 1
118 * @return the nearest value in the vector to the exact quantile.
119 */
120 T get_quantiles(double q) override
121 {
122 if (!quant_estimation_)
123 {
124 // Log error
125 # if __EXCEPTIONS
126 throw std::domain_error("Exact aggregator is not in quantile estimation mode!");
127 # else
128 std::terminate();
129 # endif
130 }
131 if (this->checkpoint_.size() == 0 || q < 0 || q > 1)
132 {
133 // Log error
134 # if __EXCEPTIONS
135 throw std::invalid_argument("Arg 'q' must be between 0 and 1, inclusive");
136 # else
137 std::terminate();
138 # endif
139 }
140 else if (q == 0 || this->checkpoint_.size() == 1)
141 {
142 return this->checkpoint_[0];
143 }
144 else if (q == 1)
145 {
146 return this->checkpoint_[this->checkpoint_.size() - 1];
147 }
148 else
149 {
150 float position = float(float(this->checkpoint_.size() - 1) * q);
151 int ceiling = int(ceil(position));
152 return this->checkpoint_[ceiling];
153 }
154 }
155
156 //////////////////////////ACCESSOR FUNCTIONS//////////////////////////
157 std::vector<T> get_checkpoint() override { return this->checkpoint_; }
158
159 std::vector<T> get_values() override { return this->values_; }
160
161 bool get_quant_estimation() override { return quant_estimation_; }
162
163 private:
164 bool quant_estimation_; // Used to switch between in-order and quantile estimation modes
165 };
166 } // namespace metrics
167 } // namespace sdk
168 OPENTELEMETRY_END_NAMESPACE
169 #endif