diff options
Diffstat (limited to 'src/lib/stats')
-rw-r--r-- | src/lib/stats/observation.cc | 63 | ||||
-rw-r--r-- | src/lib/stats/observation.h | 47 | ||||
-rw-r--r-- | src/lib/stats/stats_mgr.cc | 256 | ||||
-rw-r--r-- | src/lib/stats/stats_mgr.h | 16 | ||||
-rw-r--r-- | src/lib/stats/tests/observation_unittest.cc | 122 | ||||
-rw-r--r-- | src/lib/stats/testutils/stats_test_utils.h | 21 |
6 files changed, 323 insertions, 202 deletions
diff --git a/src/lib/stats/observation.cc b/src/lib/stats/observation.cc index c8e7b0f5fd..034f2b9745 100644 --- a/src/lib/stats/observation.cc +++ b/src/lib/stats/observation.cc @@ -9,12 +9,14 @@ #include <stats/observation.h> #include <util/chrono_time_utils.h> #include <cc/data.h> + #include <chrono> #include <utility> using namespace std; using namespace std::chrono; using namespace isc::data; +using namespace isc::util; namespace isc { namespace stats { @@ -33,6 +35,13 @@ Observation::Observation(const std::string& name, const int64_t value) : setValue(value); } +Observation::Observation(const std::string& name, const int128_t& value) : + name_(name), type_(STAT_BIG_INTEGER), + max_sample_count_(default_max_sample_count_), + max_sample_age_(default_max_sample_age_) { + setValue(value); +} + Observation::Observation(const std::string& name, const double value) : name_(name), type_(STAT_FLOAT), max_sample_count_(default_max_sample_count_), @@ -60,6 +69,10 @@ void Observation::setMaxSampleAge(const StatsDuration& duration) { setMaxSampleAgeInternal(integer_samples_, duration, STAT_INTEGER); return; } + case STAT_BIG_INTEGER: { + setMaxSampleAgeInternal(big_integer_samples_, duration, STAT_BIG_INTEGER); + return; + } case STAT_FLOAT: { setMaxSampleAgeInternal(float_samples_, duration, STAT_FLOAT); return; @@ -84,6 +97,10 @@ void Observation::setMaxSampleCount(uint32_t max_samples) { setMaxSampleCountInternal(integer_samples_, max_samples, STAT_INTEGER); return; } + case STAT_BIG_INTEGER: { + setMaxSampleCountInternal(big_integer_samples_, max_samples, STAT_BIG_INTEGER); + return; + } case STAT_FLOAT: { setMaxSampleCountInternal(float_samples_, max_samples, STAT_FLOAT); return; @@ -107,6 +124,11 @@ void Observation::addValue(const int64_t value) { setValue(current.first + value); } +void Observation::addValue(const int128_t& value) { + BigIntegerSample current = getBigInteger(); + setValue(current.first + value); +} + void Observation::addValue(const double value) { FloatSample current = getFloat(); setValue(current.first + value); @@ -126,6 +148,10 @@ void Observation::setValue(const int64_t value) { setValueInternal(value, integer_samples_, STAT_INTEGER); } +void Observation::setValue(const int128_t& value) { + setValueInternal(value, big_integer_samples_, STAT_BIG_INTEGER); +} + void Observation::setValue(const double value) { setValueInternal(value, float_samples_, STAT_FLOAT); } @@ -145,6 +171,10 @@ size_t Observation::getSize() const { size = getSizeInternal(integer_samples_, STAT_INTEGER); return (size); } + case STAT_BIG_INTEGER: { + size = getSizeInternal(big_integer_samples_, STAT_BIG_INTEGER); + return (size); + } case STAT_FLOAT: { size = getSizeInternal(float_samples_, STAT_FLOAT); return (size); @@ -223,6 +253,10 @@ IntegerSample Observation::getInteger() const { return (getValueInternal<IntegerSample>(integer_samples_, STAT_INTEGER)); } +BigIntegerSample Observation::getBigInteger() const { + return (getValueInternal<BigIntegerSample>(big_integer_samples_, STAT_BIG_INTEGER)); +} + FloatSample Observation::getFloat() const { return (getValueInternal<FloatSample>(float_samples_, STAT_FLOAT)); } @@ -256,6 +290,10 @@ std::list<IntegerSample> Observation::getIntegers() const { return (getValuesInternal<IntegerSample>(integer_samples_, STAT_INTEGER)); } +std::list<BigIntegerSample> Observation::getBigIntegers() const { + return (getValuesInternal<BigIntegerSample>(big_integer_samples_, STAT_BIG_INTEGER)); +} + std::list<FloatSample> Observation::getFloats() const { return (getValuesInternal<FloatSample>(float_samples_, STAT_FLOAT)); } @@ -370,6 +408,9 @@ std::string Observation::typeToText(Type type) { case STAT_INTEGER: tmp << "integer"; break; + case STAT_BIG_INTEGER: + tmp << "big integer"; + break; case STAT_FLOAT: tmp << "float"; break; @@ -414,6 +455,23 @@ Observation::getJSON() const { } break; } + case STAT_BIG_INTEGER: { + std::list<BigIntegerSample> const& samples(getBigIntegers()); + + // Iterate over all elements in the list and alternately add + // value and timestamp to the entry. + for (BigIntegerSample const& i : samples) { + entry = isc::data::Element::createList(); + value = isc::data::Element::create(i.first); + timestamp = isc::data::Element::create(isc::util::clockToText(i.second)); + + entry->add(value); + entry->add(timestamp); + + list->add(entry); + } + break; + } case STAT_FLOAT: { std::list<FloatSample> s = getFloats(); @@ -480,6 +538,11 @@ void Observation::reset() { setValue(static_cast<int64_t>(0)); return; } + case STAT_BIG_INTEGER: { + big_integer_samples_.clear(); + setValue(int128_t(0)); + return; + } case STAT_FLOAT: { float_samples_.clear(); setValue(0.0); diff --git a/src/lib/stats/observation.h b/src/lib/stats/observation.h index f1e0117ef4..883d7e7d1d 100644 --- a/src/lib/stats/observation.h +++ b/src/lib/stats/observation.h @@ -9,9 +9,13 @@ #include <cc/data.h> #include <exceptions/exceptions.h> +#include <util/bigints.h> + #include <boost/shared_ptr.hpp> + #include <chrono> #include <list> + #include <stdint.h> namespace isc { @@ -55,6 +59,9 @@ inline long toSeconds(const StatsDuration& dur) { /// @brief Integer (implemented as signed 64-bit integer) typedef std::pair<int64_t, SampleClock::time_point> IntegerSample; +/// @brief BigInteger (implemented as signed 128-bit integer) +typedef std::pair<isc::util::int128_t, SampleClock::time_point> BigIntegerSample; + /// @brief Float (implemented as double precision) typedef std::pair<double, SampleClock::time_point> FloatSample; @@ -93,10 +100,11 @@ public: /// int64_t and double. If convincing use cases appear to change them /// to something else, we may change the underlying type. enum Type { - STAT_INTEGER, ///< this statistic is unsigned 64-bit integer value - STAT_FLOAT, ///< this statistic is a floating point value - STAT_DURATION,///< this statistic represents time duration - STAT_STRING ///< this statistic represents a string + STAT_INTEGER, ///< this statistic is signed 64-bit integer value + STAT_BIG_INTEGER, ///< this statistic is signed 128-bit integer value + STAT_FLOAT, ///< this statistic is a floating point value + STAT_DURATION, ///< this statistic represents time duration + STAT_STRING ///< this statistic represents a string }; /// @brief Constructor for integer observations @@ -105,6 +113,12 @@ public: /// @param value integer value observed. Observation(const std::string& name, const int64_t value); + /// @brief Constructor for big integer observations + /// + /// @param name observation name + /// @param value integer value observed. + Observation(const std::string& name, const isc::util::int128_t& value); + /// @brief Constructor for floating point observations /// /// @param name observation name @@ -184,6 +198,12 @@ public: /// @throw InvalidStatType if statistic is not integer void setValue(const int64_t value); + /// @brief Records big integer observation + /// + /// @param value integer value observed + /// @throw InvalidStatType if statistic is not integer + void setValue(const isc::util::int128_t& value); + /// @brief Records absolute floating point observation /// /// @param value floating point value observed @@ -208,6 +228,12 @@ public: /// @throw InvalidStatType if statistic is not integer void addValue(const int64_t value); + /// @brief Records incremental integer observation + /// + /// @param value integer value observed + /// @throw InvalidStatType if statistic is not integer + void addValue(const isc::util::int128_t& value); + /// @brief Records incremental floating point observation /// /// @param value floating point value observed @@ -258,6 +284,11 @@ public: /// @throw InvalidStatType if statistic is not integer IntegerSample getInteger() const; + /// @brief Returns observed integer sample + /// @return observed sample (value + timestamp) + /// @throw InvalidStatType if statistic is not integer + BigIntegerSample getBigInteger() const; + /// @brief Returns observed float sample /// @return observed sample (value + timestamp) /// @throw InvalidStatType if statistic is not fp @@ -278,6 +309,11 @@ public: /// @throw InvalidStatType if statistic is not integer std::list<IntegerSample> getIntegers() const; + /// @brief Returns observed big-integer samples + /// @return list of observed samples (value + timestamp) + /// @throw InvalidStatType if statistic is not integer + std::list<BigIntegerSample> getBigIntegers() const; + /// @brief Returns observed float samples /// @return list of observed samples (value + timestamp) /// @throw InvalidStatType if statistic is not fp @@ -425,6 +461,9 @@ private: /// @brief Storage for integer samples std::list<IntegerSample> integer_samples_; + /// @brief Storage for big integer samples + std::list<BigIntegerSample> big_integer_samples_; + /// @brief Storage for floating point samples std::list<FloatSample> float_samples_; diff --git a/src/lib/stats/stats_mgr.cc b/src/lib/stats/stats_mgr.cc index 58b36abeed..37536d31d0 100644 --- a/src/lib/stats/stats_mgr.cc +++ b/src/lib/stats/stats_mgr.cc @@ -11,7 +11,10 @@ #include <cc/data.h> #include <cc/command_interpreter.h> #include <util/multi_threading_mgr.h> +#include <util/bigints.h> + #include <boost/make_shared.hpp> + #include <chrono> using namespace std; @@ -35,92 +38,68 @@ StatsMgr::StatsMgr() : void StatsMgr::setValue(const string& name, const int64_t value) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - setValueInternal(name, value); - } else { - setValueInternal(name, value); - } + MultiThreadingLock lock(*mutex_); + setValueInternal(name, value); +} + +void +StatsMgr::setValue(const string& name, const int128_t& value) { + MultiThreadingLock lock(*mutex_); + setValueInternal(name, value); } void StatsMgr::setValue(const string& name, const double value) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - setValueInternal(name, value); - } else { - setValueInternal(name, value); - } + MultiThreadingLock lock(*mutex_); + setValueInternal(name, value); } void StatsMgr::setValue(const string& name, const StatsDuration& value) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - setValueInternal(name, value); - } else { - setValueInternal(name, value); - } + MultiThreadingLock lock(*mutex_); + setValueInternal(name, value); } void StatsMgr::setValue(const string& name, const string& value) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - setValueInternal(name, value); - } else { - setValueInternal(name, value); - } + MultiThreadingLock lock(*mutex_); + setValueInternal(name, value); } void StatsMgr::addValue(const string& name, const int64_t value) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - addValueInternal(name, value); - } else { - addValueInternal(name, value); - } + MultiThreadingLock lock(*mutex_); + addValueInternal(name, value); +} + +void +StatsMgr::addValue(const string& name, const int128_t& value) { + MultiThreadingLock lock(*mutex_); + addValueInternal(name, value); } void StatsMgr::addValue(const string& name, const double value) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - addValueInternal(name, value); - } else { - addValueInternal(name, value); - } + MultiThreadingLock lock(*mutex_); + addValueInternal(name, value); } void StatsMgr::addValue(const string& name, const StatsDuration& value) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - addValueInternal(name, value); - } else { - addValueInternal(name, value); - } + MultiThreadingLock lock(*mutex_); + addValueInternal(name, value); } void StatsMgr::addValue(const string& name, const string& value) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - addValueInternal(name, value); - } else { - addValueInternal(name, value); - } + MultiThreadingLock lock(*mutex_); + addValueInternal(name, value); } ObservationPtr StatsMgr::getObservation(const string& name) const { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - return (getObservationInternal(name)); - } else { - return (getObservationInternal(name)); - } + MultiThreadingLock lock(*mutex_); + return (getObservationInternal(name)); } ObservationPtr @@ -132,12 +111,8 @@ StatsMgr::getObservationInternal(const string& name) const { void StatsMgr::addObservation(const ObservationPtr& stat) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - addObservationInternal(stat); - } else { - addObservationInternal(stat); - } + MultiThreadingLock lock(*mutex_); + addObservationInternal(stat); } void @@ -149,12 +124,8 @@ StatsMgr::addObservationInternal(const ObservationPtr& stat) { bool StatsMgr::deleteObservation(const string& name) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - return (deleteObservationInternal(name)); - } else { - return (deleteObservationInternal(name)); - } + MultiThreadingLock lock(*mutex_); + return (deleteObservationInternal(name)); } bool @@ -166,12 +137,8 @@ StatsMgr::deleteObservationInternal(const string& name) { bool StatsMgr::setMaxSampleAge(const string& name, const StatsDuration& duration) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - return (setMaxSampleAgeInternal(name, duration)); - } else { - return (setMaxSampleAgeInternal(name, duration)); - } + MultiThreadingLock lock(*mutex_); + return (setMaxSampleAgeInternal(name, duration)); } bool @@ -187,12 +154,8 @@ StatsMgr::setMaxSampleAgeInternal(const string& name, bool StatsMgr::setMaxSampleCount(const string& name, uint32_t max_samples) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - return (setMaxSampleCountInternal(name, max_samples)); - } else { - return (setMaxSampleCountInternal(name, max_samples)); - } + MultiThreadingLock lock(*mutex_); + return (setMaxSampleCountInternal(name, max_samples)); } bool @@ -208,12 +171,8 @@ StatsMgr::setMaxSampleCountInternal(const string& name, void StatsMgr::setMaxSampleAgeAll(const StatsDuration& duration) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - setMaxSampleAgeAllInternal(duration); - } else { - setMaxSampleAgeAllInternal(duration); - } + MultiThreadingLock lock(*mutex_); + setMaxSampleAgeAllInternal(duration); } void @@ -223,12 +182,8 @@ StatsMgr::setMaxSampleAgeAllInternal(const StatsDuration& duration) { void StatsMgr::setMaxSampleCountAll(uint32_t max_samples) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - setMaxSampleCountAllInternal(max_samples); - } else { - setMaxSampleCountAllInternal(max_samples); - } + MultiThreadingLock lock(*mutex_); + setMaxSampleCountAllInternal(max_samples); } void @@ -238,12 +193,8 @@ StatsMgr::setMaxSampleCountAllInternal(uint32_t max_samples) { void StatsMgr::setMaxSampleAgeDefault(const StatsDuration& duration) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - setMaxSampleAgeDefaultInternal(duration); - } else { - setMaxSampleAgeDefaultInternal(duration); - } + MultiThreadingLock lock(*mutex_); + setMaxSampleAgeDefaultInternal(duration); } void @@ -253,12 +204,8 @@ StatsMgr::setMaxSampleAgeDefaultInternal(const StatsDuration& duration) { void StatsMgr::setMaxSampleCountDefault(uint32_t max_samples) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - setMaxSampleCountDefaultInternal(max_samples); - } else { - setMaxSampleCountDefaultInternal(max_samples); - } + MultiThreadingLock lock(*mutex_); + setMaxSampleCountDefaultInternal(max_samples); } void @@ -268,12 +215,8 @@ StatsMgr::setMaxSampleCountDefaultInternal(uint32_t max_samples) { const StatsDuration& StatsMgr::getMaxSampleAgeDefault() const { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - return (getMaxSampleAgeDefaultInternal()); - } else { - return (getMaxSampleAgeDefaultInternal()); - } + MultiThreadingLock lock(*mutex_); + return (getMaxSampleAgeDefaultInternal()); } const StatsDuration& @@ -283,12 +226,8 @@ StatsMgr::getMaxSampleAgeDefaultInternal() const { uint32_t StatsMgr::getMaxSampleCountDefault() const { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - return (getMaxSampleCountDefaultInternal()); - } else { - return (getMaxSampleCountDefaultInternal()); - } + MultiThreadingLock lock(*mutex_); + return (getMaxSampleCountDefaultInternal()); } uint32_t @@ -298,12 +237,8 @@ StatsMgr::getMaxSampleCountDefaultInternal() const { bool StatsMgr::reset(const string& name) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - return (resetInternal(name)); - } else { - return (resetInternal(name)); - } + MultiThreadingLock lock(*mutex_); + return (resetInternal(name)); } bool @@ -318,12 +253,8 @@ StatsMgr::resetInternal(const string& name) { bool StatsMgr::del(const string& name) { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - return (delInternal(name)); - } else { - return (delInternal(name)); - } + MultiThreadingLock lock(*mutex_); + return (delInternal(name)); } bool @@ -333,12 +264,8 @@ StatsMgr::delInternal(const string& name) { void StatsMgr::removeAll() { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - removeAllInternal(); - } else { - removeAllInternal(); - } + MultiThreadingLock lock(*mutex_); + removeAllInternal(); } void @@ -348,12 +275,8 @@ StatsMgr::removeAllInternal() { ConstElementPtr StatsMgr::get(const string& name) const { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - return (getInternal(name)); - } else { - return (getInternal(name)); - } + MultiThreadingLock lock(*mutex_); + return (getInternal(name)); } ConstElementPtr @@ -368,12 +291,8 @@ StatsMgr::getInternal(const string& name) const { ConstElementPtr StatsMgr::getAll() const { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - return (getAllInternal()); - } else { - return (getAllInternal()); - } + MultiThreadingLock lock(*mutex_); + return (getAllInternal()); } ConstElementPtr @@ -383,12 +302,8 @@ StatsMgr::getAllInternal() const { void StatsMgr::resetAll() { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - resetAllInternal(); - } else { - resetAllInternal(); - } + MultiThreadingLock lock(*mutex_); + resetAllInternal(); } void @@ -398,12 +313,8 @@ StatsMgr::resetAllInternal() { size_t StatsMgr::getSize(const string& name) const { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - return (getSizeInternal(name)); - } else { - return (getSizeInternal(name)); - } + MultiThreadingLock lock(*mutex_); + return (getSizeInternal(name)); } size_t @@ -417,12 +328,8 @@ StatsMgr::getSizeInternal(const string& name) const { size_t StatsMgr::count() const { - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - return (countInternal()); - } else { - return (countInternal()); - } + MultiThreadingLock lock(*mutex_); + return (countInternal()); } size_t @@ -545,16 +452,10 @@ StatsMgr::statisticSetMaxSampleAgeAllHandler(const ConstElementPtr& params) { if (!StatsMgr::getStatDuration(params, duration, error)) { return (createAnswer(CONTROL_RESULT_ERROR, error)); } - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - StatsMgr::instance().setMaxSampleCountDefaultInternal(0); - StatsMgr::instance().setMaxSampleAgeDefaultInternal(duration); - StatsMgr::instance().setMaxSampleAgeAllInternal(duration); - } else { - StatsMgr::instance().setMaxSampleCountDefaultInternal(0); - StatsMgr::instance().setMaxSampleAgeDefaultInternal(duration); - StatsMgr::instance().setMaxSampleAgeAllInternal(duration); - } + MultiThreadingLock lock(*mutex_); + StatsMgr::instance().setMaxSampleCountDefaultInternal(0); + StatsMgr::instance().setMaxSampleAgeDefaultInternal(duration); + StatsMgr::instance().setMaxSampleAgeAllInternal(duration); return (createAnswer(CONTROL_RESULT_SUCCESS, "All statistics duration limit are set.")); } @@ -570,14 +471,9 @@ StatsMgr::statisticSetMaxSampleCountAllHandler(const ConstElementPtr& params) { error = "'max-samples' parameter must not be zero"; return (createAnswer(CONTROL_RESULT_ERROR, error)); } - if (MultiThreadingMgr::instance().getMode()) { - lock_guard<mutex> lock(*mutex_); - StatsMgr::instance().setMaxSampleCountDefaultInternal(max_samples); - StatsMgr::instance().setMaxSampleCountAllInternal(max_samples); - } else { - StatsMgr::instance().setMaxSampleCountDefaultInternal(max_samples); - StatsMgr::instance().setMaxSampleCountAllInternal(max_samples); - } + MultiThreadingLock lock(*mutex_); + StatsMgr::instance().setMaxSampleCountDefaultInternal(max_samples); + StatsMgr::instance().setMaxSampleCountAllInternal(max_samples); return (createAnswer(CONTROL_RESULT_SUCCESS, "All statistics count limit are set.")); } diff --git a/src/lib/stats/stats_mgr.h b/src/lib/stats/stats_mgr.h index 564df43976..c1e688d290 100644 --- a/src/lib/stats/stats_mgr.h +++ b/src/lib/stats/stats_mgr.h @@ -9,6 +9,8 @@ #include <stats/observation.h> #include <stats/context.h> +#include <util/bigints.h> + #include <boost/noncopyable.hpp> #include <boost/scoped_ptr.hpp> @@ -79,6 +81,13 @@ public: /// @throw InvalidStatType if statistic is not integer void setValue(const std::string& name, const int64_t value); + /// @brief Records an absolute big integer observation. + /// + /// @param name name of the observation + /// @param value integer value observed + /// @throw InvalidStatType if statistic is not integer + void setValue(const std::string& name, const isc::util::int128_t& value); + /// @brief Records absolute floating point observation. /// /// @param name name of the observation @@ -107,6 +116,13 @@ public: /// @throw InvalidStatType if statistic is not integer void addValue(const std::string& name, const int64_t value); + /// @brief Records an incremental big integer observation. + /// + /// @param name name of the observation + /// @param value integer value observed + /// @throw InvalidStatType if statistic is not integer + void addValue(const std::string& name, const isc::util::int128_t& value); + /// @brief Records incremental floating point observation. /// /// @param name name of the observation diff --git a/src/lib/stats/tests/observation_unittest.cc b/src/lib/stats/tests/observation_unittest.cc index ad1036809c..dc0a4d9826 100644 --- a/src/lib/stats/tests/observation_unittest.cc +++ b/src/lib/stats/tests/observation_unittest.cc @@ -6,10 +6,13 @@ #include <config.h> -#include <stats/observation.h> #include <exceptions/exceptions.h> +#include <stats/observation.h> #include <util/chrono_time_utils.h> +#include <util/bigints.h> + #include <boost/shared_ptr.hpp> + #include <gtest/gtest.h> #include <iostream> @@ -19,6 +22,7 @@ using namespace isc; using namespace isc::stats; +using namespace isc::util; using namespace std::chrono; namespace { @@ -51,13 +55,15 @@ public: a("alpha", static_cast<int64_t>(1234)), // integer b("beta", 12.34), // float c("gamma", dur1234), // duration - d("delta", "1234") { // string + d("delta", "1234"), // string + e("epsilon", int128_t(12e34)) { // big integer } Observation a; Observation b; Observation c; Observation d; + Observation e; }; // Basic tests for the Observation constructors. This test checks whether @@ -67,29 +73,40 @@ TEST_F(ObservationTest, constructor) { EXPECT_EQ(Observation::STAT_FLOAT, b.getType()); EXPECT_EQ(Observation::STAT_DURATION, c.getType()); EXPECT_EQ(Observation::STAT_STRING, d.getType()); + EXPECT_EQ(Observation::STAT_BIG_INTEGER, e.getType()); EXPECT_EQ(1234, a.getInteger().first); EXPECT_EQ(12.34, b.getFloat().first); EXPECT_EQ(dur1234, c.getDuration().first); EXPECT_EQ("1234", d.getString().first); + EXPECT_EQ(int128_t(12e34), e.getBigInteger().first); // Let's check that attempting to get a different type // than used will cause an exception. EXPECT_THROW(a.getFloat(), InvalidStatType); EXPECT_THROW(a.getDuration(), InvalidStatType); EXPECT_THROW(a.getString(), InvalidStatType); + EXPECT_THROW(a.getBigInteger(), InvalidStatType); EXPECT_THROW(b.getInteger(), InvalidStatType); EXPECT_THROW(b.getDuration(), InvalidStatType); EXPECT_THROW(b.getString(), InvalidStatType); + EXPECT_THROW(b.getBigInteger(), InvalidStatType); EXPECT_THROW(c.getInteger(), InvalidStatType); EXPECT_THROW(c.getFloat(), InvalidStatType); EXPECT_THROW(c.getString(), InvalidStatType); + EXPECT_THROW(c.getBigInteger(), InvalidStatType); EXPECT_THROW(d.getInteger(), InvalidStatType); EXPECT_THROW(d.getFloat(), InvalidStatType); EXPECT_THROW(d.getDuration(), InvalidStatType); + EXPECT_THROW(d.getBigInteger(), InvalidStatType); + + EXPECT_THROW(e.getInteger(), InvalidStatType); + EXPECT_THROW(e.getFloat(), InvalidStatType); + EXPECT_THROW(e.getDuration(), InvalidStatType); + EXPECT_THROW(e.getString(), InvalidStatType); } // This test checks whether it is possible to set to an absolute value for all @@ -99,30 +116,40 @@ TEST_F(ObservationTest, setValue) { EXPECT_NO_THROW(b.setValue(56e+78)); EXPECT_NO_THROW(c.setValue(dur5678)); EXPECT_NO_THROW(d.setValue("fiveSixSevenEight")); - + EXPECT_NO_THROW(e.setValue(int128_t(43e21))); EXPECT_EQ(5678, a.getInteger().first); EXPECT_EQ(56e+78, b.getFloat().first); EXPECT_EQ(dur5678, c.getDuration().first); EXPECT_EQ("fiveSixSevenEight", d.getString().first); + EXPECT_EQ(int128_t(43e21), e.getBigInteger().first); // Now check whether setting value to a different type does // throw an exception EXPECT_THROW(a.setValue(56e+78), InvalidStatType); EXPECT_THROW(a.setValue(dur5678), InvalidStatType); EXPECT_THROW(a.setValue("fiveSixSevenEight"), InvalidStatType); + EXPECT_THROW(a.setValue(int128_t(43e21)), InvalidStatType); EXPECT_THROW(b.setValue(static_cast<int64_t>(5678)), InvalidStatType); EXPECT_THROW(b.setValue(dur5678), InvalidStatType); EXPECT_THROW(b.setValue("fiveSixSevenEight"), InvalidStatType); + EXPECT_THROW(b.setValue(int128_t(43e21)), InvalidStatType); EXPECT_THROW(c.setValue(static_cast<int64_t>(5678)), InvalidStatType); EXPECT_THROW(c.setValue(56e+78), InvalidStatType); EXPECT_THROW(c.setValue("fiveSixSevenEight"), InvalidStatType); + EXPECT_THROW(c.setValue(int128_t(43e21)), InvalidStatType); EXPECT_THROW(d.setValue(static_cast<int64_t>(5678)), InvalidStatType); EXPECT_THROW(d.setValue(56e+78), InvalidStatType); EXPECT_THROW(d.setValue(dur5678), InvalidStatType); + EXPECT_THROW(d.setValue(int128_t(43e21)), InvalidStatType); + + EXPECT_THROW(e.setValue(int64_t(5678)), InvalidStatType); + EXPECT_THROW(e.setValue(56e+78), InvalidStatType); + EXPECT_THROW(e.setValue(dur5678), InvalidStatType); + EXPECT_THROW(e.setValue("fiveSixSevenEight"), InvalidStatType); } // This test checks whether it is possible to add value to existing @@ -135,16 +162,19 @@ TEST_F(ObservationTest, addValue) { EXPECT_NO_THROW(b.addValue(56.78)); EXPECT_NO_THROW(c.addValue(dur5678)); EXPECT_NO_THROW(d.addValue("fiveSixSevenEight")); + EXPECT_NO_THROW(e.addValue(int128_t(43e21))); EXPECT_EQ(6912, a.getInteger().first); EXPECT_EQ(69.12, b.getFloat().first); EXPECT_EQ(dur681012, c.getDuration().first); EXPECT_EQ("1234fiveSixSevenEight", d.getString().first); + EXPECT_EQ(int128_t(12e34) + int128_t(43e21), e.getBigInteger().first); ASSERT_EQ(a.getSize(), 2); ASSERT_EQ(b.getSize(), 2); ASSERT_EQ(c.getSize(), 2); ASSERT_EQ(d.getSize(), 2); + ASSERT_EQ(e.getSize(), 2); } // This test checks if collecting more than one sample @@ -153,37 +183,42 @@ TEST_F(ObservationTest, moreThanOne) { // Arrays of 4 types of samples int64_t int_samples[3] = {1234, 6912, 5678}; double float_samples[3] = {12.34, 69.12, 56e+78}; - StatsDuration duration_samples[3] = {dur1234, - dur681012, dur5678}; + StatsDuration duration_samples[3] = {dur1234, dur681012, dur5678}; std::string string_samples[3] = {"1234", "1234fiveSixSevenEight", "fiveSixSevenEight"}; + int128_t bigint_samples[3] = {int128_t(12e34), int128_t(12e34) + int128_t(43e21), + int128_t(43e21)}; EXPECT_NO_THROW(a.addValue(static_cast<int64_t>(5678))); EXPECT_NO_THROW(b.addValue(56.78)); EXPECT_NO_THROW(c.addValue(dur5678)); EXPECT_NO_THROW(d.addValue("fiveSixSevenEight")); + EXPECT_NO_THROW(e.addValue(int128_t(43e21))); EXPECT_NO_THROW(a.setValue(static_cast<int64_t>(5678))); EXPECT_NO_THROW(b.setValue(56e+78)); EXPECT_NO_THROW(c.setValue(dur5678)); EXPECT_NO_THROW(d.setValue("fiveSixSevenEight")); + EXPECT_NO_THROW(e.setValue(int128_t(43e21))); ASSERT_EQ(a.getSize(), 3); ASSERT_EQ(b.getSize(), 3); ASSERT_EQ(c.getSize(), 3); ASSERT_EQ(d.getSize(), 3); + ASSERT_EQ(e.getSize(), 3); ASSERT_NO_THROW(a.getIntegers()); ASSERT_NO_THROW(b.getFloats()); ASSERT_NO_THROW(c.getDurations()); ASSERT_NO_THROW(d.getStrings()); + ASSERT_NO_THROW(e.getBigIntegers()); std::list<IntegerSample> samples_int = a.getIntegers(); // List of all integer samples std::list<FloatSample> samples_float = b.getFloats(); // List of all float samples std::list<DurationSample> samples_dur = c.getDurations(); // List of all duration samples std::list<StringSample> samples_str = d.getStrings(); // List of all string samples + std::list<BigIntegerSample> samples_bigint = e.getBigIntegers(); // List of all big integer samples uint32_t i = 2; // Index pointed to the end of array of samples - for (std::list<IntegerSample>::iterator it = samples_int.begin(); it != samples_int.end(); ++it) { EXPECT_EQ(int_samples[i], static_cast<int64_t>((*it).first)); --i; @@ -203,6 +238,11 @@ TEST_F(ObservationTest, moreThanOne) { EXPECT_EQ(string_samples[i], (*it).first); --i; } + i = 2; + for (BigIntegerSample const& sample : samples_bigint) { + EXPECT_EQ(bigint_samples[i], sample.first); + --i; + } } // This test checks whether the size of storage @@ -213,27 +253,32 @@ TEST_F(ObservationTest, getSize) { ASSERT_EQ(b.getSize(), 1); ASSERT_EQ(c.getSize(), 1); ASSERT_EQ(d.getSize(), 1); + ASSERT_EQ(e.getSize(), 1); a.addValue(static_cast<int64_t>(5678)); b.addValue(56.78); c.addValue(dur5678); d.addValue("fiveSixSevenEight"); + e.addValue(int128_t(43e21)); EXPECT_NO_THROW(a.getSize()); EXPECT_NO_THROW(b.getSize()); EXPECT_NO_THROW(c.getSize()); EXPECT_NO_THROW(d.getSize()); + EXPECT_NO_THROW(e.getSize()); // Check if size of storages is equal to 2 ASSERT_EQ(a.getSize(), 2); ASSERT_EQ(b.getSize(), 2); ASSERT_EQ(c.getSize(), 2); ASSERT_EQ(d.getSize(), 2); + ASSERT_EQ(e.getSize(), 2); a.setValue(static_cast<int64_t>(5678)); b.setValue(56e+78); c.setValue(dur5678); d.setValue("fiveSixSevenEight"); + e.setValue(int128_t(43e21)); EXPECT_NO_THROW(a.getSize()); EXPECT_NO_THROW(b.getSize()); @@ -245,6 +290,7 @@ TEST_F(ObservationTest, getSize) { ASSERT_EQ(b.getSize(), 3); ASSERT_EQ(c.getSize(), 3); ASSERT_EQ(d.getSize(), 3); + ASSERT_EQ(e.getSize(), 3); } // Checks whether setting amount limits works properly @@ -279,18 +325,23 @@ TEST_F(ObservationTest, setCountLimit) { for (uint32_t i = 0; i < 21; ++i) { d.setValue(string_samples[i]); } + for (uint32_t i = 0; i < 21; ++i) { + e.setValue(int128_t(int_samples[i])); + } // Getting all 4 types of samples after inserting 21 values std::list<IntegerSample> samples_int = a.getIntegers(); std::list<FloatSample> samples_float = b.getFloats(); std::list<DurationSample> samples_duration = c.getDurations(); std::list<StringSample> samples_string = d.getStrings(); + std::list<BigIntegerSample> samples_bigint = e.getBigIntegers(); // Check if size of storages is equal to 20 ASSERT_EQ(a.getSize(), 20); ASSERT_EQ(b.getSize(), 20); ASSERT_EQ(c.getSize(), 20); ASSERT_EQ(d.getSize(), 20); + ASSERT_EQ(e.getSize(), 20); // And whether stored values are correct uint32_t i = 20; // index of the last element in array of test's samples @@ -313,23 +364,31 @@ TEST_F(ObservationTest, setCountLimit) { EXPECT_EQ((*it).first, string_samples[i]); --i; } + i = 20; // index of last element in array of test's samples + for (BigIntegerSample const& sample : samples_bigint) { + EXPECT_EQ(sample.first, int_samples[i]); + --i; + } // Change size of storage to smaller one ASSERT_NO_THROW(a.setMaxSampleCount(10)); ASSERT_NO_THROW(b.setMaxSampleCount(10)); ASSERT_NO_THROW(c.setMaxSampleCount(10)); ASSERT_NO_THROW(d.setMaxSampleCount(10)); + ASSERT_NO_THROW(e.setMaxSampleCount(10)); samples_int = a.getIntegers(); samples_float = b.getFloats(); samples_duration = c.getDurations(); samples_string = d.getStrings(); + samples_bigint = e.getBigIntegers(); // Check if size of storages is equal to 10 ASSERT_EQ(a.getSize(), 10); ASSERT_EQ(b.getSize(), 10); ASSERT_EQ(c.getSize(), 10); ASSERT_EQ(d.getSize(), 10); + ASSERT_EQ(e.getSize(), 10); // And whether storages contain only the 10 newest values i = 20; // index of last element in array of test's samples @@ -352,34 +411,44 @@ TEST_F(ObservationTest, setCountLimit) { EXPECT_EQ((*it).first, string_samples[i]); --i; } + i = 20; // index of last element in array of test's samples + for (BigIntegerSample const& sample : samples_bigint) { + EXPECT_EQ(sample.first, int_samples[i]); + --i; + } // Resize max_sample_count to greater ASSERT_NO_THROW(a.setMaxSampleCount(50)); ASSERT_NO_THROW(b.setMaxSampleCount(50)); ASSERT_NO_THROW(c.setMaxSampleCount(50)); ASSERT_NO_THROW(d.setMaxSampleCount(50)); + ASSERT_NO_THROW(e.setMaxSampleCount(50)); // Check if size of storages did not change without adding new value ASSERT_EQ(a.getSize(), 10); ASSERT_EQ(b.getSize(), 10); ASSERT_EQ(c.getSize(), 10); ASSERT_EQ(d.getSize(), 10); + ASSERT_EQ(e.getSize(), 10); // Add new values to each type of Observation a.setValue(static_cast<int64_t>(21)); b.setValue(21.0); c.setValue(milliseconds(21)); d.setValue("v"); + e.setValue(int128_t(21)); samples_int = a.getIntegers(); samples_float = b.getFloats(); samples_duration = c.getDurations(); samples_string = d.getStrings(); + samples_bigint = e.getBigIntegers(); ASSERT_EQ(a.getSize(), 11); ASSERT_EQ(b.getSize(), 11); ASSERT_EQ(c.getSize(), 11); ASSERT_EQ(d.getSize(), 11); + ASSERT_EQ(e.getSize(), 11); i = 21; // index of last element in array of test's samples for (std::list<IntegerSample>::iterator it = samples_int.begin(); it != samples_int.end(); ++it) { @@ -401,7 +470,11 @@ TEST_F(ObservationTest, setCountLimit) { EXPECT_EQ((*it).first, string_samples[i]); --i; } - + i = 21; // index of last element in array of test's samples + for (BigIntegerSample const& sample : samples_bigint) { + EXPECT_EQ(sample.first, int_samples[i]); + --i; + } } // Checks whether setting age limits works properly @@ -451,42 +524,50 @@ TEST_F(ObservationTest, getLimits) { EXPECT_EQ(b.getMaxSampleAge().first, false); EXPECT_EQ(c.getMaxSampleAge().first, false); EXPECT_EQ(d.getMaxSampleAge().first, false); + EXPECT_EQ(e.getMaxSampleAge().first, false); EXPECT_EQ(a.getMaxSampleCount().first, true); EXPECT_EQ(b.getMaxSampleCount().first, true); EXPECT_EQ(c.getMaxSampleCount().first, true); EXPECT_EQ(d.getMaxSampleCount().first, true); + EXPECT_EQ(e.getMaxSampleCount().first, true); EXPECT_EQ(a.getMaxSampleCount().second, 20); EXPECT_EQ(b.getMaxSampleCount().second, 20); EXPECT_EQ(c.getMaxSampleCount().second, 20); EXPECT_EQ(d.getMaxSampleCount().second, 20); + EXPECT_EQ(e.getMaxSampleCount().second, 20); // change limit to time duration ASSERT_NO_THROW(a.setMaxSampleAge(dur453)); ASSERT_NO_THROW(b.setMaxSampleAge(dur453)); ASSERT_NO_THROW(c.setMaxSampleAge(dur453)); ASSERT_NO_THROW(d.setMaxSampleAge(dur453)); + ASSERT_NO_THROW(e.setMaxSampleAge(dur453)); EXPECT_EQ(a.getMaxSampleAge().first, true); EXPECT_EQ(b.getMaxSampleAge().first, true); EXPECT_EQ(c.getMaxSampleAge().first, true); EXPECT_EQ(d.getMaxSampleAge().first, true); + EXPECT_EQ(e.getMaxSampleAge().first, true); EXPECT_EQ(a.getMaxSampleAge().second, dur453); EXPECT_EQ(b.getMaxSampleAge().second, dur453); EXPECT_EQ(c.getMaxSampleAge().second, dur453); EXPECT_EQ(d.getMaxSampleAge().second, dur453); + EXPECT_EQ(e.getMaxSampleAge().second, dur453); EXPECT_EQ(a.getMaxSampleCount().first, false); EXPECT_EQ(b.getMaxSampleCount().first, false); EXPECT_EQ(c.getMaxSampleCount().first, false); EXPECT_EQ(d.getMaxSampleCount().first, false); + EXPECT_EQ(e.getMaxSampleCount().first, false); EXPECT_EQ(a.getMaxSampleCount().second, 20); EXPECT_EQ(b.getMaxSampleCount().second, 20); EXPECT_EQ(c.getMaxSampleCount().second, 20); EXPECT_EQ(d.getMaxSampleCount().second, 20); + EXPECT_EQ(e.getMaxSampleCount().second, 20); } // limit defaults are tested with StatsMgr. @@ -525,7 +606,6 @@ TEST_F(ObservationTest, integerToJSON) { std::string exp = "[ [ 1234, \"" + isc::util::clockToText(a.getInteger().second) + "\" ]" + first_sample; - std::cout << a.getJSON()->str() << std::endl; EXPECT_EQ(exp, a.getJSON()->str()); } @@ -546,7 +626,6 @@ TEST_F(ObservationTest, floatToJSON) { std::string exp = "[ [ 1234.5, \"" + isc::util::clockToText(b.getFloat().second) + "\" ]" + first_sample; - std::cout << b.getJSON()->str() << std::endl; EXPECT_EQ(exp, b.getJSON()->str()); } @@ -564,7 +643,6 @@ TEST_F(ObservationTest, durationToJSON) { std::string exp = "[ [ \"01:02:03.004000\", \"" + isc::util::clockToText(c.getDuration().second) + "\" ]" + first_sample; - std::cout << c.getJSON()->str() << std::endl; EXPECT_EQ(exp, c.getJSON()->str()); } @@ -581,31 +659,50 @@ TEST_F(ObservationTest, stringToJSON) { std::string exp = "[ [ \"Lorem ipsum dolor sit amet\", \"" + isc::util::clockToText(d.getString().second) + "\" ]" + first_sample; - std::cout << d.getJSON()->str() << std::endl; EXPECT_EQ(exp, d.getJSON()->str()); } +// Checks whether a big integer statistic can generate proper JSON structures. +// See https://gitlab.isc.org/isc-projects/kea/wikis/designs/Stats-design +// for details. +TEST_F(ObservationTest, bigIntegerToJSON) { + // String which contains first added sample + std::string first_sample = ", [ 120000000000000007304085773727301632, \"" + + isc::util::clockToText(e.getBigInteger().second) + "\" ] ]"; + + e.setValue(int128_t(43e21)); + + std::string exp = "[ [ 43000000000000002097152, \"" + + isc::util::clockToText(e.getBigInteger().second) + "\" ]" + first_sample; + + EXPECT_EQ(exp, e.getJSON()->str()); +} + // Checks whether reset() resets the statistics properly. TEST_F(ObservationTest, reset) { EXPECT_NO_THROW(a.addValue(static_cast<int64_t>(5678))); EXPECT_NO_THROW(b.addValue(56.78)); EXPECT_NO_THROW(c.addValue(dur5678)); EXPECT_NO_THROW(d.addValue("fiveSixSevenEight")); + EXPECT_NO_THROW(e.addValue(int128_t(43e21))); a.reset(); // integer b.reset(); // float c.reset(); // duration d.reset(); // string + e.reset(); // big integer EXPECT_EQ(0, a.getInteger().first); EXPECT_EQ(0.0, b.getFloat().first); EXPECT_EQ(StatsDuration::zero(), c.getDuration().first); EXPECT_EQ("", d.getString().first); + EXPECT_EQ(0, e.getBigInteger().first); ASSERT_EQ(a.getSize(), 1); ASSERT_EQ(b.getSize(), 1); ASSERT_EQ(c.getSize(), 1); ASSERT_EQ(d.getSize(), 1); + ASSERT_EQ(e.getSize(), 1); } // Checks whether an observation can keep its name. @@ -614,6 +711,7 @@ TEST_F(ObservationTest, names) { EXPECT_EQ("beta", b.getName()); EXPECT_EQ("gamma", c.getName()); EXPECT_EQ("delta", d.getName()); + EXPECT_EQ("epsilon", e.getName()); } -} +} // namespace diff --git a/src/lib/stats/testutils/stats_test_utils.h b/src/lib/stats/testutils/stats_test_utils.h index 808dced39a..cad71a35d1 100644 --- a/src/lib/stats/testutils/stats_test_utils.h +++ b/src/lib/stats/testutils/stats_test_utils.h @@ -27,12 +27,21 @@ typedef std::map<std::string, int64_t> StatMap; /// /// @param name StatsMgr name for the statistic to check. /// @param expected_value expected value of the statistic. -inline void checkStat(const std::string& name, const int64_t expected_value) { - using namespace isc::stats; - ObservationPtr obs = StatsMgr::instance().getObservation(name); - ASSERT_TRUE(obs) << " stat: " << name << " not found "; - ASSERT_EQ(expected_value, obs->getInteger().first) - << " stat: " << name << " value wrong"; +inline void checkStat(const std::string& name, + const isc::util::int128_t expected_value) { + ObservationPtr const obs(isc::stats::StatsMgr::instance().getObservation(name)); + + ASSERT_TRUE(obs) << "stat " << name << " not found "; + if (obs->getType() == Observation::STAT_INTEGER) { + EXPECT_EQ(expected_value, obs->getInteger().first) + << " wrong value for stat " << name; + } else if (obs->getType() == Observation::STAT_BIG_INTEGER) { + EXPECT_EQ(expected_value, obs->getBigInteger().first) + << " wrong value for stat " << name; + } else { + GTEST_FAIL() << "unexpected statistic type: " + << Observation::typeToText(obs->getType()); + } } /// @brief Check if a statistic does not exists. |