diff --git a/daemon/call.c b/daemon/call.c index 32700d8b7..9f39a147f 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_graphite_min_max; +struct global_stats_gauge_min_max rtpe_stats_gauge_graphite_min_max_interval; struct global_stats_ax rtpe_stats; struct global_stats_counter rtpe_stats_interval; diff --git a/daemon/control_ng.c b/daemon/control_ng.c index e1c375d88..1e727589d 100644 --- a/daemon/control_ng.c +++ b/daemon/control_ng.c @@ -50,30 +50,6 @@ const char *ng_command_strings_short[NGC_COUNT] = { "Pub", "SubReq", "SubAns", "Unsub", }; -void timeval_update_request_time(struct request_time *request, const struct timeval *offer_diff) { - // lock offers - mutex_lock(&request->lock); - - // update min value - if (timeval_us(&request->time_min) == 0 || - timeval_cmp(&request->time_min, offer_diff) > 0) { - timeval_from_us(&request->time_min, timeval_us(offer_diff)); - } - - // update max value - if (timeval_us(&request->time_max) == 0 || - timeval_cmp(&request->time_max, offer_diff) < 0) { - timeval_from_us(&request->time_max, timeval_us(offer_diff)); - } - - // update avg value - timeval_add(&request->time_avg, &request->time_avg, offer_diff); - request->count++; - - // unlock offers - mutex_unlock(&request->lock); -} - static void pretty_print(bencode_item_t *el, GString *s) { bencode_item_t *chld; @@ -351,15 +327,15 @@ int control_ng_process(str *buf, const endpoint_t *sin, char *addr, switch (command) { case NGC_OFFER: RTPE_STATS_INC(offers); - timeval_update_request_time(&rtpe_totalstats_interval.offer, &cmd_process_time); + RTPE_GAUGE_SET(offer_time, timeval_us(&cmd_process_time)); break; case NGC_ANSWER: RTPE_STATS_INC(answers); - timeval_update_request_time(&rtpe_totalstats_interval.answer, &cmd_process_time); + RTPE_GAUGE_SET(answer_time, timeval_us(&cmd_process_time)); break; case NGC_DELETE: RTPE_STATS_INC(deletes); - timeval_update_request_time(&rtpe_totalstats_interval.delete, &cmd_process_time); + RTPE_GAUGE_SET(delete_time, timeval_us(&cmd_process_time)); break; default: break; diff --git a/daemon/graphite.c b/daemon/graphite.c index 17d409f6c..5838867d9 100644 --- a/daemon/graphite.c +++ b/daemon/graphite.c @@ -46,23 +46,6 @@ void free_prefix(void) { g_free(graphite_prefix); } -static struct request_time timeval_clear_request_time(struct request_time *request) { - struct request_time ret; - - mutex_lock(&request->lock); - ret = *request; - request->time_min.tv_sec = 0; - request->time_min.tv_usec = 0; - request->time_max.tv_sec = 0; - request->time_max.tv_usec = 0; - request->time_avg.tv_sec = 0; - request->time_avg.tv_usec = 0; - request->count = 0; - mutex_unlock(&request->lock); - - return ret; -} - static int connect_to_graphite_server(const endpoint_t *graphite_ep) { int rc; @@ -94,6 +77,7 @@ GString *print_graphite_data(struct totalstats *sent_data) { long long time_diff_us = timeval_diff(&rtpe_now, &rtpe_latest_graphite_interval_start); stats_counters_ax_calc_avg(&rtpe_stats_graphite, time_diff_us, &rtpe_stats_graphite_interval); stats_counters_min_max_reset(&rtpe_stats_graphite_min_max, &rtpe_stats_graphite_min_max_interval); + stats_gauge_calc_avg_reset(&rtpe_stats_gauge_graphite_min_max_interval, &rtpe_stats_gauge_graphite_min_max); struct totalstats *ts = sent_data; @@ -113,10 +97,6 @@ GString *print_graphite_data(struct totalstats *sent_data) { //ZERO(rtpe_totalstats_interval.total_calls_duration_interval); mutex_unlock(&rtpe_totalstats_interval.total_calls_duration_lock); - ts->offer = timeval_clear_request_time(&rtpe_totalstats_interval.offer); - ts->answer = timeval_clear_request_time(&rtpe_totalstats_interval.answer); - ts->delete = timeval_clear_request_time(&rtpe_totalstats_interval.delete); - rwlock_lock_r(&rtpe_callhash_lock); mutex_lock(&rtpe_totalstats_interval.managed_sess_lock); ts->managed_sess_max = rtpe_totalstats_interval.managed_sess_max; @@ -129,11 +109,6 @@ GString *print_graphite_data(struct totalstats *sent_data) { mutex_unlock(&rtpe_totalstats_interval.managed_sess_lock); rwlock_unlock_r(&rtpe_callhash_lock); - // compute average offer/answer/delete time - timeval_divide(&ts->offer.time_avg, &ts->offer.time_avg, ts->offer.count); - timeval_divide(&ts->answer.time_avg, &ts->answer.time_avg, ts->answer.count); - timeval_divide(&ts->delete.time_avg, &ts->delete.time_avg, ts->delete.count); - GString *graph_str = g_string_new(""); #define GPF(fmt, ...) \ @@ -141,17 +116,17 @@ GString *print_graphite_data(struct totalstats *sent_data) { g_string_append(graph_str, graphite_prefix); \ g_string_append_printf(graph_str, fmt " %llu\n", ##__VA_ARGS__, (unsigned long long)rtpe_now.tv_sec) - GPF("offer_time_min %llu.%06llu",(unsigned long long)ts->offer.time_min.tv_sec,(unsigned long long)ts->offer.time_min.tv_usec); - GPF("offer_time_max %llu.%06llu",(unsigned long long)ts->offer.time_max.tv_sec,(unsigned long long)ts->offer.time_max.tv_usec); - GPF("offer_time_avg %llu.%06llu",(unsigned long long)ts->offer.time_avg.tv_sec,(unsigned long long)ts->offer.time_avg.tv_usec); + GPF("offer_time_min %.6f", (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.min.offer_time) / 1000000.0); + GPF("offer_time_max %.6f", (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.max.offer_time) / 1000000.0); + GPF("offer_time_avg %.6f", (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.avg.offer_time) / 1000000.0); - GPF("answer_time_min %llu.%06llu",(unsigned long long)ts->answer.time_min.tv_sec,(unsigned long long)ts->answer.time_min.tv_usec); - GPF("answer_time_max %llu.%06llu",(unsigned long long)ts->answer.time_max.tv_sec,(unsigned long long)ts->answer.time_max.tv_usec); - GPF("answer_time_avg %llu.%06llu",(unsigned long long)ts->answer.time_avg.tv_sec,(unsigned long long)ts->answer.time_avg.tv_usec); + GPF("answer_time_min %.6f", (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.min.answer_time) / 1000000.0); + GPF("answer_time_max %.6f", (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.max.answer_time) / 1000000.0); + GPF("answer_time_avg %.6f", (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.avg.answer_time) / 1000000.0); - GPF("delete_time_min %llu.%06llu",(unsigned long long)ts->delete.time_min.tv_sec,(unsigned long long)ts->delete.time_min.tv_usec); - GPF("delete_time_max %llu.%06llu",(unsigned long long)ts->delete.time_max.tv_sec,(unsigned long long)ts->delete.time_max.tv_usec); - GPF("delete_time_avg %llu.%06llu",(unsigned long long)ts->delete.time_avg.tv_sec,(unsigned long long)ts->delete.time_avg.tv_usec); + GPF("delete_time_min %.6f", (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.min.delete_time) / 1000000.0); + GPF("delete_time_max %.6f", (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.max.delete_time) / 1000000.0); + GPF("delete_time_avg %.6f", (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.avg.delete_time) / 1000000.0); GPF("call_dur %llu.%06llu",(unsigned long long)ts->total_calls_duration_interval.tv_sec,(unsigned long long)ts->total_calls_duration_interval.tv_usec); GPF("average_call_dur %llu.%06llu",(unsigned long long)ts->total_average_call_dur.tv_sec,(unsigned long long)ts->total_average_call_dur.tv_usec); @@ -235,18 +210,18 @@ GString *print_graphite_data(struct totalstats *sent_data) { (unsigned long long ) ts->total_calls_duration_interval.tv_usec, (unsigned long long ) rtpe_now.tv_sec); - ilog(LOG_DEBUG, "Min/Max/Avg offer processing delay: %llu.%06llu/%llu.%06llu/%llu.%06llu sec", - (unsigned long long)ts->offer.time_min.tv_sec,(unsigned long long)ts->offer.time_min.tv_usec, - (unsigned long long)ts->offer.time_max.tv_sec,(unsigned long long)ts->offer.time_max.tv_usec, - (unsigned long long)ts->offer.time_avg.tv_sec,(unsigned long long)ts->offer.time_avg.tv_usec); - ilog(LOG_DEBUG, "Min/Max/Avg answer processing delay: %llu.%06llu/%llu.%06llu/%llu.%06llu sec", - (unsigned long long)ts->answer.time_min.tv_sec,(unsigned long long)ts->answer.time_min.tv_usec, - (unsigned long long)ts->answer.time_max.tv_sec,(unsigned long long)ts->answer.time_max.tv_usec, - (unsigned long long)ts->answer.time_avg.tv_sec,(unsigned long long)ts->answer.time_avg.tv_usec); - ilog(LOG_DEBUG, "Min/Max/Avg delete processing delay: %llu.%06llu/%llu.%06llu/%llu.%06llu sec", - (unsigned long long)ts->delete.time_min.tv_sec,(unsigned long long)ts->delete.time_min.tv_usec, - (unsigned long long)ts->delete.time_max.tv_sec,(unsigned long long)ts->delete.time_max.tv_usec, - (unsigned long long)ts->delete.time_avg.tv_sec,(unsigned long long)ts->delete.time_avg.tv_usec); + ilog(LOG_DEBUG, "Min/Max/Avg offer processing delay: %.6f/%.6f/%.6f sec", + (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.min.offer_time) / 1000000.0, + (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.max.offer_time) / 1000000.0, + (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.avg.offer_time) / 1000000.0); + ilog(LOG_DEBUG, "Min/Max/Avg answer processing delay: %.6f/%.6f/%.6f sec", + (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.min.answer_time) / 1000000.0, + (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.max.answer_time) / 1000000.0, + (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.avg.answer_time) / 1000000.0); + ilog(LOG_DEBUG, "Min/Max/Avg delete processing delay: %.6f/%.6f/%.6f sec", + (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.min.delete_time) / 1000000.0, + (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.max.delete_time) / 1000000.0, + (double) atomic64_get_na(&rtpe_stats_gauge_graphite_min_max_interval.avg.delete_time) / 1000000.0); return graph_str; } diff --git a/daemon/statistics.c b/daemon/statistics.c index 617941e79..57b2e1c0d 100644 --- a/daemon/statistics.c +++ b/daemon/statistics.c @@ -421,7 +421,6 @@ GQueue *statistics_gather_metrics(void) { struct timeval avg, calls_dur_iv; uint64_t cur_sessions, num_sessions, min_sess_iv, max_sess_iv; - struct request_time offer_iv, answer_iv, delete_iv; mutex_lock(&rtpe_totalstats.total_average_lock); avg = rtpe_totalstats.total_average_call_dur; @@ -504,9 +503,6 @@ GQueue *statistics_gather_metrics(void) { calls_dur_iv = rtpe_totalstats_lastinterval.total_calls_duration_interval; min_sess_iv = rtpe_totalstats_lastinterval.managed_sess_min; max_sess_iv = rtpe_totalstats_lastinterval.managed_sess_max; - offer_iv = rtpe_totalstats_lastinterval.offer; - answer_iv = rtpe_totalstats_lastinterval.answer; - delete_iv = rtpe_totalstats_lastinterval.delete; mutex_unlock(&rtpe_totalstats_lastinterval_lock); HEADER(NULL, ""); @@ -520,27 +516,27 @@ GQueue *statistics_gather_metrics(void) { METRIC("minmanagedsessions", "Min managed sessions", UINT64F, UINT64F, min_sess_iv); METRIC("maxmanagedsessions", "Max managed sessions", UINT64F, UINT64F, max_sess_iv); - METRICl("Min/Max/Avg offer processing delay", "%llu.%06llu/%llu.%06llu/%llu.%06llu sec", - (unsigned long long)offer_iv.time_min.tv_sec,(unsigned long long)offer_iv.time_min.tv_usec, - (unsigned long long)offer_iv.time_max.tv_sec,(unsigned long long)offer_iv.time_max.tv_usec, - (unsigned long long)offer_iv.time_avg.tv_sec,(unsigned long long)offer_iv.time_avg.tv_usec); - METRICsva("minofferdelay", "%llu.%06llu", (unsigned long long)offer_iv.time_min.tv_sec,(unsigned long long)offer_iv.time_min.tv_usec); - METRICsva("maxofferdelay", "%llu.%06llu", (unsigned long long)offer_iv.time_max.tv_sec,(unsigned long long)offer_iv.time_max.tv_usec); - METRICsva("avgofferdelay", "%llu.%06llu", (unsigned long long)offer_iv.time_avg.tv_sec,(unsigned long long)offer_iv.time_avg.tv_usec); - METRICl("Min/Max/Avg answer processing delay", "%llu.%06llu/%llu.%06llu/%llu.%06llu sec", - (unsigned long long)answer_iv.time_min.tv_sec,(unsigned long long)answer_iv.time_min.tv_usec, - (unsigned long long)answer_iv.time_max.tv_sec,(unsigned long long)answer_iv.time_max.tv_usec, - (unsigned long long)answer_iv.time_avg.tv_sec,(unsigned long long)answer_iv.time_avg.tv_usec); - METRICsva("minanswerdelay", "%llu.%06llu", (unsigned long long)answer_iv.time_min.tv_sec,(unsigned long long)answer_iv.time_min.tv_usec); - METRICsva("maxanswerdelay", "%llu.%06llu", (unsigned long long)answer_iv.time_max.tv_sec,(unsigned long long)answer_iv.time_max.tv_usec); - METRICsva("avganswerdelay", "%llu.%06llu", (unsigned long long)answer_iv.time_avg.tv_sec,(unsigned long long)answer_iv.time_avg.tv_usec); - METRICl("Min/Max/Avg delete processing delay", "%llu.%06llu/%llu.%06llu/%llu.%06llu sec", - (unsigned long long)delete_iv.time_min.tv_sec,(unsigned long long)delete_iv.time_min.tv_usec, - (unsigned long long)delete_iv.time_max.tv_sec,(unsigned long long)delete_iv.time_max.tv_usec, - (unsigned long long)delete_iv.time_avg.tv_sec,(unsigned long long)delete_iv.time_avg.tv_usec); - METRICsva("mindeletedelay", "%llu.%06llu", (unsigned long long)delete_iv.time_min.tv_sec,(unsigned long long)delete_iv.time_min.tv_usec); - METRICsva("maxdeletedelay", "%llu.%06llu", (unsigned long long)delete_iv.time_max.tv_sec,(unsigned long long)delete_iv.time_max.tv_usec); - METRICsva("avgdeletedelay", "%llu.%06llu", (unsigned long long)delete_iv.time_avg.tv_sec,(unsigned long long)delete_iv.time_avg.tv_usec); + METRICl("Min/Max/Avg offer processing delay", "%.6f/%.6f/%.6f sec", + (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.min.offer_time) / 1000000.0, + (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.max.offer_time) / 1000000.0, + (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.avg.offer_time) / 1000000.0); + METRICsva("minofferdelay", "%.6f", (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.min.offer_time) / 1000000.0); + METRICsva("maxofferdelay", "%.6f", (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.max.offer_time) / 1000000.0); + METRICsva("avgofferdelay", "%.6f", (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.avg.offer_time) / 1000000.0); + METRICl("Min/Max/Avg answer processing delay", "%.6f/%.6f/%.6f sec", + (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.min.answer_time) / 1000000.0, + (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.max.answer_time) / 1000000.0, + (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.avg.answer_time) / 1000000.0); + METRICsva("minanswerdelay", "%.6f", (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.min.answer_time) / 1000000.0); + METRICsva("maxanswerdelay", "%.6f", (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.max.answer_time) / 1000000.0); + METRICsva("avganswerdelay", "%.6f", (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.avg.answer_time) / 1000000.0); + METRICl("Min/Max/Avg delete processing delay", "%.6f/%.6f/%.6f sec", + (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.min.delete_time) / 1000000.0, + (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.max.delete_time) / 1000000.0, + (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.avg.delete_time) / 1000000.0); + METRICsva("mindeletedelay", "%.6f", (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.min.delete_time) / 1000000.0); + METRICsva("maxdeletedelay", "%.6f", (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.max.delete_time) / 1000000.0); + METRICsva("avgdeletedelay", "%.6f", (double) atomic64_get(&rtpe_stats_gauge_graphite_min_max_interval.avg.delete_time) / 1000000.0); METRICl("Min/Max/Avg offer requests per second", "%llu/%llu/%llu per sec", (unsigned long long) atomic64_get(&rtpe_stats_graphite_min_max_interval.min.offers), @@ -753,10 +749,6 @@ void statistics_free() { mutex_destroy(&rtpe_totalstats_lastinterval_lock); - mutex_destroy(&rtpe_totalstats_interval.offer.lock); - mutex_destroy(&rtpe_totalstats_interval.answer.lock); - mutex_destroy(&rtpe_totalstats_interval.delete.lock); - mutex_destroy(&rtpe_codec_stats_lock); g_hash_table_destroy(rtpe_codec_stats); } @@ -780,10 +772,6 @@ void statistics_init() { mutex_init(&rtpe_totalstats_lastinterval_lock); - mutex_init(&rtpe_totalstats_interval.offer.lock); - mutex_init(&rtpe_totalstats_interval.answer.lock); - mutex_init(&rtpe_totalstats_interval.delete.lock); - mutex_init(&rtpe_codec_stats_lock); rtpe_codec_stats = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, codec_stats_free); } diff --git a/include/call.h b/include/call.h index 012d74d45..fc360cb6c 100644 --- a/include/call.h +++ b/include/call.h @@ -543,6 +543,7 @@ 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_graphite_min_max; +extern struct global_stats_gauge_min_max rtpe_stats_gauge_graphite_min_max_interval; #define RTPE_GAUGE_SET(field, num) \ do { \ diff --git a/include/control_ng.h b/include/control_ng.h index 79743202e..de3c1ed63 100644 --- a/include/control_ng.h +++ b/include/control_ng.h @@ -75,7 +75,6 @@ void control_ng_init(void); void control_ng_cleanup(void); int control_ng_process(str *buf, const endpoint_t *sin, char *addr, void (*cb)(str *, str *, const endpoint_t *, void *), void *p1, struct obj *); -void timeval_update_request_time(struct request_time *request, const struct timeval *offer_diff); INLINE void ng_buffer_release(struct ng_buffer *ngbuf) { mutex_unlock(&ngbuf->lock); diff --git a/include/gauge_stats_fields.inc b/include/gauge_stats_fields.inc index 9fcee8b85..fb405eb7a 100644 --- a/include/gauge_stats_fields.inc +++ b/include/gauge_stats_fields.inc @@ -3,3 +3,6 @@ F(transcoded_media) F(ipv4_sessions) F(ipv6_sessions) F(mixed_sessions) +F(offer_time) +F(answer_time) +F(delete_time) diff --git a/include/statistics.h b/include/statistics.h index 770eea891..f1110bf83 100644 --- a/include/statistics.h +++ b/include/statistics.h @@ -52,13 +52,6 @@ struct global_stats_min_max { }; -struct request_time { - mutex_t lock; - uint64_t count; - struct timeval time_min, time_max, time_avg; -}; - - struct totalstats { time_t started; @@ -72,8 +65,6 @@ struct totalstats { mutex_t total_calls_duration_lock; /* for these two below */ struct timeval total_calls_duration_interval; - - struct request_time offer, answer, delete; }; struct rtp_stats { @@ -192,6 +183,22 @@ INLINE void stats_counters_min_max_reset(struct global_stats_min_max *mm, struct atomic64_inc(&min_max_struct.count.field); \ } while (0) +INLINE void stats_gauge_calc_avg_reset(struct global_stats_gauge_min_max *out, + struct global_stats_gauge_min_max *in_reset) +{ + uint64_t count; + +#define F(x) \ + atomic64_set(&out->min.x, atomic64_get_set(&in_reset->min.x, 0)); \ + atomic64_set(&out->max.x, atomic64_get_set(&in_reset->max.x, 0)); \ + count = atomic64_get_set(&in_reset->count.x, 0); \ + atomic64_set(&out->count.x, count); \ + atomic64_set(&out->avg.x, count ? atomic64_get_set(&in_reset->avg.x, 0) / count : 0); +#include "gauge_stats_fields.inc" +#undef F +} + + void statistics_init(void); void statistics_free(void); diff --git a/t/test-stats.c b/t/test-stats.c index b51033693..16d0dd6f4 100644 --- a/t/test-stats.c +++ b/t/test-stats.c @@ -368,12 +368,10 @@ int main(void) { "}\n"); RTPE_STATS_INC(offers); - struct timeval diff = {2,500000}; - timeval_update_request_time(&rtpe_totalstats_interval.offer, &diff); + RTPE_GAUGE_SET(offer_time, 2500000); RTPE_STATS_INC(offers); - diff = (struct timeval) {3,200000}; - timeval_update_request_time(&rtpe_totalstats_interval.offer, &diff); + RTPE_GAUGE_SET(offer_time, 3200000); graph_str = print_graphite_data(&rtpe_totalstats_lastinterval); assert_g_string_eq(graph_str, @@ -670,8 +668,7 @@ int main(void) { "}\n"); RTPE_STATS_INC(answers); - diff = (struct timeval) {3,200000}; - timeval_update_request_time(&rtpe_totalstats_interval.answer, &diff); + RTPE_GAUGE_SET(answer_time, 3200000); graph_str = print_graphite_data(&rtpe_totalstats_lastinterval); assert_g_string_eq(graph_str,