... | ... |
@@ -13,6 +13,7 @@ |
13 | 13 |
#include "../../error.h" |
14 | 14 |
#include "t_reply.h" |
15 | 15 |
#include "t_cancel.h" |
16 |
+#include "t_stats.h" |
|
16 | 17 |
|
17 | 18 |
unsigned int transaction_count( void ) |
18 | 19 |
{ |
... | ... |
@@ -278,6 +279,12 @@ void insert_into_hash_table_unsafe( struct s_table *hash_table, |
278 | 279 |
|
279 | 280 |
/* update stats */ |
280 | 281 |
p_entry->entries++; |
282 |
+ cur_stats->transactions++; |
|
283 |
+ acc_stats->transactions++; |
|
284 |
+ if (p_cell->local) { |
|
285 |
+ cur_stats->client_transactions++; |
|
286 |
+ acc_stats->client_transactions++; |
|
287 |
+ } |
|
281 | 288 |
} |
282 | 289 |
|
283 | 290 |
|
... | ... |
@@ -313,6 +320,9 @@ void remove_from_hash_table_unsafe(struct s_table *hash_table, |
313 | 320 |
p_entry->last_cell = p_cell->prev_cell; |
314 | 321 |
/* update stats */ |
315 | 322 |
p_entry->entries--; |
323 |
+ cur_stats->transactions--; |
|
324 |
+ if (p_cell->local) cur_stats->client_transactions--; |
|
325 |
+ cur_stats->waiting--; |
|
316 | 326 |
|
317 | 327 |
/* unlock( &(p_entry->mutex) ); */ |
318 | 328 |
} |
... | ... |
@@ -23,6 +23,7 @@ |
23 | 23 |
#include "t_lookup.h" |
24 | 24 |
#include "t_fwd.h" |
25 | 25 |
#include "fix_lumps.h" |
26 |
+#include "t_stats.h" |
|
26 | 27 |
|
27 | 28 |
/* where to go if there is no positive reply */ |
28 | 29 |
static int goto_on_negative=0; |
... | ... |
@@ -49,6 +50,20 @@ unsigned int get_on_negative() |
49 | 50 |
return goto_on_negative; |
50 | 51 |
} |
51 | 52 |
|
53 |
+static void update_reply_stats( int code ) { |
|
54 |
+ if (code>=600) { |
|
55 |
+ acc_stats->completed_6xx++; |
|
56 |
+ } else if (code>=500) { |
|
57 |
+ acc_stats->completed_5xx++; |
|
58 |
+ } else if (code>=400) { |
|
59 |
+ acc_stats->completed_4xx++; |
|
60 |
+ } else if (code>=300) { |
|
61 |
+ acc_stats->completed_3xx++; |
|
62 |
+ } else if (code>=200) { |
|
63 |
+ acc_stats->completed_2xx++; |
|
64 |
+ } |
|
65 |
+} |
|
66 |
+ |
|
52 | 67 |
|
53 | 68 |
/* the main code of stateful replying */ |
54 | 69 |
static int _reply( struct cell *t, struct sip_msg* p_msg, unsigned int code, |
... | ... |
@@ -174,7 +189,8 @@ static int _reply( struct cell *trans, struct sip_msg* p_msg, |
174 | 189 |
/* needs to be protected too because what timers are set depends |
175 | 190 |
on current transactions status */ |
176 | 191 |
/* t_update_timers_after_sending_reply( rb ); */ |
177 |
- |
|
192 |
+ update_reply_stats( code ); |
|
193 |
+ acc_stats->replied_localy++; |
|
178 | 194 |
if (lock) UNLOCK_REPLIES( trans ); |
179 | 195 |
|
180 | 196 |
/* do UAC cleanup procedures in case we generated |
... | ... |
@@ -335,6 +351,7 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch, |
335 | 351 |
free_via_lump(&relayed_msg->repl_add_rm); |
336 | 352 |
} |
337 | 353 |
} |
354 |
+ update_reply_stats( relayed_code ); |
|
338 | 355 |
if (!buf) { |
339 | 356 |
LOG(L_ERR, "ERROR: relay_reply: " |
340 | 357 |
"no mem for outbound reply buffer\n"); |
... | ... |
@@ -454,6 +471,7 @@ enum rps local_reply( struct cell *t, struct sip_msg *p_msg, int branch, |
454 | 471 |
winning_code=winning_msg->REPLY_STATUS; |
455 | 472 |
} |
456 | 473 |
t->uas.status = winning_code; |
474 |
+ update_reply_stats( winning_code ); |
|
457 | 475 |
} |
458 | 476 |
UNLOCK_REPLIES(t); |
459 | 477 |
if (local_winner>=0 && winning_code>=200 ) { |
460 | 478 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,104 @@ |
1 |
+/* |
|
2 |
+ * |
|
3 |
+ * $Id$ |
|
4 |
+ * |
|
5 |
+ */ |
|
6 |
+ |
|
7 |
+ |
|
8 |
+#include <stdio.h> |
|
9 |
+#include "t_stats.h" |
|
10 |
+#include "../../mem/shm_mem.h" |
|
11 |
+#include "../../dprint.h" |
|
12 |
+#include "../../config.h" |
|
13 |
+#include "../../fifo_server.h" |
|
14 |
+ |
|
15 |
+struct t_stats *cur_stats, *acc_stats; |
|
16 |
+ |
|
17 |
+int print_stats( FILE *f ) |
|
18 |
+{ |
|
19 |
+ time_t now; |
|
20 |
+ |
|
21 |
+ time(&now); |
|
22 |
+ |
|
23 |
+ fprintf(f, "Time:\n----------------\n"); |
|
24 |
+ fprintf(f, "Now: %s", ctime(&now)); |
|
25 |
+ fprintf(f, "Up since: %s", ctime(&acc_stats->up_since)); |
|
26 |
+ fprintf(f, "Up time: %.f [sec]\n", difftime(now, acc_stats->up_since)); |
|
27 |
+ fprintf(f, "\nCurrent values:\n----------------\n"); |
|
28 |
+ fprintf(f, "# of transactions: %d\n", |
|
29 |
+ cur_stats->transactions ); |
|
30 |
+ fprintf(f, " - local: %d\n", |
|
31 |
+ cur_stats->client_transactions ); |
|
32 |
+ fprintf(f, " - waiting: %d\n", |
|
33 |
+ cur_stats->waiting ); |
|
34 |
+ |
|
35 |
+ fprintf(f, "\nCummulative values:\n----------------\n"); |
|
36 |
+ fprintf(f, "# of transactions: %d\n", |
|
37 |
+ acc_stats->transactions ); |
|
38 |
+ fprintf(f, " - local: %d\n", |
|
39 |
+ acc_stats->client_transactions ); |
|
40 |
+ fprintf(f, " - waiting: %d\n", |
|
41 |
+ acc_stats->waiting ); |
|
42 |
+ |
|
43 |
+ fprintf(f, "Replied localy: %d\n", |
|
44 |
+ acc_stats->replied_localy ); |
|
45 |
+ fprintf(f, "Completion status 6xx: %d\n", |
|
46 |
+ acc_stats->completed_6xx ); |
|
47 |
+ fprintf(f, "Completion status 5xx: %d\n", |
|
48 |
+ acc_stats->completed_5xx ); |
|
49 |
+ fprintf(f, "Completion status 4xx: %d\n", |
|
50 |
+ acc_stats->completed_4xx ); |
|
51 |
+ fprintf(f, "Completion status 3xx: %d\n", |
|
52 |
+ acc_stats->completed_3xx ); |
|
53 |
+ fprintf(f, "Completion status 2xx: %d\n", |
|
54 |
+ acc_stats->completed_2xx ); |
|
55 |
+ |
|
56 |
+ return 1; |
|
57 |
+} |
|
58 |
+ |
|
59 |
+int static fifo_stats( FILE *pipe, char *response_file ) |
|
60 |
+{ |
|
61 |
+ FILE *file; |
|
62 |
+ |
|
63 |
+ if (response_file==0 || *response_file==0 ) { |
|
64 |
+ LOG(L_ERR, "ERROR: fifo_stats: null file\n"); |
|
65 |
+ return -1; |
|
66 |
+ } |
|
67 |
+ |
|
68 |
+ file=fopen(response_file, "w" ); |
|
69 |
+ if (file==NULL) { |
|
70 |
+ LOG(L_ERR, "ERROR: fifo_stats: file %s bad: %s\n", |
|
71 |
+ response_file, strerror(errno) ); |
|
72 |
+ return -1; |
|
73 |
+ } |
|
74 |
+ print_stats( file ); |
|
75 |
+ fclose(file); |
|
76 |
+ |
|
77 |
+ return 1; |
|
78 |
+ |
|
79 |
+} |
|
80 |
+ |
|
81 |
+int init_stats(void) |
|
82 |
+{ |
|
83 |
+ cur_stats=shm_malloc(sizeof(struct t_stats)); |
|
84 |
+ if (cur_stats==0) { |
|
85 |
+ LOG(L_ERR, "ERROR: init_stats: no mem for stats\n"); |
|
86 |
+ return -1; |
|
87 |
+ } |
|
88 |
+ acc_stats=shm_malloc(sizeof(struct t_stats)); |
|
89 |
+ if (acc_stats==0) { |
|
90 |
+ LOG(L_ERR, "ERROR: init_stats: no mem for stats\n"); |
|
91 |
+ shm_free(cur_stats); |
|
92 |
+ return -1; |
|
93 |
+ } |
|
94 |
+ |
|
95 |
+ if (register_fifo_cmd(fifo_stats, "t_stats", 0)<0) { |
|
96 |
+ LOG(L_CRIT, "cannot register fifo stats\n"); |
|
97 |
+ return -1; |
|
98 |
+ } |
|
99 |
+ |
|
100 |
+ memset(cur_stats, 0, sizeof(struct t_stats) ); |
|
101 |
+ memset(acc_stats, 0, sizeof(struct t_stats) ); |
|
102 |
+ time(&acc_stats->up_since); |
|
103 |
+ return 1; |
|
104 |
+} |
0 | 105 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,30 @@ |
1 |
+/* |
|
2 |
+ * |
|
3 |
+ * $Id$ |
|
4 |
+ * |
|
5 |
+ */ |
|
6 |
+ |
|
7 |
+#ifndef _T_STATS_H |
|
8 |
+#define _T_STATS_H |
|
9 |
+ |
|
10 |
+#include <time.h> |
|
11 |
+ |
|
12 |
+extern struct t_stats *cur_stats, *acc_stats; |
|
13 |
+ |
|
14 |
+struct t_stats { |
|
15 |
+ /* number of server transactions */ |
|
16 |
+ unsigned int transactions; |
|
17 |
+ /* number of UAC transactions (part of transactions) */ |
|
18 |
+ unsigned int client_transactions; |
|
19 |
+ /* number of transactions in wait state */ |
|
20 |
+ unsigned int waiting; |
|
21 |
+ /* number of transactions which completed with this status */ |
|
22 |
+ unsigned int completed_3xx, completed_4xx, completed_5xx, |
|
23 |
+ completed_6xx, completed_2xx; |
|
24 |
+ unsigned int replied_localy; |
|
25 |
+ time_t up_since; |
|
26 |
+}; |
|
27 |
+ |
|
28 |
+int init_stats(void); |
|
29 |
+ |
|
30 |
+#endif |
... | ... |
@@ -76,6 +76,8 @@ |
76 | 76 |
#include "../../dprint.h" |
77 | 77 |
#include "lock.h" |
78 | 78 |
|
79 |
+#include "t_stats.h" |
|
80 |
+ |
|
79 | 81 |
int timer_group[NR_OF_TIMER_LISTS] = |
80 | 82 |
{ |
81 | 83 |
TG_FR, TG_FR, |
... | ... |
@@ -321,6 +323,12 @@ void set_1timer( struct s_table *hash_table, |
321 | 323 |
/* make sure I'm not already on a list */ |
322 | 324 |
/* remove_timer_unsafe( new_tl ); */ |
323 | 325 |
add_timer_unsafe( list, new_tl, get_ticks()+timeout); |
326 |
+ |
|
327 |
+ /* set_1timer is used only by WAIT -- that's why we can |
|
328 |
+ afford updating wait statistics; I admit its not nice |
|
329 |
+ but it greatly utilizes existing lock |
|
330 |
+ */ |
|
331 |
+ cur_stats->waiting++;acc_stats->waiting++; |
|
324 | 332 |
} |
325 | 333 |
unlock(list->mutex); |
326 | 334 |
} |
... | ... |
@@ -26,6 +26,7 @@ |
26 | 26 |
#include "uac.h" |
27 | 27 |
#include "t_fwd.h" |
28 | 28 |
#include "t_lookup.h" |
29 |
+#include "t_stats.h" |
|
29 | 30 |
|
30 | 31 |
|
31 | 32 |
|
... | ... |
@@ -236,6 +237,11 @@ static int mod_init(void) |
236 | 237 |
LOG(L_CRIT, "cannot register fifo uac\n"); |
237 | 238 |
return -1; |
238 | 239 |
} |
240 |
+ |
|
241 |
+ if (init_stats()<0) { |
|
242 |
+ LOG(L_CRIT, "ERROR: mod_init: failed to init stats\n"); |
|
243 |
+ return -1; |
|
244 |
+ } |
|
239 | 245 |
|
240 | 246 |
if (tm_startup()==-1) return -1; |
241 | 247 |
uac_init(); |
... | ... |
@@ -8,6 +8,11 @@ |
8 | 8 |
# realm |
9 | 9 |
DOMAIN=iptel.org |
10 | 10 |
|
11 |
+# ser's FIFO server |
|
12 |
+SER_FIFO=/tmp/ser_fifo |
|
13 |
+# period in which stats are reprinted |
|
14 |
+WATCH_PERIOD=2 |
|
15 |
+ |
|
11 | 16 |
# SQL config |
12 | 17 |
SQL_DB=csps107 |
13 | 18 |
SQL_HOST=dbhost |
... | ... |
@@ -98,6 +103,16 @@ prompt_pw() { |
98 | 103 |
fi |
99 | 104 |
} |
100 | 105 |
|
106 |
+# $1 = name $2=path $3=attempt |
|
107 |
+print_stats() { |
|
108 |
+echo "[cycle: $3; if screen empty, make sure server is alive]" |
|
109 |
+cat > $SER_FIFO <<EOF |
|
110 |
+ |
|
111 |
+:t_stats:$1 |
|
112 |
+EOF |
|
113 |
+cat < $2 |
|
114 |
+} |
|
115 |
+ |
|
101 | 116 |
|
102 | 117 |
# input: sql query, optional mysql command-line params |
103 | 118 |
sql_query() { |
... | ... |
@@ -370,6 +385,30 @@ case $1 in |
370 | 385 |
fi |
371 | 386 |
;; |
372 | 387 |
|
388 |
+ stats) |
|
389 |
+ name=ser_receiver_$$ |
|
390 |
+ path=/tmp/$name |
|
391 |
+ if [ ! -w $SER_FIFO ]; then |
|
392 |
+ echo "Error opening ser's FIFO $SER_FIFO" |
|
393 |
+ echo "Make sure you have line fifo=$SER_FIFO in your config" |
|
394 |
+ exit 1 |
|
395 |
+ fi |
|
396 |
+ mkfifo $path |
|
397 |
+ if [ $? -ne 0 ] ; then |
|
398 |
+ echo "error opening read fifo $path" |
|
399 |
+ exit 1 |
|
400 |
+ fi |
|
401 |
+ attempt=0 |
|
402 |
+ while [ 1 -eq 1 ]; do |
|
403 |
+ attempt=`expr $attempt + 1` |
|
404 |
+ clear |
|
405 |
+ print_stats $name $path $attempt |
|
406 |
+ sleep $WATCH_PERIOD |
|
407 |
+ done |
|
408 |
+ rm $path |
|
409 |
+ exit 0 |
|
410 |
+ ;; |
|
411 |
+ |
|
373 | 412 |
mail) |
374 | 413 |
if [ $# -ne 2 ] ; then |
375 | 414 |
usage |