/proc/self/cwd/source/common/stats/histogram_impl.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include "source/common/stats/histogram_impl.h" |
2 | | |
3 | | #include <algorithm> |
4 | | #include <string> |
5 | | |
6 | | #include "source/common/common/utility.h" |
7 | | |
8 | | #include "absl/strings/str_join.h" |
9 | | |
10 | | namespace Envoy { |
11 | | namespace Stats { |
12 | | |
13 | | namespace { |
14 | | const ConstSupportedBuckets default_buckets{}; |
15 | | } |
16 | | |
17 | | HistogramStatisticsImpl::HistogramStatisticsImpl() |
18 | 0 | : supported_buckets_(default_buckets), computed_quantiles_(supportedQuantiles().size(), 0.0) {} |
19 | | |
20 | | HistogramStatisticsImpl::HistogramStatisticsImpl(const histogram_t* histogram_ptr, |
21 | | Histogram::Unit unit, |
22 | | ConstSupportedBuckets& supported_buckets) |
23 | | : supported_buckets_(supported_buckets), |
24 | 75.0k | computed_quantiles_(HistogramStatisticsImpl::supportedQuantiles().size(), 0.0), unit_(unit) { |
25 | 75.0k | refresh(histogram_ptr); |
26 | 75.0k | } |
27 | | |
28 | 301k | const std::vector<double>& HistogramStatisticsImpl::supportedQuantiles() const { |
29 | 301k | CONSTRUCT_ON_FIRST_USE(std::vector<double>, |
30 | 301k | {0, 0.25, 0.5, 0.75, 0.90, 0.95, 0.99, 0.995, 0.999, 1}); |
31 | 301k | } |
32 | | |
33 | 0 | std::vector<uint64_t> HistogramStatisticsImpl::computeDisjointBuckets() const { |
34 | 0 | std::vector<uint64_t> buckets; |
35 | 0 | buckets.reserve(computed_buckets_.size()); |
36 | 0 | uint64_t previous_computed_bucket = 0; |
37 | 0 | for (uint64_t computed_bucket : computed_buckets_) { |
38 | 0 | buckets.push_back(computed_bucket - previous_computed_bucket); |
39 | 0 | previous_computed_bucket = computed_bucket; |
40 | 0 | } |
41 | 0 | return buckets; |
42 | 0 | } |
43 | | |
44 | 0 | std::string HistogramStatisticsImpl::quantileSummary() const { |
45 | 0 | std::vector<std::string> summary; |
46 | 0 | const std::vector<double>& supported_quantiles = supportedQuantiles(); |
47 | 0 | summary.reserve(supported_quantiles.size()); |
48 | 0 | for (size_t i = 0; i < supported_quantiles.size(); ++i) { |
49 | 0 | summary.push_back( |
50 | 0 | fmt::format("P{:g}: {:g}", 100 * supported_quantiles[i], computed_quantiles_[i])); |
51 | 0 | } |
52 | 0 | return absl::StrJoin(summary, ", "); |
53 | 0 | } |
54 | | |
55 | 0 | std::string HistogramStatisticsImpl::bucketSummary() const { |
56 | 0 | std::vector<std::string> bucket_summary; |
57 | 0 | ConstSupportedBuckets& supported_buckets = supportedBuckets(); |
58 | 0 | bucket_summary.reserve(supported_buckets.size()); |
59 | 0 | for (size_t i = 0; i < supported_buckets.size(); ++i) { |
60 | 0 | bucket_summary.push_back(fmt::format("B{:g}: {}", supported_buckets[i], computed_buckets_[i])); |
61 | 0 | } |
62 | 0 | return absl::StrJoin(bucket_summary, ", "); |
63 | 0 | } |
64 | | |
65 | | /** |
66 | | * Clears the old computed values and refreshes it with values computed from passed histogram. |
67 | | */ |
68 | 75.4k | void HistogramStatisticsImpl::refresh(const histogram_t* new_histogram_ptr) { |
69 | | // Convert to double once to avoid needing to cast it on every use. Use a double |
70 | | // to ensure the compiler doesn't try to convert the expression to integer math. |
71 | 75.4k | constexpr double percent_scale = Histogram::PercentScale; |
72 | | |
73 | 75.4k | std::fill(computed_quantiles_.begin(), computed_quantiles_.end(), 0.0); |
74 | 75.4k | ASSERT(supportedQuantiles().size() == computed_quantiles_.size()); |
75 | 75.4k | hist_approx_quantile(new_histogram_ptr, supportedQuantiles().data(), supportedQuantiles().size(), |
76 | 75.4k | computed_quantiles_.data()); |
77 | 75.4k | if (unit_ == Histogram::Unit::Percent) { |
78 | 0 | for (double& val : computed_quantiles_) { |
79 | 0 | val /= percent_scale; |
80 | 0 | } |
81 | 0 | } |
82 | | |
83 | 75.4k | sample_count_ = hist_sample_count(new_histogram_ptr); |
84 | 75.4k | sample_sum_ = hist_approx_sum(new_histogram_ptr); |
85 | 75.4k | if (unit_ == Histogram::Unit::Percent) { |
86 | 0 | sample_sum_ /= percent_scale; |
87 | 0 | } |
88 | | |
89 | 75.4k | computed_buckets_.clear(); |
90 | 75.4k | ConstSupportedBuckets& supported_buckets = supportedBuckets(); |
91 | 75.4k | computed_buckets_.reserve(supported_buckets.size()); |
92 | 1.43M | for (auto bucket : supported_buckets) { |
93 | 1.43M | if (unit_ == Histogram::Unit::Percent) { |
94 | 0 | bucket *= percent_scale; |
95 | 0 | } |
96 | 1.43M | computed_buckets_.emplace_back(hist_approx_count_below(new_histogram_ptr, bucket)); |
97 | 1.43M | } |
98 | 75.4k | } |
99 | | |
100 | | HistogramSettingsImpl::HistogramSettingsImpl(const envoy::config::metrics::v3::StatsConfig& config) |
101 | 5.40k | : configs_([&config]() { |
102 | 5.40k | std::vector<Config> configs; |
103 | 5.40k | for (const auto& matcher : config.histogram_bucket_settings()) { |
104 | 746 | std::vector<double> buckets{matcher.buckets().begin(), matcher.buckets().end()}; |
105 | 746 | std::sort(buckets.begin(), buckets.end()); |
106 | 746 | configs.emplace_back(matcher.match(), std::move(buckets)); |
107 | 746 | } |
108 | | |
109 | 5.40k | return configs; |
110 | 5.40k | }()) {} |
111 | | |
112 | 37.6k | const ConstSupportedBuckets& HistogramSettingsImpl::buckets(absl::string_view stat_name) const { |
113 | 37.6k | for (const auto& config : configs_) { |
114 | 0 | if (config.first.match(stat_name)) { |
115 | 0 | return config.second; |
116 | 0 | } |
117 | 0 | } |
118 | 37.6k | return defaultBuckets(); |
119 | 37.6k | } |
120 | | |
121 | 37.6k | const ConstSupportedBuckets& HistogramSettingsImpl::defaultBuckets() { |
122 | 37.6k | CONSTRUCT_ON_FIRST_USE(ConstSupportedBuckets, |
123 | 37.6k | {0.5, 1, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000, 30000, |
124 | 37.6k | 60000, 300000, 600000, 1800000, 3600000}); |
125 | 37.6k | } |
126 | | |
127 | | } // namespace Stats |
128 | | } // namespace Envoy |