43 for (
unsigned i (0); i < n; ++i)
45 Children::iterator i (children_.begin());
46 Children::iterator
const i_end (children_.end());
47 for (; i != i_end; ++i)
48 i->second.enter(n, cnt_, min_, avg_, max_, dev_);
53 Children::iterator i (children_.find(rank));
54 if (i == children_.end())
62 Children::const_iterator i (children_.find(rank));
63 if (i == children_.end())
70 std::pair<Children::iterator, bool> state (
71 children_.insert(std::make_pair(rank,
Collector(
this, rank))) );
74 return state.first->second;
80 OutputMap::iterator i (outputs_.find(n));
81 if (i == outputs_.end()) {
82 i = outputs_.insert(std::make_pair(n, OutputEntry(n))).first;
84 nm <<
"output" <<
path() <<
":" << n;
86 detail::StatisticsLoggerRegistry::instance().apply(*
this, n, i->second.dir);
114 os << boost::format(
"%s%-5d%|15t| %12.5g %19.5g %12.5g %12.5g\n")
115 % std::string(2*level,
' ') %
rank()
118 OutputMap::const_iterator i (outputs_.begin());
119 OutputMap::const_iterator i_end (outputs_.end());
120 for (; i != i_end; ++i)
121 os << boost::format(
" %3d %12.5g %19.5g %12.5g %12.5g\n")
129 Children::const_iterator i (children_.begin());
130 Children::const_iterator
const i_end (children_.end());
131 for (; i != i_end; ++i)
132 i->second.consoleList(level+1, os);
136 prefix_ void senf::StatisticsBase::generateOutput()
138 queue_.push_front(QueueEntry(cnt_, min_, avg_, max_, dev_));
139 while (queue_.size() > maxQueueLen_)
142 OutputMap::iterator i (outputs_.begin());
143 OutputMap::iterator
const i_end (outputs_.end());
144 for (; i != i_end; ++i) {
146 i->second.min = FLT_MAX;
147 i->second.max = -FLT_MAX;
148 i->second.avg = i->second.dev = 0.0f;
149 Queue::const_iterator j (queue_.begin());
150 Queue::const_iterator
const j_end (queue_.end());
151 unsigned n (0), num (0);
152 for (; n < i->second.n && j != j_end; ++n, ++j) {
154 i->second.cnt += j->cnt;
155 i->second.min = std::min(i->second.min, j->min);
156 i->second.avg += j->avg;
157 i->second.max = std::max( i->second.max, j->max);
158 i->second.dev += j->dev;
163 i->second.avg /= num;
164 i->second.dev /= num;
166 i->second.signal(i->second.cnt, i->second.min, i->second.avg, i->second.max, i->second.dev);
173 prefix_ void senf::StatisticsBase::OutputEntry::consoleList(std::ostream & os)
175 for (boost::ptr_vector<TargetBase>::iterator i (targets_.begin());
176 i != targets_.end(); ++i)
177 if (! i->label.empty())
178 os << i->label <<
"\n";
186 #ifndef SENF_DISABLE_CONSOLE 187 namespace fty = console::factory;
189 dir.add(
"list", fty::Command(&Statistics::consoleList,
this)
190 .doc(
"List statistics collection intervals and current values.\n" 193 " RANK Number of values collected. Since the statistics collectors form\n" 194 " a tree, the value is indented according to it's tree location.\n" 195 " WIN Size of output average window.\n" 196 " MIN Last entered minimum value.\n" 197 " AVG Last entered average value.\n" 198 " DEV Standard deviation of average value over the collector rank.\n" 199 " MAX Last entered maximum value." 200 " CNT Number of samples represented by this collector") );
201 dir.add(
"collect", fty::Command(&Statistics::consoleCollect,
this)
202 .doc(
"Add statistics collection groups. The argument gives a sequence of collector\n" 203 "ranks each building on the preceding collector:\n" 205 " $ collect (10 60 60)\n" 207 "Will start by collecting every 10 values together to a new value. 60 of such\n" 208 "combined values will be collected together in the next step again followed by\n" 209 "a collection of 60 values. If the statistics is entered with a frequency of\n" 210 "10 values per second, this will provide combined statistics over the second,\n" 211 "minutes and hours ranges.\n" 213 "You may call collect multiple times. Any missing collection ranks will be\n" 215 .arg(
"ranks",
"chain of collector ranks") );
216 dir.add(
"output", fty::Command(&Statistics::consoleOutput,
this)
217 .doc(
"Generate statistics output. This statement will add an additional output\n" 218 "generator. This generator will be attached to the collector specified by\n" 219 "the {rank} parameter. This parameter is a chain of successive rank values\n" 220 "which specifies the exact collector to use. If the collector does not\n" 221 "exist, it will be created (this is like automatically calling 'collect'\n" 222 "with {rank} as argument).\n" 224 "If the output is to be sent somewhere it must be connected to a statistics\n" 227 "The output may optionally be built using a sliding average over the last\n" 232 "will output the basic statistics value each time a new value is entered.\n" 234 " $ output (10 60) 5\n" 236 "Assuming that new data values are entered 10 times per second, this command\n" 237 "will generate output once every minute. The value will be the average over\n" 238 "the last 5 minutes.")
239 .arg(
"rank",
"Rank chain selecting the value to generate output for")
240 .arg(
"window",
"Optional size of sliding average window",
241 console::kw::default_value = 1u) );
245 prefix_ void senf::Statistics::consoleList(std::ostream & os)
248 os <<
"RANK WIN MIN AVG MAX CNT\n";
252 prefix_ void senf::Statistics::consoleCollect(std::vector<unsigned> & ranks)
255 std::vector<unsigned>::const_iterator i (ranks.begin());
256 std::vector<unsigned>::const_iterator
const i_end (ranks.end());
259 for (; i != i_end; ++i)
260 stats = &(*stats)[*i];
264 for (; i != i_end; ++i)
265 stats = & (stats->
collect(*i));
268 prefix_ boost::shared_ptr<senf::console::DirectoryNode>
269 senf::Statistics::consoleOutput(std::vector<unsigned> & ranks,
unsigned window)
272 std::vector<unsigned>::const_iterator i (ranks.begin());
273 std::vector<unsigned>::const_iterator
const i_end (ranks.end());
276 for (; i != i_end; ++i)
277 stats = &(*stats)[*i];
281 for (; i != i_end; ++i)
282 stats = & (stats->
collect(*i));
284 return stats->
output(window).dir().node().thisptr();
292 prefix_ std::string senf::Statistics::v_path()
306 if (
min < accMin_) accMin_ =
min;
307 if (
max > accMax_) accMax_ =
max;
310 if ((i_+l_) + n >= rank_) {
312 accCnt_ += (rank_ - (i_+l_)) *
cnt;
313 accSum_ += (rank_ - (i_+l_)) *
avg;
314 accSumSq_ += (rank_ - (i_+l_)) * (rank_ - (i_+l_)) * (
avg*
avg + dev*
dev);
316 float accAvg (accSum_ / (rank_ - l_));
317 float accDev (std::sqrt(std::max(0.0f,accSumSq_ / (rank_ - l_) - accAvg*accAvg)));
324 n -= (rank_ - (i_+l_));
329 std::div_t d (std::div(
int(n),
int(rank_)));
339 accSumSq_ += n*n * (avg*avg+dev*
dev);
341 if (
min < accMin_) accMin_ =
min;
342 if (
max > accMax_) accMax_ =
max;
351 return owner_->
base();
354 prefix_ std::string senf::Collector::v_path()
357 return owner_->path() +
"-" +
senf::str(rank_);
std::string path() const
Get the path to this collector.
std::string str(T const &t)
Get string representation.
OutputProxy< StatisticsBase > output(unsigned n=1u)
Register output.
Internal: Generic Statistics collection.
Statistics public header.
unsigned cnt() const
Last cnt value entered.
Collector & operator[](unsigned rank)
Get child collector.
Collect statistics and generate log messages.
NodeType & add(std::string const &name, boost::shared_ptr< NodeType > node)
float avg() const
Last avg value entered.
float max() const
Last max value entered.
float dev() const
Last dev value entered.
DirectoryNode & node() const
Statistics const & base() const
Output connection interface.
Accumulated statistics collector.
console::ScopedDirectory dir
void consoleList(unsigned level, std::ostream &os) const
void enter(unsigned n, unsigned cnt, float min, float avg, float max, float dev)
StatisticsTargets public header.
Collector & collect(unsigned rank)
Register a new collector.
virtual unsigned rank() const
Return collectors rank value.
float min() const
Last min value entered.