Browse Source

[1958] Added custom counters and unit tests.

Marcin Siodelski 12 years ago
parent
commit
f3a0b65d58
2 changed files with 156 additions and 1 deletions
  1. 118 1
      tests/tools/perfdhcp/stats_mgr.h
  2. 38 0
      tests/tools/perfdhcp/tests/stats_mgr_unittest.cc

+ 118 - 1
tests/tools/perfdhcp/stats_mgr.h

@@ -52,6 +52,68 @@ template <class T>
 class StatsMgr : public boost::noncopyable {
 class StatsMgr : public boost::noncopyable {
 public:
 public:
 
 
+    /// \brief Custom Counter
+    ///
+    /// This class represents custom statistics counters. Client class
+    /// may create unlimited number of counters. Such counters are
+    /// being stored in map in Statistics Manager and access using
+    /// unique string key.
+    class CustomCounter {
+    public:
+        /// \brief Constructor.
+        ///
+        /// This constructor sets counter name. This name is used in
+        /// log file to report value of each counter.
+        ///
+        /// \param name name of the counter used in log file.
+        CustomCounter(const std::string& name) :
+            counter_(0),
+            name_(name) { };
+
+        /// \brief Increment operator.
+        const CustomCounter& operator++() {
+            ++counter_;
+            return *this;
+        }
+
+        /// \brief Increment operator.
+        const CustomCounter& operator++(int) {
+            CustomCounter& this_counter(*this);
+            operator++();
+            return this_counter;
+        }
+
+        /// \brief Return counter value.
+        ///
+        /// Method returns counter value.
+        ///
+        /// \return counter value.
+        uint64_t getValue() const {
+            return counter_;
+        }
+
+        /// \brief Return counter name.
+        ///
+        /// Method returns counter name.
+        ///
+        /// \return counter name.
+        const std::string& getName() const {
+            return name_;
+        }
+    private:
+        /// \brief Default constructor.
+        ///
+        /// Default constrcutor is private because we don't want client
+        /// class to call it because we want client class to specify
+        /// counter's name.
+        CustomCounter() { };
+
+        uint64_t counter_;  ///< Counter's value.
+        std::string name_;  ///< Counter's name.
+    };
+
+    typedef typename boost::shared_ptr<CustomCounter> CustomCounterPtr;
+
     /// DHCP packet exchange types.
     /// DHCP packet exchange types.
     enum ExchangeType {
     enum ExchangeType {
         XCHG_DO,  ///< DHCPv4 DISCOVER-OFFER
         XCHG_DO,  ///< DHCPv4 DISCOVER-OFFER
@@ -431,6 +493,16 @@ public:
     typedef typename std::map<ExchangeType, ExchangeStatsPtr> ExchangesMap;
     typedef typename std::map<ExchangeType, ExchangeStatsPtr> ExchangesMap;
     /// Iterator poiting to \ref ExchangesMap
     /// Iterator poiting to \ref ExchangesMap
     typedef typename ExchangesMap::const_iterator ExchangesMapIterator;
     typedef typename ExchangesMap::const_iterator ExchangesMapIterator;
+    /// Map containing custom counters.
+    typedef typename std::map<std::string, CustomCounterPtr> CustomCountersMap;
+    /// Iterator for \ref CustomCountersMap.
+    typedef typename CustomCountersMap::iterator CustomCountersMapIterator;
+
+    /// \brief Constructor.
+    StatsMgr()
+        : exchanges_(),
+          custom_counters_() {
+    }
 
 
     /// \brief Specify new exchange type.
     /// \brief Specify new exchange type.
     ///
     ///
@@ -447,6 +519,49 @@ public:
         exchanges_[xchg_type] = ExchangeStatsPtr(new ExchangeStats(xchg_type));
         exchanges_[xchg_type] = ExchangeStatsPtr(new ExchangeStats(xchg_type));
     }
     }
 
 
+    /// \brief Add named custom uint64 counter.
+    ///
+    /// Method creates new named counter and stores in counter's map under
+    /// key specified here as short_name.
+    ///
+    /// \param short_name key to use to access counter in the map.
+    /// \param long_name name of the counter presented in the log file.
+    void addCustomCounter(const std::string& short_name,
+                          const std::string& long_name) {
+        if (custom_counters_.find(short_name) != custom_counters_.end()) {
+            isc_throw(BadValue,
+                      "Custom counter " << short_name << " already added.");
+        }
+        custom_counters_[short_name] =
+            CustomCounterPtr(new CustomCounter(long_name));
+    }
+
+    /// \brief Return specified counter.
+    ///
+    /// Method returns specified counter.
+    ///
+    /// \param counter_key key poiting to the counter in the counters map.
+    /// \return pointer to specified counter object.
+    CustomCounterPtr getCounter(const std::string& counter_key) {
+        CustomCountersMapIterator it = custom_counters_.find(counter_key);
+        if (it == custom_counters_.end()) {
+            isc_throw(BadValue,
+                      "Custom counter " << counter_key << "does not exist");
+        }
+        return it->second;
+    }
+
+    /// \brief Increment specified counter.
+    ///
+    /// Increement counter value by one.
+    ///
+    /// \param counter_key key poitinh to the counter in the counters map.
+    /// \return pointer to specified counter after incrementation.
+    const CustomCounter& IncrementCounter(const std::string& counter_key) {
+        CustomCounterPtr counter = getCounter(counter_key);
+        return ++(*counter);
+    }
+
     /// \brief Adds new packet to the sent packets list.
     /// \brief Adds new packet to the sent packets list.
     ///
     ///
     /// Method adds new packet to the sent packets list.
     /// Method adds new packet to the sent packets list.
@@ -622,6 +737,7 @@ public:
         ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
         ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
         return xchg_stats->getRcvdPacketsNum();
         return xchg_stats->getRcvdPacketsNum();
     }
     }
+
 private:
 private:
     /// \brief Return exchange stats object for given exchange type
     /// \brief Return exchange stats object for given exchange type
     ///
     ///
@@ -639,7 +755,8 @@ private:
         return xchg_stats;
         return xchg_stats;
     }
     }
 
 
-    ExchangesMap exchanges_;        ///< Map of exchange types.
+    ExchangesMap exchanges_;            ///< Map of exchange types.
+    CustomCountersMap custom_counters_; ///< Map with custom counters.
 };
 };
 
 
 } // namespace perfdhcp
 } // namespace perfdhcp

+ 38 - 0
tests/tools/perfdhcp/tests/stats_mgr_unittest.cc

@@ -324,4 +324,42 @@ TEST_F(StatsMgrTest, Delays) {
     EXPECT_GT(stats_mgr->getSquareSumDelay(StatsMgr4::XCHG_DO), 1);
     EXPECT_GT(stats_mgr->getSquareSumDelay(StatsMgr4::XCHG_DO), 1);
 }
 }
 
 
+TEST_F(StatsMgrTest, CustomCounters) {
+    boost::scoped_ptr<StatsMgr4> stats_mgr(new StatsMgr4());
+
+    // Specify counter keys and names.
+    const std::string too_short_key("tooshort");
+    const std::string too_short_name("Too short packets");
+    const std::string too_late_key("toolate");
+    const std::string too_late_name("Packets sent too late");
+
+    // Add two custom counters.
+    stats_mgr->addCustomCounter(too_short_key, too_short_name);
+    stats_mgr->addCustomCounter(too_late_key, too_late_name);
+
+    // Increment one of the counters 10 times.
+    const uint64_t tooshort_num = 10;
+    for (uint64_t i = 0; i < tooshort_num; ++i) {
+        stats_mgr->IncrementCounter(too_short_key);
+    }
+
+    // Increment another counter by 5 times.
+    const uint64_t toolate_num = 5;
+    for (uint64_t i = 0; i < toolate_num; ++i) {
+        stats_mgr->IncrementCounter(too_late_key);
+    }
+
+    // Check counter's current value and name.
+    StatsMgr4::CustomCounterPtr tooshort_counter =
+        stats_mgr->getCounter(too_short_key);
+    EXPECT_EQ(too_short_name, tooshort_counter->getName());
+    EXPECT_EQ(tooshort_num, tooshort_counter->getValue());
+
+    // Check counter's current value and name.
+    StatsMgr4::CustomCounterPtr toolate_counter =
+        stats_mgr->getCounter(too_late_key);
+    EXPECT_EQ(too_late_name, toolate_counter->getName());
+    EXPECT_EQ(toolate_num, toolate_counter->getValue());
+}
+
 }
 }