MT#11157 - Add call info stats dump

- Calls info (call_code, period) data is accumulated into $stats_db.'call_info'
      table on the cdr insert
    - Add stats_db and stats_period options (1=hour, 2=day, 3=month)

Change-Id: I4e1f7655eebfbe45a43e2c34d9c3b3bffe05fb40
changes/23/1023/6
Kirill Solomko 12 years ago
parent 28117e1bdf
commit e348692a55

@ -26,6 +26,9 @@ char *config_prov_pass = MEDIATOR_DEFAULT_PROVPASS;
char *config_prov_db = MEDIATOR_DEFAULT_PROVDB;
unsigned int config_prov_port = MEDIATOR_DEFAULT_PROVPORT;
char *config_stats_db = MEDIATOR_DEFAULT_STATSDB;
med_stats_period_t config_stats_period = MEDIATOR_DEFAULT_STATS_PERIOD;
static u_int8_t config_pid_path_free = 0;
static u_int8_t config_med_host_free = 0;
@ -43,6 +46,7 @@ static u_int8_t config_prov_user_free = 0;
static u_int8_t config_prov_pass_free = 0;
static u_int8_t config_prov_db_free = 0;
static u_int8_t config_stats_db_free = 0;
static void config_help(const char *self)
{
@ -67,18 +71,21 @@ static void config_help(const char *self)
" -R\tThe prov db user (default = '%s').\n" \
" -A\tThe prov db pass (default = '%s').\n" \
" -N\tThe prov db name (default = '%s').\n" \
" -X\tThe stats db name (default = '%s').\n" \
" -x\tThe stats db period (default = '%d', 1=hour, 2=day, 3=month).\n" \
" -?\tDisplays this message.\n",
self, config_pid_path, config_interval,
config_med_host, config_med_port, config_med_user, config_med_pass, config_med_db,
config_cdr_host, config_cdr_port, config_cdr_user, config_cdr_pass, config_cdr_db,
config_prov_host, config_prov_port, config_prov_user, config_prov_pass, config_prov_db);
config_prov_host, config_prov_port, config_prov_user, config_prov_pass, config_prov_db,
config_stats_db, config_stats_period);
}
int config_parse_cmdopts(int argc, char **argv)
{
int c;
while((c = getopt(argc, argv, "D:i:dl?h:u:p:b:o:H:U:P:B:O:S:T:R:A:N:")) != -1)
while((c = getopt(argc, argv, "D:i:dl?h:u:p:b:o:H:U:P:B:O:S:T:R:A:N:X:x:")) != -1)
{
if(c == '?')
{
@ -174,6 +181,15 @@ int config_parse_cmdopts(int argc, char **argv)
{
config_prov_port = atoi(optarg);
}
else if(c == 'X')
{
config_stats_db = (char*)strdup(optarg);
config_stats_db_free = 1;
}
else if(c == 'x')
{
config_stats_period = (med_stats_period_t)atoi(optarg);
}
}
return 0;
@ -233,4 +249,8 @@ void config_cleanup()
{
free(config_prov_db);
}
if(config_stats_db_free)
{
free(config_stats_db);
}
}

@ -26,6 +26,9 @@ extern char *config_prov_user;
extern char *config_prov_pass;
extern char *config_prov_db;
extern char *config_stats_db;
extern med_stats_period_t config_stats_period;
extern unsigned int config_interval;
extern u_int8_t config_dumpcdr;

@ -17,3 +17,5 @@ PROV_PORT="3306"
PROV_USER="mediator"
PROV_PASS='GimmeAllUr$$$'
PROV_DB="provisioning"
STATS_DB="stats"
STATS_PERIOD=1

@ -59,6 +59,8 @@ OPTIONS=""
[ -z "$PROV_USER" ] || OPTIONS="$OPTIONS -R $PROV_USER"
[ -z "$PROV_PASS" ] || OPTIONS="$OPTIONS -A $PROV_PASS"
[ -z "$PROV_DB" ] || OPTIONS="$OPTIONS -N $PROV_DB"
[ -z "$STATS_DB" ] || OPTIONS="$OPTIONS -X $STATS_DB"
[ -z "$STATS_PERIOD" ] || OPTIONS="$OPTIONS -x $STATS_PERIOD"
if test "$FORK" = "yes" ; then
OPTIONS="$OPTIONS -d"
fi

@ -25,7 +25,7 @@ GHashTable *med_peer_ip_table = NULL;
GHashTable *med_peer_host_table = NULL;
GHashTable *med_peer_id_table = NULL;
GHashTable *med_uuid_table = NULL;
GHashTable *med_call_stat_info_table = NULL;
/**********************************************************************/
static int mediator_load_maps()
@ -60,11 +60,14 @@ static void mediator_destroy_maps()
g_hash_table_destroy(med_peer_id_table);
if(med_uuid_table)
g_hash_table_destroy(med_uuid_table);
if(med_call_stat_info_table)
g_hash_table_destroy(med_call_stat_info_table);
med_peer_ip_table = NULL;
med_peer_host_table = NULL;
med_peer_id_table = NULL;
med_uuid_table = NULL;
med_call_stat_info_table = NULL;
}
/**********************************************************************/

@ -38,6 +38,9 @@
#define MEDIATOR_DEFAULT_PROVDB "provisioning"
#define MEDIATOR_DEFAULT_PROVPORT 0
#define MEDIATOR_DEFAULT_STATSDB "stats"
#define MEDIATOR_DEFAULT_STATS_PERIOD MED_STATS_HOUR
#define MED_GW_STRING "gw"
#define MED_AS_STRING "as"
#define MED_PEER_STRING "peer"
@ -77,6 +80,7 @@ extern GHashTable *med_peer_host_table;
extern GHashTable *med_peer_ip_table;
extern GHashTable *med_peer_id_table;
extern GHashTable *med_uuid_table;
extern GHashTable *med_call_stat_info_table;
void critical(const char *);
@ -89,5 +93,10 @@ static inline int check_shutdown(void) {
return 0;
}
typedef enum {
MED_STATS_HOUR = 1,
MED_STATS_DAY = 2,
MED_STATS_MONTH = 3
} med_stats_period_t;
#endif /* _MEDIATOR_H */

@ -26,6 +26,7 @@ static MYSQL *prov_handler = NULL;
static int medmysql_flush_cdr(struct medmysql_batches *);
static int medmysql_flush_medlist(struct medmysql_str *);
static int medmysql_flush_call_stat_info();
static int mysql_query_wrapper(MYSQL *mysql, const char *stmt_str, unsigned long length) {
@ -474,6 +475,9 @@ int medmysql_insert_cdrs(cdr_entry_t *entries, u_int64_t count, struct medmysql_
CDRPRINT("),");
// no check for return codes here we should keep on nevertheless
medmysql_update_call_stat_info(e->call_code, e->start_time, batches);
if (check_shutdown())
return -1;
}
@ -484,6 +488,49 @@ int medmysql_insert_cdrs(cdr_entry_t *entries, u_int64_t count, struct medmysql_
return 0;
}
/**********************************************************************/
int medmysql_update_call_stat_info(const char *call_code, const double start_time, struct medmysql_batches *batches)
{
if (!med_call_stat_info_table)
return -1;
char period[STAT_PERIOD_SIZE];
time_t etime = (time_t)start_time;
char period_key[STAT_PERIOD_SIZE+4];
struct medmysql_call_stat_info_t * period_t;
switch (config_stats_period)
{
case MED_STATS_HOUR:
strftime(period, STAT_PERIOD_SIZE, "%Y-%m-%d %H:00:00", localtime(&etime));
break;
case MED_STATS_DAY:
strftime(period, STAT_PERIOD_SIZE, "%Y-%m-%d 00:00:00", localtime(&etime));
break;
case MED_STATS_MONTH:
strftime(period, STAT_PERIOD_SIZE, "%Y-%m-01 00:00:00", localtime(&etime));
break;
default:
syslog(LOG_CRIT, "Undefinied or wrong config_stats_period %d",
config_stats_period);
return -1;
}
sprintf(period_key, "%s-%s", period, call_code);
if ((period_t = g_hash_table_lookup(med_call_stat_info_table, &period_key)) == NULL) {
period_t = malloc(sizeof(struct medmysql_call_stat_info_t));
strcpy(period_t->period, period);
strcpy(period_t->call_code, call_code);
period_t->amount = 1;
g_hash_table_insert(med_call_stat_info_table, strdup(period_key), period_t);
} else {
period_t->amount += 1;
}
return 0;
}
/**********************************************************************/
int medmysql_load_maps(GHashTable *ip_table, GHashTable *host_table, GHashTable *id_table)
{
@ -591,6 +638,9 @@ int medmysql_batch_start(struct medmysql_batches *batches) {
if (mysql_query_wrapper(med_handler, "start transaction", 17))
return -1;
if (!med_call_stat_info_table)
med_call_stat_info_table = g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
batches->cdrs.len = 0;
batches->acc_backup.len = 0;
batches->acc_trash.len = 0;
@ -660,6 +710,53 @@ static int medmysql_flush_medlist(struct medmysql_str *str) {
return 0;
}
static int medmysql_flush_call_stat_info() {
if (!med_handler)
return 0;
if (!med_call_stat_info_table)
return 0;
GHashTable * call_stat_info = med_call_stat_info_table;
struct medmysql_str query;
struct medmysql_call_stat_info_t * period_t;
GList * keys = g_hash_table_get_keys(call_stat_info);
GList * iter;
for (iter = keys; iter != NULL; iter = iter->next) {
char * period_key = iter->data;
if ((period_t = g_hash_table_lookup(call_stat_info, period_key)) == NULL) {
syslog(LOG_CRIT,
"Error dumping call stats info: no data for period_key %s\n",
period_key
);
return -1;
}
query.len = sprintf(query.str,
"insert into %s.call_info set period='%s', sip_code='%s', amount=%" PRIu64 " on duplicate key update period='%s', sip_code='%s', amount=(amount+%" PRIu64 ");",
config_stats_db,
period_t->period, period_t->call_code, period_t->amount,
period_t->period, period_t->call_code, period_t->amount
);
//syslog(LOG_DEBUG, "updating call stats info: %s -- %s", period_t->call_code, period_t->period);
//syslog(LOG_DEBUG, "sql: %s", query.str);
if(mysql_query_wrapper(med_handler, query.str, query.len) != 0)
{
syslog(LOG_CRIT, "Error executing call info stats query: %s",
mysql_error(med_handler));
critical("Failed to execute potentially crucial SQL query, check syslog for details");
return -1;
}
period_t->amount = 0; // reset code counter on success
}
g_list_free(keys);
g_list_free(iter);
return 0;
}
int medmysql_batch_end(struct medmysql_batches *batches) {
if (medmysql_flush_cdr(batches) || check_shutdown())
return -1;
@ -669,6 +766,8 @@ int medmysql_batch_end(struct medmysql_batches *batches) {
return -1;
if (medmysql_flush_medlist(&batches->to_delete) || check_shutdown())
return -1;
if (medmysql_flush_call_stat_info() || check_shutdown())
return -1;
if (mysql_query_wrapper(cdr_handler, "commit", 6))
return -1;

@ -8,6 +8,8 @@
#define PACKET_SIZE (1024*1024)
#define STAT_PERIOD_SIZE 30
struct medmysql_str {
char str[PACKET_SIZE];
unsigned int len;
@ -20,6 +22,12 @@ struct medmysql_batches {
struct medmysql_str to_delete;
};
struct medmysql_call_stat_info_t {
char period[STAT_PERIOD_SIZE];
char call_code[4];
u_int64_t amount;
};
int medmysql_init();
void medmysql_cleanup();
int medmysql_fetch_callids(med_callid_t **callids, u_int64_t *count);
@ -32,5 +40,6 @@ int medmysql_load_maps(GHashTable *ip_table, GHashTable *host_table, GHashTable
int medmysql_load_uuids(GHashTable *uuid_table);
int medmysql_batch_start(struct medmysql_batches *);
int medmysql_batch_end(struct medmysql_batches *);
int medmysql_update_call_stat_info(const char *call_code, const double start_time, struct medmysql_batches *batches);
#endif /* _MED_MYSQL_H */

Loading…
Cancel
Save