mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
stats: port to C++
This commit is contained in:
parent
f05b2ae952
commit
c842914bc5
16 changed files with 318 additions and 343 deletions
|
@ -25,7 +25,7 @@
|
|||
|
||||
#include <jansson.h>
|
||||
|
||||
#include <villas/stats.h>
|
||||
#include <villas/stats.hpp>
|
||||
#include <villas/common.h>
|
||||
|
||||
/* Forward declarations */
|
||||
|
@ -70,8 +70,8 @@ struct mapping_entry {
|
|||
} data;
|
||||
|
||||
struct {
|
||||
enum stats_metric metric;
|
||||
enum stats_type type;
|
||||
enum villas::Stats::Metric metric;
|
||||
enum villas::Stats::Type type;
|
||||
} stats;
|
||||
|
||||
struct {
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <villas/sample.h>
|
||||
#include <villas/list.h>
|
||||
#include <villas/queue.h>
|
||||
#include <villas/stats.hpp>
|
||||
#include <villas/common.h>
|
||||
|
||||
#if defined(LIBNL3_ROUTE_FOUND) && defined(__linux__)
|
||||
|
@ -67,7 +68,7 @@ struct node {
|
|||
|
||||
uint64_t sequence; /**< This is a counter of received samples, in case the node-type does not generate sequence numbers itself. */
|
||||
|
||||
struct stats *stats; /**< Statistic counters. This is a pointer to the statistic hooks private data. */
|
||||
villas::Stats *stats; /**< Statistic counters. This is a pointer to the statistic hooks private data. */
|
||||
|
||||
struct node_direction in, out;
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <jansson.h>
|
||||
|
||||
#include <villas/node.h>
|
||||
#include <villas/stats.h>
|
||||
#include <villas/stats.hpp>
|
||||
#include <villas/task.h>
|
||||
#include <villas/list.h>
|
||||
|
||||
|
@ -40,8 +40,8 @@ struct stats_node_signal {
|
|||
struct node *node;
|
||||
char *node_str;
|
||||
|
||||
enum stats_metric metric;
|
||||
enum stats_type type;
|
||||
enum villas::Stats::Metric metric;
|
||||
enum villas::Stats::Type type;
|
||||
};
|
||||
|
||||
struct stats_node {
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
/** Statistic collection.
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASnode
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <jansson.h>
|
||||
|
||||
#include <villas/common.h>
|
||||
#include <villas/hist.hpp>
|
||||
#include <villas/signal.h>
|
||||
|
||||
/* Forward declarations */
|
||||
struct sample;
|
||||
struct node;
|
||||
|
||||
enum stats_format {
|
||||
STATS_FORMAT_HUMAN,
|
||||
STATS_FORMAT_JSON,
|
||||
STATS_FORMAT_MATLAB
|
||||
};
|
||||
|
||||
enum stats_metric {
|
||||
STATS_METRIC_INVALID = -1,
|
||||
|
||||
STATS_METRIC_SMPS_SKIPPED, /**< Counter for skipped samples due to hooks. */
|
||||
STATS_METRIC_SMPS_REORDERED, /**< Counter for reordered samples. */
|
||||
|
||||
/* Timings */
|
||||
STATS_METRIC_GAP_SAMPLE, /**< Histogram for inter sample timestamps (as sent by remote). */
|
||||
STATS_METRIC_GAP_RECEIVED, /**< Histogram for inter sample arrival time (as seen by this instance). */
|
||||
STATS_METRIC_OWD, /**< Histogram for one-way-delay (OWD) of received samples. */
|
||||
STATS_METRIC_AGE, /**< Processing time of packets within VILLASnode. */
|
||||
|
||||
/* RTP metrics */
|
||||
STATS_METRIC_RTP_LOSS_FRACTION, /**< Fraction lost since last RTP SR/RR. */
|
||||
STATS_METRIC_RTP_PKTS_LOST, /**< Cumul. no. pkts lost. */
|
||||
STATS_METRIC_RTP_JITTER, /**< Interarrival jitter. */
|
||||
|
||||
/* Always last */
|
||||
STATS_METRIC_COUNT /**< Just here to have an updated number of statistics. */
|
||||
};
|
||||
|
||||
enum stats_type {
|
||||
STATS_TYPE_INVALID = -1,
|
||||
STATS_TYPE_LAST,
|
||||
STATS_TYPE_HIGHEST,
|
||||
STATS_TYPE_LOWEST,
|
||||
STATS_TYPE_MEAN,
|
||||
STATS_TYPE_VAR,
|
||||
STATS_TYPE_STDDEV,
|
||||
STATS_TYPE_TOTAL,
|
||||
STATS_TYPE_COUNT
|
||||
};
|
||||
|
||||
struct stats_metric_description {
|
||||
const char *name;
|
||||
enum stats_metric metric;
|
||||
const char *unit;
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
struct stats_type_description {
|
||||
const char *name;
|
||||
enum stats_type type;
|
||||
enum signal_type signal_type;
|
||||
};
|
||||
|
||||
struct stats {
|
||||
enum state state;
|
||||
villas::Hist histograms[STATS_METRIC_COUNT];
|
||||
};
|
||||
|
||||
extern struct stats_metric_description stats_metrics[];
|
||||
extern struct stats_type_description stats_types[];
|
||||
|
||||
int stats_lookup_format(const char *str);
|
||||
|
||||
enum stats_metric stats_lookup_metric(const char *str);
|
||||
|
||||
enum stats_type stats_lookup_type(const char *str);
|
||||
|
||||
int stats_init(struct stats *s, int buckets, int warmup);
|
||||
|
||||
int stats_destroy(struct stats *s);
|
||||
|
||||
void stats_update(struct stats *s, enum stats_metric id, double val);
|
||||
|
||||
json_t * stats_json(struct stats *s);
|
||||
|
||||
void stats_reset(struct stats *s);
|
||||
|
||||
void stats_print_header(enum stats_format fmt);
|
||||
|
||||
void stats_print_periodic(struct stats *s, FILE *f, enum stats_format fmt, struct node *p);
|
||||
|
||||
void stats_print(struct stats *s, FILE *f, enum stats_format fmt, int verbose);
|
||||
|
||||
union signal_data stats_get_value(const struct stats *s, enum stats_metric sm, enum stats_type st);
|
||||
|
132
include/villas/stats.hpp
Normal file
132
include/villas/stats.hpp
Normal file
|
@ -0,0 +1,132 @@
|
|||
/** Statistic collection.
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASnode
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <jansson.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <villas/common.h>
|
||||
#include <villas/hist.hpp>
|
||||
#include <villas/table.hpp>
|
||||
#include <villas/signal.h>
|
||||
|
||||
/* Forward declarations */
|
||||
struct sample;
|
||||
struct node;
|
||||
|
||||
namespace villas {
|
||||
|
||||
class Stats {
|
||||
|
||||
public:
|
||||
enum class Format {
|
||||
HUMAN,
|
||||
JSON,
|
||||
MATLAB
|
||||
};
|
||||
|
||||
enum class Metric {
|
||||
SMPS_SKIPPED, /**< Counter for skipped samples due to hooks. */
|
||||
SMPS_REORDERED, /**< Counter for reordered samples. */
|
||||
|
||||
/* Timings */
|
||||
GAP_SAMPLE, /**< Histogram for inter sample timestamps (as sent by remote). */
|
||||
GAP_RECEIVED, /**< Histogram for inter sample arrival time (as seen by this instance). */
|
||||
OWD, /**< Histogram for one-way-delay (OWD) of received samples. */
|
||||
AGE, /**< Processing time of packets within VILLASnode. */
|
||||
|
||||
/* RTP metrics */
|
||||
RTP_LOSS_FRACTION, /**< Fraction lost since last RTP SR/RR. */
|
||||
RTP_PKTS_LOST, /**< Cumul. no. pkts lost. */
|
||||
RTP_JITTER /**< Interarrival jitter. */
|
||||
};
|
||||
|
||||
enum class Type {
|
||||
LAST,
|
||||
HIGHEST,
|
||||
LOWEST,
|
||||
MEAN,
|
||||
VAR,
|
||||
STDDEV,
|
||||
TOTAL
|
||||
};
|
||||
|
||||
protected:
|
||||
std::unordered_map<Metric, villas::Hist> histograms;
|
||||
|
||||
struct MetricDescription {
|
||||
const char *name;
|
||||
const char *unit;
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
struct TypeDescription {
|
||||
const char *name;
|
||||
enum signal_type signal_type;
|
||||
};
|
||||
|
||||
static std::shared_ptr<Table> table;
|
||||
|
||||
static void setupTable();
|
||||
|
||||
public:
|
||||
|
||||
Stats(int buckets, int warmup);
|
||||
|
||||
static
|
||||
enum Format lookupFormat(const std::string &str);
|
||||
|
||||
static
|
||||
enum Metric lookupMetric(const std::string &str);
|
||||
|
||||
static
|
||||
enum Type lookupType(const std::string &str);
|
||||
|
||||
void update(enum Metric id, double val);
|
||||
|
||||
void reset();
|
||||
|
||||
json_t * toJson() const;
|
||||
|
||||
static
|
||||
void printHeader(enum Format fmt);
|
||||
|
||||
void printPeriodic(FILE *f, enum Format fmt, struct node *p) const;
|
||||
|
||||
void print(FILE *f, enum Format fmt, int verbose) const;
|
||||
|
||||
union signal_data getValue(enum Metric sm, enum Type st) const;
|
||||
|
||||
const villas::Hist & getHistogram(enum Metric sm) const;
|
||||
|
||||
static std::unordered_map<Metric, MetricDescription> metrics;
|
||||
static std::unordered_map<Type, TypeDescription> types;
|
||||
static std::vector<TableColumn> columns;
|
||||
};
|
||||
|
||||
} /* namespace villas */
|
|
@ -25,7 +25,7 @@
|
|||
#include <villas/super_node.hpp>
|
||||
#include <villas/node.h>
|
||||
#include <villas/utils.hpp>
|
||||
#include <villas/stats.h>
|
||||
#include <villas/stats.hpp>
|
||||
#include <villas/api/action.hpp>
|
||||
#include <villas/api/session.hpp>
|
||||
|
||||
|
@ -58,7 +58,7 @@ public:
|
|||
);
|
||||
|
||||
if (n->stats)
|
||||
json_object_set_new(json_node, "stats", stats_json(n->stats));
|
||||
json_object_set_new(json_node, "stats", n->stats->toJson());
|
||||
|
||||
/* Add all additional fields of node here.
|
||||
* This can be used for metadata */
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#include <villas/log.h>
|
||||
#include <villas/node.h>
|
||||
#include <villas/stats.h>
|
||||
#include <villas/stats.hpp>
|
||||
#include <villas/super_node.hpp>
|
||||
#include <villas/utils.hpp>
|
||||
#include <villas/api/session.hpp>
|
||||
|
@ -58,7 +58,7 @@ public:
|
|||
|
||||
if (n->stats) {
|
||||
if (reset) {
|
||||
stats_reset(n->stats);
|
||||
n->stats->reset();
|
||||
info("Stats resetted for node %s", node_name(n));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include <villas/advio.h>
|
||||
#include <villas/hook.hpp>
|
||||
#include <villas/node/exceptions.hpp>
|
||||
#include <villas/stats.h>
|
||||
#include <villas/stats.hpp>
|
||||
#include <villas/node.h>
|
||||
#include <villas/timing.h>
|
||||
|
||||
|
@ -53,11 +53,11 @@ public:
|
|||
|
||||
virtual int process(sample *smp)
|
||||
{
|
||||
stats *s = node->stats;
|
||||
Stats *s = node->stats;
|
||||
|
||||
timespec now = time_now();
|
||||
|
||||
stats_update(s, STATS_METRIC_AGE, time_delta(&smp->ts.received, &now));
|
||||
s->update(Stats::Metric::AGE, time_delta(&smp->ts.received, &now));
|
||||
|
||||
return HOOK_OK;
|
||||
}
|
||||
|
@ -96,22 +96,22 @@ public:
|
|||
|
||||
virtual int process(sample *smp)
|
||||
{
|
||||
stats *s = node->stats;
|
||||
Stats *s = node->stats;
|
||||
|
||||
if (last) {
|
||||
if (smp->flags & last->flags & SAMPLE_HAS_TS_RECEIVED)
|
||||
stats_update(s, STATS_METRIC_GAP_RECEIVED, time_delta(&last->ts.received, &smp->ts.received));
|
||||
s->update(Stats::Metric::GAP_RECEIVED, time_delta(&last->ts.received, &smp->ts.received));
|
||||
|
||||
if (smp->flags & last->flags & SAMPLE_HAS_TS_ORIGIN)
|
||||
stats_update(s, STATS_METRIC_GAP_SAMPLE, time_delta(&last->ts.origin, &smp->ts.origin));
|
||||
s->update(Stats::Metric::GAP_SAMPLE, time_delta(&last->ts.origin, &smp->ts.origin));
|
||||
|
||||
if ((smp->flags & SAMPLE_HAS_TS_ORIGIN) && (smp->flags & SAMPLE_HAS_TS_RECEIVED))
|
||||
stats_update(s, STATS_METRIC_OWD, time_delta(&smp->ts.origin, &smp->ts.received));
|
||||
s->update(Stats::Metric::OWD, time_delta(&smp->ts.origin, &smp->ts.received));
|
||||
|
||||
if (smp->flags & last->flags & SAMPLE_HAS_SEQUENCE) {
|
||||
int dist = smp->sequence - (int32_t) last->sequence;
|
||||
if (dist != 1)
|
||||
stats_update(s, STATS_METRIC_SMPS_REORDERED, dist);
|
||||
s->update(Stats::Metric::SMPS_REORDERED, dist);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,12 +129,12 @@ public:
|
|||
class StatsHook : public Hook {
|
||||
|
||||
protected:
|
||||
struct stats stats;
|
||||
Stats stats;
|
||||
|
||||
StatsReadHook *readHook;
|
||||
StatsWriteHook *writeHook;
|
||||
|
||||
enum stats_format format;
|
||||
enum Stats::Format format;
|
||||
int verbose;
|
||||
int warmup;
|
||||
int buckets;
|
||||
|
@ -146,20 +146,14 @@ public:
|
|||
|
||||
StatsHook(struct path *p, struct node *n, int fl, int prio, bool en = true) :
|
||||
Hook(p, n, fl, prio, en),
|
||||
format(STATS_FORMAT_HUMAN),
|
||||
stats(buckets, warmup),
|
||||
format(Stats::Format::HUMAN),
|
||||
verbose(0),
|
||||
warmup(500),
|
||||
buckets(20),
|
||||
output(nullptr),
|
||||
uri(nullptr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
stats.state = STATE_DESTROYED;
|
||||
ret = stats_init(&stats, buckets, warmup);
|
||||
if (ret)
|
||||
throw RuntimeError("Failed to initialize stats");
|
||||
|
||||
/* Register statistic object to path.
|
||||
*
|
||||
* This allows the path code to update statistics. */
|
||||
|
@ -178,8 +172,7 @@ public:
|
|||
if (uri)
|
||||
free(uri);
|
||||
|
||||
if (stats.state != STATE_DESTROYED)
|
||||
stats_destroy(&stats);
|
||||
stats.~Stats();
|
||||
}
|
||||
|
||||
virtual void start()
|
||||
|
@ -199,7 +192,7 @@ public:
|
|||
{
|
||||
assert(state == STATE_STARTED);
|
||||
|
||||
stats_print(&stats, uri ? output->file : stdout, format, verbose);
|
||||
stats.print(uri ? output->file : stdout, format, verbose);
|
||||
|
||||
if (uri)
|
||||
afclose(output);
|
||||
|
@ -211,19 +204,19 @@ public:
|
|||
{
|
||||
assert(state == STATE_STARTED);
|
||||
|
||||
stats_reset(&stats);
|
||||
stats.reset();
|
||||
}
|
||||
|
||||
virtual void periodic()
|
||||
{
|
||||
assert(state == STATE_STARTED);
|
||||
|
||||
stats_print_periodic(&stats, uri ? output->file : stdout, format, node);
|
||||
stats.printPeriodic(uri ? output->file : stdout, format, node);
|
||||
}
|
||||
|
||||
virtual void parse(json_t *cfg)
|
||||
{
|
||||
int ret, fmt;
|
||||
int ret;
|
||||
json_error_t err;
|
||||
|
||||
assert(state != STATE_STARTED);
|
||||
|
@ -242,11 +235,11 @@ public:
|
|||
throw ConfigError(cfg, err, "node-config-hook-stats");
|
||||
|
||||
if (f) {
|
||||
fmt = stats_lookup_format(f);
|
||||
if (fmt < 0)
|
||||
try {
|
||||
format = Stats::lookupFormat(f);
|
||||
} catch (std::invalid_argument &e) {
|
||||
throw ConfigError(cfg, "node-config-hook-stats", "Invalid statistic output format: {}", f);
|
||||
|
||||
format = static_cast<stats_format>(fmt);
|
||||
}
|
||||
}
|
||||
|
||||
if (u)
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <villas/node.h>
|
||||
#include <villas/signal.h>
|
||||
|
||||
using namespace villas;
|
||||
using namespace villas::utils;
|
||||
|
||||
int mapping_parse_str(struct mapping_entry *me, const char *str, struct vlist *nodes)
|
||||
|
@ -76,13 +77,8 @@ int mapping_parse_str(struct mapping_entry *me, const char *str, struct vlist *n
|
|||
if (!type)
|
||||
goto invalid_format;
|
||||
|
||||
me->stats.metric = stats_lookup_metric(metric);
|
||||
if (me->stats.metric < 0)
|
||||
goto invalid_format;
|
||||
|
||||
me->stats.type = stats_lookup_type(type);
|
||||
if (me->stats.type < 0)
|
||||
goto invalid_format;
|
||||
me->stats.metric = Stats::lookupMetric(metric);
|
||||
me->stats.type = Stats::lookupType(type);
|
||||
}
|
||||
else if (!strcmp(type, "hdr")) {
|
||||
me->type = MAPPING_TYPE_HEADER;
|
||||
|
@ -245,7 +241,7 @@ int mapping_update(const struct mapping_entry *me, struct sample *remapped, cons
|
|||
|
||||
switch (me->type) {
|
||||
case MAPPING_TYPE_STATS:
|
||||
remapped->data[me->offset] = stats_get_value(me->node->stats, me->stats.metric, me->stats.type);
|
||||
remapped->data[me->offset] = me->node->stats->getValue(me->stats.metric, me->stats.type);
|
||||
break;
|
||||
|
||||
case MAPPING_TYPE_TIMESTAMP: {
|
||||
|
@ -350,8 +346,8 @@ int mapping_to_str(const struct mapping_entry *me, unsigned index, char **str)
|
|||
switch (me->type) {
|
||||
case MAPPING_TYPE_STATS:
|
||||
strcatf(str, "stats.%s.%s",
|
||||
stats_metrics[me->stats.metric].name,
|
||||
stats_types[me->stats.type].name
|
||||
Stats::metrics[me->stats.metric].name,
|
||||
Stats::types[me->stats.type].name
|
||||
);
|
||||
break;
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <villas/kernel/tc_netem.h>
|
||||
#endif /* WITH_NETEM */
|
||||
|
||||
using namespace villas;
|
||||
using namespace villas::utils;
|
||||
|
||||
int node_init(struct node *n, struct node_type *vt)
|
||||
|
@ -427,7 +428,7 @@ int node_read(struct node *n, struct sample *smps[], unsigned cnt, unsigned *rel
|
|||
int skipped = nread - rread;
|
||||
|
||||
if (skipped > 0 && n->stats != nullptr) {
|
||||
stats_update(n->stats, STATS_METRIC_SMPS_SKIPPED, skipped);
|
||||
n->stats->update(Stats::Metric::SMPS_SKIPPED, skipped);
|
||||
}
|
||||
|
||||
debug(LOG_NODE | 5, "Received %u samples from node %s of which %d have been skipped", nread, node_name(n), skipped);
|
||||
|
|
|
@ -42,7 +42,7 @@ extern "C" {
|
|||
#include <villas/plugin.h>
|
||||
#include <villas/nodes/socket.hpp>
|
||||
#include <villas/utils.hpp>
|
||||
#include <villas/stats.h>
|
||||
#include <villas/stats.hpp>
|
||||
#include <villas/hook.h>
|
||||
#include <villas/format_type.h>
|
||||
#include <villas/super_node.hpp>
|
||||
|
@ -53,6 +53,7 @@ extern "C" {
|
|||
|
||||
static pthread_t re_pthread;
|
||||
|
||||
using namespace villas;
|
||||
using namespace villas::node;
|
||||
using namespace villas::utils;
|
||||
|
||||
|
@ -300,9 +301,9 @@ static void rtcp_handler(const struct sa *src, struct rtcp_msg *msg, void *arg)
|
|||
rtp_aimd(n, loss_frac);
|
||||
|
||||
if (n->stats) {
|
||||
stats_update(n->stats, STATS_METRIC_RTP_PKTS_LOST, rr->lost);
|
||||
stats_update(n->stats, STATS_METRIC_RTP_LOSS_FRACTION, loss_frac);
|
||||
stats_update(n->stats, STATS_METRIC_RTP_JITTER, rr->jitter);
|
||||
n->stats->update(Stats::Metric::RTP_PKTS_LOST, rr->lost);
|
||||
n->stats->update(Stats::Metric::RTP_LOSS_FRACTION, loss_frac);
|
||||
n->stats->update(Stats::Metric::RTP_JITTER, rr->jitter);
|
||||
}
|
||||
|
||||
r->logger->info("RTCP: rr: num_rrs={}, loss_frac={}, pkts_lost={}, jitter={}", r->rtcp.num_rrs, loss_frac, rr->lost, rr->jitter);
|
||||
|
|
|
@ -25,13 +25,12 @@
|
|||
#include <villas/nodes/stats.hpp>
|
||||
#include <villas/hook.h>
|
||||
#include <villas/plugin.h>
|
||||
#include <villas/stats.h>
|
||||
#include <villas/stats.hpp>
|
||||
#include <villas/super_node.hpp>
|
||||
#include <villas/sample.h>
|
||||
#include <villas/node.h>
|
||||
|
||||
#define STATS_METRICS 6
|
||||
|
||||
using namespace villas;
|
||||
using namespace villas::node;
|
||||
using namespace villas::utils;
|
||||
|
||||
|
@ -72,13 +71,8 @@ int stats_node_signal_parse(struct stats_node_signal *s, json_t *cfg)
|
|||
if (!type)
|
||||
goto invalid_format;
|
||||
|
||||
s->metric = stats_lookup_metric(metric);
|
||||
if (s->metric < 0)
|
||||
goto invalid_format;
|
||||
|
||||
s->type = stats_lookup_type(type);
|
||||
if (s->type < 0)
|
||||
goto invalid_format;
|
||||
s->metric = Stats::lookupMetric(metric);
|
||||
s->type = Stats::lookupType(type);
|
||||
|
||||
s->node_str = strdup(node);
|
||||
|
||||
|
@ -196,16 +190,16 @@ int stats_node_parse(struct node *n, json_t *cfg)
|
|||
error("Failed to parse statistics signal definition of node %s", node_name(n));
|
||||
|
||||
if (!sig->name) {
|
||||
const char *metric = stats_metrics[stats_sig->metric].name;
|
||||
const char *type = stats_types[stats_sig->type].name;
|
||||
const char *metric = Stats::metrics[stats_sig->metric].name;
|
||||
const char *type = Stats::types[stats_sig->type].name;
|
||||
|
||||
sig->name = strf("%s.%s.%s", stats_sig->node_str, metric, type);
|
||||
}
|
||||
|
||||
if (!sig->unit)
|
||||
sig->unit = strdup(stats_metrics[stats_sig->metric].unit);
|
||||
sig->unit = strdup(Stats::metrics[stats_sig->metric].unit);
|
||||
|
||||
if (sig->type != stats_types[stats_sig->type].signal_type)
|
||||
if (sig->type != Stats::types[stats_sig->type].signal_type)
|
||||
error("Invalid type for signal %zu in node %s", i, node_name(n));
|
||||
|
||||
vlist_push(&s->signals, stats_sig);
|
||||
|
@ -226,14 +220,14 @@ int stats_node_read(struct node *n, struct sample *smps[], unsigned cnt, unsigne
|
|||
unsigned len = MIN(vlist_length(&s->signals), smps[0]->capacity);
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
struct stats *st;
|
||||
Stats *st;
|
||||
struct stats_node_signal *sig = (struct stats_node_signal *) vlist_at(&s->signals, i);
|
||||
|
||||
st = sig->node->stats;
|
||||
if (!st)
|
||||
return -1;
|
||||
|
||||
smps[0]->data[i] = stats_get_value(st, sig->metric, sig->type);
|
||||
smps[0]->data[i] = st->getValue(sig->metric, sig->type);
|
||||
}
|
||||
|
||||
smps[0]->length = len;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <villas/node.h>
|
||||
#include <villas/mapping.h>
|
||||
|
||||
using namespace villas;
|
||||
using namespace villas::utils;
|
||||
|
||||
int signal_init(struct signal *s)
|
||||
|
@ -57,7 +58,7 @@ int signal_init_from_mapping(struct signal *s, const struct mapping_entry *me, u
|
|||
|
||||
switch (me->type) {
|
||||
case MAPPING_TYPE_STATS:
|
||||
s->type = stats_types[me->stats.type].signal_type;
|
||||
s->type = Stats::types[me->stats.type].signal_type;
|
||||
break;
|
||||
|
||||
case MAPPING_TYPE_HEADER:
|
||||
|
|
268
lib/stats.cpp
268
lib/stats.cpp
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include <villas/stats.h>
|
||||
#include <villas/stats.hpp>
|
||||
#include <villas/hist.hpp>
|
||||
#include <villas/timing.h>
|
||||
#include <villas/node.h>
|
||||
|
@ -34,180 +34,155 @@
|
|||
using namespace villas;
|
||||
using namespace villas::utils;
|
||||
|
||||
struct stats_metric_description stats_metrics[] = {
|
||||
{ "skipped", STATS_METRIC_SMPS_SKIPPED, "samples", "Skipped samples and the distance between them" },
|
||||
{ "reordered", STATS_METRIC_SMPS_REORDERED, "samples", "Reordered samples and the distance between them" },
|
||||
{ "gap_sent", STATS_METRIC_GAP_SAMPLE, "seconds", "Inter-message timestamps (as sent by remote)" },
|
||||
{ "gap_received", STATS_METRIC_GAP_RECEIVED, "seconds", "Inter-message arrival time (as received by this instance)" },
|
||||
{ "owd", STATS_METRIC_OWD, "seconds", "One-way-delay (OWD) of received messages" },
|
||||
{ "age", STATS_METRIC_AGE, "seconds", "Processing time of packets within the from receive to sent" },
|
||||
{ "rtp.loss_fraction", STATS_METRIC_RTP_LOSS_FRACTION, "percent", "Fraction lost since last RTP SR/RR." },
|
||||
{ "rtp.pkts_lost", STATS_METRIC_RTP_PKTS_LOST, "packets", "Cumulative number of packtes lost" },
|
||||
{ "rtp.jitter", STATS_METRIC_RTP_JITTER, "seconds", "Interarrival jitter" },
|
||||
std::unordered_map<Stats::Metric, Stats::MetricDescription> Stats::metrics = {
|
||||
{ Stats::Metric::SMPS_SKIPPED, { "skipped", "samples", "Skipped samples and the distance between them" }},
|
||||
{ Stats::Metric::SMPS_REORDERED, { "reordered", "samples", "Reordered samples and the distance between them" }},
|
||||
{ Stats::Metric::GAP_SAMPLE, { "gap_sent", "seconds", "Inter-message timestamps (as sent by remote)" }},
|
||||
{ Stats::Metric::GAP_RECEIVED, { "gap_received", "seconds", "Inter-message arrival time (as received by this instance)" }},
|
||||
{ Stats::Metric::OWD, { "owd", "seconds", "One-way-delay (OWD) of received messages" }},
|
||||
{ Stats::Metric::AGE, { "age", "seconds", "Processing time of packets within the from receive to sent" }},
|
||||
{ Stats::Metric::RTP_LOSS_FRACTION, { "rtp.loss_fraction", "percent", "Fraction lost since last RTP SR/RR." }},
|
||||
{ Stats::Metric::RTP_PKTS_LOST, { "rtp.pkts_lost", "packets", "Cumulative number of packtes lost" }},
|
||||
{ Stats::Metric::RTP_JITTER, { "rtp.jitter", "seconds", "Interarrival jitter" }},
|
||||
};
|
||||
|
||||
struct stats_type_description stats_types[] = {
|
||||
{ "last", STATS_TYPE_LAST, SIGNAL_TYPE_FLOAT },
|
||||
{ "highest", STATS_TYPE_HIGHEST, SIGNAL_TYPE_FLOAT },
|
||||
{ "lowest", STATS_TYPE_LOWEST, SIGNAL_TYPE_FLOAT },
|
||||
{ "mean", STATS_TYPE_MEAN, SIGNAL_TYPE_FLOAT },
|
||||
{ "var", STATS_TYPE_VAR, SIGNAL_TYPE_FLOAT },
|
||||
{ "stddev", STATS_TYPE_STDDEV, SIGNAL_TYPE_FLOAT },
|
||||
{ "total", STATS_TYPE_TOTAL, SIGNAL_TYPE_INTEGER }
|
||||
std::unordered_map<Stats::Type, Stats::TypeDescription> Stats::types = {
|
||||
{ Stats::Type::LAST, { "last", SIGNAL_TYPE_FLOAT }},
|
||||
{ Stats::Type::HIGHEST, { "highest", SIGNAL_TYPE_FLOAT }},
|
||||
{ Stats::Type::LOWEST, { "lowest", SIGNAL_TYPE_FLOAT }},
|
||||
{ Stats::Type::MEAN, { "mean", SIGNAL_TYPE_FLOAT }},
|
||||
{ Stats::Type::VAR, { "var", SIGNAL_TYPE_FLOAT }},
|
||||
{ Stats::Type::STDDEV, { "stddev", SIGNAL_TYPE_FLOAT }},
|
||||
{ Stats::Type::TOTAL, { "total", SIGNAL_TYPE_INTEGER }}
|
||||
};
|
||||
|
||||
int stats_lookup_format(const char *str)
|
||||
std::vector<TableColumn> Stats::columns = {
|
||||
{ 10, TableColumn::Alignment::LEFT, "Node", "%s" },
|
||||
{ 10, TableColumn::Alignment::RIGHT, "Recv", "%ju", "pkts" },
|
||||
{ 10, TableColumn::Alignment::RIGHT, "Sent", "%ju", "pkts" },
|
||||
{ 10, TableColumn::Alignment::RIGHT, "Drop", "%ju", "pkts" },
|
||||
{ 10, TableColumn::Alignment::RIGHT, "Skip", "%ju", "pkts" },
|
||||
{ 10, TableColumn::Alignment::RIGHT, "OWD last", "%lf", "secs" },
|
||||
{ 10, TableColumn::Alignment::RIGHT, "OWD mean", "%lf", "secs" },
|
||||
{ 10, TableColumn::Alignment::RIGHT, "Rate last", "%lf", "pkt/sec" },
|
||||
{ 10, TableColumn::Alignment::RIGHT, "Rate mean", "%lf", "pkt/sec" },
|
||||
{ 10, TableColumn::Alignment::RIGHT, "Age mean", "%lf", "secs" },
|
||||
{ 10, TableColumn::Alignment::RIGHT, "Age Max", "%lf", "sec" }
|
||||
};
|
||||
|
||||
enum Stats::Format Stats::lookupFormat(const std::string &str)
|
||||
{
|
||||
if (!strcmp(str, "human"))
|
||||
return STATS_FORMAT_HUMAN;
|
||||
else if (!strcmp(str, "json"))
|
||||
return STATS_FORMAT_JSON;
|
||||
else if (!strcmp(str, "matlab"))
|
||||
return STATS_FORMAT_MATLAB;
|
||||
else
|
||||
return -1;
|
||||
if (str == "human")
|
||||
return Format::HUMAN;
|
||||
else if (str == "json")
|
||||
return Format::JSON;
|
||||
else if (str == "matlab")
|
||||
return Format::MATLAB;
|
||||
|
||||
throw std::invalid_argument("Invalid format");
|
||||
}
|
||||
|
||||
enum stats_metric stats_lookup_metric(const char *str)
|
||||
enum Stats::Metric Stats::lookupMetric(const std::string &str)
|
||||
{
|
||||
for (int i = 0; i < STATS_METRIC_COUNT; i++) {
|
||||
struct stats_metric_description *d = &stats_metrics[i];
|
||||
|
||||
if (!strcmp(str, d->name))
|
||||
return d->metric;
|
||||
for (auto m : metrics) {
|
||||
if (str == m.second.name)
|
||||
return m.first;
|
||||
}
|
||||
|
||||
return STATS_METRIC_INVALID;
|
||||
throw std::invalid_argument("Invalid metric");
|
||||
}
|
||||
|
||||
enum stats_type stats_lookup_type(const char *str)
|
||||
enum Stats::Type Stats::lookupType(const std::string &str)
|
||||
{
|
||||
for (int i = 0; i < STATS_TYPE_COUNT; i++) {
|
||||
struct stats_type_description *d = &stats_types[i];
|
||||
|
||||
if (!strcmp(str, d->name))
|
||||
return d->type;
|
||||
for (auto t : types) {
|
||||
if (str == t.second.name)
|
||||
return t.first;
|
||||
}
|
||||
|
||||
return STATS_TYPE_INVALID;
|
||||
throw std::invalid_argument("Invalid type");
|
||||
}
|
||||
|
||||
int stats_init(struct stats *s, int buckets, int warmup)
|
||||
Stats::Stats(int buckets, int warmup)
|
||||
{
|
||||
assert(s->state == STATE_DESTROYED);
|
||||
|
||||
for (int i = 0; i < STATS_METRIC_COUNT; i++)
|
||||
new (&s->histograms[i]) Hist(buckets, warmup);
|
||||
|
||||
s->state = STATE_INITIALIZED;
|
||||
|
||||
return 0;
|
||||
for (auto m : metrics)
|
||||
histograms[m.first] = Hist(buckets, warmup);
|
||||
}
|
||||
|
||||
int stats_destroy(struct stats *s)
|
||||
void Stats::update(enum Metric m, double val)
|
||||
{
|
||||
assert(s->state != STATE_DESTROYED);
|
||||
|
||||
for (int i = 0; i < STATS_METRIC_COUNT; i++)
|
||||
s->histograms[i].~Hist();
|
||||
|
||||
s->state = STATE_DESTROYED;
|
||||
|
||||
return 0;
|
||||
histograms[m].put(val);
|
||||
}
|
||||
|
||||
void stats_update(struct stats *s, enum stats_metric id, double val)
|
||||
void Stats::reset()
|
||||
{
|
||||
assert(s->state == STATE_INITIALIZED);
|
||||
|
||||
s->histograms[id].put(val);
|
||||
for (auto m : metrics)
|
||||
histograms[m.first].reset();
|
||||
}
|
||||
|
||||
json_t * stats_json(struct stats *s)
|
||||
json_t * Stats::toJson() const
|
||||
{
|
||||
assert(s->state == STATE_INITIALIZED);
|
||||
|
||||
json_t *obj = json_object();
|
||||
|
||||
for (int i = 0; i < STATS_METRIC_COUNT; i++) {
|
||||
struct stats_metric_description *d = &stats_metrics[i];
|
||||
const Hist &h = s->histograms[i];
|
||||
for (auto m : metrics) {
|
||||
const Hist &h = histograms.at(m.first);
|
||||
|
||||
json_object_set_new(obj, d->name, h.toJson());
|
||||
json_object_set_new(obj, m.second.name, h.toJson());
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
void stats_reset(struct stats *s)
|
||||
{
|
||||
assert(s->state == STATE_INITIALIZED);
|
||||
|
||||
for (int i = 0; i < STATS_METRIC_COUNT; i++)
|
||||
s->histograms[i].reset();
|
||||
}
|
||||
|
||||
static std::vector<TableColumn> stats_columns = {
|
||||
{ 10, TableColumn::align::LEFT, "Node", "%s" },
|
||||
{ 10, TableColumn::align::RIGHT, "Recv", "%ju", "pkts" },
|
||||
{ 10, TableColumn::align::RIGHT, "Sent", "%ju", "pkts" },
|
||||
{ 10, TableColumn::align::RIGHT, "Drop", "%ju", "pkts" },
|
||||
{ 10, TableColumn::align::RIGHT, "Skip", "%ju", "pkts" },
|
||||
{ 10, TableColumn::align::RIGHT, "OWD last", "%lf", "secs" },
|
||||
{ 10, TableColumn::align::RIGHT, "OWD mean", "%lf", "secs" },
|
||||
{ 10, TableColumn::align::RIGHT, "Rate last", "%lf", "pkt/sec" },
|
||||
{ 10, TableColumn::align::RIGHT, "Rate mean", "%lf", "pkt/sec" },
|
||||
{ 10, TableColumn::align::RIGHT, "Age mean", "%lf", "secs" },
|
||||
{ 10, TableColumn::align::RIGHT, "Age Max", "%lf", "sec" }
|
||||
};
|
||||
|
||||
static Table stats_table = Table(stats_columns);
|
||||
|
||||
void stats_print_header(enum stats_format fmt)
|
||||
void Stats::printHeader(enum Format fmt)
|
||||
{
|
||||
switch (fmt) {
|
||||
case STATS_FORMAT_HUMAN:
|
||||
stats_table.header();
|
||||
case Format::HUMAN:
|
||||
setupTable();
|
||||
table->header();
|
||||
break;
|
||||
|
||||
default: { }
|
||||
}
|
||||
}
|
||||
|
||||
void stats_print_periodic(struct stats *s, FILE *f, enum stats_format fmt, struct node *n)
|
||||
void Stats::setupTable()
|
||||
{
|
||||
assert(s->state == STATE_INITIALIZED);
|
||||
if (!table)
|
||||
table = std::make_shared<Table>(columns);
|
||||
}
|
||||
|
||||
void Stats::printPeriodic(FILE *f, enum Format fmt, struct node *n) const
|
||||
{
|
||||
switch (fmt) {
|
||||
case STATS_FORMAT_HUMAN:
|
||||
stats_table.row(11,
|
||||
case Format::HUMAN:
|
||||
setupTable();
|
||||
table->row(11,
|
||||
node_name_short(n),
|
||||
(uintmax_t) s->histograms[STATS_METRIC_OWD].getTotal(),
|
||||
(uintmax_t) s->histograms[STATS_METRIC_AGE].getTotal(),
|
||||
(uintmax_t) s->histograms[STATS_METRIC_SMPS_REORDERED].getTotal(),
|
||||
(uintmax_t) s->histograms[STATS_METRIC_SMPS_SKIPPED].getTotal(),
|
||||
(double) s->histograms[STATS_METRIC_OWD].getLast(),
|
||||
(double) s->histograms[STATS_METRIC_OWD].getMean(),
|
||||
(double) 1.0 / s->histograms[STATS_METRIC_GAP_RECEIVED].getLast(),
|
||||
(double) 1.0 / s->histograms[STATS_METRIC_GAP_RECEIVED].getMean(),
|
||||
(double) s->histograms[STATS_METRIC_AGE].getMean(),
|
||||
(double) s->histograms[STATS_METRIC_AGE].getHighest()
|
||||
(uintmax_t) histograms.at(Metric::OWD).getTotal(),
|
||||
(uintmax_t) histograms.at(Metric::AGE).getTotal(),
|
||||
(uintmax_t) histograms.at(Metric::SMPS_REORDERED).getTotal(),
|
||||
(uintmax_t) histograms.at(Metric::SMPS_SKIPPED).getTotal(),
|
||||
(double) histograms.at(Metric::OWD).getLast(),
|
||||
(double) histograms.at(Metric::OWD).getMean(),
|
||||
(double) 1.0 / histograms.at(Metric::GAP_RECEIVED).getLast(),
|
||||
(double) 1.0 / histograms.at(Metric::GAP_RECEIVED).getMean(),
|
||||
(double) histograms.at(Metric::AGE).getMean(),
|
||||
(double) histograms.at(Metric::AGE).getHighest()
|
||||
);
|
||||
break;
|
||||
|
||||
case STATS_FORMAT_JSON: {
|
||||
case Format::JSON: {
|
||||
json_t *json_stats = json_pack("{ s: s, s: i, s: i, s: i, s: i, s: f, s: f, s: f, s: f, s: f, s: f }",
|
||||
"node", node_name(n),
|
||||
"recv", s->histograms[STATS_METRIC_OWD].getTotal(),
|
||||
"sent", s->histograms[STATS_METRIC_AGE].getTotal(),
|
||||
"dropped", s->histograms[STATS_METRIC_SMPS_REORDERED].getTotal(),
|
||||
"skipped", s->histograms[STATS_METRIC_SMPS_SKIPPED].getTotal(),
|
||||
"owd_last", 1.0 / s->histograms[STATS_METRIC_OWD].getLast(),
|
||||
"owd_mean", 1.0 / s->histograms[STATS_METRIC_OWD].getMean(),
|
||||
"rate_last", 1.0 / s->histograms[STATS_METRIC_GAP_SAMPLE].getLast(),
|
||||
"rate_mean", 1.0 / s->histograms[STATS_METRIC_GAP_SAMPLE].getMean(),
|
||||
"age_mean", s->histograms[STATS_METRIC_AGE].getMean(),
|
||||
"age_max", s->histograms[STATS_METRIC_AGE].getHighest()
|
||||
"recv", histograms.at(Metric::OWD).getTotal(),
|
||||
"sent", histograms.at(Metric::AGE).getTotal(),
|
||||
"dropped", histograms.at(Metric::SMPS_REORDERED).getTotal(),
|
||||
"skipped", histograms.at(Metric::SMPS_SKIPPED).getTotal(),
|
||||
"owd_last", 1.0 / histograms.at(Metric::OWD).getLast(),
|
||||
"owd_mean", 1.0 / histograms.at(Metric::OWD).getMean(),
|
||||
"rate_last", 1.0 / histograms.at(Metric::GAP_SAMPLE).getLast(),
|
||||
"rate_mean", 1.0 / histograms.at(Metric::GAP_SAMPLE).getMean(),
|
||||
"age_mean", histograms.at(Metric::AGE).getMean(),
|
||||
"age_max", histograms.at(Metric::AGE).getHighest()
|
||||
);
|
||||
json_dumpf(json_stats, f, 0);
|
||||
break;
|
||||
|
@ -217,64 +192,56 @@ void stats_print_periodic(struct stats *s, FILE *f, enum stats_format fmt, struc
|
|||
}
|
||||
}
|
||||
|
||||
void stats_print(struct stats *s, FILE *f, enum stats_format fmt, int verbose)
|
||||
void Stats::print(FILE *f, enum Format fmt, int verbose) const
|
||||
{
|
||||
assert(s->state == STATE_INITIALIZED);
|
||||
|
||||
switch (fmt) {
|
||||
case STATS_FORMAT_HUMAN:
|
||||
for (int i = 0; i < STATS_METRIC_COUNT; i++) {
|
||||
struct stats_metric_description *d = &stats_metrics[i];
|
||||
|
||||
info("%s: %s", d->name, d->desc);
|
||||
s->histograms[i].print(verbose);
|
||||
case Format::HUMAN:
|
||||
for (auto m : metrics) {
|
||||
info("%s: %s", m.second.name, m.second.desc);
|
||||
histograms.at(m.first).print(verbose);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATS_FORMAT_JSON: {
|
||||
json_t *json_stats = stats_json(s);
|
||||
json_dumpf(json_stats, f, 0);
|
||||
case Format::JSON:
|
||||
json_dumpf(toJson(), f, 0);
|
||||
fflush(f);
|
||||
break;
|
||||
}
|
||||
|
||||
default: { }
|
||||
}
|
||||
}
|
||||
|
||||
union signal_data stats_get_value(const struct stats *s, enum stats_metric sm, enum stats_type st)
|
||||
union signal_data Stats::getValue(enum Metric sm, enum Type st) const
|
||||
{
|
||||
assert(s->state == STATE_INITIALIZED);
|
||||
|
||||
const Hist &h = s->histograms[sm];
|
||||
const Hist &h = histograms.at(sm);
|
||||
union signal_data d;
|
||||
|
||||
switch (st) {
|
||||
case STATS_TYPE_TOTAL:
|
||||
case Type::TOTAL:
|
||||
d.i = h.getTotal();
|
||||
break;
|
||||
|
||||
case STATS_TYPE_LAST:
|
||||
case Type::LAST:
|
||||
d.f = h.getLast();
|
||||
break;
|
||||
|
||||
case STATS_TYPE_HIGHEST:
|
||||
case Type::HIGHEST:
|
||||
d.f = h.getHighest();
|
||||
break;
|
||||
|
||||
case STATS_TYPE_LOWEST:
|
||||
case Type::LOWEST:
|
||||
d.f = h.getLowest();
|
||||
break;
|
||||
|
||||
case STATS_TYPE_MEAN:
|
||||
case Type::MEAN:
|
||||
d.f = h.getMean();
|
||||
break;
|
||||
|
||||
case STATS_TYPE_STDDEV:
|
||||
case Type::STDDEV:
|
||||
d.f = h.getStddev();
|
||||
break;
|
||||
|
||||
case STATS_TYPE_VAR:
|
||||
case Type::VAR:
|
||||
d.f = h.getVar();
|
||||
break;
|
||||
|
||||
|
@ -284,3 +251,10 @@ union signal_data stats_get_value(const struct stats *s, enum stats_metric sm, e
|
|||
|
||||
return d;
|
||||
}
|
||||
|
||||
const Hist & Stats::getHistogram(enum Metric sm) const
|
||||
{
|
||||
return histograms.at(sm);
|
||||
}
|
||||
|
||||
std::shared_ptr<Table> Stats::table = std::shared_ptr<Table>();
|
||||
|
|
|
@ -382,7 +382,7 @@ void SuperNode::start()
|
|||
if (ret)
|
||||
throw RuntimeError("Failed to create timer");
|
||||
|
||||
stats_print_header(STATS_FORMAT_HUMAN);
|
||||
Stats::printHeader(Stats::Format::HUMAN);
|
||||
|
||||
state = STATE_STARTED;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <villas/utils.hpp>
|
||||
#include <villas/signal.h>
|
||||
|
||||
using namespace villas;
|
||||
|
||||
Test(mapping, parse_nodes)
|
||||
{
|
||||
int ret;
|
||||
|
@ -73,8 +75,8 @@ Test(mapping, parse_nodes)
|
|||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(m.node, vlist_lookup(&nodes, "cherry"));
|
||||
cr_assert_eq(m.type, MAPPING_TYPE_STATS);
|
||||
cr_assert_eq(m.stats.metric, STATS_METRIC_OWD);
|
||||
cr_assert_eq(m.stats.type, STATS_TYPE_MEAN);
|
||||
cr_assert_eq(m.stats.metric, Stats::Metric::OWD);
|
||||
cr_assert_eq(m.stats.type, Stats::Type::MEAN);
|
||||
|
||||
ret = mapping_parse_str(&m, "carrot.data[1-2]", &nodes);
|
||||
cr_assert_eq(ret, 0);
|
||||
|
@ -126,8 +128,8 @@ Test(mapping, parse)
|
|||
ret = mapping_parse_str(&m, "stats.owd.mean", nullptr);
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(m.type, MAPPING_TYPE_STATS);
|
||||
cr_assert_eq(m.stats.metric, STATS_METRIC_OWD);
|
||||
cr_assert_eq(m.stats.type, STATS_TYPE_MEAN);
|
||||
cr_assert_eq(m.stats.metric, Stats::Metric::OWD);
|
||||
cr_assert_eq(m.stats.type, Stats::Type::MEAN);
|
||||
|
||||
ret = mapping_parse_str(&m, "data[1-2]", nullptr);
|
||||
cr_assert_eq(ret, 0);
|
||||
|
|
Loading…
Add table
Reference in a new issue