diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ee6812c..d7979e7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,6 +107,10 @@ endif() # prometheus-cpp +if(WIN32) + add_compile_definitions(NOMINMAX) +endif() + add_subdirectory(core) if(ENABLE_PULL) diff --git a/core/include/prometheus/collectable.h b/core/include/prometheus/collectable.h index 4d1489a2..0ec61642 100644 --- a/core/include/prometheus/collectable.h +++ b/core/include/prometheus/collectable.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include "prometheus/detail/core_export.h" @@ -21,7 +21,8 @@ class PROMETHEUS_CPP_CORE_EXPORT Collectable { /// \brief Returns a list of metrics and their samples. virtual std::vector Collect() const = 0; - virtual std::vector Collect(std::time_t) const = 0; + virtual std::vector Collect( + const std::chrono::system_clock::time_point& time) const = 0; }; } // namespace prometheus diff --git a/core/include/prometheus/counter.h b/core/include/prometheus/counter.h index 9c61654b..f8fc593f 100644 --- a/core/include/prometheus/counter.h +++ b/core/include/prometheus/counter.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include "prometheus/client_metric.h" #include "prometheus/detail/builder.h" // IWYU pragma: export @@ -47,7 +47,14 @@ class PROMETHEUS_CPP_CORE_EXPORT Counter { /// /// Collect is called by the Registry when collecting metrics. ClientMetric Collect() const; - bool Expired(std::time_t, double) const; + + /// \brief Check if the counter has expired. + /// + /// Expires is called by the Registry when collecting metrics. + /// + /// A counter never expires. + static bool Expired(const std::chrono::system_clock::time_point& time, + const std::chrono::seconds& ttl); private: Gauge gauge_{0.0}; diff --git a/core/include/prometheus/detail/builder.h b/core/include/prometheus/detail/builder.h index 8e4b119f..4c0afd3a 100644 --- a/core/include/prometheus/detail/builder.h +++ b/core/include/prometheus/detail/builder.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "prometheus/labels.h" @@ -21,14 +22,14 @@ class Builder { Builder& Labels(const ::prometheus::Labels& labels); Builder& Name(const std::string&); Builder& Help(const std::string&); - Builder& Seconds(double); + Builder& TTL(const std::chrono::seconds& ttl); Family& Register(Registry&); private: ::prometheus::Labels labels_; std::string name_; std::string help_; - double seconds_; + std::chrono::seconds ttl_{std::chrono::seconds::max()}; }; } // namespace detail diff --git a/core/include/prometheus/detail/time_window_quantiles.h b/core/include/prometheus/detail/time_window_quantiles.h index 498baed2..8b0b8182 100644 --- a/core/include/prometheus/detail/time_window_quantiles.h +++ b/core/include/prometheus/detail/time_window_quantiles.h @@ -13,7 +13,7 @@ namespace prometheus { namespace detail { class PROMETHEUS_CPP_CORE_EXPORT TimeWindowQuantiles { - using Clock = std::chrono::steady_clock; + using Clock = std::chrono::system_clock; public: TimeWindowQuantiles(const std::vector& quantiles, diff --git a/core/include/prometheus/family.h b/core/include/prometheus/family.h index 71420153..8ad48d83 100644 --- a/core/include/prometheus/family.h +++ b/core/include/prometheus/family.h @@ -2,8 +2,8 @@ #include #include +#include #include -#include #include #include #include @@ -92,9 +92,12 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable { /// \param constant_labels Assign a set of key-value pairs (= labels) to the /// metric. All these labels are propagated to each time series within the /// metric. + /// \param ttl Set the time to live in seconds. Any gauges that are not + /// updated within `ttl` seconds will not be collected. /// \throw std::runtime_exception on invalid metric or label names. Family(const std::string& name, const std::string& help, - const Labels& constant_labels, double seconds); + const Labels& constant_labels, + const std::chrono::seconds& ttl = std::chrono::seconds::max()); /// \brief Add a new dimensional data. /// @@ -145,7 +148,17 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable { /// /// \return Zero or more samples for each dimensional data. std::vector Collect() const override; - std::vector Collect(std::time_t) const override; + + /// \brief Returns the current value of each dimensional data. + /// + /// Collect is called by the Registry when collecting metrics. + /// + /// \param time The current time. This is used to check for + /// expired gauges. + /// + /// \return Zero or more samples for each dimensional data. + std::vector Collect( + const std::chrono::system_clock::time_point& time) const override; private: std::unordered_map, detail::LabelHasher> metrics_; @@ -153,7 +166,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable { const std::string name_; const std::string help_; const Labels constant_labels_; - double seconds_; + std::chrono::seconds ttl_{std::chrono::seconds::max()}; mutable std::mutex mutex_; ClientMetric CollectMetric(const Labels& labels, T* metric) const; diff --git a/core/include/prometheus/gauge.h b/core/include/prometheus/gauge.h index 13665682..bc6df38d 100644 --- a/core/include/prometheus/gauge.h +++ b/core/include/prometheus/gauge.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include "prometheus/client_metric.h" #include "prometheus/detail/builder.h" // IWYU pragma: export @@ -57,12 +57,26 @@ class PROMETHEUS_CPP_CORE_EXPORT Gauge { /// /// Collect is called by the Registry when collecting metrics. ClientMetric Collect() const; - bool Expired(std::time_t, double) const; + + /// \brief Check if the gauge has expired. + /// + /// Expires is called by the Registry when collecting metrics. + /// + /// A gauge has expired if it has been more than `ttl` seconds + /// since `time`. + /// + /// \param time The current time. + /// \param time Time to live in seconds. + /// + /// \return Has the gauge expired. + bool Expired(const std::chrono::system_clock::time_point& time, + const std::chrono::seconds& ttl) const; private: void Change(double); std::atomic value_{0.0}; - std::atomic time_{std::time(nullptr)}; + std::atomic time_{ + std::chrono::system_clock::now()}; }; /// \brief Return a builder to configure and register a Gauge metric. @@ -77,6 +91,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Gauge { /// .Name("some_name") /// .Help("Additional description.") /// .Labels({{"key", "value"}}) +/// .TTL(360) /// .Register(*registry); /// /// ... @@ -89,6 +104,8 @@ class PROMETHEUS_CPP_CORE_EXPORT Gauge { /// - Help(const std::string&) to set an additional description. /// - Labels(const Labels&) to assign a set of /// key-value pairs (= labels) to the metric. +/// - TTL(const std::chrono::seconds&)` to set the time to live. Gauges that +/// are not updated within `ttl` seconds will not be collected. /// /// To finish the configuration of the Gauge metric register it with /// Register(Registry&). diff --git a/core/include/prometheus/histogram.h b/core/include/prometheus/histogram.h index fb1ba759..30fe914b 100644 --- a/core/include/prometheus/histogram.h +++ b/core/include/prometheus/histogram.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -67,7 +67,14 @@ class PROMETHEUS_CPP_CORE_EXPORT Histogram { /// /// Collect is called by the Registry when collecting metrics. ClientMetric Collect() const; - bool Expired(std::time_t, double) const; + + /// \brief Check if the histogram has expired. + /// + /// Expires is called by the Registry when collecting metrics. + /// + /// A histogram never expires. + static bool Expired(const std::chrono::system_clock::time_point& time, + const std::chrono::seconds& ttl); private: const BucketBoundaries bucket_boundaries_; diff --git a/core/include/prometheus/registry.h b/core/include/prometheus/registry.h index 1f5c0e50..769bb2d9 100644 --- a/core/include/prometheus/registry.h +++ b/core/include/prometheus/registry.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include @@ -80,7 +80,18 @@ class PROMETHEUS_CPP_CORE_EXPORT Registry : public Collectable { /// /// \return Zero or more metrics and their samples. std::vector Collect() const override; - std::vector Collect(std::time_t) const override; + + /// \brief Returns a list of metrics and their samples. + /// + /// Every time the Registry is scraped it calls each of the metrics Collect + /// function. + /// + /// \param time The current time. This is used to check for + /// expired gauges. + /// + /// \return Zero or more metrics and their samples. + std::vector Collect( + const std::chrono::system_clock::time_point& time) const override; /// \brief Removes a metrics family from the registry. /// @@ -107,7 +118,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Registry : public Collectable { template Family& Add(const std::string& name, const std::string& help, - const Labels& labels, double seconds); + const Labels& labels, const std::chrono::seconds& ttl); const InsertBehavior insert_behavior_; std::vector>> counters_; diff --git a/core/include/prometheus/summary.h b/core/include/prometheus/summary.h index 0bebf4bd..8de46a90 100644 --- a/core/include/prometheus/summary.h +++ b/core/include/prometheus/summary.h @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -83,7 +82,14 @@ class PROMETHEUS_CPP_CORE_EXPORT Summary { /// /// Collect is called by the Registry when collecting metrics. ClientMetric Collect() const; - bool Expired(std::time_t, double) const; + + /// \brief Check if the summary has expired. + /// + /// Expires is called by the Registry when collecting metrics. + /// + /// A summary never expires. + static bool Expired(const std::chrono::system_clock::time_point& time, + const std::chrono::seconds& ttl); private: const Quantiles quantiles_; diff --git a/core/src/counter.cc b/core/src/counter.cc index 61d0f8f6..89c4ceac 100644 --- a/core/src/counter.cc +++ b/core/src/counter.cc @@ -19,9 +19,10 @@ ClientMetric Counter::Collect() const { return metric; } -bool Counter::Expired(const std::time_t time, const double seconds) const { +bool Counter::Expired(const std::chrono::system_clock::time_point& time, + const std::chrono::seconds& ttl) { (void)time; - (void)seconds; + (void)ttl; return false; } diff --git a/core/src/detail/builder.cc b/core/src/detail/builder.cc index 84ec6ab5..d1f173a3 100644 --- a/core/src/detail/builder.cc +++ b/core/src/detail/builder.cc @@ -30,14 +30,14 @@ Builder& Builder::Help(const std::string& help) { } template -Builder& Builder::Seconds(const double seconds) { - seconds_ = seconds; +Builder& Builder::TTL(const std::chrono::seconds& ttl) { + ttl_ = ttl; return *this; } template Family& Builder::Register(Registry& registry) { - return registry.Add(name_, help_, labels_, seconds_); + return registry.Add(name_, help_, labels_, ttl_); } template class PROMETHEUS_CPP_CORE_EXPORT Builder; diff --git a/core/src/family.cc b/core/src/family.cc index c74d6942..49a71a2f 100644 --- a/core/src/family.cc +++ b/core/src/family.cc @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -17,11 +18,9 @@ namespace prometheus { template Family::Family(const std::string& name, const std::string& help, - const Labels& constant_labels, const double seconds) - : name_(name), - help_(help), - constant_labels_(constant_labels), - seconds_(seconds) { + const Labels& constant_labels, + const std::chrono::seconds& ttl) + : name_(name), help_(help), constant_labels_(constant_labels), ttl_(ttl) { if (!CheckMetricName(name_)) { throw std::invalid_argument("Invalid metric name"); } @@ -90,12 +89,12 @@ const Labels Family::GetConstantLabels() const { template std::vector Family::Collect() const { - const auto time = std::time(nullptr); - return Collect(time); + return Collect(std::chrono::system_clock::now()); } template -std::vector Family::Collect(const std::time_t time) const { +std::vector Family::Collect( + const std::chrono::system_clock::time_point& time) const { std::lock_guard lock{mutex_}; if (metrics_.empty()) { @@ -108,7 +107,7 @@ std::vector Family::Collect(const std::time_t time) const { family.type = T::metric_type; family.metric.reserve(metrics_.size()); for (const auto& m : metrics_) { - if (!m.second.get()->Expired(time, seconds_)) { + if (!m.second->Expired(time, ttl_)) { family.metric.push_back( std::move(CollectMetric(m.first, m.second.get()))); } diff --git a/core/src/gauge.cc b/core/src/gauge.cc index 916848bd..e2f2aa92 100644 --- a/core/src/gauge.cc +++ b/core/src/gauge.cc @@ -1,5 +1,7 @@ #include "prometheus/gauge.h" +#include + namespace prometheus { Gauge::Gauge(const double value) : value_{value} {} @@ -14,7 +16,7 @@ void Gauge::Decrement(const double value) { Change(-1.0 * value); } void Gauge::Set(const double value) { value_.store(value); - time_.store(std::time(nullptr)); + time_.store(std::chrono::system_clock::now()); } void Gauge::Change(const double value) { @@ -23,7 +25,7 @@ void Gauge::Change(const double value) { while (!value_.compare_exchange_weak(current, current + value)) { // intentionally empty block } - time_.store(std::time(nullptr)); + time_.store(std::chrono::system_clock::now()); } void Gauge::SetToCurrentTime() { @@ -39,8 +41,10 @@ ClientMetric Gauge::Collect() const { return metric; } -bool Gauge::Expired(const std::time_t time, const double seconds) const { - return std::difftime(time, time_) > seconds; +bool Gauge::Expired(const std::chrono::system_clock::time_point& time, + const std::chrono::seconds& ttl) const { + return std::chrono::duration_cast(time - + time_.load()) >= ttl; } } // namespace prometheus diff --git a/core/src/histogram.cc b/core/src/histogram.cc index 777d977e..f6446547 100644 --- a/core/src/histogram.cc +++ b/core/src/histogram.cc @@ -80,9 +80,10 @@ ClientMetric Histogram::Collect() const { return metric; } -bool Histogram::Expired(const std::time_t time, const double seconds) const { +bool Histogram::Expired(const std::chrono::system_clock::time_point& time, + const std::chrono::seconds& ttl) { (void)time; - (void)seconds; + (void)ttl; return false; } diff --git a/core/src/registry.cc b/core/src/registry.cc index f1361ee5..2240fa21 100644 --- a/core/src/registry.cc +++ b/core/src/registry.cc @@ -1,6 +1,7 @@ #include "prometheus/registry.h" #include +#include #include #include #include @@ -16,7 +17,7 @@ namespace prometheus { namespace { template void CollectAll(std::vector& results, const T& families, - const std::time_t time) { + const std::chrono::system_clock::time_point& time) { for (auto&& collectable : families) { auto metrics = collectable->Collect(time); results.insert(results.end(), std::make_move_iterator(metrics.begin()), @@ -44,11 +45,11 @@ Registry::Registry(InsertBehavior insert_behavior) Registry::~Registry() = default; std::vector Registry::Collect() const { - const auto time = std::time(nullptr); - return Collect(time); + return Collect(std::chrono::system_clock::now()); } -std::vector Registry::Collect(const std::time_t time) const { +std::vector Registry::Collect( + const std::chrono::system_clock::time_point& time) const { std::lock_guard lock{mutex_}; auto results = std::vector{}; @@ -102,7 +103,8 @@ bool Registry::NameExistsInOtherType(const std::string& name) const { template Family& Registry::Add(const std::string& name, const std::string& help, - const Labels& labels, const double seconds) { + const Labels& labels, + const std::chrono::seconds& ttl) { std::lock_guard lock{mutex_}; if (NameExistsInOtherType(name)) { @@ -135,7 +137,7 @@ Family& Registry::Add(const std::string& name, const std::string& help, throw std::invalid_argument("Family name already exists"); } - auto family = detail::make_unique>(name, help, labels, seconds); + auto family = detail::make_unique>(name, help, labels, ttl); auto& ref = *family; families.push_back(std::move(family)); return ref; @@ -143,19 +145,23 @@ Family& Registry::Add(const std::string& name, const std::string& help, template Family& Registry::Add(const std::string& name, const std::string& help, - const Labels& labels, double seconds); + const Labels& labels, + const std::chrono::seconds& ttl); template Family& Registry::Add(const std::string& name, const std::string& help, - const Labels& labels, double seconds); + const Labels& labels, + const std::chrono::seconds& ttl); template Family& Registry::Add(const std::string& name, const std::string& help, - const Labels& labels, double seconds); + const Labels& labels, + const std::chrono::seconds& ttl); template Family& Registry::Add(const std::string& name, const std::string& help, - const Labels& labels, double seconds); + const Labels& labels, + const std::chrono::seconds& ttl); template bool Registry::Remove(const Family& family) { diff --git a/core/src/summary.cc b/core/src/summary.cc index 5a698241..743ecf19 100644 --- a/core/src/summary.cc +++ b/core/src/summary.cc @@ -37,9 +37,10 @@ ClientMetric Summary::Collect() const { return metric; } -bool Summary::Expired(const std::time_t time, const double seconds) const { +bool Summary::Expired(const std::chrono::system_clock::time_point& time, + const std::chrono::seconds& ttl) { (void)time; - (void)seconds; + (void)ttl; return false; } diff --git a/core/tests/builder_test.cc b/core/tests/builder_test.cc index e3764f04..dbd0d8ab 100644 --- a/core/tests/builder_test.cc +++ b/core/tests/builder_test.cc @@ -2,10 +2,12 @@ #include #include +#include #include #include #include #include +#include #include #include @@ -64,6 +66,7 @@ TEST_F(BuilderTest, build_counter) { .Name(name) .Help(help) .Labels(const_labels) + .TTL(std::chrono::seconds::max()) .Register(registry); family.Add(more_labels); @@ -75,6 +78,7 @@ TEST_F(BuilderTest, build_gauge) { .Name(name) .Help(help) .Labels(const_labels) + .TTL(std::chrono::seconds::max()) .Register(registry); family.Add(more_labels); @@ -86,6 +90,7 @@ TEST_F(BuilderTest, build_histogram) { .Name(name) .Help(help) .Labels(const_labels) + .TTL(std::chrono::seconds::max()) .Register(registry); family.Add(more_labels, Histogram::BucketBoundaries{1, 2}); @@ -97,11 +102,41 @@ TEST_F(BuilderTest, build_summary) { .Name(name) .Help(help) .Labels(const_labels) + .TTL(std::chrono::seconds::max()) .Register(registry); family.Add(more_labels, Summary::Quantiles{}); verifyCollectedLabels(); } +TEST_F(BuilderTest, build_gauge_expired) { + auto& family = BuildGauge() + .Name(name) + .Help(help) + .Labels(const_labels) + .TTL(std::chrono::seconds(1)) + .Register(registry); + family.Add(more_labels); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + const auto collected = registry.Collect(); + ASSERT_EQ(1U, collected.size()); + EXPECT_TRUE(collected.at(0).metric.empty()); +} + +TEST_F(BuilderTest, build_gauge_not_expired) { + auto& family = BuildGauge() + .Name(name) + .Help(help) + .Labels(const_labels) + .Register(registry); + family.Add(more_labels); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + const auto collected = registry.Collect(); + ASSERT_EQ(1U, collected.size()); + EXPECT_EQ(1U, collected.at(0).metric.size()); +} + } // namespace } // namespace prometheus diff --git a/core/tests/counter_test.cc b/core/tests/counter_test.cc index 9087e9bd..a6fa1f55 100644 --- a/core/tests/counter_test.cc +++ b/core/tests/counter_test.cc @@ -2,6 +2,9 @@ #include +#include +#include + namespace prometheus { namespace { @@ -37,5 +40,13 @@ TEST(CounterTest, inc_negative_value) { EXPECT_EQ(counter.Value(), 5.0); } +TEST(CounterTest, not_expired) { + Counter counter; + counter.Increment(); + std::this_thread::sleep_for(std::chrono::seconds(1)); + EXPECT_FALSE(counter.Expired(std::chrono::system_clock::now(), + std::chrono::seconds(1))); +} + } // namespace } // namespace prometheus diff --git a/core/tests/family_test.cc b/core/tests/family_test.cc index cf18d3ac..e3a0fbac 100644 --- a/core/tests/family_test.cc +++ b/core/tests/family_test.cc @@ -3,12 +3,14 @@ #include #include -#include +#include #include +#include #include "prometheus/client_metric.h" #include "prometheus/counter.h" #include "prometheus/detail/future_std.h" +#include "prometheus/gauge.h" #include "prometheus/histogram.h" #include "prometheus/labels.h" @@ -19,10 +21,11 @@ TEST(FamilyTest, labels) { auto const_label = ClientMetric::Label{"component", "test"}; auto dynamic_label = ClientMetric::Label{"status", "200"}; - Family family{"total_requests", - "Counts all requests", - {{const_label.name, const_label.value}}, - std::numeric_limits::max()}; + Family family{ + "total_requests", + "Counts all requests", + {{const_label.name, const_label.value}}, + }; family.Add({{dynamic_label.name, dynamic_label.value}}); auto collected = family.Collect(); ASSERT_GE(collected.size(), 1U); @@ -34,16 +37,12 @@ TEST(FamilyTest, labels) { TEST(FamilyTest, reject_same_label_keys) { auto labels = Labels{{"component", "test"}}; - Family family{"total_requests", "Counts all requests", labels, - std::numeric_limits::max()}; + Family family{"total_requests", "Counts all requests", labels}; EXPECT_ANY_THROW(family.Add(labels)); } TEST(FamilyTest, counter_value) { - Family family{"total_requests", - "Counts all requests", - {}, - std::numeric_limits::max()}; + Family family{"total_requests", "Counts all requests", {}}; auto& counter = family.Add({}); counter.Increment(); auto collected = family.Collect(); @@ -53,10 +52,7 @@ TEST(FamilyTest, counter_value) { } TEST(FamilyTest, remove) { - Family family{"total_requests", - "Counts all requests", - {}, - std::numeric_limits::max()}; + Family family{"total_requests", "Counts all requests", {}}; auto& counter1 = family.Add({{"name", "counter1"}}); family.Add({{"name", "counter2"}}); family.Remove(&counter1); @@ -66,18 +62,12 @@ TEST(FamilyTest, remove) { } TEST(FamilyTest, removeUnknownMetricMustNotCrash) { - Family family{"total_requests", - "Counts all requests", - {}, - std::numeric_limits::max()}; + Family family{"total_requests", "Counts all requests", {}}; family.Remove(nullptr); } TEST(FamilyTest, Histogram) { - Family family{"request_latency", - "Latency Histogram", - {}, - std::numeric_limits::max()}; + Family family{"request_latency", "Latency Histogram", {}}; auto& histogram1 = family.Add({{"name", "histogram1"}}, Histogram::BucketBoundaries{0, 1, 2}); histogram1.Observe(0); @@ -88,10 +78,7 @@ TEST(FamilyTest, Histogram) { } TEST(FamilyTest, add_twice) { - Family family{"total_requests", - "Counts all requests", - {}, - std::numeric_limits::max()}; + Family family{"total_requests", "Counts all requests", {}}; auto& counter = family.Add({{"name", "counter1"}}); auto& counter1 = family.Add({{"name", "counter1"}}); ASSERT_EQ(&counter, &counter1); @@ -99,8 +86,7 @@ TEST(FamilyTest, add_twice) { TEST(FamilyTest, throw_on_invalid_metric_name) { auto create_family_with_invalid_name = []() { - return detail::make_unique>( - "", "empty name", Labels{}, std::numeric_limits::max()); + return detail::make_unique>("", "empty name", Labels{}); }; EXPECT_ANY_THROW(create_family_with_invalid_name()); } @@ -109,16 +95,13 @@ TEST(FamilyTest, throw_on_invalid_constant_label_name) { auto create_family_with_invalid_labels = []() { return detail::make_unique>( "total_requests", "Counts all requests", - Labels{{"__inavlid", "counter1"}}, std::numeric_limits::max()); + Labels{{"__inavlid", "counter1"}}); }; EXPECT_ANY_THROW(create_family_with_invalid_labels()); } TEST(FamilyTest, should_throw_on_invalid_labels) { - Family family{"total_requests", - "Counts all requests", - {}, - std::numeric_limits::max()}; + Family family{"total_requests", "Counts all requests", {}}; auto add_metric_with_invalid_label_name = [&family]() { family.Add({{"__invalid", "counter1"}}); }; @@ -126,23 +109,28 @@ TEST(FamilyTest, should_throw_on_invalid_labels) { } TEST(FamilyTest, should_not_collect_empty_metrics) { - Family family{"total_requests", - "Counts all requests", - {}, - std::numeric_limits::max()}; + Family family{"total_requests", "Counts all requests", {}}; auto collected = family.Collect(); EXPECT_TRUE(collected.empty()); } TEST(FamilyTest, query_family_if_metric_already_exists) { - Family family{"total_rquests", - "Counts all requests", - {}, - std::numeric_limits::max()}; + Family family{"total_rquests", "Counts all requests", {}}; family.Add({{"name", "counter1"}}); EXPECT_TRUE(family.Has({{"name", "counter1"}})); EXPECT_FALSE(family.Has({{"name", "couner2"}})); } +TEST(FamilyTest, expired_gauge) { + Family family{ + "expired", "Some expired gauge", {}, std::chrono::seconds(1)}; + auto& gauge = family.Add({}); + gauge.Increment(); + std::this_thread::sleep_for(std::chrono::seconds(1)); + auto collected = family.Collect(); + ASSERT_EQ(collected.size(), 1U); + EXPECT_TRUE(collected.at(0).metric.empty()); +} + } // namespace } // namespace prometheus diff --git a/core/tests/gauge_test.cc b/core/tests/gauge_test.cc index 690754b0..a5b37885 100644 --- a/core/tests/gauge_test.cc +++ b/core/tests/gauge_test.cc @@ -2,6 +2,9 @@ #include +#include +#include + namespace prometheus { namespace { @@ -76,5 +79,35 @@ TEST(GaugeTest, set_to_current_time) { EXPECT_GT(gauge.Value(), 0.0); } +TEST(GaugeTest, set_expired) { + Gauge gauge; + gauge.Set(1.0); + std::this_thread::sleep_for(std::chrono::seconds(1)); + EXPECT_TRUE( + gauge.Expired(std::chrono::system_clock::now(), std::chrono::seconds(1))); +} + +TEST(GaugeTest, set_not_expired) { + Gauge gauge; + gauge.Set(1.0); + EXPECT_FALSE( + gauge.Expired(std::chrono::system_clock::now(), std::chrono::seconds(1))); +} + +TEST(GaugeTest, increment_expired) { + Gauge gauge; + gauge.Increment(); + std::this_thread::sleep_for(std::chrono::seconds(1)); + EXPECT_TRUE( + gauge.Expired(std::chrono::system_clock::now(), std::chrono::seconds(1))); +} + +TEST(GaugeTest, increment_not_expired) { + Gauge gauge; + gauge.Increment(); + EXPECT_FALSE( + gauge.Expired(std::chrono::system_clock::now(), std::chrono::seconds(1))); +} + } // namespace } // namespace prometheus diff --git a/core/tests/histogram_test.cc b/core/tests/histogram_test.cc index 5b9959ae..6d6b3cb1 100644 --- a/core/tests/histogram_test.cc +++ b/core/tests/histogram_test.cc @@ -2,9 +2,11 @@ #include +#include #include #include #include +#include namespace prometheus { namespace { @@ -126,5 +128,13 @@ TEST(HistogramTest, sum_can_go_down) { EXPECT_LT(metric2.histogram.sample_sum, metric1.histogram.sample_sum); } +TEST(HistogramTest, not_expired) { + Histogram histogram{{1}}; + histogram.Observe(0); + std::this_thread::sleep_for(std::chrono::seconds(1)); + EXPECT_FALSE(histogram.Expired(std::chrono::system_clock::now(), + std::chrono::seconds(1))); +} + } // namespace } // namespace prometheus diff --git a/core/tests/registry_test.cc b/core/tests/registry_test.cc index 5b899379..994491e4 100644 --- a/core/tests/registry_test.cc +++ b/core/tests/registry_test.cc @@ -42,8 +42,7 @@ TEST(RegistryTest, build_histogram_family) { } TEST(RegistryTest, unable_to_remove_family) { - Family family{ - "name", "help", {}, std::numeric_limits::max()}; + Family family{"name", "help", {}}; Registry registry{}; EXPECT_FALSE(registry.Remove(family)); } diff --git a/core/tests/serializer_test.cc b/core/tests/serializer_test.cc index 45568f8c..ebf8fd73 100644 --- a/core/tests/serializer_test.cc +++ b/core/tests/serializer_test.cc @@ -19,8 +19,7 @@ namespace { class SerializerTest : public testing::Test { public: void SetUp() override { - Family family{ - "requests_total", "", {}, std::numeric_limits::max()}; + Family family{"requests_total", "", {}}; auto& counter = family.Add({}); counter.Increment(); diff --git a/core/tests/summary_test.cc b/core/tests/summary_test.cc index 32b1e804..813d60b4 100644 --- a/core/tests/summary_test.cc +++ b/core/tests/summary_test.cc @@ -101,5 +101,13 @@ TEST(SummaryTest, construction_with_dynamic_quantile_vector) { summary.Observe(8.0); } +TEST(SummaryTest, not_expired) { + Summary summary{Summary::Quantiles{{0.5, 0.05}}}; + summary.Observe(0); + std::this_thread::sleep_for(std::chrono::seconds(1)); + EXPECT_FALSE(summary.Expired(std::chrono::system_clock::now(), + std::chrono::seconds(1))); +} + } // namespace } // namespace prometheus