diff options
author | Tomek Mrugalski <tomasz@isc.org> | 2015-05-07 19:41:22 +0200 |
---|---|---|
committer | Tomek Mrugalski <tomasz@isc.org> | 2015-05-07 19:41:22 +0200 |
commit | e76178c19ed93ee4171d075db11df5721eea599a (patch) | |
tree | a3ea4fd23e0cbac7c50df89df618d68f7d063858 /src/lib/stats | |
parent | [3793] Observation class + unittests, skeleton impl of StatsMgr (diff) | |
download | kea-e76178c19ed93ee4171d075db11df5721eea599a.tar.xz kea-e76178c19ed93ee4171d075db11df5721eea599a.zip |
[3793] Remaining features in Observation implemented.
Diffstat (limited to 'src/lib/stats')
-rw-r--r-- | src/lib/stats/observation.cc | 29 | ||||
-rw-r--r-- | src/lib/stats/observation.h | 93 | ||||
-rw-r--r-- | src/lib/stats/tests/observation_unittest.cc | 68 |
3 files changed, 104 insertions, 86 deletions
diff --git a/src/lib/stats/observation.cc b/src/lib/stats/observation.cc index 72bd1559ce..019120200f 100644 --- a/src/lib/stats/observation.cc +++ b/src/lib/stats/observation.cc @@ -1,4 +1,3 @@ - #include <boost/date_time/posix_time/posix_time.hpp> #include <stats/observation.h> #include <cc/data.h> @@ -11,23 +10,23 @@ using namespace boost::posix_time; namespace isc { namespace stats { -Observation::Observation(uint64_t value) - :type_(STAT_INTEGER), max_samples_(1) { +Observation::Observation(const std::string& name, uint64_t value) + :name_(name), type_(STAT_INTEGER) { setValue(value); } -Observation::Observation(double value) - :type_(STAT_FLOAT), max_samples_(1) { +Observation::Observation(const std::string& name, double value) + :name_(name), type_(STAT_FLOAT) { setValue(value); } -Observation::Observation(StatsDuration value) - :type_(STAT_DURATION), max_samples_(1) { +Observation::Observation(const std::string& name, StatsDuration value) + :name_(name), type_(STAT_DURATION) { setValue(value); } -Observation::Observation(const std::string& value) - :type_(STAT_STRING), max_samples_(1) { +Observation::Observation(const std::string& name, const std::string& value) + :name_(name), type_(STAT_STRING) { setValue(value); } @@ -158,10 +157,13 @@ Observation::durationToText(StatsDuration dur) { isc::data::ConstElementPtr Observation::getJSON() { - ElementPtr list = isc::data::Element::createList(); + ElementPtr entry = isc::data::Element::createList(); // a single observation ElementPtr value; ElementPtr timestamp; + /// @todo: Add support for retrieving more than one sample for a given + /// observation + switch (type_) { case STAT_INTEGER: { IntegerSample s = getInteger(); @@ -191,8 +193,11 @@ Observation::getJSON() { isc_throw(InvalidStatType, "Unknown stat type: " << typeToText(type_)); }; - list->add(value); - list->add(timestamp); + entry->add(value); + entry->add(timestamp); + + ElementPtr list = isc::data::Element::createList(); // a single observation + list->add(entry); return (list); } diff --git a/src/lib/stats/observation.h b/src/lib/stats/observation.h index a3a3bf733c..9328ceb3c5 100644 --- a/src/lib/stats/observation.h +++ b/src/lib/stats/observation.h @@ -41,7 +41,7 @@ public: /// implementations: boost::posix_time::{hours,minutes,seconds,millisec,nanosec}. /// For statistics purposes, the most appropriate choice seems to be milliseconds /// precision, so we'll stick with that. -typedef boost::posix_time::millisec::time_duration StatsDuration; +typedef boost::posix_time::microsec::time_duration StatsDuration; /// @defgroup stat_samples Specifies supported observation types. /// @@ -99,23 +99,27 @@ class Observation { /// @brief Constructor for integer observations /// + /// @param name observation name /// @param value integer value observed. - Observation(uint64_t value); + Observation(const std::string& name, uint64_t value); /// @brief Constructor for floating point observations /// + /// @param name observation name /// @param value floating point value observed. - Observation(double value); + Observation(const std::string& name, double value); /// @brief Constructor for duration observations /// + /// @param name observation name /// @param value duration observed. - Observation(StatsDuration value); + Observation(const std::string& name, StatsDuration value); /// @brief Constructor for string observations /// + /// @param name observation name /// @param value string observed. - Observation(const std::string& value); + Observation(const std::string& name, const std::string& value); /// @brief Records absolute integer observation /// @@ -178,65 +182,102 @@ class Observation { /// @brief Returns observed integer sample /// @return observed sample (value + timestamp) + /// @throw InvalidStatType if statistic is not integer IntegerSample getInteger(); /// @brief Returns observed float sample /// @return observed sample (value + timestamp) + /// @throw InvalidStatType if statistic is not fp FloatSample getFloat(); /// @brief Returns observed duration sample /// @return observed sample (value + timestamp) + /// @throw InvalidStatType if statistic is not time duration DurationSample getDuration(); /// @brief Returns observed string sample /// @return observed sample (value + timestamp) + /// @throw InvalidStatType if statistic is not a string StringSample getString(); - const std::list<IntegerSample>& getIntegerList() { - return (integer_samples_); - } - - const std::list<FloatSample>& getFloatList() { - return (float_samples_); - } - - const std::list<DurationSample>& getDurationList() { - return (duration_samples_); - } - - const std::list<StringSample>& getStringList() { - return (string_samples_); - } - - /// Returns as a JSON structure + /// @brief Returns as a JSON structure + /// @return JSON structures representing all observations isc::data::ConstElementPtr getJSON(); + /// @brief Converts statistic type to string + /// @return textual name of statistic type static std::string typeToText(Type type); + /// @brief Converts ptime structure to text + /// @return a string representing time static std::string ptimeToText(boost::posix_time::ptime time); + /// @brief Converts StatsDuration to text + /// @return a string representing time static std::string durationToText(StatsDuration dur); + /// @brief Returns observation name + std::string getName() { + return (name_); + } + protected: + /// @brief Records absolute sample (internal version) + /// + /// This method records an absolute value of an observation. + /// It is used by public methods to add sample to one of + /// available storages. + /// + /// @tparam SampleType type of sample (e.g. IntegerSample) + /// @tparam StorageType type of storage (e.g. list<IntegerSample>) + /// @param value observation to be recorded + /// @param storage observation will be stored here + /// @param exp_type expected observation type (used for sanity checking) + /// @throw InvalidStatType if observation type mismatches template<typename SampleType, typename StorageType> - void setValueInternal(SampleType value, StorageType& storage, - Type exp_type); + void setValueInternal(SampleType value, StorageType& storage, + Type exp_type); + /// @brief Returns a sample + /// + /// @tparam SampleType type of sample (e.g. IntegerSample) + /// @tparam StorageType type of storage (e.g. list<IntegerSample>) + /// @param observation storage + /// @param exp_type expected observation type (used for sanity checking) + /// @throw InvalidStatType if observation type mismatches + /// @return Observed sample template<typename SampleType, typename Storage> SampleType getValueInternal(Storage& storage, Type exp_type); + /// @brief Observation (statistic) name std::string name_; + + /// @brief Observation (statistic) type) Type type_; - size_t max_samples_; + /// @defgroup samples_storage Storage for supported observations + /// + /// @brief The following containers serve as a storage for all supported + /// observation types. + /// + /// @{ + /// @brief Storage for integer samples std::list<IntegerSample> integer_samples_; + + /// @brief Storage for floating point samples std::list<FloatSample> float_samples_; + + /// @brief Storage for time duration samples std::list<DurationSample> duration_samples_; + + /// @brief Storage for string samples std::list<StringSample> string_samples_; + /// @} }; - typedef boost::shared_ptr<Observation> ObservationPtr; +/// @brief Observation pointer +typedef boost::shared_ptr<Observation> ObservationPtr; }; }; diff --git a/src/lib/stats/tests/observation_unittest.cc b/src/lib/stats/tests/observation_unittest.cc index 32c3a86c64..c6d192a181 100644 --- a/src/lib/stats/tests/observation_unittest.cc +++ b/src/lib/stats/tests/observation_unittest.cc @@ -35,10 +35,10 @@ namespace { class ObservationTest : public ::testing::Test { public: ObservationTest() - :a(static_cast<uint64_t>(1234)), // integer - b(12.34), // float - c(millisec::time_duration(1,2,3,4)), // duration - d("1234") { // string + :a("alpha", static_cast<uint64_t>(1234)), // integer + b("beta", 12.34), // float + c("gamma", millisec::time_duration(1,2,3,4)), // duration + d("delta", "1234") { // string } Observation a; @@ -135,42 +135,6 @@ TEST_F(ObservationTest, addValue) { EXPECT_EQ("1234fiveSixSevenEight", d.getString().first); } -// Observation will be extended to cover multiple samples of the same -// property. That is not implemented for now, so regardless of the -// number of recorded observation, always the last one is kept. -TEST_F(ObservationTest, getLists) { - - // Let's record some data! - for (int i = 0; i <= 42; ++i) { - - a.setValue(static_cast<uint64_t>(i)); - b.setValue(0.25*i); - c.setValue(millisec::time_duration(0,0,i,0)); - - std::stringstream tmp; - tmp << i; - d.setValue(tmp.str()); - } - - // Get the lists. - std::list<IntegerSample> int_list = a.getIntegerList(); - std::list<FloatSample> float_list = b.getFloatList(); - std::list<DurationSample> dur_list = c.getDurationList(); - std::list<StringSample> str_list = d.getStringList(); - - // Check that they have only one observation. - ASSERT_EQ(1, int_list.size()); - ASSERT_EQ(1, float_list.size()); - ASSERT_EQ(1, dur_list.size()); - ASSERT_EQ(1, str_list.size()); - - // Now check that that the recorded value is correct. - EXPECT_EQ(42, int_list.begin()->first); - EXPECT_EQ(10.5, float_list.begin()->first); - EXPECT_EQ(millisec::time_duration(0,0,42,0), dur_list.begin()->first); - EXPECT_EQ("42", str_list.begin()->first); -} - // Test checks whether timing is reported properly. TEST_F(ObservationTest, timers) { ptime min = microsec_clock::local_time(); @@ -197,8 +161,8 @@ TEST_F(ObservationTest, integerToJSON) { a.setValue(static_cast<uint64_t>(1234)); - std::string exp = "[ 1234, \"" - + Observation::ptimeToText(a.getInteger().second) + "\" ]"; + std::string exp = "[ [ 1234, \"" + + Observation::ptimeToText(a.getInteger().second) + "\" ] ]"; std::cout << a.getJSON()->str() << std::endl; EXPECT_EQ(exp, a.getJSON()->str()); @@ -212,8 +176,8 @@ TEST_F(ObservationTest, floatToJSON) { // No need to deal with infinite fractions in binary systems. b.setValue(1234.5); - std::string exp = "[ 1234.5, \"" - + Observation::ptimeToText(b.getFloat().second) + "\" ]"; + std::string exp = "[ [ 1234.5, \"" + + Observation::ptimeToText(b.getFloat().second) + "\" ] ]"; std::cout << b.getJSON()->str() << std::endl; EXPECT_EQ(exp, b.getJSON()->str()); @@ -226,8 +190,8 @@ TEST_F(ObservationTest, durationToJSON) { // 1 hour 2 minutes 3 seconds and 4 milliseconds c.setValue(time_duration(1,2,3,4)); - std::string exp = "[ \"01:02:03.000004\", \"" - + Observation::ptimeToText(c.getDuration().second) + "\" ]"; + std::string exp = "[ [ \"01:02:03.000004\", \"" + + Observation::ptimeToText(c.getDuration().second) + "\" ] ]"; std::cout << c.getJSON()->str() << std::endl; EXPECT_EQ(exp, c.getJSON()->str()); @@ -240,8 +204,8 @@ TEST_F(ObservationTest, stringToJSON) { // d.setValue("Lorem ipsum dolor sit amet"); - std::string exp = "[ \"Lorem ipsum dolor sit amet\", \"" - + Observation::ptimeToText(d.getString().second) + "\" ]"; + std::string exp = "[ [ \"Lorem ipsum dolor sit amet\", \"" + + Observation::ptimeToText(d.getString().second) + "\" ] ]"; std::cout << d.getJSON()->str() << std::endl; EXPECT_EQ(exp, d.getJSON()->str()); @@ -260,4 +224,12 @@ TEST_F(ObservationTest, reset) { EXPECT_EQ("", d.getString().first); } +// Checks whether an observation can keep its name. +TEST_F(ObservationTest, names) { + EXPECT_EQ("alpha", a.getName()); + EXPECT_EQ("beta", b.getName()); + EXPECT_EQ("gamma", c.getName()); + EXPECT_EQ("delta", d.getName()); +} + }; |