From 91e84d94cb267bf6f16e97b535433fee19a184a6 Mon Sep 17 00:00:00 2001 From: Vicente Hernando Date: Mon, 2 Jul 2018 11:17:22 +0200 Subject: [PATCH 1/2] benchmark: RPC commands timer_list and timer_name_list --- src/modules/benchmark/benchmark.c | 185 +++++++++++++++++++++++++++++- src/modules/benchmark/benchmark.h | 3 + 2 files changed, 187 insertions(+), 1 deletion(-) diff --git a/src/modules/benchmark/benchmark.c b/src/modules/benchmark/benchmark.c index cfa646913e0..c30476d31ba 100644 --- a/src/modules/benchmark/benchmark.c +++ b/src/modules/benchmark/benchmark.c @@ -244,6 +244,9 @@ void bm_reset_timer(int i) bm_mycfg->tindex[i]->last_sum = 0; bm_mycfg->tindex[i]->global_max = 0; bm_mycfg->tindex[i]->global_min = 0xffffffff; + bm_mycfg->tindex[i]->period_sum = 0; + bm_mycfg->tindex[i]->period_max = 0; + bm_mycfg->tindex[i]->period_min = 0xffffffff; } void reset_timers(void) @@ -361,6 +364,11 @@ int _bm_log_timer(unsigned int id) bm_mycfg->tindex[id]->global_max, ((double)bm_mycfg->tindex[id]->sum)/bm_mycfg->tindex[id]->calls); + /* Fill data for last period. */ + bm_mycfg->tindex[id]->period_sum = bm_mycfg->tindex[id]->last_sum; + bm_mycfg->tindex[id]->period_max = bm_mycfg->tindex[id]->last_max; + bm_mycfg->tindex[id]->period_min = bm_mycfg->tindex[id]->last_min; + bm_mycfg->tindex[id]->last_sum = 0; bm_mycfg->tindex[id]->last_max = 0; bm_mycfg->tindex[id]->last_min = 0xffffffff; @@ -610,6 +618,167 @@ void bm_rpc_loglevel(rpc_t* rpc, void* ctx) bm_mycfg->loglevel = v1; } +/** + * Internal buffer to convert llu numbers into strings. + */ +#define BUFFER_S_LEN 100 +static char buffer_s[BUFFER_S_LEN]; + +/** + * Create a RPC structure for a timer. + * + * /return 0 on success. + */ +int bm_rpc_timer_struct(rpc_t* rpc, void* ctx, int id) +{ + void *handle; /* Handle for RPC structure. */ + + /* Create empty structure and obtain its handle */ + if (rpc->add(ctx, "{", &handle) < 0) { + return -1; + } + + int enabled = timer_active(id); + + if (rpc->struct_add(handle, "s", "name", bm_mycfg->tindex[id]->name) < 0) { + return -1; + } + + if (rpc->struct_add(handle, "s", "state", (enabled==0)?"disabled":"enabled") < 0) { + return -1; + } + + if (rpc->struct_add(handle, "d", "id", id) < 0) { + return -1; + } + + if (rpc->struct_add(handle, "d", "granularity", bm_mycfg->granularity) < 0) { + return -1; + } + + /* We use a string to represent long long unsigned integers. */ + int len; + len = snprintf(buffer_s, BUFFER_S_LEN, "%llu", bm_mycfg->tindex[id]->period_sum); + if (len <= 0 || len >= BUFFER_S_LEN) { + LM_ERR("Buffer overflow\n"); + return -1; + } + if (rpc->struct_add(handle, "s", "period_sum", buffer_s) < 0) { + return -1; + } + + len = snprintf(buffer_s, BUFFER_S_LEN, "%llu", bm_mycfg->tindex[id]->period_min); + if (len <= 0 || len >= BUFFER_S_LEN) { + LM_ERR("Buffer overflow\n"); + return -1; + } + if (rpc->struct_add(handle, "s", "period_min", buffer_s) < 0) { + return -1; + } + + len = snprintf(buffer_s, BUFFER_S_LEN, "%llu", bm_mycfg->tindex[id]->period_max); + if (len <= 0 || len >= BUFFER_S_LEN) { + LM_ERR("Buffer overflow\n"); + return -1; + } + if (rpc->struct_add(handle, "s", "period_max", buffer_s) < 0) { + return -1; + } + + if (bm_mycfg->granularity > 0) { + double media = ((double)bm_mycfg->tindex[id]->period_sum)/bm_mycfg->granularity; + + if (rpc->struct_add(handle, "f", "period_media", media) < 0) { + return -1; + } + } + + len = snprintf(buffer_s, BUFFER_S_LEN, "%llu", bm_mycfg->tindex[id]->calls); + if (len <= 0 || len >= BUFFER_S_LEN) { + LM_ERR("Buffer overflow\n"); + return -1; + } + if (rpc->struct_add(handle, "s", "calls", buffer_s) < 0) { + return -1; + } + + len = snprintf(buffer_s, BUFFER_S_LEN, "%llu", bm_mycfg->tindex[id]->sum); + if (len <= 0 || len >= BUFFER_S_LEN) { + LM_ERR("Buffer overflow\n"); + return -1; + } + if (rpc->struct_add(handle, "s", "sum", buffer_s) < 0) { + return -1; + } + + len = snprintf(buffer_s, BUFFER_S_LEN, "%llu", bm_mycfg->tindex[id]->global_min); + if (len <= 0 || len >= BUFFER_S_LEN) { + LM_ERR("Buffer overflow\n"); + return -1; + } + if (rpc->struct_add(handle, "s", "global_min", buffer_s) < 0) { + return -1; + } + + len = snprintf(buffer_s, BUFFER_S_LEN, "%llu", bm_mycfg->tindex[id]->global_max); + if (len <= 0 || len >= BUFFER_S_LEN) { + LM_ERR("Buffer overflow\n"); + return -1; + } + if (rpc->struct_add(handle, "s", "global_max", buffer_s) < 0) { + return -1; + } + + if (bm_mycfg->tindex[id]->calls > 0) { + double media = ((double)bm_mycfg->tindex[id]->sum)/bm_mycfg->tindex[id]->calls; + + if (rpc->struct_add(handle, "f", "global_media", media) < 0) { + return -1; + } + } + + return 0; +} + +void bm_rpc_timer_list(rpc_t* rpc, void* ctx) +{ + int id; + + for (id = 0; id < bm_mycfg->nrtimers; id++) { + + if (bm_rpc_timer_struct(rpc, ctx, id)) { + LM_ERR("Failure writing RPC structure for timer: %d\n", id); + return; + } + + } /* for (id = 0; id < bm_mycfg->nrtimers; id++) */ + + return; +} + +void bm_rpc_timer_name_list(rpc_t* rpc, void* ctx) +{ + char *name = NULL; + unsigned int id = 0; + + if(rpc->scan(ctx, "s", &name) < 1) { + LM_WARN("invalid timer name\n"); + rpc->fault(ctx, 400, "Invalid timer name"); + return; + } + if(_bm_register_timer(name, 0, &id)!=0) { + rpc->fault(ctx, 500, "Register timer failure"); + return; + } + + if (bm_rpc_timer_struct(rpc, ctx, id)) { + LM_ERR("Failure writing RPC structure for timer: %d\n", id); + return; + } + + return; +} + static const char* bm_rpc_enable_global_doc[2] = { "Enable/disable benchmarking", 0 @@ -630,6 +799,16 @@ static const char* bm_rpc_loglevel_doc[2] = { 0 }; +static const char* bm_rpc_timer_list_doc[2] = { + "List all timers", + 0 +}; + +static const char* bm_rpc_timer_name_list_doc[2] = { + "List a timer based on its name", + 0 +}; + rpc_export_t bm_rpc_cmds[] = { {"benchmark.enable_global", bm_rpc_enable_global, bm_rpc_enable_global_doc, 0}, @@ -639,6 +818,10 @@ rpc_export_t bm_rpc_cmds[] = { bm_rpc_granularity_doc, 0}, {"benchmark.loglevel", bm_rpc_loglevel, bm_rpc_loglevel_doc, 0}, + {"benchmark.timer_list", bm_rpc_timer_list, + bm_rpc_timer_list_doc, 0}, + {"benchmark.timer_name_list", bm_rpc_timer_name_list, + bm_rpc_timer_name_list_doc, 0}, {0, 0, 0, 0} }; @@ -683,4 +866,4 @@ int mod_register(char *path, int *dlflags, void *p1, void *p2) /*@} */ -/* End of file */ \ No newline at end of file +/* End of file */ diff --git a/src/modules/benchmark/benchmark.h b/src/modules/benchmark/benchmark.h index fea0649720e..9859f4a36a6 100644 --- a/src/modules/benchmark/benchmark.h +++ b/src/modules/benchmark/benchmark.h @@ -66,6 +66,9 @@ typedef struct benchmark_timer unsigned long long last_min; /* Maximum ... */ unsigned long long global_max; /* Global minimum, since start */ unsigned long long global_min; /* ... maximum ... */ + unsigned long long period_sum; /* Sum for last completed period (between granularity) */ + unsigned long long period_max; /* Maximum for last completed period ... */ + unsigned long long period_min; /* Minimum for last completed period ... */ struct benchmark_timer *next; } benchmark_timer_t; From 71d1c721321d523553ac4975e6c2df95cc56a197 Mon Sep 17 00:00:00 2001 From: Vicente Hernando Date: Mon, 2 Jul 2018 12:33:43 +0200 Subject: [PATCH 2/2] benchmark: documentation for RPC functions timer_list and timer_name_list --- src/modules/benchmark/doc/benchmark_admin.xml | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/modules/benchmark/doc/benchmark_admin.xml b/src/modules/benchmark/doc/benchmark_admin.xml index d01bbc81ee2..10f94b2b5c4 100644 --- a/src/modules/benchmark/doc/benchmark_admin.xml +++ b/src/modules/benchmark/doc/benchmark_admin.xml @@ -332,6 +332,86 @@ bm_log_timer("test"); Modifies the module log level. See "loglevel" variable. +
+ <function moreinfo="none">benchmark.timer_list</function> + + List data for all timers (Last complete period and global data) + Displays info close to the one output in the log by using a RPC structure. + period_sum, period_min and period_media show data for last granularity + period already completed. + + + List all timers + +... +&kamcmd; benchmark.timer_list +{ + name: test + state: enabled + id: 0 + granularity: 2 + period_sum: 69 + period_min: 22 + period_max: 47 + period_media: 34.500000 + calls: 4 + sum: 217 + global_min: 22 + global_max: 88 + global_media: 54.250000 +} +{ + name: test2 + state: enabled + id: 1 + granularity: 2 + period_sum: 122 + period_min: 25 + period_max: 97 + period_media: 61.000000 + calls: 4 + sum: 349 + global_min: 25 + global_max: 151 + global_media: 87.250000 +} +... + + +
+
+ <function moreinfo="none">benchmark.timer_name_list</function> + + List data for one timer based on its name (Last complete period and global data) + It displays info close to the one output in the log by using a RPC structure. + period_sum, period_min and period_media show data for last granularity + period already completed. + + + List one timer + +... +&kamcmd; benchmark.timer_name_list test +{ + name: test + state: enabled + id: 0 + granularity: 2 + period_sum: 69 + period_min: 22 + period_max: 47 + period_media: 34.500000 + calls: 4 + sum: 217 + global_min: 22 + global_max: 88 + global_media: 54.250000 +} +... + + +
+