Browse code

introduced statistics pollable through FIFO

Jiri Kuthan authored on 16/08/2002 21:04:58
Showing 8 changed files
... ...
@@ -99,6 +99,7 @@
99 99
 #define MAX_CONSUME_BUFFER 1024
100 100
 /* where reply pipes may be opened */
101 101
 #define FIFO_DIR "/tmp/"
102
+#define FIFO_DIR_LEN 5
102 103
 /* max length of the text of fifo 'print' command */
103 104
 #define MAX_PRINT_TEXT 256
104 105
 
... ...
@@ -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