// $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>
/** \defgroup senf_statistics Statistics
The statistics functionality has two parts:
-
+
\li the senf::Statistics class
\li statistics sources
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 {
// 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
/**< 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. */
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
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. */
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_;