// $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 "Exception.hh"
#include <senf/Utils/Logger/Logger.hh>
-#include <senf/Utils/Console/Console.hh>
+#include <senf/Utils/Console/ScopedDirectory.hh>
+#include "StatisticAccumulator.hh"
+#include "Exception.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;
+ // why we can't use ::__gnu_cxx::select2nd instead?!?!
struct Transform {
typedef Children::value_type & first_argument_type;
typedef Collector & result_type;
struct OutputEntry;
public:
- ///////////////////////////////////////////////////////////////////////////
+ //-////////////////////////////////////////////////////////////////////////
// Types
typedef boost::iterator_range<ValueIterator> CollectorRange;
// Function object
struct Collector
{
- void operator()(float min, float avg, float max)
+ void operator()(float min, float avg, float max, float dev)
{ ... }
};
\endcode
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
private:
#endif
OutputProxy(Owner * owner, OutputEntry * entry);
- template <class OtherOwner>
+ template <class OtherOwner>
OutputProxy(Owner * owner, OutputProxy<OtherOwner> const & other);
private:
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
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
is empty, otherwise it is built by joining the
collector ranks. */
- ///\}
- ///////////////////////////////////////////////////////////////////////////
+ //\}
+ //-////////////////////////////////////////////////////////////////////////
///\name Result generation
OutputProxy<StatisticsBase> output(unsigned n = 1u);
\endcode
\param[in] n size of sliding average window */
- ///\}
- ///////////////////////////////////////////////////////////////////////////
+ //\}
+ StatisticsData data() const; ///< Get the Statistics data as senf::StatisticsData
+ /**< Return a Statistic Data object containing values
+ from this instance. */
+
+
+ //-////////////////////////////////////////////////////////////////////////
// Exceptions
struct InvalidRankException : public senf::Exception
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_;
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) {}
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;
.collect(10u) // seconds
.collect(60u) // minutes
.collect(60u); // hours
-
+
packetStats[10u].collect(100u); // 100 seconds
rateAnalyzer.startStatistics(senf::ClockService::milliseconds(100u));
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
\see senf::StatisticsBase::OutputProxy for the output proxy (connect) interface
\ingroup senf_statistics
*/
- class Statistics
+ class Statistics
: public StatisticsBase, boost::noncopyable
{
public:
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);
- void consoleList(std::ostream & os);
+ void consoleList(std::ostream & os) const;
void consoleCollect(std::vector<unsigned> & ranks);
boost::shared_ptr<senf::console::DirectoryNode> consoleOutput(
std::vector<unsigned> & ranks, unsigned window);
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_;
}
-///////////////////////////////hh.e////////////////////////////////////////
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
#include "Statistics.cci"
//#include "Statistics.ct"
#include "Statistics.cti"