+// 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 <exceptions/exceptions.h>
+#include <stats/stats_mgr.h>
+
+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<std::string, ObservationPtr>::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<std::string, ObservationPtr>::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());
+}
+
+
+
+};
+};
class StatsMgr : public boost::noncopyable {
public:
+ /// @brief Statistics Manager accessor method.
static StatsMgr& instance();
// methods used data producers
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
/// @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();
/// @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<typename DataType>
+ 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<typename DataType>
+ 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_;