Coverage Report

Created: 2024-09-19 09:45

/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
55.6k
      computed_quantiles_(HistogramStatisticsImpl::supportedQuantiles().size(), 0.0), unit_(unit) {
25
55.6k
  refresh(histogram_ptr);
26
55.6k
}
27
28
222k
const std::vector<double>& HistogramStatisticsImpl::supportedQuantiles() const {
29
222k
  CONSTRUCT_ON_FIRST_USE(std::vector<double>,
30
222k
                         {0, 0.25, 0.5, 0.75, 0.90, 0.95, 0.99, 0.995, 0.999, 1});
31
222k
}
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
55.7k
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
55.7k
  constexpr double percent_scale = Histogram::PercentScale;
72
73
55.7k
  std::fill(computed_quantiles_.begin(), computed_quantiles_.end(), 0.0);
74
55.7k
  ASSERT(supportedQuantiles().size() == computed_quantiles_.size());
75
55.7k
  hist_approx_quantile(new_histogram_ptr, supportedQuantiles().data(), supportedQuantiles().size(),
76
55.7k
                       computed_quantiles_.data());
77
55.7k
  if (unit_ == Histogram::Unit::Percent) {
78
0
    for (double& val : computed_quantiles_) {
79
0
      val /= percent_scale;
80
0
    }
81
0
  }
82
83
55.7k
  sample_count_ = hist_sample_count(new_histogram_ptr);
84
55.7k
  sample_sum_ = hist_approx_sum(new_histogram_ptr);
85
55.7k
  if (unit_ == Histogram::Unit::Percent) {
86
0
    sample_sum_ /= percent_scale;
87
0
  }
88
89
55.7k
  computed_buckets_.clear();
90
55.7k
  ConstSupportedBuckets& supported_buckets = supportedBuckets();
91
55.7k
  computed_buckets_.reserve(supported_buckets.size());
92
1.05M
  for (auto bucket : supported_buckets) {
93
1.05M
    if (unit_ == Histogram::Unit::Percent) {
94
0
      bucket *= percent_scale;
95
0
    }
96
1.05M
    computed_buckets_.emplace_back(hist_approx_count_below(new_histogram_ptr, bucket));
97
1.05M
  }
98
99
55.7k
  out_of_bound_count_ = hist_approx_count_above(new_histogram_ptr, supported_buckets.back());
100
55.7k
}
101
102
HistogramSettingsImpl::HistogramSettingsImpl(const envoy::config::metrics::v3::StatsConfig& config,
103
                                             Server::Configuration::CommonFactoryContext& context)
104
4.52k
    : configs_([&config, &context]() {
105
4.52k
        std::vector<Config> configs;
106
4.52k
        for (const auto& matcher : config.histogram_bucket_settings()) {
107
632
          std::vector<double> buckets{matcher.buckets().begin(), matcher.buckets().end()};
108
632
          std::sort(buckets.begin(), buckets.end());
109
632
          configs.emplace_back(Matchers::StringMatcherImpl<envoy::type::matcher::v3::StringMatcher>(
110
632
                                   matcher.match(), context),
111
632
                               std::move(buckets));
112
632
        }
113
114
4.52k
        return configs;
115
4.52k
      }()) {}
116
117
28.0k
const ConstSupportedBuckets& HistogramSettingsImpl::buckets(absl::string_view stat_name) const {
118
28.0k
  for (const auto& config : configs_) {
119
0
    if (config.first.match(stat_name)) {
120
0
      return config.second;
121
0
    }
122
0
  }
123
28.0k
  return defaultBuckets();
124
28.0k
}
125
126
28.0k
const ConstSupportedBuckets& HistogramSettingsImpl::defaultBuckets() {
127
28.0k
  CONSTRUCT_ON_FIRST_USE(ConstSupportedBuckets,
128
28.0k
                         {0.5, 1, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000, 30000,
129
28.0k
                          60000, 300000, 600000, 1800000, 3600000});
130
28.0k
}
131
132
} // namespace Stats
133
} // namespace Envoy