added data() member in StatisticsBase class to directly get a senf::StatisticsData
[senf.git] / senf / Utils / Statistics.hh
index 6409ab1..cdea0da 100644 (file)
@@ -1,24 +1,29 @@
 // $Id$
 //
-// Copyright (C) 2008 
+// Copyright (C) 2008
 // Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-//     Stefan Bund <g0dil@berlios.de>
 //
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
+// The contents of this file are subject to the Fraunhofer FOKUS Public License
+// Version 1.0 (the "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at 
+// http://senf.berlios.de/license.html
 //
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// The Fraunhofer FOKUS Public License Version 1.0 is based on, 
+// but modifies the Mozilla Public License Version 1.1.
+// See the full license text for the amendments.
 //
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// Software distributed under the License is distributed on an "AS IS" basis, 
+// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
+// for the specific language governing rights and limitations under the License.
+//
+// The Original Code is Fraunhofer FOKUS code.
+//
+// The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
+// (registered association), Hansastraße 27 c, 80686 Munich, Germany.
+// All Rights Reserved.
+//
+// Contributor(s):
+//   Stefan Bund <g0dil@berlios.de>
 
 /** \file
     \brief Statistics public header */
 #include <boost/utility.hpp>
 #include <boost/ptr_container/ptr_vector.hpp>
 #include <boost/signals.hpp>
+#include <senf/Utils/Logger/Logger.hh>
+#include <senf/Utils/Console/ScopedDirectory.hh>
+#include "StatisticAccumulator.hh"
 #include "Exception.hh"
-#include "Logger/Logger.hh"
-#include "Console/Console.hh"
 
 //#include "Statistics.mpp"
-///////////////////////////////hh.p////////////////////////////////////////
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 
 namespace senf {
 
     /** \defgroup senf_statistics Statistics
 
         The statistics functionality has two parts:
-        
+
         \li the senf::Statistics class
+        \li the senf::StatisticsAccumulator class
         \li statistics sources
 
         Each senf::Statistics instance collects information about a single parameter. Which
         parameter is set up by connecting the Statistics instance with an arbitrary statistics
         source.
 
-        %Statistics sources are <a href="http://www.boost.org/doc/libs/1_37_0/doc/html/signals.html">
+        %Statistics sources are <a href="http://www.boost.org/doc/libs/release/doc/html/signals.html">
         Boost Signals</a> which are emitted periodically to provide new data.
      */
 
     class Collector;
     class Statistics;
-    
+
     /** \brief Internal: Generic Statistics collection */
     class StatisticsBase
-    { 
+    {
         typedef std::map<unsigned, Collector> Children;
 
         struct Transform {
@@ -78,7 +85,7 @@ namespace senf {
         struct OutputEntry;
 
     public:
-        ///////////////////////////////////////////////////////////////////////////
+        //-////////////////////////////////////////////////////////////////////////
         // Types
 
         typedef boost::iterator_range<ValueIterator> CollectorRange;
@@ -111,7 +118,7 @@ namespace senf {
             // Function object
             struct Collector
             {
-                void operator()(float min, float avg, float max) 
+                void operator()(float min, float avg, float max, float dev)
                     { ... }
             };
             \endcode
@@ -125,7 +132,7 @@ namespace senf {
             template <class Target> Owner & connect(Target & target,
                                                     std::string label="") const;
                                         ///< Connect externally managed target
-            template <class PTarget> Owner & connect(std::auto_ptr<PTarget> target, 
+            template <class PTarget> Owner & connect(std::auto_ptr<PTarget> target,
                                                      std::string label="") const;
                                         ///< Connect internally managed target
             Owner & noconnect() const;  ///< Don't connect the output
@@ -136,7 +143,7 @@ namespace senf {
         private:
 #endif
             OutputProxy(Owner * owner, OutputEntry * entry);
-            template <class OtherOwner> 
+            template <class OtherOwner>
             OutputProxy(Owner * owner, OutputProxy<OtherOwner> const & other);
 
         private:
@@ -145,30 +152,39 @@ namespace senf {
 
             template <class OtherOwner> friend class OutputProxy;
         };
-            
-        ///////////////////////////////////////////////////////////////////////////
+
+        //-////////////////////////////////////////////////////////////////////////
         ///\name Accessing the current value
-        ///\{
+        //\{
 
         float min() const;              ///< Last min value entered
         float avg() const;              ///< Last avg value entered
         float max() const;              ///< Last max value entered
+        float dev() const;              ///< Last dev value entered
 
         virtual unsigned rank() const;  ///< Return collectors rank value
                                         /**< \returns number of basic values collected into each new
                                              value by this collector. */
 
-        ///\}
-        ///////////////////////////////////////////////////////////////////////////
+        //\}
+        //-////////////////////////////////////////////////////////////////////////
         ///\name Child collectors
-        ///\{
+        //\{
 
         Collector & operator[](unsigned rank);
                                         ///< Get child collector
                                         /**< This member will return a reference to the collector
                                              collecting \a rank values.
                                              \param[in] rank Number of values the requested
-                                                 collector collects into each combined value. 
+                                                 collector collects into each combined value.
+                                             \throws InvalidRankException if \a rank is not a valid
+                                                 registered rank value. */
+        Collector const & operator[](unsigned rank) const;
+                                        ///< Get child collector
+                                        /**< This member will return a const reference to the
+                                             collector collecting \a rank values.
+                                             \param[in] rank Number of values the requested
+                                                 collector collects into each combined value.
                                              \throws InvalidRankException if \a rank is not a valid
                                                  registered rank value. */
         CollectorRange collectors();    ///< List all child collectors
@@ -186,7 +202,7 @@ namespace senf {
         Statistics & base();            ///< Get base statistics object
                                         /**< Returns the base statistics object. If this is
                                              a child collector, this will return the outermost
-                                             statistics object, otherwise it will return 
+                                             statistics object, otherwise it will return
                                              \c *this. */
 
         std::string path() const;       ///< Get the path to this collector
@@ -195,8 +211,8 @@ namespace senf {
                                              is empty, otherwise it is built by joining the
                                              collector ranks. */
 
-        ///\}
-        ///////////////////////////////////////////////////////////////////////////
+        //\}
+        //-////////////////////////////////////////////////////////////////////////
         ///\name Result generation
 
         OutputProxy<StatisticsBase> output(unsigned n = 1u);
@@ -212,8 +228,14 @@ namespace senf {
                                              \endcode
                                              \param[in] n size of sliding average window */
 
-        ///\}
-        ///////////////////////////////////////////////////////////////////////////
+        //\}
+        StatisticsData data();      ///< Get the Statistics data as senf::StatisticsData
+                                    /**< Return a Statistic Data object containing values
+                                         from this instance.
+                                     */
+
+
+        //-////////////////////////////////////////////////////////////////////////
         // Exceptions
 
         struct InvalidRankException : public senf::Exception
@@ -227,27 +249,28 @@ namespace senf {
     protected:
         StatisticsBase();
         virtual ~StatisticsBase();
-        void enter(float min, float avg, float max);
+        void enter(unsigned n, float min, float avg, float max, float dev);
 
     private:
         virtual Statistics & v_base() = 0;
         virtual std::string v_path() const = 0;
 
         void generateOutput();
-        void signalChildren();
 
         float min_;
         float avg_;
         float max_;
+        float dev_;
         Children children_;
-        
+
         struct QueueEntry {
             float min;
             float avg;
             float max;
-            QueueEntry() : min(), avg(), max() {}
-            QueueEntry(float min_, float avg_, float max_)
-                : min(min_), avg(avg_), max(max_) {}
+            float dev;
+            QueueEntry() : min(), avg(), max(), dev() {}
+            QueueEntry(float min_, float avg_, float max_, float dev_)
+                : min(min_), avg(avg_), max(max_), dev(dev_) {}
         };
         typedef std::deque<QueueEntry> Queue;
         Queue queue_;
@@ -264,7 +287,7 @@ namespace senf {
             struct Target : public TargetBase
             {
                 boost::scoped_ptr<PTarget> target_;
-                Target(std::auto_ptr<PTarget> target, std::string const & label) 
+                Target(std::auto_ptr<PTarget> target, std::string const & label)
                     : TargetBase (label), target_ (target.release()) {}
                 explicit Target(std::string const & label)
                     : TargetBase (label), target_ (0) {}
@@ -282,8 +305,9 @@ namespace senf {
             float min;
             float avg;
             float max;
+            float dev;
 
-            boost::signal<void(float,float,float)> signal;
+            boost::signal<void(float,float,float,float)> signal;
             boost::ptr_vector<TargetBase> targets_;
 
             senf::console::ScopedDirectory<> dir;
@@ -333,7 +357,7 @@ namespace senf {
             .collect(10u)                // seconds
             .collect(60u)                // minutes
             .collect(60u);               // hours
-        
+
         packetStats[10u].collect(100u);  // 100 seconds
 
         rateAnalyzer.startStatistics(senf::ClockService::milliseconds(100u));
@@ -378,8 +402,8 @@ namespace senf {
         statslog.route<senf::StatisticsStream>();
         \endcode
 
-        We use a StatisticsLogger to send the log messages to the senf::StatisticsStream log
-        stream. The stream, area an level to send the statistics log messages to may be configured
+        We use a StatisticsLogger to send the %log messages to the senf::StatisticsStream %log
+        stream. The stream, area an level to send the statistics %log messages to may be configured
         using template arguments to StatisticsLogger.
 
         It is also possible to skip sending the output to any target or send one output to several
@@ -406,7 +430,7 @@ namespace senf {
         \see senf::StatisticsBase::OutputProxy for the output proxy (connect) interface
         \ingroup senf_statistics
      */
-    class Statistics 
+    class Statistics
         : public StatisticsBase, boost::noncopyable
     {
     public:
@@ -416,24 +440,54 @@ namespace senf {
 
         Statistics();
 
-        void operator()(float min, float avg, float max);
+        void operator()(unsigned n, float min, float avg, float max, float dev);
                                         ///< Enter new data
-                                        /**< This member must be called whenever a new data value is
-                                             available. It is important to call this member \e
-                                             periodically. The frequency at which this member is
-                                             called defines the basic statistics time scale.
+                                        /**< This member must be called whenever new data is
+                                             available.
 
                                              If \a min and \a max values are not available, this
                                              member should be called with \a min, \a avg and \a max
-                                             set to the same value.
-
+                                             set to the same value. If no error estimate is
+                                             available, call with \a dev = 0.
+
+                                             In the most common case, this member is to be called
+                                             periodically and \a n will be 1 on all calls. The
+                                             interval, at which this member is called then defines
+                                             the statistics time scale.
+
+                                             Calling with \a n > 1 will submit the value \a n
+                                             times. This makes it possible to aggregate multiple
+                                             time slices into a single call. This does not change
+                                             the basic time scale but can change the number of
+                                             submits per unit time. If the basic time slice is
+                                             small, this allows to submit values almost arbitrarily
+                                             non-periodic.
+
+                                             \param[in] n number of time-slices
                                              \param[in] min minimal data value since last call
                                              \param[in] avg average data value since last call
-                                             \param[in] max maximal data values since last call */
-
-        void operator()(float value);   ///< Same as enter() with \a min == \a avg == \a max
+                                             \param[in] max maximal data values since last call
+                                             \param[in] dev standard deviation of avg value */
+        void operator()(float min, float avg, float max, float dev=0.0f);
+                                        ///< Same as operator() with \a n==1
                                         /**< Provided so a Statistics instance can be directly used
                                              as a signal target. */
+        void operator()(float value, float dev=0.0f);
+                                        ///< Same as operator() with \a min == \a avg == \a max
+                                        /**< Provided so a Statistics instance can be directly used
+                                             as a signal target. */
+        void operator()(StatisticsData const & data);
+                                        ///< Same as operator(), but imports statistics data from a StatisticsData object
+                                        /**< Provided so a Statistics instance can be directly used
+                                             as a signal target. */
+        template <class Value>
+        void operator()(unsigned n, StatisticAccumulator<Value> & sa);
+                                        ///< Same as operator() gathers values from StatisticAccumulator
+                                        /**< Provided so a Statistics instance can be directly used
+                                             as a signal target. Caution: Clears values in
+                                             StatisticAccumulator afterwards
+                                             \param[in] n number of time-slices
+                                             \param[in] sa StatisticAccumulator*/
 
         StatisticsBase::OutputProxy<Statistics> output(unsigned n = 1u);
 
@@ -457,20 +511,21 @@ namespace senf {
     class Collector : public StatisticsBase
     {
     public:
-        virtual unsigned rank() const;  
+        virtual unsigned rank() const;
 
         StatisticsBase::OutputProxy<Collector> output(unsigned n = 1u);
-        
+
     private:
         Collector(StatisticsBase * owner, unsigned rank);
-        void enter(float min, float avg, float max);
+        void enter(unsigned n, float min, float avg, float max, float dev);
         Statistics & v_base();
         std::string v_path() const;
 
         unsigned rank_;
         unsigned i_;
         float accMin_;
-        float accAvg_;
+        float accSum_;
+        float accSumSq_;
         float accMax_;
         StatisticsBase * owner_;
 
@@ -479,7 +534,7 @@ namespace senf {
 
 }
 
-///////////////////////////////hh.e////////////////////////////////////////
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 #include "Statistics.cci"
 //#include "Statistics.ct"
 #include "Statistics.cti"