diff --git a/server/include/stats.h b/server/include/stats.h new file mode 100644 index 000000000..324476163 --- /dev/null +++ b/server/include/stats.h @@ -0,0 +1,28 @@ +/** Hook functions to collect statistics + * + * @file + * @author Steffen Vogel + * @copyright 2014-2015, Institute for Automation of Complex Power Systems, EONERC + * This file is part of S2SS. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + *********************************************************************************/ + +#ifndef _STATS_H_ +#define _STATS_H_ + +/* Forward declarations */ +struct path; + +int stats_line(struct path *p); + +int stats_show(struct path *p); + +int stats_collect(struct path *p); + +int stats_start(struct path *p); + +int stats_stop(struct path *p); + +int stats_reset(struct path *p); + +#endif \ No newline at end of file diff --git a/server/src/path.c b/server/src/path.c index 39c49b8df..54d951f2c 100644 --- a/server/src/path.c +++ b/server/src/path.c @@ -14,6 +14,7 @@ #include "socket.h" #include "timing.h" #include "config.h" +#include "stats.h" #ifndef sigev_notify_thread_id #define sigev_notify_thread_id _sigev_un._tid @@ -204,6 +205,18 @@ struct path * path_create() hook_add(HOOK_MSG, 1, hook_verify); hook_add(HOOK_MSG, 2, hook_restart); hook_add(HOOK_MSG, 3, hook_drop); + hook_add(HOOK_MSG, 4, stats_collect); + + hook_add(HOOK_PATH_START, 1, stats_start); + + hook_add(HOOK_PATH_STOP, 1, stats_line); + hook_add(HOOK_PATH_STOP, 2, stats_show); + hook_add(HOOK_PATH_STOP, 3, stats_stop); + + hook_add(HOOK_PATH_RESTART, 1, stats_line); + hook_add(HOOK_PATH_RESTART, 3, stats_reset); + + hook_add(HOOK_PERIODIC, 1, stats_line); return p; } diff --git a/server/src/stats.c b/server/src/stats.c new file mode 100644 index 000000000..293d2e1d2 --- /dev/null +++ b/server/src/stats.c @@ -0,0 +1,75 @@ +/** Hook functions to collect statistics + * + * @file + * @author Steffen Vogel + * @copyright 2014-2015, Institute for Automation of Complex Power Systems, EONERC + * This file is part of S2SS. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + *********************************************************************************/ + +#include "stats.h" +#include "path.h" +#include "timing.h" +#include "utils.h" + +int stats_line(struct path *p) +{ + char buf[33]; + path_print(p, buf, sizeof(buf)); + + info("%-32s : %-8u %-8u %-8u %-8u %-8u", buf, + p->sent, p->received, p->dropped, p->skipped, p->invalid); + + return 0; +} + +int stats_show(struct path *p) +{ + if (p->hist_delay.length) { info("One-way delay:"); hist_print(&p->hist_delay); } + if (p->hist_gap.length) { info("Message gap time:"); hist_print(&p->hist_gap); } + if (p->hist_sequence.length) { info("Sequence number gaps:"); hist_print(&p->hist_sequence); } + + return 0; +} + +int stats_collect(struct path *p) +{ + int dist = p->current->sequence - (int32_t) p->previous->sequence; + + struct timespec ts1 = MSG_TS(p->current); + struct timespec ts2 = MSG_TS(p->previous); + + hist_put(&p->hist_sequence, dist); + hist_put(&p->hist_delay, time_delta(&ts1, &p->ts_recv)); + hist_put(&p->hist_gap, time_delta(&ts2, &ts1)); + + return 0; +} + +int stats_start(struct path *p) +{ + /** @todo Allow configurable bounds for histograms */ + hist_create(&p->hist_sequence, -HIST_SEQ, +HIST_SEQ, 1); + hist_create(&p->hist_delay, 0, 2, 100e-3); + hist_create(&p->hist_gap, 0, 40e-3, 1e-3); + + return 0; +} + +int stats_stop(struct path *p) +{ + hist_destroy(&p->hist_sequence); + hist_destroy(&p->hist_delay); + hist_destroy(&p->hist_gap); + + return 0; +} + +int stats_reset(struct path *p) +{ + hist_reset(&p->hist_sequence); + hist_reset(&p->hist_delay); + hist_reset(&p->hist_gap); + + return 0; +} \ No newline at end of file