From 2b01685208ba584a5ff3f324a19ab923ae26ebe8 Mon Sep 17 00:00:00 2001 From: Tomek Mrugalski Date: Fri, 8 May 2015 16:27:16 +0200 Subject: [PATCH] [3793] StatsMgr implementation added. --- src/lib/stats/stats_mgr.cc | 148 +++++++++++++++++++++++++++++++++++++ src/lib/stats/stats_mgr.h | 64 +++++++++++++--- 2 files changed, 202 insertions(+), 10 deletions(-) diff --git a/src/lib/stats/stats_mgr.cc b/src/lib/stats/stats_mgr.cc index e69de29bb2..e9730b2c97 100644 --- a/src/lib/stats/stats_mgr.cc +++ b/src/lib/stats/stats_mgr.cc @@ -0,0 +1,148 @@ +// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +#include +#include + +using namespace std; + +namespace isc { +namespace stats { + +StatsMgr& StatsMgr::instance() { + static StatsMgr stats_mgr; + return (stats_mgr); +} + +StatsMgr::StatsMgr() + :global_(new StatContext()) { + +} + +void StatsMgr::setValue(const std::string& name, uint64_t value) { + setValueInternal(name, value); +} + +void StatsMgr::setValue(const std::string& name, double value) { + setValueInternal(name, value); +} + +void StatsMgr::setValue(const std::string& name, StatsDuration value) { + setValueInternal(name, value); +} +void StatsMgr::setValue(const std::string& name, const std::string& value) { + setValueInternal(name, value); +} + +void StatsMgr::addValue(const std::string& name, uint64_t value) { + addValueInternal(name, value); +} + +void StatsMgr::addValue(const std::string& name, double value) { + addValueInternal(name, value); +} + +void StatsMgr::addValue(const std::string& name, StatsDuration value) { + addValueInternal(name, value); +} + +void StatsMgr::addValue(const std::string& name, const std::string& value) { + addValueInternal(name, value); +} + +ObservationPtr StatsMgr::getObservation(const std::string& name) const { + /// @todo: Implement contexts. + // Currently we keep everyting is a global context. + return (global_->get(name)); +} + +void StatsMgr::addObservation(const ObservationPtr& stat) { + /// @todo: Implement contexts. + // Currently we keep everyting is a global context. + return (global_->add(stat)); +} + +bool StatsMgr::deleteObservation(const std::string& name) { + /// @todo: Implement contexts. + // Currently we keep everyting is a global context. + return (global_->del(name)); +} + +void StatsMgr::setMaxSampleAge(const std::string& , + boost::posix_time::time_duration) { + isc_throw(NotImplemented, "setMaxSampleAge not implemented"); +} + +void StatsMgr::setMaxSampleCount(const std::string& , uint32_t){ + isc_throw(NotImplemented, "setMaxSampleCount not implemented"); +} + +bool StatsMgr::reset(const std::string& name) { + ObservationPtr obs = getObservation(name); + if (obs) { + obs->reset(); + return (true); + } else { + return (false); + } +} + +bool StatsMgr::del(const std::string& name) { + return (global_->del(name)); +} + +void StatsMgr::removeAll() { + global_->stats_.clear(); +} + +isc::data::ConstElementPtr StatsMgr::get(const std::string& name) const { + isc::data::ElementPtr response = isc::data::Element::createMap(); // a map + ObservationPtr obs = getObservation(name); + if (obs) { + response->set(name, obs->getJSON()); // that contains the observation + } + return (response); +} + +isc::data::ConstElementPtr StatsMgr::getAll() const { + isc::data::ElementPtr map = isc::data::Element::createMap(); // a map + + // Let's iterate over all stored statistics... + for (std::map::iterator s = global_->stats_.begin(); + s != global_->stats_.end(); ++s) { + + // ... and add each of them to the map. + map->set(s->first, s->second->getJSON()); + } + return (map); +} + +void StatsMgr::resetAll() { + // Let's iterate over all stored statistics... + for (std::map::iterator s = global_->stats_.begin(); + s != global_->stats_.end(); ++s) { + + // ... and reset each statistic. + s->second->reset(); + } +} + +size_t StatsMgr::count() const { + return (global_->stats_.size()); +} + + + +}; +}; diff --git a/src/lib/stats/stats_mgr.h b/src/lib/stats/stats_mgr.h index 7319bbbcd4..f1ab7f109f 100644 --- a/src/lib/stats/stats_mgr.h +++ b/src/lib/stats/stats_mgr.h @@ -29,6 +29,7 @@ namespace stats { class StatsMgr : public boost::noncopyable { public: + /// @brief Statistics Manager accessor method. static StatsMgr& instance(); // methods used data producers @@ -36,9 +37,9 @@ class StatsMgr : public boost::noncopyable { void addValue(const std::string& name, double value); void addValue(const std::string& name, StatsDuration time); void addValue(const std::string& name, const std::string& value); - void setValue(const std::string& name, uint64_t value = 1); - void setValue(const std::string& name, double value = 1.0f); - void setValue(const std::string& name, StatsDuration time); + void setValue(const std::string& name, uint64_t value); + void setValue(const std::string& name, double value); + void setValue(const std::string& name, StatsDuration value); void setValue(const std::string& name, const std::string& value); /// @brief determines whether a given statistic is kept as a single value @@ -83,7 +84,7 @@ class StatsMgr : public boost::noncopyable { /// @brief Removes specified statistic. /// @param name name of the statistic to be removed. /// @return true if successful, false if there's no such statistic - bool remove(const std::string& name); + bool del(const std::string& name); /// @brief Resets all collected statistics back to zero. void resetAll(); @@ -93,26 +94,69 @@ class StatsMgr : public boost::noncopyable { /// @brief Returns number of available statistics. /// @return number of recorded statistics. - size_t count(); + size_t count() const; /// @brief Returns a single statistic as a JSON structure /// @return JSON structures representing a single statistic - isc::data::ConstElementPtr get(const std::string& name); + isc::data::ConstElementPtr get(const std::string& name) const; /// @brief Returns all statistics as a JSON structure /// @return JSON structures representing all statistics - isc::data::ConstElementPtr getAll(); + isc::data::ConstElementPtr getAll() const; /// @brief Returns an observation /// /// Used in testing only. Production code should use @ref get() method. /// @param name name of the statistic /// @return Pointer to the Observation object - ObservationPtr getObservation(const std::string& name); + ObservationPtr getObservation(const std::string& name) const; private: - /// @brief returns a context for specified name - StatContextPtr getContext(const std::string& name); + + template + void setValueInternal(const std::string& name, DataType value) { + ObservationPtr stat = getObservation(name); + if (stat) { + stat->setValue(value); + } else { + stat.reset(new Observation(name, value)); + addObservation(stat); + } + } + + template + void addValueInternal(const std::string& name, DataType value) { + ObservationPtr existing = getObservation(name); + if (!existing) { + // We tried to add to a non-existing statistic. We can recover from + // that. Simply add the new incremental value as a new statistic and + // we're done. + setValue(name, value); + return; + } else { + // Let's hope it is of correct type. If not, the underlying + // addValue() method will throw. + existing->addValue(value); + } + } + + /// @brief Private constructor + /// StatsMgr is a singleton. It should be accessed using @ref instance + /// method. + StatsMgr(); + + /// @brief Adds a new observation + /// + /// That's an utility method used by public @ref setValue() and + /// @ref addValue() methods. + /// @param obs observation + void addObservation(const ObservationPtr& o); + + /// @brief Tries to delete an observation + /// + /// @param name of the statistic to be deleted + /// @return true if deleted, false if not found + bool deleteObservation(const std::string& name); // This is a global context. All stats will initially be stored here. StatContextPtr global_; -- GitLab