瀏覽代碼

introduced statistics pollable through FIFO

Jiri Kuthan 23 年之前
父節點
當前提交
c55b0dfd5d
共有 8 個文件被更改,包括 217 次插入1 次删除
  1. 1 0
      config.h
  2. 10 0
      modules/tm/h_table.c
  3. 19 1
      modules/tm/t_reply.c
  4. 104 0
      modules/tm/t_stats.c
  5. 30 0
      modules/tm/t_stats.h
  6. 8 0
      modules/tm/timer.c
  7. 6 0
      modules/tm/tm_mod.c
  8. 39 0
      scripts/sc

+ 1 - 0
config.h

@@ -99,6 +99,7 @@
 #define MAX_CONSUME_BUFFER 1024
 /* where reply pipes may be opened */
 #define FIFO_DIR "/tmp/"
+#define FIFO_DIR_LEN 5
 /* max length of the text of fifo 'print' command */
 #define MAX_PRINT_TEXT 256
 

+ 10 - 0
modules/tm/h_table.c

@@ -13,6 +13,7 @@
 #include "../../error.h"
 #include "t_reply.h"
 #include "t_cancel.h"
+#include "t_stats.h"
 
 unsigned int transaction_count( void )
 {
@@ -278,6 +279,12 @@ void insert_into_hash_table_unsafe( struct s_table *hash_table,
 
 	/* update stats */
 	p_entry->entries++;
+	cur_stats->transactions++;
+	acc_stats->transactions++;
+	if (p_cell->local) {
+		cur_stats->client_transactions++;
+		acc_stats->client_transactions++;
+	}
 }
 
 
@@ -313,6 +320,9 @@ void remove_from_hash_table_unsafe(struct s_table *hash_table,
 		p_entry->last_cell = p_cell->prev_cell;
 	/* update stats */
 	p_entry->entries--;
+	cur_stats->transactions--;
+	if (p_cell->local) cur_stats->client_transactions--;
+	cur_stats->waiting--;
 
 	/* unlock( &(p_entry->mutex) ); */
 }

+ 19 - 1
modules/tm/t_reply.c

@@ -23,6 +23,7 @@
 #include "t_lookup.h"
 #include "t_fwd.h"
 #include "fix_lumps.h"
+#include "t_stats.h"
 
 /* where to go if there is no positive reply */
 static int goto_on_negative=0;
@@ -49,6 +50,20 @@ unsigned int get_on_negative()
 	return goto_on_negative;
 }
 
+static void update_reply_stats( int code ) {
+	if (code>=600) {
+		acc_stats->completed_6xx++;
+	} else if (code>=500) {
+		acc_stats->completed_5xx++;
+	} else if (code>=400) {
+		acc_stats->completed_4xx++;
+	} else if (code>=300) {
+		acc_stats->completed_3xx++;
+	} else if (code>=200) {
+		acc_stats->completed_2xx++;
+	}
+}
+
 
 /* the main code of stateful replying */
 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,
 	/* needs to be protected too because what timers are set depends
 	   on current transactions status */
 	/* t_update_timers_after_sending_reply( rb ); */
-
+	update_reply_stats( code );
+	acc_stats->replied_localy++;
 	if (lock) UNLOCK_REPLIES( trans );
 	
 	/* 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,
 				free_via_lump(&relayed_msg->repl_add_rm);
 			}
 		}
+		update_reply_stats( relayed_code );
 		if (!buf) {
 			LOG(L_ERR, "ERROR: relay_reply: "
 				"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,
 			winning_code=winning_msg->REPLY_STATUS;
 		}
 		t->uas.status = winning_code;
+		update_reply_stats( winning_code );
 	}
 	UNLOCK_REPLIES(t);
 	if (local_winner>=0 && winning_code>=200 ) {

+ 104 - 0
modules/tm/t_stats.c

@@ -0,0 +1,104 @@
+/*
+ *
+ * $Id$
+ *
+ */
+
+
+#include <stdio.h>
+#include "t_stats.h"
+#include "../../mem/shm_mem.h"
+#include "../../dprint.h"
+#include "../../config.h"
+#include "../../fifo_server.h"
+
+struct t_stats *cur_stats, *acc_stats;
+
+int print_stats(  FILE *f )
+{
+	time_t now;
+
+	time(&now);
+
+	fprintf(f, "Time:\n----------------\n");
+	fprintf(f, "Now: %s", ctime(&now));
+	fprintf(f, "Up since: %s", ctime(&acc_stats->up_since));
+	fprintf(f, "Up time: %.f [sec]\n", difftime(now, acc_stats->up_since));
+	fprintf(f, "\nCurrent values:\n----------------\n");
+	fprintf(f, "# of transactions: %d\n", 
+		cur_stats->transactions );
+	fprintf(f, "    - local: %d\n",
+		cur_stats->client_transactions );
+	fprintf(f, "    - waiting: %d\n",
+		cur_stats->waiting );
+
+	fprintf(f, "\nCummulative values:\n----------------\n");
+	fprintf(f, "# of transactions: %d\n",	
+		acc_stats->transactions );
+	fprintf(f, "    - local: %d\n",
+		acc_stats->client_transactions );
+	fprintf(f, "    - waiting: %d\n",
+		acc_stats->waiting );
+
+	fprintf(f, "Replied localy: %d\n",
+		acc_stats->replied_localy );
+	fprintf(f, "Completion status 6xx: %d\n",
+		acc_stats->completed_6xx );
+	fprintf(f, "Completion status 5xx: %d\n",
+		acc_stats->completed_5xx );
+	fprintf(f, "Completion status 4xx: %d\n",
+		acc_stats->completed_4xx );
+	fprintf(f, "Completion status 3xx: %d\n",
+		acc_stats->completed_3xx );
+	fprintf(f, "Completion status 2xx: %d\n",
+		acc_stats->completed_2xx );
+	
+	return 1;
+}
+
+int static fifo_stats( FILE *pipe, char *response_file )
+{
+	FILE *file;
+
+	if (response_file==0 || *response_file==0 ) {
+		LOG(L_ERR, "ERROR: fifo_stats: null file\n");
+		return -1;
+	}
+
+	file=fopen(response_file, "w" );
+	if (file==NULL) {
+		LOG(L_ERR, "ERROR: fifo_stats: file %s bad: %s\n",
+			response_file, strerror(errno) );
+		return -1;
+	}
+	print_stats( file );
+	fclose(file);
+	
+	return 1;
+
+}
+
+int init_stats(void)
+{
+	cur_stats=shm_malloc(sizeof(struct t_stats));
+	if (cur_stats==0) {
+		LOG(L_ERR, "ERROR: init_stats: no mem for stats\n");
+		return -1;
+	}
+	acc_stats=shm_malloc(sizeof(struct t_stats));
+	if (acc_stats==0) {
+		LOG(L_ERR, "ERROR: init_stats: no mem for stats\n");
+		shm_free(cur_stats);
+		return -1;
+	}
+
+	if (register_fifo_cmd(fifo_stats, "t_stats", 0)<0) {
+		LOG(L_CRIT, "cannot register fifo stats\n");
+		return -1;
+	}
+
+	memset(cur_stats, 0, sizeof(struct t_stats) );
+	memset(acc_stats, 0, sizeof(struct t_stats) );
+	time(&acc_stats->up_since);
+	return 1;
+}

+ 30 - 0
modules/tm/t_stats.h

@@ -0,0 +1,30 @@
+/*
+ *
+ * $Id$
+ *
+ */
+
+#ifndef _T_STATS_H
+#define _T_STATS_H
+
+#include <time.h>
+
+extern struct t_stats *cur_stats, *acc_stats;
+
+struct t_stats {
+	/* number of server transactions */
+	unsigned int transactions;
+	/* number of UAC transactions (part of transactions) */
+	unsigned int client_transactions;
+	/* number of transactions in wait state */
+	unsigned int waiting;
+	/* number of transactions which completed with this status */
+	unsigned int completed_3xx, completed_4xx, completed_5xx, 
+		completed_6xx, completed_2xx;
+	unsigned int replied_localy;
+	time_t up_since;
+};
+
+int init_stats(void);
+
+#endif

+ 8 - 0
modules/tm/timer.c

@@ -76,6 +76,8 @@
 #include "../../dprint.h"
 #include "lock.h"
 
+#include "t_stats.h"
+
 int timer_group[NR_OF_TIMER_LISTS] = 
 {
 	TG_FR, TG_FR,
@@ -321,6 +323,12 @@ void set_1timer( struct s_table *hash_table,
 		/* make sure I'm not already on a list */
 		/* remove_timer_unsafe( new_tl ); */
 		add_timer_unsafe( list, new_tl, get_ticks()+timeout);
+
+		/* set_1timer is used only by WAIT -- that's why we can
+		   afford updating wait statistics; I admit its not nice
+		   but it greatly utilizes existing lock 
+		*/
+		cur_stats->waiting++;acc_stats->waiting++;
 	}
 	unlock(list->mutex);
 }

+ 6 - 0
modules/tm/tm_mod.c

@@ -26,6 +26,7 @@
 #include "uac.h"
 #include "t_fwd.h"
 #include "t_lookup.h"
+#include "t_stats.h"
 
 
 
@@ -236,6 +237,11 @@ static int mod_init(void)
 		LOG(L_CRIT, "cannot register fifo uac\n");
 		return -1;
 	}
+	
+	if (init_stats()<0) {
+		LOG(L_CRIT, "ERROR: mod_init: failed to init stats\n");
+		return -1;
+	}
 
 	if (tm_startup()==-1) return -1;
 	uac_init();

+ 39 - 0
scripts/sc

@@ -8,6 +8,11 @@
 # realm
 DOMAIN=iptel.org
 
+# ser's FIFO server
+SER_FIFO=/tmp/ser_fifo
+# period in which stats are reprinted
+WATCH_PERIOD=2
+
 # SQL config
 SQL_DB=csps107
 SQL_HOST=dbhost
@@ -98,6 +103,16 @@ prompt_pw() {
 	fi
 }
 
+# $1 = name $2=path $3=attempt
+print_stats() {
+echo "[cycle: $3; if screen empty, make sure server is alive]"
+cat > $SER_FIFO <<EOF
+
+:t_stats:$1
+EOF
+cat < $2
+}
+
 
 # input: sql query, optional mysql command-line params
 sql_query() {
@@ -370,6 +385,30 @@ case $1 in
 		fi
 		;;
 
+	stats)
+		name=ser_receiver_$$
+		path=/tmp/$name
+		if [ ! -w $SER_FIFO ]; then
+			echo "Error opening ser's FIFO $SER_FIFO"
+			echo "Make sure you have line fifo=$SER_FIFO in your config"
+			exit 1
+		fi
+		mkfifo $path
+		if [ $? -ne 0 ] ; then
+			echo "error opening read fifo $path"
+			exit 1
+		fi
+		attempt=0
+		while [ 1 -eq 1 ]; do
+			attempt=`expr $attempt + 1`
+			clear
+			print_stats $name $path $attempt
+			sleep $WATCH_PERIOD
+		done
+		rm $path
+		exit 0
+		;;
+
 	mail)
 		if [ $# -ne 2 ] ; then
 			usage