Skip to content

Commit 46b16ec

Browse files
authored
Histogram Aggregation: Fix bucket detection logic, performance improvements, and benchmark tests (#1869)
1 parent 57d1a47 commit 46b16ec

15 files changed

Lines changed: 481 additions & 70 deletions

File tree

examples/metrics_simple/metrics_ostream.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ void InitMetrics(const std::string &name)
7474
std::shared_ptr<opentelemetry::sdk::metrics::AggregationConfig> aggregation_config{
7575
new opentelemetry::sdk::metrics::HistogramAggregationConfig};
7676
static_cast<opentelemetry::sdk::metrics::HistogramAggregationConfig *>(aggregation_config.get())
77-
->boundaries_ = std::list<double>{0.0, 50.0, 100.0, 250.0, 500.0, 750.0,
78-
1000.0, 2500.0, 5000.0, 10000.0, 20000.0};
77+
->boundaries_ = std::vector<double>{0.0, 50.0, 100.0, 250.0, 500.0, 750.0,
78+
1000.0, 2500.0, 5000.0, 10000.0, 20000.0};
7979
std::unique_ptr<metric_sdk::View> histogram_view{new metric_sdk::View{
8080
name, "description", metric_sdk::AggregationType::kHistogram, aggregation_config}};
8181
p->AddView(std::move(histogram_instrument_selector), std::move(histogram_meter_selector),

exporters/ostream/test/ostream_metric_test.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,14 @@ TEST(OStreamMetricsExporter, ExportHistogramPointData)
9797
std::unique_ptr<metric_sdk::PushMetricExporter>(new exportermetrics::OStreamMetricExporter);
9898

9999
metric_sdk::HistogramPointData histogram_point_data{};
100-
histogram_point_data.boundaries_ = std::list<double>{10.1, 20.2, 30.2};
100+
histogram_point_data.boundaries_ = std::vector<double>{10.1, 20.2, 30.2};
101101
histogram_point_data.count_ = 3;
102102
histogram_point_data.counts_ = {200, 300, 400, 500};
103103
histogram_point_data.sum_ = 900.5;
104104
histogram_point_data.min_ = 1.8;
105105
histogram_point_data.max_ = 12.0;
106106
metric_sdk::HistogramPointData histogram_point_data2{};
107-
histogram_point_data2.boundaries_ = std::list<double>{10.0, 20.0, 30.0};
107+
histogram_point_data2.boundaries_ = std::vector<double>{10.0, 20.0, 30.0};
108108
histogram_point_data2.count_ = 3;
109109
histogram_point_data2.counts_ = {200, 300, 400, 500};
110110
histogram_point_data2.sum_ = (int64_t)900;

exporters/otlp/test/otlp_metrics_serialization_test.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ static metrics_sdk::MetricData CreateHistogramAggregationData()
5454
s_data_1.sum_ = 100.2;
5555
s_data_1.count_ = 22;
5656
s_data_1.counts_ = {2, 9, 4, 7};
57-
s_data_1.boundaries_ = std::list<double>({0.0, 10.0, 20.0, 30.0});
57+
s_data_1.boundaries_ = std::vector<double>({0.0, 10.0, 20.0, 30.0});
5858
s_data_2.sum_ = 200.2;
5959
s_data_2.count_ = 20;
6060
s_data_2.counts_ = {0, 8, 5, 7};
61-
s_data_2.boundaries_ = std::list<double>({0.0, 10.0, 20.0, 30.0});
61+
s_data_2.boundaries_ = std::vector<double>({0.0, 10.0, 20.0, 30.0});
6262

6363
data.aggregation_temporality = metrics_sdk::AggregationTemporality::kCumulative;
6464
data.end_ts = opentelemetry::common::SystemTimestamp(std::chrono::system_clock::now());

exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class PrometheusExporterUtils
6767
*/
6868
template <typename T>
6969
static void SetData(std::vector<T> values,
70-
const std::list<double> &boundaries,
70+
const std::vector<double> &boundaries,
7171
const std::vector<uint64_t> &counts,
7272
const opentelemetry::sdk::metrics::PointAttributes &labels,
7373
std::chrono::nanoseconds time,
@@ -104,7 +104,7 @@ class PrometheusExporterUtils
104104
*/
105105
template <typename T>
106106
static void SetValue(std::vector<T> values,
107-
const std::list<double> &boundaries,
107+
const std::vector<double> &boundaries,
108108
const std::vector<uint64_t> &counts,
109109
::prometheus::ClientMetric *metric);
110110
};

exporters/prometheus/src/exporter_utils.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ void PrometheusExporterUtils::SetData(std::vector<T> values,
221221
*/
222222
template <typename T>
223223
void PrometheusExporterUtils::SetData(std::vector<T> values,
224-
const std::list<double> &boundaries,
224+
const std::vector<double> &boundaries,
225225
const std::vector<uint64_t> &counts,
226226
const metric_sdk::PointAttributes &labels,
227227
std::chrono::nanoseconds time,
@@ -340,7 +340,7 @@ void PrometheusExporterUtils::SetValue(std::vector<T> values,
340340
*/
341341
template <typename T>
342342
void PrometheusExporterUtils::SetValue(std::vector<T> values,
343-
const std::list<double> &boundaries,
343+
const std::vector<double> &boundaries,
344344
const std::vector<uint64_t> &counts,
345345
prometheus_client::ClientMetric *metric)
346346
{

sdk/include/opentelemetry/sdk/metrics/aggregation/aggregation_config.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33

44
#pragma once
55

6-
#include <list>
76
#include "opentelemetry/version.h"
7+
8+
#include <vector>
9+
810
OPENTELEMETRY_BEGIN_NAMESPACE
911
namespace sdk
1012
{
@@ -19,7 +21,7 @@ class AggregationConfig
1921
class HistogramAggregationConfig : public AggregationConfig
2022
{
2123
public:
22-
std::list<double> boundaries_;
24+
std::vector<double> boundaries_;
2325
bool record_min_max_ = true;
2426
};
2527
} // namespace metrics

sdk/include/opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,13 @@ void HistogramDiff(HistogramPointData &current, HistogramPointData &next, Histog
108108
diff.record_min_max_ = false;
109109
}
110110

111+
template <class T>
112+
size_t BucketBinarySearch(T value, const std::vector<double> &boundaries)
113+
{
114+
auto low = std::lower_bound(boundaries.begin(), boundaries.end(), value);
115+
return low - boundaries.begin();
116+
}
117+
111118
} // namespace metrics
112119
} // namespace sdk
113120
OPENTELEMETRY_END_NAMESPACE

sdk/include/opentelemetry/sdk/metrics/data/point_data.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include "opentelemetry/sdk/metrics/instruments.h"
99
#include "opentelemetry/version.h"
1010

11-
#include <list>
11+
#include <vector>
1212

1313
OPENTELEMETRY_BEGIN_NAMESPACE
1414
namespace sdk
@@ -55,14 +55,14 @@ class HistogramPointData
5555
HistogramPointData &operator=(HistogramPointData &&) = default;
5656
HistogramPointData(const HistogramPointData &) = default;
5757
HistogramPointData() = default;
58-
HistogramPointData(std::list<double> &boundaries) : boundaries_(boundaries) {}
59-
std::list<double> boundaries_ = {};
60-
ValueType sum_ = {};
61-
ValueType min_ = {};
62-
ValueType max_ = {};
63-
std::vector<uint64_t> counts_ = {};
64-
uint64_t count_ = {};
65-
bool record_min_max_ = true;
58+
HistogramPointData(std::vector<double> &boundaries) : boundaries_(boundaries) {}
59+
std::vector<double> boundaries_ = {};
60+
ValueType sum_ = {};
61+
ValueType min_ = {};
62+
ValueType max_ = {};
63+
std::vector<uint64_t> counts_ = {};
64+
uint64_t count_ = {};
65+
bool record_min_max_ = true;
6666
};
6767

6868
class DropPointData

sdk/include/opentelemetry/sdk/metrics/state/temporal_metric_storage.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "opentelemetry/sdk/metrics/state/attributes_hashmap.h"
99
#include "opentelemetry/sdk/metrics/state/metric_collector.h"
1010

11+
#include <list>
1112
#include <memory>
1213

1314
OPENTELEMETRY_BEGIN_NAMESPACE

sdk/src/metrics/aggregation/histogram_aggregation.cc

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
#include "opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h"
5+
#include "opentelemetry/version.h"
6+
57
#include <algorithm>
68
#include <iomanip>
79
#include <limits>
810
#include <memory>
9-
#include "opentelemetry/version.h"
10-
1111
#include <mutex>
12+
1213
OPENTELEMETRY_BEGIN_NAMESPACE
1314
namespace sdk
1415
{
@@ -59,16 +60,8 @@ void LongHistogramAggregation::Aggregate(int64_t value,
5960
point_data_.min_ = std::min(nostd::get<int64_t>(point_data_.min_), value);
6061
point_data_.max_ = std::max(nostd::get<int64_t>(point_data_.max_), value);
6162
}
62-
size_t index = 0;
63-
for (auto it = point_data_.boundaries_.begin(); it != point_data_.boundaries_.end(); ++it)
64-
{
65-
if (value < *it)
66-
{
67-
point_data_.counts_[index] += 1;
68-
return;
69-
}
70-
index++;
71-
}
63+
size_t index = BucketBinarySearch(value, point_data_.boundaries_);
64+
point_data_.counts_[index] += 1;
7265
}
7366

7467
std::unique_ptr<Aggregation> LongHistogramAggregation::Merge(
@@ -77,7 +70,10 @@ std::unique_ptr<Aggregation> LongHistogramAggregation::Merge(
7770
auto curr_value = nostd::get<HistogramPointData>(ToPoint());
7871
auto delta_value = nostd::get<HistogramPointData>(
7972
(static_cast<const LongHistogramAggregation &>(delta).ToPoint()));
80-
LongHistogramAggregation *aggr = new LongHistogramAggregation();
73+
HistogramAggregationConfig agg_config;
74+
agg_config.boundaries_ = curr_value.boundaries_;
75+
agg_config.record_min_max_ = record_min_max_;
76+
LongHistogramAggregation *aggr = new LongHistogramAggregation(&agg_config);
8177
HistogramMerge<int64_t>(curr_value, delta_value, aggr->point_data_);
8278
return std::unique_ptr<Aggregation>(aggr);
8379
}
@@ -87,7 +83,10 @@ std::unique_ptr<Aggregation> LongHistogramAggregation::Diff(const Aggregation &n
8783
auto curr_value = nostd::get<HistogramPointData>(ToPoint());
8884
auto next_value = nostd::get<HistogramPointData>(
8985
(static_cast<const LongHistogramAggregation &>(next).ToPoint()));
90-
LongHistogramAggregation *aggr = new LongHistogramAggregation();
86+
HistogramAggregationConfig agg_config;
87+
agg_config.boundaries_ = curr_value.boundaries_;
88+
agg_config.record_min_max_ = record_min_max_;
89+
LongHistogramAggregation *aggr = new LongHistogramAggregation(&agg_config);
9190
HistogramDiff<int64_t>(curr_value, next_value, aggr->point_data_);
9291
return std::unique_ptr<Aggregation>(aggr);
9392
}
@@ -107,8 +106,8 @@ DoubleHistogramAggregation::DoubleHistogramAggregation(const AggregationConfig *
107106
}
108107
else
109108
{
110-
point_data_.boundaries_ =
111-
std::list<double>{0.0, 5.0, 10.0, 25.0, 50.0, 75.0, 100.0, 250.0, 500.0, 1000.0};
109+
point_data_.boundaries_ = {0.0, 5.0, 10.0, 25.0, 50.0, 75.0, 100.0, 250.0,
110+
500.0, 750.0, 1000.0, 2500.0, 5000.0, 7500.0, 10000.0};
112111
}
113112
if (ac)
114113
{
@@ -141,16 +140,8 @@ void DoubleHistogramAggregation::Aggregate(double value,
141140
point_data_.min_ = std::min(nostd::get<double>(point_data_.min_), value);
142141
point_data_.max_ = std::max(nostd::get<double>(point_data_.max_), value);
143142
}
144-
size_t index = 0;
145-
for (auto it = point_data_.boundaries_.begin(); it != point_data_.boundaries_.end(); ++it)
146-
{
147-
if (value < *it)
148-
{
149-
point_data_.counts_[index] += 1;
150-
return;
151-
}
152-
index++;
153-
}
143+
size_t index = BucketBinarySearch(value, point_data_.boundaries_);
144+
point_data_.counts_[index] += 1;
154145
}
155146

156147
std::unique_ptr<Aggregation> DoubleHistogramAggregation::Merge(
@@ -159,12 +150,10 @@ std::unique_ptr<Aggregation> DoubleHistogramAggregation::Merge(
159150
auto curr_value = nostd::get<HistogramPointData>(ToPoint());
160151
auto delta_value = nostd::get<HistogramPointData>(
161152
(static_cast<const DoubleHistogramAggregation &>(delta).ToPoint()));
162-
std::shared_ptr<AggregationConfig> aggregation_config(new HistogramAggregationConfig);
163-
static_cast<opentelemetry::sdk::metrics::HistogramAggregationConfig *>(aggregation_config.get())
164-
->boundaries_ = curr_value.boundaries_;
165-
static_cast<opentelemetry::sdk::metrics::HistogramAggregationConfig *>(aggregation_config.get())
166-
->record_min_max_ = record_min_max_;
167-
DoubleHistogramAggregation *aggr = new DoubleHistogramAggregation(aggregation_config.get());
153+
HistogramAggregationConfig agg_config;
154+
agg_config.boundaries_ = curr_value.boundaries_;
155+
agg_config.record_min_max_ = record_min_max_;
156+
DoubleHistogramAggregation *aggr = new DoubleHistogramAggregation(&agg_config);
168157
HistogramMerge<double>(curr_value, delta_value, aggr->point_data_);
169158
return std::unique_ptr<Aggregation>(aggr);
170159
}
@@ -175,7 +164,10 @@ std::unique_ptr<Aggregation> DoubleHistogramAggregation::Diff(
175164
auto curr_value = nostd::get<HistogramPointData>(ToPoint());
176165
auto next_value = nostd::get<HistogramPointData>(
177166
(static_cast<const DoubleHistogramAggregation &>(next).ToPoint()));
178-
DoubleHistogramAggregation *aggr = new DoubleHistogramAggregation();
167+
HistogramAggregationConfig agg_config;
168+
agg_config.boundaries_ = curr_value.boundaries_;
169+
agg_config.record_min_max_ = record_min_max_;
170+
DoubleHistogramAggregation *aggr = new DoubleHistogramAggregation(&agg_config);
179171
HistogramDiff<double>(curr_value, next_value, aggr->point_data_);
180172
return std::unique_ptr<Aggregation>(aggr);
181173
}

0 commit comments

Comments
 (0)