counters.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. /*$Id$
  2. *
  3. * Copyright (C) 2010 iptelorg GmbH
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /**
  18. * @brief counters/statistics rpcs and script functions
  19. * @file
  20. * @ingroup counters
  21. * Module: counters.
  22. */
  23. /*
  24. * History:
  25. * -------
  26. * 2010-08-06 created by andrei
  27. */
  28. #include "../../modparam.h"
  29. #include "../../dprint.h"
  30. #include "../../compiler_opt.h"
  31. #include "../../counters.h"
  32. MODULE_VERSION
  33. /* default script counter group name */
  34. static char* cnt_script_grp = "script";
  35. static int add_script_counter(modparam_t type, void* val);
  36. static int cnt_inc_f(struct sip_msg*, char*, char*);
  37. static int cnt_add_f(struct sip_msg*, char*, char*);
  38. static int cnt_reset_f(struct sip_msg*, char*, char*);
  39. static int cnt_fixup1(void** param, int param_no);
  40. static int cnt_int_fixup(void** param, int param_no);
  41. static cmd_export_t cmds[] = {
  42. {"cnt_inc", cnt_inc_f, 1, cnt_fixup1,
  43. REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|ONSEND_ROUTE},
  44. {"cnt_add", cnt_add_f, 2, cnt_int_fixup,
  45. REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|ONSEND_ROUTE},
  46. {"cnt_reset", cnt_reset_f, 1, cnt_fixup1,
  47. REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|ONSEND_ROUTE},
  48. {0,0,0,0,0}
  49. };
  50. static param_export_t params[] = {
  51. {"script_cnt_grp_name", PARAM_STRING, &cnt_script_grp},
  52. {"script_counter", PARAM_STRING|PARAM_USE_FUNC, add_script_counter},
  53. {0,0,0}
  54. };
  55. static void cnt_get_rpc(rpc_t* rpc, void* ctx);
  56. static const char* cnt_get_doc[] = {
  57. "get counter value (takes group and counter name as parameters)", 0
  58. };
  59. static void cnt_reset_rpc(rpc_t* rpc, void* ctx);
  60. static const char* cnt_reset_doc[] = {
  61. "reset counter (takes group and counter name as parameters)", 0
  62. };
  63. static void cnt_get_raw_rpc(rpc_t* rpc, void* ctx);
  64. static const char* cnt_get_raw_doc[] = {
  65. "get raw counter value (debugging version)", 0
  66. };
  67. static void cnt_grps_list_rpc(rpc_t* rpc, void* ctx);
  68. static const char* cnt_grps_list_doc[] = {
  69. "list all the counter group names", 0
  70. };
  71. static void cnt_var_list_rpc(rpc_t* rpc, void* ctx);
  72. static const char* cnt_var_list_doc[] = {
  73. "list all the counters names in a specified group", 0
  74. };
  75. static void cnt_grp_get_all_rpc(rpc_t* rpc, void* ctx);
  76. static const char* cnt_grp_get_all_doc[] = {
  77. "list all counter names and values in a specified group", 0
  78. };
  79. static void cnt_help_rpc(rpc_t* rpc, void* ctx);
  80. static const char* cnt_help_doc[] = {
  81. "print the description of a counter (group and counter name required).", 0
  82. };
  83. static rpc_export_t counters_rpc[] = {
  84. {"cnt.get", cnt_get_rpc, cnt_get_doc, 0 },
  85. {"cnt.reset", cnt_reset_rpc, cnt_reset_doc, 0 },
  86. {"cnt.get_raw", cnt_get_raw_rpc, cnt_get_raw_doc, 0 },
  87. {"cnt.grps_list", cnt_grps_list_rpc, cnt_grps_list_doc, RET_ARRAY },
  88. {"cnt.var_list", cnt_var_list_rpc, cnt_var_list_doc, RET_ARRAY },
  89. {"cnt.grp_get_all", cnt_grp_get_all_rpc, cnt_grp_get_all_doc, 0 },
  90. {"cnt.help", cnt_help_rpc, cnt_help_doc, 0},
  91. { 0, 0, 0, 0}
  92. };
  93. struct module_exports exports= {
  94. "counters",
  95. cmds,
  96. counters_rpc, /* RPC methods */
  97. params,
  98. 0, /* module initialization function */
  99. 0, /* response function */
  100. 0, /* destroy function */
  101. 0, /* on_cancel function */
  102. 0, /* per-child init function */
  103. };
  104. /** parse the the script_counter modparam.
  105. * Format: [grp.]name[( |:)desc]
  106. * E.g.:
  107. * "name" => new counter: *cnt_script_grp."name"
  108. * "grp.name" => new counter: "grp"."name"
  109. * "name desc" => new counter "name", desc = "desc"
  110. * "grp.name desc" => "grp"."name", desc = "desc".
  111. */
  112. static int add_script_counter(modparam_t type, void* val)
  113. {
  114. char* name;
  115. counter_handle_t h;
  116. int ret;
  117. char* grp;
  118. char* desc;
  119. char* p;
  120. if ((type & PARAM_STRING) == 0) {
  121. BUG("bad parameter type %d\n", type);
  122. goto error;
  123. }
  124. name = (char*) val;
  125. grp = cnt_script_grp; /* default group */
  126. desc = "custom script counter."; /* default desc. */
  127. if ((p = strchr(name, ':')) != 0 ||
  128. (p = strchr(name, ' ')) != 0) {
  129. /* found desc. */
  130. *p = 0;
  131. for(p = p+1; *p && (*p == ' ' || *p == '\t'); p++);
  132. if (*p)
  133. desc = p;
  134. }
  135. if ((p = strchr(name, '.')) != 0) {
  136. /* found group */
  137. grp = name;
  138. *p = 0;
  139. name = p+1;
  140. }
  141. ret = counter_register(&h, grp, name, 0, 0, 0, desc, 0);
  142. if (ret < 0) {
  143. if (ret == -2) {
  144. ERR("counter %s.%s already registered\n", grp, name);
  145. return 0;
  146. }
  147. ERR("failed to register counter %s.%s\n", grp, name);
  148. goto error;
  149. }
  150. return 0;
  151. error:
  152. return -1;
  153. }
  154. static int cnt_fixup1(void** param, int param_no)
  155. {
  156. char* name;
  157. char* grp;
  158. char* p;
  159. counter_handle_t h;
  160. name = (char*)*param;
  161. grp = cnt_script_grp; /* default group */
  162. if ((p = strchr(name, '.')) != 0) {
  163. /* found group */
  164. grp = name;
  165. name = p+1;
  166. *p = 0;
  167. }
  168. if (counter_lookup(&h, grp, name) < 0) {
  169. ERR("counter %s.%s does not exist (forgot to define it?)\n",
  170. grp, name);
  171. return -1;
  172. }
  173. *param = (void*)(long)h.id;
  174. return 0;
  175. }
  176. static int cnt_int_fixup(void** param, int param_no)
  177. {
  178. char* name;
  179. char* grp;
  180. char* p;
  181. counter_handle_t h;
  182. if (param_no == 1) {
  183. name = (char*)*param;
  184. grp = cnt_script_grp; /* default group */
  185. if ((p = strchr(name, '.')) != 0) {
  186. /* found group */
  187. grp = name;
  188. name = p+1;
  189. *p = 0;
  190. }
  191. if (counter_lookup(&h, grp, name) < 0) {
  192. ERR("counter %s.%s does not exist (forgot to define it?)\n",
  193. grp, name);
  194. return -1;
  195. }
  196. *param = (void*)(long)h.id;
  197. } else
  198. return fixup_var_int_2(param, param_no);
  199. return 0;
  200. }
  201. static int cnt_inc_f(struct sip_msg* msg, char* handle, char* bar)
  202. {
  203. counter_handle_t h;
  204. h.id = (long)(void*)handle;
  205. counter_inc(h);
  206. return 1;
  207. }
  208. static int cnt_add_f(struct sip_msg* msg, char* handle, char* val)
  209. {
  210. counter_handle_t h;
  211. int v;
  212. h.id = (long)(void*)handle;
  213. if (unlikely(get_int_fparam(&v, msg, (fparam_t*)val) < 0)) {
  214. ERR("non integer parameter\n");
  215. return -1;
  216. }
  217. counter_add(h, v);
  218. return 1;
  219. }
  220. static int cnt_reset_f(struct sip_msg* msg, char* handle, char* bar)
  221. {
  222. counter_handle_t h;
  223. h.id = (long)(void*)handle;
  224. counter_reset(h);
  225. return 1;
  226. }
  227. static void cnt_grp_get_all(rpc_t* rpc, void* c, char* group);
  228. static void cnt_get_rpc(rpc_t* rpc, void* c)
  229. {
  230. char* group;
  231. char* name;
  232. counter_val_t v;
  233. counter_handle_t h;
  234. if (rpc->scan(c, "s", &group) < 1)
  235. return;
  236. if (rpc->scan(c, "*s", &name) < 1)
  237. cnt_grp_get_all(rpc, c, group);
  238. return;
  239. /* group & name read */
  240. if (counter_lookup(&h, group, name) < 0) {
  241. rpc->fault(c, 400, "non-existent counter %s.%s\n", group, name);
  242. return;
  243. }
  244. v = counter_get_val(h);
  245. rpc->add(c, "d", (int)v);
  246. return;
  247. }
  248. static void cnt_get_raw_rpc(rpc_t* rpc, void* c)
  249. {
  250. char* group;
  251. char* name;
  252. counter_val_t v;
  253. counter_handle_t h;
  254. if (rpc->scan(c, "ss", &group, &name) < 2) {
  255. /* rpc->fault(c, 400, "group and counter name required"); */
  256. return;
  257. }
  258. if (counter_lookup(&h, group, name) < 0) {
  259. rpc->fault(c, 400, "non-existent counter %s.%s\n", group, name);
  260. return;
  261. }
  262. v = counter_get_raw_val(h);
  263. rpc->add(c, "d", (int)v);
  264. return;
  265. }
  266. static void cnt_reset_rpc(rpc_t* rpc, void* c)
  267. {
  268. char* group;
  269. char* name;
  270. counter_handle_t h;
  271. if (rpc->scan(c, "ss", &group, &name) < 2) {
  272. /* rpc->fault(c, 400, "group and counter name required"); */
  273. return;
  274. }
  275. if (counter_lookup(&h, group, name) < 0) {
  276. rpc->fault(c, 400, "non-existent counter %s.%s\n", group, name);
  277. return;
  278. }
  279. counter_reset(h);
  280. return;
  281. }
  282. struct rpc_list_params {
  283. rpc_t* rpc;
  284. void* ctx;
  285. };
  286. /* helper callback for iterating groups or names */
  287. static void rpc_print_name(void* param, str* n)
  288. {
  289. struct rpc_list_params* p;
  290. rpc_t* rpc;
  291. void* ctx;
  292. p = param;
  293. rpc = p->rpc;
  294. ctx = p->ctx;
  295. rpc->add(ctx, "S", n);
  296. }
  297. /* helper callback for iterating on variable names & values*/
  298. static void rpc_print_name_val(void* param, str* g, str* n,
  299. counter_handle_t h)
  300. {
  301. struct rpc_list_params* p;
  302. rpc_t* rpc;
  303. void* s;
  304. p = param;
  305. rpc = p->rpc;
  306. s = p->ctx;
  307. rpc->struct_add(s, "d", n->s, (int)counter_get_val(h));
  308. }
  309. static void cnt_grps_list_rpc(rpc_t* rpc, void* c)
  310. {
  311. struct rpc_list_params packed_params;
  312. packed_params.rpc = rpc;
  313. packed_params.ctx = c;
  314. counter_iterate_grp_names(rpc_print_name, &packed_params);
  315. }
  316. static void cnt_var_list_rpc(rpc_t* rpc, void* c)
  317. {
  318. char* group;
  319. struct rpc_list_params packed_params;
  320. if (rpc->scan(c, "s", &group) < 1) {
  321. /* rpc->fault(c, 400, "group name required"); */
  322. return;
  323. }
  324. packed_params.rpc = rpc;
  325. packed_params.ctx = c;
  326. counter_iterate_grp_var_names(group, rpc_print_name, &packed_params);
  327. }
  328. static void cnt_grp_get_all(rpc_t* rpc, void* c, char* group)
  329. {
  330. void* s;
  331. struct rpc_list_params packed_params;
  332. if (rpc->add(c, "{", &s) < 0) return;
  333. packed_params.rpc = rpc;
  334. packed_params.ctx = s;
  335. counter_iterate_grp_vars(group, rpc_print_name_val, &packed_params);
  336. }
  337. static void cnt_grp_get_all_rpc(rpc_t* rpc, void* c)
  338. {
  339. char* group;
  340. if (rpc->scan(c, "s", &group) < 1) {
  341. /* rpc->fault(c, 400, "group name required"); */
  342. return;
  343. }
  344. cnt_grp_get_all(rpc, c, group);
  345. }
  346. static void cnt_help_rpc(rpc_t* rpc, void* ctx)
  347. {
  348. char* group;
  349. char* name;
  350. char* desc;
  351. counter_handle_t h;
  352. if (rpc->scan(ctx, "ss", &group, &name) < 2) {
  353. /* rpc->fault(c, 400, "group and counter name required"); */
  354. return;
  355. }
  356. if (counter_lookup(&h, group, name) < 0) {
  357. rpc->fault(ctx, 400, "non-existent counter %s.%s\n", group, name);
  358. return;
  359. }
  360. desc = counter_get_doc(h);
  361. if (desc)
  362. rpc->add(ctx, "s", desc);
  363. else
  364. rpc->fault(ctx, 400, "no description for counter %s.%s\n",
  365. group, name);
  366. return;
  367. }
  368. /* vi: set ts=4 sw=4 tw=79:ai:cindent: */