From 6b5a8f556019aa6971f96c7350ab9bf79db47c28 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 19 May 2022 05:08:19 -0400 Subject: [PATCH] TT#178352 generalise metrics gathering and printing Keep a running lifetime total of all "gauge" type metrics. Also track the square of the sums of all "gauge" type metrics in order to determine the standard deviation. Change-Id: I23f60774a6421636f1a913674c7d1b54a1c5f702 --- daemon/call.c | 1 + daemon/ssrc.c | 5 ++-- daemon/statistics.c | 40 ++++++++++++++++++-------------- include/call.h | 2 ++ include/counter_stats_fields.inc | 3 --- include/gauge_stats_fields.inc | 1 + include/statistics.h | 2 ++ t/test-payload-tracker.c | 1 + 8 files changed, 32 insertions(+), 23 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index 69e00717a..0c5d5be00 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -65,6 +65,7 @@ struct xmlrpc_helper { struct global_stats_gauge rtpe_stats_gauge; +struct global_stats_gauge_min_max rtpe_stats_gauge_cumulative; struct global_stats_gauge_min_max rtpe_stats_gauge_graphite_min_max; struct global_stats_gauge_min_max rtpe_stats_gauge_graphite_min_max_interval; diff --git a/daemon/ssrc.c b/daemon/ssrc.c index 501ddf38b..f818312cc 100644 --- a/daemon/ssrc.c +++ b/daemon/ssrc.c @@ -395,14 +395,13 @@ void ssrc_receiver_report(struct call_media *m, const struct ssrc_receiver_repor .reported = *tv, .packetloss = (unsigned int) rr->fraction_lost * 100 / 256, }; + other_e->packets_lost = rr->packets_lost; mos_calc(ssb); if (ssb->mos) { ilog(LOG_DEBUG, "Calculated MOS from RR for %s%x%s is %.1f", FMT_M(rr->from), (double) ssb->mos / 10.0); - RTPE_STATS_ADD(mos, ssb->mos); - RTPE_STATS_ADD(mos2, ssb->mos * ssb->mos); - RTPE_STATS_INC(mos_num); + RTPE_GAUGE_SET(mos, ssb->mos); } // got a new stats block, add it to reporting ssrc diff --git a/daemon/statistics.c b/daemon/statistics.c index f9da9c3f9..8faa73c24 100644 --- a/daemon/statistics.c +++ b/daemon/statistics.c @@ -523,25 +523,31 @@ GQueue *statistics_gather_metrics(void) { HEADER(NULL, ""); HEADER("}", ""); + uint64_t metric_num, metric_tot, metric2_tot; + double metric_mean, metric_variance; + +#define STAT_GET_PRINT(stat_name, name, divisor) \ + metric_num = atomic64_get(&rtpe_stats_gauge_cumulative.count.stat_name); \ + metric_tot = atomic64_get(&rtpe_stats_gauge_cumulative.avg.stat_name); \ + metric2_tot = atomic64_get(&rtpe_stats_gauge_cumulative.stddev.stat_name); \ + metric_mean = metric_num ? (double) metric_tot / (double) metric_num : 0.0; \ + metric_variance = metric_num \ + ? fabs((double) metric2_tot / (double) metric_num - metric_mean * metric_mean) \ + : 0.0; \ + METRIC(#stat_name "_total", "Sum of all " name " values sampled", "%.6f", "%.6f", \ + (double) metric_tot / (divisor)); \ + PROM(#stat_name "_total", "counter"); \ + METRIC(#stat_name "2_total", "Sum of all " name " square values sampled", "%.6f", "%.6f", \ + (double) metric2_tot / (divisor * divisor)); \ + PROM(#stat_name "2_total", "counter"); \ + METRIC(#stat_name "_samples_total", "Total number of " name " samples", UINT64F, UINT64F, metric_num); \ + PROM(#stat_name "_samples_total", "counter"); \ + METRIC(#stat_name "_average", "Average " name, "%.6f", "%.6f", metric_mean / 10.0); \ + METRIC(#stat_name "_stddev", name " standard deviation", "%.6f", "%.6f", sqrt(metric_variance) / 10.0); \ + HEADER("mos", "MOS statistics:"); HEADER("{", ""); - uint64_t mos_num = atomic64_get(&rtpe_stats_cumulative.mos_num); - uint64_t mos_tot = atomic64_get(&rtpe_stats_cumulative.mos); - uint64_t mos2_tot = atomic64_get(&rtpe_stats_cumulative.mos2); - double mos_mean = mos_num ? (double) mos_tot / (double) mos_num : 0.0; - double mos_variance = mos_num - ? fabs((double) mos2_tot / (double) mos_num - mos_mean * mos_mean) - : 0.0; - METRIC("mos_total", "Sum of all MOS values sampled", "%.6f", "%.6f", - (double) mos_tot / 10.0); - PROM("mos_total", "counter"); - METRIC("mos2_total", "Sum of all MOS square values sampled", "%.6f", "%.6f", - (double) mos2_tot / 100.0); - PROM("mos2_total", "counter"); - METRIC("mos_samples_total", "Total number of MOS samples", UINT64F, UINT64F, mos_num); - PROM("mos_samples_total", "counter"); - METRIC("mos_average", "Average MOS", "%.6f", "%.6f", mos_mean / 10.0); - METRIC("mos_stddev", "MOS standard deviation", "%.6f", "%.6f", sqrt(mos_variance) / 10.0); + STAT_GET_PRINT(mos, "MOS", 10.0); HEADER(NULL, ""); HEADER("}", ""); diff --git a/include/call.h b/include/call.h index 687da9f3a..99946aee0 100644 --- a/include/call.h +++ b/include/call.h @@ -605,12 +605,14 @@ extern GHashTable *rtpe_callhash; extern struct call_iterator_list rtpe_call_iterators[NUM_CALL_ITERATORS]; extern struct global_stats_gauge rtpe_stats_gauge; +extern struct global_stats_gauge_min_max rtpe_stats_gauge_cumulative; // lifetime min/max/average/sums extern struct global_stats_gauge_min_max rtpe_stats_gauge_graphite_min_max; extern struct global_stats_gauge_min_max rtpe_stats_gauge_graphite_min_max_interval; #define RTPE_GAUGE_SET(field, num) \ do { \ atomic64_set(&rtpe_stats_gauge.field, num); \ + RTPE_GAUGE_SET_MIN_MAX(field, rtpe_stats_gauge_cumulative, num); \ RTPE_GAUGE_SET_MIN_MAX(field, rtpe_stats_gauge_graphite_min_max, num); \ } while (0) #define RTPE_GAUGE_ADD(field, num) \ diff --git a/include/counter_stats_fields.inc b/include/counter_stats_fields.inc index 5f7cb93b2..7d130ff8d 100644 --- a/include/counter_stats_fields.inc +++ b/include/counter_stats_fields.inc @@ -19,6 +19,3 @@ F(oneway_stream_sess) F(call_duration) F(call_duration2) F(total_calls_duration_intv) -F(mos) -F(mos2) -F(mos_num) diff --git a/include/gauge_stats_fields.inc b/include/gauge_stats_fields.inc index a26b3edf3..2d614c254 100644 --- a/include/gauge_stats_fields.inc +++ b/include/gauge_stats_fields.inc @@ -8,3 +8,4 @@ FdA(ng_command_times, NGC_COUNT) F(userspace_streams) F(kernel_only_streams) F(kernel_user_streams) +F(mos) diff --git a/include/statistics.h b/include/statistics.h index 356f7f8b4..e834f47f5 100644 --- a/include/statistics.h +++ b/include/statistics.h @@ -42,6 +42,7 @@ struct global_stats_gauge_min_max { struct global_stats_gauge min; struct global_stats_gauge max; struct global_stats_gauge avg; // sum while accumulation is running + struct global_stats_gauge stddev; // sum^2 while accumulation is running struct global_stats_gauge count; }; @@ -177,6 +178,7 @@ INLINE void stats_counters_min_max_reset(struct global_stats_min_max *mm, struct atomic64_min(&min_max_struct.min.field, val); \ atomic64_max(&min_max_struct.max.field, val); \ atomic64_add(&min_max_struct.avg.field, val); \ + atomic64_add(&min_max_struct.stddev.field, (val) * (val)); \ atomic64_inc(&min_max_struct.count.field); \ } while (0) diff --git a/t/test-payload-tracker.c b/t/test-payload-tracker.c index 4c5acfcc0..0ce8a6cb2 100644 --- a/t/test-payload-tracker.c +++ b/t/test-payload-tracker.c @@ -7,6 +7,7 @@ struct rtpengine_config rtpe_config; struct global_stats_gauge rtpe_stats_gauge; +struct global_stats_gauge_min_max rtpe_stats_gauge_cumulative; struct global_stats_gauge_min_max rtpe_stats_gauge_graphite_min_max; struct global_stats_gauge_min_max rtpe_stats_gauge_graphite_min_max_interval; struct global_stats_ax rtpe_stats;