Переглянути джерело

benchmark: RPC commands timer_list and timer_name_list

Vicente Hernando 7 роки тому
батько
коміт
91e84d94cb
2 змінених файлів з 187 додано та 1 видалено
  1. 184 1
      src/modules/benchmark/benchmark.c
  2. 3 0
      src/modules/benchmark/benchmark.h

+ 184 - 1
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 */
+/* End of file */

+ 3 - 0
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;