diff --git a/conanfile.py b/conanfile.py index dc77b54..29c377a 100644 --- a/conanfile.py +++ b/conanfile.py @@ -5,7 +5,7 @@ class CxxmetricsConan(ConanFile): name = "cxxmetrics" - version = "0.0.7" + version = "0.0.8" license = "Apache 2.0" settings = "os" url = "https://github.com/kmaragon/cxxmetrics" diff --git a/cxxmetrics/ewma.hpp b/cxxmetrics/ewma.hpp index 0854142..0127f15 100644 --- a/cxxmetrics/ewma.hpp +++ b/cxxmetrics/ewma.hpp @@ -216,7 +216,7 @@ TValue ewma::tick(const clock_point &at) if (missed_intervals > 0) { // we missed some intervals - we'll average in zeros - if ((at - last) > period(TWindow) && TWindow > TInterval) + if ((TWindow > TInterval) && (at - last) > period(TWindow)) { constexpr auto intervals_per_window = TWindow / TInterval; period::value missed_windows = missed_intervals / intervals_per_window; diff --git a/cxxmetrics/exponential_decay.hpp b/cxxmetrics/exponential_decay.hpp deleted file mode 100644 index df25821..0000000 --- a/cxxmetrics/exponential_decay.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef CXXMETRICS_EXPONENTIAL_DECAY_HPP -#define CXXMETRICS_EXPONENTIAL_DECAY_HPP - -namespace cxxmetrics -{ - -} - -#endif //CXXMETRICS_EXPONENTIAL_DECAY_HPP diff --git a/cxxmetrics/metric_value.hpp b/cxxmetrics/metric_value.hpp index cd11336..55271e1 100644 --- a/cxxmetrics/metric_value.hpp +++ b/cxxmetrics/metric_value.hpp @@ -863,9 +863,9 @@ class metric_value } template - operator std::chrono::nanoseconds() const + operator std::chrono::duration() const { - return value_.to_nanos(); + return std::chrono::duration_cast>(value_.to_nanos()); } }; diff --git a/cxxmetrics/snapshots.hpp b/cxxmetrics/snapshots.hpp index 58e3fcf..89eca9e 100644 --- a/cxxmetrics/snapshots.hpp +++ b/cxxmetrics/snapshots.hpp @@ -289,6 +289,50 @@ class reservoir_snapshot return values_[index - 1] + metric_value((pos - index) * static_cast(values_[index] - values_[index - 1])); } + /** + * \brief Sample n values from the snapshot, calling a function for each + * sampled value + * + * \tparam Handler The handler type + * + * The handler will receive a const metric_value and quantile + * + * \param max_to_visit The maximum number of values + * \param hnd The handler to call for each metric_value in the snapshot + */ + template + void sample(std::size_t max_to_visit, Handler hnd) const + { + long double q_proportion = 1.0L / std::min( + static_cast(max_to_visit + 1), + static_cast(values_.size() - 1)); + + for (std::size_t i = 0; i < max_to_visit; i++) { + long double q = q_proportion * (i + 1); + + auto pos = q * (values_.size() + 1); + auto index = static_cast(pos); + if (index >= values_.size()) + return; + + if (index < 1) { + hnd(min(), pos * 100 / static_cast(values_.size() + 1)); + continue; + } + + if (index >= values_.size()) { + hnd(max(), pos * 100 / static_cast(values_.size() + 1)); + continue; + } + + hnd(values_[index - 1] + + metric_value( + (pos - static_cast(index)) * + static_cast(values_[index] - values_[index - 1])), + pos * 100 / static_cast(values_.size() + 1)); + } + } + /** * \brief Get the mean value in the snapshot * diff --git a/test/conanfile.py b/test/conanfile.py index 90694aa..fc15287 100644 --- a/test/conanfile.py +++ b/test/conanfile.py @@ -6,7 +6,7 @@ class CxxmetricsTestConan(ConanFile): settings = "os", "compiler", "build_type", "arch" generators = "cmake" exports = "CMakeLists.txt", "../test*" - build_requires = "catch2/2.3.0@bincrafters/stable" + build_requires = "catch2/2.13.9" def source(self): tools.replace_in_file("CMakeLists.txt", "project(\"cxxmetrics_test\" CXX)", '''project("cxxmetrics_test" CXX) diff --git a/test/publisher_tests.cpp b/test/publisher_tests.cpp index b6d8ad1..20b5b9b 100644 --- a/test/publisher_tests.cpp +++ b/test/publisher_tests.cpp @@ -326,6 +326,10 @@ TEST_CASE("Publisher can get histogram options", "[publisher]") { values.emplace(q, round(v)); }); + + ss.sample(9, [&](const metric_value& v, quantile q) { + values.emplace(q, round(v)); + }); }); }; @@ -337,7 +341,7 @@ TEST_CASE("Publisher can get histogram options", "[publisher]") subject.visit_registry(visitor); REQUIRE(value == metric_value(50)); - REQUIRE(values.size() == 3); // defaults + REQUIRE(values.size() == 12); // defaults REQUIRE(count == 2); print_percentiles(values); @@ -348,6 +352,6 @@ TEST_CASE("Publisher can get histogram options", "[publisher]") print_percentiles(values); REQUIRE(value == metric_value(0)); - REQUIRE(values.size() == 1); + REQUIRE(values.size() == 10); REQUIRE(count == 4); } diff --git a/test/reservoir_test.cpp b/test/reservoir_test.cpp index 4ebac98..34de1be 100644 --- a/test/reservoir_test.cpp +++ b/test/reservoir_test.cpp @@ -99,7 +99,7 @@ TEST_CASE("Simple Reservoir threaded updates with snapshots", "[reservoir]") for (int i = 0; i < 1000; i++) { auto s = r.snapshot(); - CAPTURE(i) + CAPTURE(i); REQUIRE(s.size() >= minsize); }