00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00034 #include <string.h>
00035
00036 #include "../../lib/kcore/statistics.h"
00037 #include "../../lib/kmi/mi.h"
00038 #include "../../events.h"
00039 #include "../../dprint.h"
00040 #include "../../timer.h"
00041 #include "../../parser/msg_parser.h"
00042 #include "../../script_cb.h"
00043 #include "../../mem/meminfo.h"
00044 #include "../../mem/shm_mem.h"
00045
00046
00047 #ifdef STATISTICS
00048
00049 stat_var* rcv_reqs;
00050 stat_var* rcv_rpls;
00051 stat_var* fwd_reqs;
00052 stat_var* fwd_rpls;
00053 stat_var* drp_reqs;
00054 stat_var* drp_rpls;
00055 stat_var* err_reqs;
00056 stat_var* err_rpls;
00057 stat_var* bad_URIs;
00058 stat_var* unsupported_methods;
00059 stat_var* bad_msg_hdr;
00063 stat_export_t core_stats[] = {
00064 {"rcv_requests" , 0, &rcv_reqs },
00065 {"rcv_replies" , 0, &rcv_rpls },
00066 {"fwd_requests" , 0, &fwd_reqs },
00067 {"fwd_replies" , 0, &fwd_rpls },
00068 {"drop_requests" , 0, &drp_reqs },
00069 {"drop_replies" , 0, &drp_rpls },
00070 {"err_requests" , 0, &err_reqs },
00071 {"err_replies" , 0, &err_rpls },
00072 {"bad_URIs_rcvd", 0, &bad_URIs },
00073 {"unsupported_methods", 0, &unsupported_methods },
00074 {"bad_msg_hdr", 0, &bad_msg_hdr },
00075 {0,0,0}
00076 };
00077
00078 unsigned long shm_stats_get_size(void);
00079 unsigned long shm_stats_get_used(void);
00080 unsigned long shm_stats_get_rused(void);
00081 unsigned long shm_stats_get_mused(void);
00082 unsigned long shm_stats_get_free(void);
00083 unsigned long shm_stats_get_frags(void);
00084
00085 stat_export_t shm_stats[] = {
00086 {"total_size" , STAT_IS_FUNC, (stat_var**)shm_stats_get_size },
00087 {"used_size" , STAT_IS_FUNC, (stat_var**)shm_stats_get_used },
00088 {"real_used_size" , STAT_IS_FUNC, (stat_var**)shm_stats_get_rused },
00089 {"max_used_size" , STAT_IS_FUNC, (stat_var**)shm_stats_get_mused },
00090 {"free_size" , STAT_IS_FUNC, (stat_var**)shm_stats_get_free },
00091 {"fragments" , STAT_IS_FUNC, (stat_var**)shm_stats_get_frags },
00092 {0,0,0}
00093 };
00094
00095 static struct mi_root *mi_get_stats(struct mi_root *cmd, void *param);
00096 static struct mi_root *mi_reset_stats(struct mi_root *cmd, void *param);
00097 static struct mi_root *mi_clear_stats(struct mi_root *cmd, void *param);
00098
00099 static mi_export_t mi_stat_cmds[] = {
00100 { "get_statistics", mi_get_stats, 0 , 0, 0 },
00101 { "reset_statistics", mi_reset_stats, 0 , 0, 0 },
00102 { "clear_statistics", mi_clear_stats, 0 , 0, 0 },
00103 { 0, 0, 0, 0, 0}
00104 };
00105
00106 int register_mi_stats(void)
00107 {
00108
00109 if (register_mi_mod("core", mi_stat_cmds)<0) {
00110 LM_ERR("unable to register MI cmds\n");
00111 return -1;
00112 }
00113 return 0;
00114 }
00115
00116 static int km_cb_req_stats(struct sip_msg *msg,
00117 unsigned int flags, void *param)
00118 {
00119 update_stat(rcv_reqs, 1);
00120 if(msg->first_line.u.request.method_value==METHOD_OTHER)
00121 update_stat(unsupported_methods, 1);
00122 return 1;
00123 }
00124
00125 static int km_cb_rpl_stats(struct sip_msg *msg,
00126 unsigned int flags, void *param)
00127 {
00128 update_stat(rcv_rpls, 1);
00129 return 1;
00130 }
00131
00132
00133 static int sts_update_core_stats(void *data)
00134 {
00135 int type;
00136
00137 type = (int)(long)data;
00138 switch(type) {
00139 case 1:
00140
00141 update_stat(fwd_reqs, 1);
00142 break;
00143 case 2:
00144
00145 update_stat(fwd_rpls, 1);
00146 break;
00147 case 3:
00148
00149 update_stat(drp_reqs, 1);
00150 break;
00151 case 4:
00152
00153 update_stat(drp_rpls, 1);
00154 break;
00155 case 5:
00156
00157 update_stat(err_reqs, 1);
00158 break;
00159 case 6:
00160
00161 update_stat(err_rpls, 1);
00162 break;
00163 case 7:
00164
00165 update_stat(bad_URIs, 1);
00166 break;
00167 case 8:
00168
00169 update_stat(bad_msg_hdr, 1);
00170 break;
00171 }
00172 return 0;
00173 }
00174
00175 int register_core_stats(void)
00176 {
00177
00178 if (register_module_stats( "core", core_stats)!=0 ) {
00179 LM_ERR("failed to register core statistics\n");
00180 return -1;
00181 }
00182
00183 if (register_module_stats( "shmem", shm_stats)!=0 ) {
00184 LM_ERR("failed to register sh_mem statistics\n");
00185 return -1;
00186 }
00187 if (register_script_cb(km_cb_req_stats, PRE_SCRIPT_CB|REQUEST_CB, 0)<0 ) {
00188 LM_ERR("failed to register PRE request callback\n");
00189 return -1;
00190 }
00191 if (register_script_cb(km_cb_rpl_stats, PRE_SCRIPT_CB|ONREPLY_CB, 0)<0 ) {
00192 LM_ERR("failed to register PRE request callback\n");
00193 return -1;
00194 }
00195 sr_event_register_cb(SREV_CORE_STATS, sts_update_core_stats);
00196
00197 return 0;
00198 }
00199
00200
00201
00202 inline static int mi_add_stat(struct mi_node *rpl, stat_var *stat)
00203 {
00204 struct mi_node *node;
00205
00206 if (stats_support()==0) return -1;
00207
00208 node = addf_mi_node_child(rpl, 0, 0, 0, "%s:%s = %lu",
00209 ZSW(get_stat_module(stat)),
00210 ZSW(get_stat_name(stat)),
00211 get_stat_val(stat) );
00212
00213 if (node==0)
00214 return -1;
00215 return 0;
00216 }
00217
00218
00219
00220
00221 static void mi_add_grp_vars_cbk(void* r, str* g, str* n, counter_handle_t h)
00222 {
00223 struct mi_node *rpl;
00224
00225 rpl = r;
00226 addf_mi_node_child(rpl, 0, 0, 0, "%.*s:%.*s = %lu",
00227 g->len, g->s, n->len, n->s, counter_get_val(h));
00228 }
00229
00230
00231
00232 static void mi_add_all_grps_cbk(void* p, str* g)
00233 {
00234 counter_iterate_grp_vars(g->s, mi_add_grp_vars_cbk, p);
00235 }
00236
00237 static struct mi_root *mi_get_stats(struct mi_root *cmd, void *param)
00238 {
00239 struct mi_root *rpl_tree;
00240 struct mi_node *rpl;
00241 struct mi_node *arg;
00242 stat_var *stat;
00243 str val;
00244
00245
00246 if(stats_support()==0)
00247 return init_mi_tree( 404, "Statistics Not Found", 20);
00248
00249 if (cmd->node.kids==NULL)
00250 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00251
00252 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00253 if (rpl_tree==0)
00254 return 0;
00255 rpl = &rpl_tree->node;
00256
00257 for( arg=cmd->node.kids ; arg ; arg=arg->next) {
00258 if (arg->value.len==0)
00259 continue;
00260
00261 val = arg->value;
00262
00263 if ( val.len==3 && memcmp(val.s,"all",3)==0) {
00264
00265
00266 counter_iterate_grp_names(mi_add_all_grps_cbk, rpl);
00267 } else if ( val.len>1 && val.s[val.len-1]==':') {
00268
00269 val.len--;
00270 val.s[val.len]=0;
00271
00272 counter_iterate_grp_vars(val.s, mi_add_grp_vars_cbk, rpl);
00273 val.s[val.len]=':' ;
00274 } else {
00275
00276 stat = get_stat( &val );
00277 if (stat==0)
00278 continue;
00279 if (mi_add_stat(rpl,stat)!=0)
00280 goto error;
00281 }
00282 }
00283
00284 if (rpl->kids==0) {
00285 free_mi_tree(rpl_tree);
00286 return init_mi_tree( 404, "Statistics Not Found", 20);
00287 }
00288
00289 return rpl_tree;
00290 error:
00291 free_mi_tree(rpl_tree);
00292 return 0;
00293 }
00294
00295
00296
00297 static struct mi_root *mi_reset_stats(struct mi_root *cmd, void *param)
00298 {
00299 struct mi_root *rpl_tree;
00300 struct mi_node *arg;
00301 stat_var *stat;
00302 int found;
00303
00304 if (cmd->node.kids==NULL)
00305 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00306
00307 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00308 if (rpl_tree==0)
00309 return 0;
00310 found = 0;
00311
00312 for( arg=cmd->node.kids ; arg ; arg=arg->next) {
00313 if (arg->value.len==0)
00314 continue;
00315
00316 stat = get_stat( &arg->value );
00317 if (stat==0)
00318 continue;
00319
00320 reset_stat( stat );
00321 found = 1;
00322 }
00323
00324 if (!found) {
00325 free_mi_tree(rpl_tree);
00326 return init_mi_tree( 404, "Statistics Not Found", 20);
00327 }
00328
00329 return rpl_tree;
00330 }
00331
00332
00333 inline static int mi_reset_and_add_stat(struct mi_node *rpl, stat_var *stat)
00334 {
00335 struct mi_node *node;
00336 long old_val, new_val;
00337
00338 if (stats_support()==0) return -1;
00339
00340 old_val=get_stat_val(stat);
00341 reset_stat(stat);
00342 new_val=get_stat_val(stat);
00343
00344 if (old_val==new_val)
00345 {
00346 node = addf_mi_node_child(rpl, 0, 0, 0, "%s:%s = %lu",
00347 ZSW(get_stat_module(stat)),
00348 ZSW(get_stat_name(stat)),
00349 new_val);
00350 } else {
00351 node = addf_mi_node_child(rpl, 0, 0, 0, "%s:%s = %lu (%lu)",
00352 ZSW(get_stat_module(stat)),
00353 ZSW(get_stat_name(stat)),
00354 new_val, old_val );
00355 }
00356
00357 if (node==0)
00358 return -1;
00359 return 0;
00360 }
00361
00362
00363
00364 static void mi_add_grp_vars_cbk2(void* r, str* g, str* n, counter_handle_t h)
00365 {
00366 struct mi_node *rpl;
00367 counter_val_t old_val, new_val;
00368
00369 rpl = r;
00370 old_val = counter_get_val(h);
00371 counter_reset(h);
00372 new_val = counter_get_val(h);
00373
00374 if (old_val==new_val)
00375 {
00376 addf_mi_node_child(rpl, 0, 0, 0, "%.*s:%.*s = %lu",
00377 g->len, g->s, n->len, n->s, new_val);
00378 } else {
00379 addf_mi_node_child(rpl, 0, 0, 0, "%.*s:%.*s = %lu (%lu)",
00380 g->len, g->s, n->len, n->s, new_val, old_val);
00381 }
00382 }
00383
00384
00385
00386 static void mi_add_all_grps_cbk2(void* p, str* g)
00387 {
00388 counter_iterate_grp_vars(g->s, mi_add_grp_vars_cbk2, p);
00389 }
00390
00391
00392 static struct mi_root *mi_clear_stats(struct mi_root *cmd, void *param)
00393 {
00394 struct mi_root *rpl_tree;
00395 struct mi_node *rpl;
00396 struct mi_node *arg;
00397 stat_var *stat;
00398 str val;
00399
00400 if(stats_support()==0)
00401 return init_mi_tree( 404, "Statistics Not Found", 20);
00402
00403 if (cmd->node.kids==NULL)
00404 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00405
00406 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00407 if (rpl_tree==0)
00408 return 0;
00409 rpl = &rpl_tree->node;
00410
00411 for( arg=cmd->node.kids ; arg ; arg=arg->next)
00412 {
00413 if (arg->value.len==0)
00414 continue;
00415
00416 val = arg->value;
00417
00418 if ( val.len==3 && memcmp(val.s,"all",3)==0) {
00419
00420
00421 counter_iterate_grp_names(mi_add_all_grps_cbk2, rpl);
00422 } else if ( val.len>1 && val.s[val.len-1]==':') {
00423
00424 val.len--;
00425 val.s[val.len]=0;
00426
00427 counter_iterate_grp_vars(val.s, mi_add_grp_vars_cbk2, rpl);
00428 val.s[val.len]=':' ;
00429 } else {
00430
00431 stat = get_stat( &val );
00432
00433 if (stat==0)
00434 continue;
00435 if (mi_reset_and_add_stat(rpl,stat)!=0)
00436 goto error;
00437 }
00438 }
00439
00440 if (rpl->kids==0) {
00441 free_mi_tree(rpl_tree);
00442 return init_mi_tree( 404, "Statistics Not Found", 20);
00443 }
00444
00445 return rpl_tree;
00446 error:
00447 free_mi_tree(rpl_tree);
00448 return 0;
00449 }
00450
00451
00452
00453 static struct mem_info _stats_shm_mi;
00454 static ticks_t _stats_shm_tm = 0;
00455 void stats_shm_update(void)
00456 {
00457 ticks_t t;
00458 t = get_ticks();
00459 if(t!=_stats_shm_tm) {
00460 shm_info(&_stats_shm_mi);
00461 _stats_shm_tm = t;
00462 }
00463 }
00464 unsigned long shm_stats_get_size(void)
00465 {
00466 stats_shm_update();
00467 return _stats_shm_mi.total_size;
00468 }
00469
00470 unsigned long shm_stats_get_used(void)
00471 {
00472 stats_shm_update();
00473 return _stats_shm_mi.used;
00474 }
00475
00476 unsigned long shm_stats_get_rused(void)
00477 {
00478 stats_shm_update();
00479 return _stats_shm_mi.real_used;
00480 }
00481
00482 unsigned long shm_stats_get_mused(void)
00483 {
00484 stats_shm_update();
00485 return _stats_shm_mi.max_used;
00486 }
00487
00488 unsigned long shm_stats_get_free(void)
00489 {
00490 stats_shm_update();
00491 return _stats_shm_mi.free;
00492 }
00493
00494 unsigned long shm_stats_get_frags(void)
00495 {
00496 stats_shm_update();
00497 return _stats_shm_mi.total_frags;
00498 }
00499
00500 #endif