1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

more improvements to make statistic subsystem extensible

This commit is contained in:
Steffen Vogel 2016-11-07 22:18:26 -05:00
parent b23484550f
commit 735f08f551
3 changed files with 124 additions and 78 deletions

View file

@ -23,20 +23,24 @@ struct sample;
struct path;
struct node;
struct stats {
struct {
uintmax_t invalid; /**< Counter for invalid messages */
uintmax_t skipped; /**< Counter for skipped messages due to hooks */
uintmax_t dropped; /**< Counter for dropped messages due to reordering */
} counter;
enum stats_id {
STATS_INVALID, /**< Counter for invalid messages */
STATS_SKIPPED, /**< Counter for skipped messages due to hooks */
STATS_DROPPED, /**< Counter for dropped messages due to reordering */
STATS_GAP_SEQUENCE, /**< Histogram of sequence number displacement of received messages */
STATS_GAP_SAMPLE, /**< Histogram for inter message timestamps (as sent by remote) */
STATS_GAP_RECEIVED, /**< Histogram for inter message arrival time (as seen by this instance) */
STATS_OWD, /**< Histogram for one-way-delay (OWD) of received messages */
STATS_COUNT /**< Just here to have an updated number of statistics */
};
struct stats_delta {
double vals[STATS_COUNT];
};
struct stats {
struct hist histograms[STATS_COUNT];
struct {
struct hist owd; /**< Histogram for one-way-delay (OWD) of received messages */
struct hist gap_msg; /**< Histogram for inter message timestamps (as sent by remote) */
struct hist gap_recv; /**< Histogram for inter message arrival time (as seen by this instance) */
struct hist gap_seq; /**< Histogram of sequence number displacement of received messages */
} histogram;
struct sample *last;
};
@ -44,8 +48,14 @@ int stats_init(struct stats *s);
void stats_destroy(struct stats *s);
void stats_update(struct stats *s, enum stats_id id, double val);
int stats_commit(struct stats *s, struct stats_delta *d);
void stats_collect(struct stats *s, struct sample *smps[], size_t cnt);
void stats_decollect(struct stats *s, struct sample *smps[], size_t cnt);
#ifdef WITH_JANSSON
json_t * stats_json(struct stats *s);
#endif
@ -56,7 +66,7 @@ void stats_print_header();
void stats_print_periodic(struct stats *s, struct path *p);
void stats_print(struct stats *s);
void stats_print(struct stats *s, int details);
void stats_send(struct stats *s, struct node *n);

View file

@ -85,7 +85,7 @@ int hook_drop(struct hook *h, int when, struct hook_info *j)
if (h->prev) {
dist = h->last->sequence - (int32_t) h->prev->sequence;
if (dist <= 0) {
j->path->stats->counter.dropped++;
stats_update(j->path->stats, STATS_DROPPED, dist);
warn("Dropped sample: dist = %d, i = %d", dist, i);
}
else {

View file

@ -13,38 +13,81 @@
#include "sample.h"
#include "log.h"
static struct stats_desc {
const char *name;
const char *unit;
const char *desc;
struct {
double min;
double max;
double resolution;
} hist;
} stats_table[] = {
{ "invalid", "", "invalid messages", {0, 0, -1, }},
{ "skipped", "", "skipped messages by hooks", {0, 0, -1, }},
{ "dropped", "", "dropped messages because of reordering", {0, 0, -1, }},
{ "gap_sequence", "", "sequence number displacement of received messages", {-10, 10, 20, }},
{ "gap_sample", "", "inter message timestamps (as sent by remote)", {90e-3, 110e-3, 1e-3, }},
{ "gap_received", "", "Histogram for inter message arrival time (as seen by this instance)", {90e-3, 110e-3, 1e-3, }},
{ "owd", "s", "Histogram for one-way-delay (OWD) of received messages", {0, 1, 100e-3, }}
};
int stats_init(struct stats *s)
{
/** @todo Allow configurable bounds for histograms */
hist_create(&s->histogram.owd, 0, 1, 100e-3);
hist_create(&s->histogram.gap_msg, 90e-3, 110e-3, 1e-3);
hist_create(&s->histogram.gap_recv, 90e-3, 110e-3, 1e-3);
hist_create(&s->histogram.gap_seq, -HIST_SEQ, +HIST_SEQ, 1);
for (int i = 0; i < STATS_COUNT; i++) {
struct stats_desc *desc = &stats_table[i];
hist_create(&s->histograms[i], desc->hist.min, desc->hist.max, desc->hist.resolution);
}
return 0;
}
void stats_destroy(struct stats *s)
{
hist_destroy(&s->histogram.owd);
hist_destroy(&s->histogram.gap_msg);
hist_destroy(&s->histogram.gap_recv);
hist_destroy(&s->histogram.gap_seq);
for (int i = 0; i < STATS_COUNT; i++) {
hist_destroy(&s->histograms[i]);
}
}
void stats_update(struct stats *s, enum stats_id id, double val)
{
if (!s)
return;
hist_put(&s->histograms[id], val);
}
#if 0
int stats_delta(struct stats_delta *d, struct sample *s, struct sample *p)
{
d->histogram.owd = time_delta(&smps[i]->ts.origin, &smps[i]->ts.received);
d->histogram.gap = time_delta(&s->last->ts.origin, &smps[i]->ts.origin);
d->histogram.gap_seq = s->sequence - (int32_t) p->sequence;
d->histogram.gap_recv = time_delta(&s->last->ts.received, &smps[i]->ts.received);
d->counter.dropped = d->histogram.gap_seq <= 0 ? 1 : 0;
d->counter.invalid = 0;
return 0;
}
#endif
int stats_commit(struct stats *s, struct stats_delta *d)
{
for (int i = 0; i < STATS_COUNT; i++) {
hist_put(&s->histograms[i], d->vals[i]);
}
return 0;
}
void stats_collect(struct stats *s, struct sample *smps[], size_t cnt)
{
for (int i = 0; i < cnt; i++) {
if (s->last) {
int gap_seq = smps[i]->sequence - (int32_t) s->last->sequence;
double owd = time_delta(&smps[i]->ts.origin, &smps[i]->ts.received);
double gap = time_delta(&s->last->ts.origin, &smps[i]->ts.origin);
double gap_recv = time_delta(&s->last->ts.received, &smps[i]->ts.received);
hist_put(&s->histogram.owd, owd);
hist_put(&s->histogram.gap_msg, gap);
hist_put(&s->histogram.gap_seq, gap_seq);
hist_put(&s->histogram.gap_recv, gap_recv);
// struct stats_delta d;
// stats_get_delta(&d, smps[i], s->last);
// stats_commit(s, &d);
}
if (i == 0 && s->last)
@ -59,30 +102,25 @@ void stats_collect(struct stats *s, struct sample *smps[], size_t cnt)
#ifdef WITH_JANSSON
json_t * stats_json(struct stats *s)
{
return json_pack("{ s: { s: i, s: i, s: i }, s: { s: o, s: o, s: o } }",
"counter",
"dropped", s->counter.dropped,
"invalid", s->counter.invalid,
"skipped", s->counter.skipped,
"histogram",
"owd", hist_json(&s->histogram.owd),
"gap_msg", hist_json(&s->histogram.gap_msg),
"gap_recv",hist_json(&s->histogram.gap_recv),
"gap_seq", hist_json(&s->histogram.gap_seq)
);
json_t *obj = json_object();
for (int i = 0; i < STATS_COUNT; i++) {
struct stats_desc *desc = &stats_table[i];
json_t *stats = hist_json(&s->histograms[i]);
json_object_set(obj, desc->name, stats);
}
return obj;
}
#endif
void stats_reset(struct stats *s)
{
s->counter.invalid =
s->counter.skipped =
s->counter.dropped = 0;
hist_reset(&s->histogram.owd);
hist_reset(&s->histogram.gap_seq);
hist_reset(&s->histogram.gap_msg);
hist_reset(&s->histogram.gap_recv);
for (int i = 0; i < STATS_COUNT; i++) {
hist_reset(&s->histograms[i]);
}
}
void stats_print_header()
@ -101,41 +139,39 @@ void stats_print_header()
void stats_print_periodic(struct stats *s, struct path *p)
{
stats("%-40.40s|%10s|%10s|%10ju|%10ju|%10ju|", path_name(p), "", "",
s->counter.dropped, s->counter.skipped, s->counter.invalid);
stats("%-40.40s|%10f|%10f|%10ju|%10ju|%10ju|", path_name(p),
s->histograms[STATS_OWD].last,
1.0 / s->histograms[STATS_GAP_SAMPLE].last,
s->histograms[STATS_DROPPED].total,
s->histograms[STATS_SKIPPED].total,
s->histograms[STATS_INVALID].total
);
}
void stats_print(struct stats *s)
void stats_print(struct stats *s, int details)
{
stats("Dropped samples: %ju", s->counter.dropped);
stats("Skipped samples: %ju", s->counter.skipped);
stats("Invalid samples: %ju", s->counter.invalid);
stats("One-way delay:");
hist_print(&s->histogram.owd);
stats("Inter-message arrival time:");
hist_print(&s->histogram.gap_recv);
stats("Inter-message ts gap:");
hist_print(&s->histogram.gap_msg);
stats("Inter-message sequence number gaps:");
hist_print(&s->histogram.gap_seq);
for (int i = 0; i < STATS_COUNT; i++) {
struct stats_desc *desc = &stats_table[i];
stats("%s: %s", desc->name, desc->desc);
hist_print(&s->histograms[i], details);
}
}
void stats_send(struct stats *s, struct node *n)
{
char buf[SAMPLE_LEN(16)];
char buf[SAMPLE_LEN(STATS_COUNT * 5)];
struct sample *smp = (struct sample *) buf;
int i = 0;
smp->data[i++].f = s->counter.invalid; /**< Use integer here? */
smp->data[i++].f = s->counter.skipped;
smp->data[i++].f = s->counter.dropped;
smp->data[i++].f = s->histogram.owd.last,
smp->data[i++].f = 1.0 / s->histogram.gap_msg.last;
smp->data[i++].f = 1.0 / s->histogram.gap_recv.last;
for (int j = 0; j < STATS_COUNT; j++) {
smp->data[i++].f = s->histograms[j].last;
smp->data[i++].f = s->histograms[j].highest;
smp->data[i++].f = s->histograms[j].lowest;
smp->data[i++].f = hist_mean(&s->histograms[j]);
smp->data[i++].f = hist_var(&s->histograms[j]);
}
smp->length = i;
node_write(n, &smp, 1); /* Send single message with statistics to destination node */