// $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>
#include "Exception.hh"
#include <senf/Utils/Logger/Logger.hh>
#include <senf/Utils/Console/Console.hh>
+#include "StatisticAccumulator.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 {
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 */
- ///\}
- ///////////////////////////////////////////////////////////////////////////
+ //\}
+ //-////////////////////////////////////////////////////////////////////////
// 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));
\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);
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"