diff --git a/daemon/call.c b/daemon/call.c index a3f60af96..553970cf7 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -466,6 +466,24 @@ destroy: atomic64_add(&ps->stats.x, d); \ atomic64_add(&rtpe_statsps.x, d); \ } while (0) + +static void update_requests_per_second_stats(struct requests_ps *request, u_int64_t new_val) { + mutex_lock(&request->lock); + + request->count++; + request->ps_avg += new_val; + + if ((request->ps_min == 0) || (request->ps_min > new_val)) { + request->ps_min = new_val; + } + + if ((request->ps_max == 0) || (request->ps_max < new_val)) { + request->ps_max = new_val; + } + + mutex_unlock(&request->lock); +} + static void call_timer(void *ptr) { struct iterator_helper hlp; GList *i, *l, *calls = NULL; @@ -477,6 +495,7 @@ static void call_timer(void *ptr) { struct rtp_stats *rs; unsigned int pt; endpoint_t ep; + u_int64_t offers, answers, deletes; ZERO(hlp); hlp.addr_sfd = g_hash_table_new(g_endpoint_hash, g_endpoint_eq); @@ -503,6 +522,16 @@ static void call_timer(void *ptr) { atomic64_set(&rtpe_stats.packets, atomic64_get_na(&tmpstats.packets)); atomic64_set(&rtpe_stats.errors, atomic64_get_na(&tmpstats.errors)); + /* update statistics regarding requests per second */ + offers = atomic64_get_set(&rtpe_statsps.offers, 0); + update_requests_per_second_stats(&rtpe_totalstats_interval.offers_ps, offers); + + answers = atomic64_get_set(&rtpe_statsps.answers, 0); + update_requests_per_second_stats(&rtpe_totalstats_interval.answers_ps, answers); + + deletes = atomic64_get_set(&rtpe_statsps.deletes, 0); + update_requests_per_second_stats(&rtpe_totalstats_interval.deletes_ps, deletes); + i = kernel_list(); while (i) { ke = i->data; diff --git a/daemon/cli.c b/daemon/cli.c index 56f1897e1..dd8b56644 100644 --- a/daemon/cli.c +++ b/daemon/cli.c @@ -171,6 +171,7 @@ static void cli_incoming_list_totals(str *instr, struct streambuf *replybuffer) struct timeval avg, calls_dur_iv; u_int64_t num_sessions, min_sess_iv, max_sess_iv; struct request_time offer_iv, answer_iv, delete_iv; + struct requests_ps offers_ps, answers_ps, deletes_ps; mutex_lock(&rtpe_totalstats.total_average_lock); avg = rtpe_totalstats.total_average_call_dur; @@ -199,13 +200,11 @@ static void cli_incoming_list_totals(str *instr, struct streambuf *replybuffer) offer_iv = rtpe_totalstats_lastinterval.offer; answer_iv = rtpe_totalstats_lastinterval.answer; delete_iv = rtpe_totalstats_lastinterval.delete; + offers_ps = rtpe_totalstats_lastinterval.offers_ps; + answers_ps = rtpe_totalstats_lastinterval.answers_ps; + deletes_ps = rtpe_totalstats_lastinterval.deletes_ps; mutex_unlock(&rtpe_totalstats_lastinterval_lock); - // compute average offer/answer/delete time - timeval_divide(&offer_iv.time_avg, &offer_iv.time_avg, offer_iv.count); - timeval_divide(&answer_iv.time_avg, &answer_iv.time_avg, answer_iv.count); - timeval_divide(&delete_iv.time_avg, &delete_iv.time_avg, delete_iv.count); - streambuf_printf(replybuffer, "\nGraphite interval statistics (last reported values to graphite):\n"); streambuf_printf(replybuffer, " Total calls duration :%ld.%06ld\n\n",calls_dur_iv.tv_sec,calls_dur_iv.tv_usec); streambuf_printf(replybuffer, " Min managed sessions :"UINT64F"\n", min_sess_iv); @@ -223,6 +222,18 @@ static void cli_incoming_list_totals(str *instr, struct streambuf *replybuffer) (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); + streambuf_printf(replybuffer, " Min/Max/Avg offer requests per second :%llu/%llu/%llu per sec\n", + (unsigned long long)offers_ps.ps_min, + (unsigned long long)offers_ps.ps_max, + (unsigned long long)offers_ps.ps_avg); + streambuf_printf(replybuffer, " Min/Max/Avg answer requests per second :%llu/%llu/%llu per sec\n", (unsigned long long)answers_ps.ps_min, + (unsigned long long)answers_ps.ps_max, + (unsigned long long)answers_ps.ps_avg); + streambuf_printf(replybuffer, " Min/Max/Avg delete requests per second :%llu/%llu/%llu per sec\n", + (unsigned long long)deletes_ps.ps_min, + (unsigned long long)deletes_ps.ps_max, + (unsigned long long)deletes_ps.ps_avg); + streambuf_printf(replybuffer, "\n\n"); streambuf_printf(replybuffer, "Control statistics:\n\n"); diff --git a/daemon/control_ng.c b/daemon/control_ng.c index fc10944b2..a41318991 100644 --- a/daemon/control_ng.c +++ b/daemon/control_ng.c @@ -193,6 +193,7 @@ static void control_ng_incoming(struct obj *obj, str *buf, const endpoint_t *sin // print offer duration timeval_from_us(&offer_stop, timeval_diff(&offer_stop, &offer_start)); ilog(LOG_INFO, "offer time = %llu.%06llu sec", (unsigned long long)offer_stop.tv_sec, (unsigned long long)offer_stop.tv_usec); + } else if (!str_cmp(&cmd, "answer")) { // start answer timer @@ -248,10 +249,13 @@ static void control_ng_incoming(struct obj *obj, str *buf, const endpoint_t *sin // update interval statistics if (!str_cmp(&cmd, "offer")) { + atomic64_inc(&rtpe_statsps.offers); timeval_update_request_time(&rtpe_totalstats_interval.offer, &offer_stop); } else if (!str_cmp(&cmd, "answer")) { + atomic64_inc(&rtpe_statsps.answers); timeval_update_request_time(&rtpe_totalstats_interval.answer, &answer_stop); } else if (!str_cmp(&cmd, "delete")) { + atomic64_inc(&rtpe_statsps.deletes); timeval_update_request_time(&rtpe_totalstats_interval.delete, &delete_stop); } diff --git a/daemon/graphite.c b/daemon/graphite.c index 39e2343d3..c10845fed 100644 --- a/daemon/graphite.c +++ b/daemon/graphite.c @@ -42,6 +42,18 @@ void set_prefix(char* prefix) { graphite_prefix = prefix; } +static struct requests_ps clear_requests_per_second(struct requests_ps *requests) { + struct requests_ps ret; + mutex_lock(&requests->lock); + ret = *requests; + requests->count=0; + requests->ps_max = 0; + requests->ps_min = 0; + requests->ps_avg = 0; + mutex_unlock(&requests->lock); + return ret; +} + static struct request_time timeval_clear_request_time(struct request_time *request) { struct request_time ret; @@ -129,6 +141,10 @@ int send_graphite_data(struct totalstats *sent_data) { ts->answer = timeval_clear_request_time(&rtpe_totalstats_interval.answer); ts->delete = timeval_clear_request_time(&rtpe_totalstats_interval.delete); + ts->offers_ps = clear_requests_per_second(&rtpe_totalstats_interval.offers_ps); + ts->answers_ps = clear_requests_per_second(&rtpe_totalstats_interval.answers_ps); + ts->deletes_ps = clear_requests_per_second(&rtpe_totalstats_interval.deletes_ps); + rwlock_lock_r(&rtpe_callhash_lock); mutex_lock(&rtpe_totalstats_interval.managed_sess_lock); ts->managed_sess_max = rtpe_totalstats_interval.managed_sess_max; @@ -145,6 +161,10 @@ int send_graphite_data(struct totalstats *sent_data) { 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); + //compute average offers/answers/deletes per second + ts->offers_ps.ps_avg = (ts->offers_ps.count?(ts->offers_ps.ps_avg/ts->offers_ps.count):0); + ts->answers_ps.ps_avg = (ts->answers_ps.count?(ts->answers_ps.ps_avg/ts->answers_ps.count):0); + ts->deletes_ps.ps_avg = (ts->deletes_ps.count?(ts->deletes_ps.ps_avg/ts->deletes_ps.count):0); if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"offer_time_min %llu.%06llu %llu\n",(unsigned long long)ts->offer.time_min.tv_sec,(unsigned long long)ts->offer.time_min.tv_usec,(unsigned long long)rtpe_now.tv_sec); ptr += rc; @@ -204,6 +224,27 @@ int send_graphite_data(struct totalstats *sent_data) { if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"reject_sess "UINT64F" %llu\n", atomic64_get_na(&ts->total_rejected_sess),(unsigned long long)rtpe_now.tv_sec); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } + rc = sprintf(ptr,"offers_ps_min %llu %llu\n",(unsigned long long)ts->offers_ps.ps_min,(unsigned long long)rtpe_now.tv_sec); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } + rc = sprintf(ptr,"offers_ps_max %llu %llu\n",(unsigned long long)ts->offers_ps.ps_max,(unsigned long long)rtpe_now.tv_sec); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } + rc = sprintf(ptr,"offers_ps_avg %llu %llu\n",(unsigned long long)ts->offers_ps.ps_avg,(unsigned long long)rtpe_now.tv_sec); ptr += rc; + + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } + rc = sprintf(ptr,"answers_ps_min %llu %llu\n",(unsigned long long)ts->answers_ps.ps_min,(unsigned long long)rtpe_now.tv_sec); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } + rc = sprintf(ptr,"answers_ps_max %llu %llu\n",(unsigned long long)ts->answers_ps.ps_max,(unsigned long long)rtpe_now.tv_sec); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } + rc = sprintf(ptr,"answers_ps_avg %llu %llu\n",(unsigned long long)ts->answers_ps.ps_avg,(unsigned long long)rtpe_now.tv_sec); ptr += rc; + + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } + rc = sprintf(ptr,"deletes_ps_min %llu %llu\n",(unsigned long long)ts->deletes_ps.ps_min,(unsigned long long)rtpe_now.tv_sec); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } + rc = sprintf(ptr,"deletes_ps_max %llu %llu\n",(unsigned long long)ts->deletes_ps.ps_max,(unsigned long long)rtpe_now.tv_sec); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s",graphite_prefix); ptr += rc; } + rc = sprintf(ptr,"deletes_ps_avg %llu %llu\n",(unsigned long long)ts->deletes_ps.ps_avg,(unsigned long long)rtpe_now.tv_sec); ptr += rc; + ilog(LOG_DEBUG, "min_sessions:%llu max_sessions:%llu, call_dur_per_interval:%llu.%06llu at time %llu\n", (unsigned long long) ts->managed_sess_min, (unsigned long long) ts->managed_sess_max, @@ -309,7 +350,7 @@ void graphite_loop_run(endpoint_t *graphite_ep, int seconds) { connection_state = STATE_DISCONNECTED; } - copy_with_lock(&rtpe_totalstats_lastinterval, &graphite_stats, &rtpe_totalstats_lastinterval.total_average_lock); + copy_with_lock(&rtpe_totalstats_lastinterval, &graphite_stats, &rtpe_totalstats_lastinterval_lock); } } diff --git a/daemon/statistics.c b/daemon/statistics.c index 74bfd04de..de7d9e70c 100644 --- a/daemon/statistics.c +++ b/daemon/statistics.c @@ -226,4 +226,12 @@ void statistics_init() { //rtpe_totalstats_interval.managed_sess_max = 0; 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_totalstats_interval.offers_ps.lock); + mutex_init(&rtpe_totalstats_interval.answers_ps.lock); + mutex_init(&rtpe_totalstats_interval.deletes_ps.lock); } diff --git a/daemon/statistics.h b/daemon/statistics.h index 0f3bf4150..01c4bfb69 100644 --- a/daemon/statistics.h +++ b/daemon/statistics.h @@ -12,6 +12,9 @@ struct stats { u_int64_t delay_max; u_int8_t in_tos_tclass; /* XXX shouldn't be here - not stats */ atomic64 foreign_sessions; // unresponsible via redis notification + atomic64 offers; + atomic64 answers; + atomic64 deletes; }; @@ -21,6 +24,14 @@ struct request_time { struct timeval time_min, time_max, time_avg; }; +struct requests_ps { + mutex_t lock; + u_int64_t count; + u_int64_t ps_min; + u_int64_t ps_max; + u_int64_t ps_avg; +}; + struct totalstats { time_t started; @@ -52,6 +63,7 @@ struct totalstats { struct timeval total_calls_duration_interval; struct request_time offer, answer, delete; + struct requests_ps offers_ps, answers_ps, deletes_ps; }; struct rtp_stats {