mod_cdr_pg_csv: make disk spool format user-selectable

This commit is contained in:
Daniel Swarbrick 2011-01-03 18:59:41 +01:00
parent 7b28994121
commit a3d66bb4f0
2 changed files with 36 additions and 19 deletions

View File

@ -9,6 +9,8 @@
<param name="default-template" value="example"/> <param name="default-template" value="example"/>
<!-- 'cdr-pg-csv' will always be appended to log-base --> <!-- 'cdr-pg-csv' will always be appended to log-base -->
<!--<param name="log-base" value="/var/log"/>--> <!--<param name="log-base" value="/var/log"/>-->
<!-- Disk spool format if DB connection/insert fails - csv (default) or sql -->
<param name="spool-format" value="csv"/>
<param name="rotate-on-hup" value="true"/> <param name="rotate-on-hup" value="true"/>
<!-- This is like the info app but after the call is hung up --> <!-- This is like the info app but after the call is hung up -->
<!--<param name="debug" value="true"/>--> <!--<param name="debug" value="true"/>-->

View File

@ -67,6 +67,7 @@ static struct {
cdr_leg_t legs; cdr_leg_t legs;
char *db_info; char *db_info;
char *db_table; char *db_table;
char *spool_format;
PGconn *db_connection; PGconn *db_connection;
int db_online; int db_online;
switch_mutex_t *db_mutex; switch_mutex_t *db_mutex;
@ -141,6 +142,7 @@ static void do_rotate(cdr_fd_t *fd)
static void write_cdr(const char *path, const char *log_line) static void write_cdr(const char *path, const char *log_line)
{ {
cdr_fd_t *fd = NULL; cdr_fd_t *fd = NULL;
char *log_line_lf = NULL;
unsigned int bytes_in, bytes_out; unsigned int bytes_in, bytes_out;
int loops = 0; int loops = 0;
@ -154,8 +156,17 @@ static void write_cdr(const char *path, const char *log_line)
switch_core_hash_insert(globals.fd_hash, path, fd); switch_core_hash_insert(globals.fd_hash, path, fd);
} }
if (end_of(log_line) != '\n') {
size_t len = strlen(log_line) + 2;
log_line_lf = switch_core_alloc(globals.pool, len);
switch_snprintf(log_line_lf, len, "%s\n", log_line);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Adding LF to log_line.\n");
} else {
log_line_lf = switch_core_strdup(globals.pool, log_line);
}
switch_mutex_lock(fd->mutex); switch_mutex_lock(fd->mutex);
bytes_out = (unsigned) strlen(log_line); bytes_out = (unsigned) strlen(log_line_lf);
if (fd->fd < 0) { if (fd->fd < 0) {
do_reopen(fd); do_reopen(fd);
@ -169,7 +180,7 @@ static void write_cdr(const char *path, const char *log_line)
do_rotate(fd); do_rotate(fd);
} }
while ((bytes_in = write(fd->fd, log_line, bytes_out)) != bytes_out && ++loops < 10) { while ((bytes_in = write(fd->fd, log_line_lf, bytes_out)) != bytes_out && ++loops < 10) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Write error to file %s %d/%d\n", path, (int) bytes_in, (int) bytes_out); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Write error to file %s %d/%d\n", path, (int) bytes_in, (int) bytes_out);
do_rotate(fd); do_rotate(fd);
switch_yield(250000); switch_yield(250000);
@ -184,7 +195,7 @@ static void write_cdr(const char *path, const char *log_line)
switch_mutex_unlock(fd->mutex); switch_mutex_unlock(fd->mutex);
} }
static switch_status_t save_cdr(const char * const template, const char * const cdr, const char * const log_dir) static switch_status_t save_cdr(const char * const template, const char * const cdr)
{ {
char *columns, *values; char *columns, *values;
char *p, *q; char *p, *q;
@ -214,7 +225,7 @@ static switch_status_t save_cdr(const char * const template, const char * const
/* /*
* In the expanded vars, replace double quotes (") with single quotes (') * In the expanded vars, replace double quotes (") with single quotes (')
* for correct PostgreSQL syntax, and replace semi-colon with space to * for correct PostgreSQL syntax, and replace semi-colon with space to
* prevent SQL injection attacks. * prevent SQL injection attacks
*/ */
values = strdup(cdr); values = strdup(cdr);
for (p = values; *p; ++p) { for (p = values; *p; ++p) {
@ -309,9 +320,7 @@ static switch_status_t save_cdr(const char * const template, const char * const
values = nullValues; values = nullValues;
free(tp); free(tp);
//----------------------------- END_OF_PATCH ------------------------------- sql = switch_mprintf("INSERT INTO %s (%s) VALUES (%s);", globals.db_table, columns, values);
sql = switch_mprintf("INSERT INTO %s (%s) VALUES (%s);\n", globals.db_table, columns, values);
assert(sql); assert(sql);
free(columns); free(columns);
free(values); free(values);
@ -355,22 +364,27 @@ static switch_status_t save_cdr(const char * const template, const char * const
switch_mutex_unlock(globals.db_mutex); switch_mutex_unlock(globals.db_mutex);
/* SQL INSERT failed for whatever reason. Spool the attempted query to disk */ /* SQL INSERT failed for whatever reason. Spool the attempted query to disk */
path = switch_mprintf("%s%scdr-spool.sql", log_dir, SWITCH_PATH_SEPARATOR); if (!strcasecmp(globals.spool_format, "sql")) {
path = switch_mprintf("%s%scdr-spool.sql", globals.log_dir, SWITCH_PATH_SEPARATOR);
assert(path); assert(path);
write_cdr(path, sql); write_cdr(path, sql);
} else {
path = switch_mprintf("%s%scdr-spool.csv", globals.log_dir, SWITCH_PATH_SEPARATOR);
assert(path);
write_cdr(path, cdr);
}
free(path); free(path);
free(sql); free(sql);
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
static switch_status_t my_on_reporting(switch_core_session_t *session) static switch_status_t my_on_reporting(switch_core_session_t *session)
{ {
switch_channel_t *channel = switch_core_session_get_channel(session); switch_channel_t *channel = switch_core_session_get_channel(session);
switch_status_t status = SWITCH_STATUS_SUCCESS; switch_status_t status = SWITCH_STATUS_SUCCESS;
const char *log_dir = NULL, *template_str = NULL; const char *template_str = NULL;
char *expanded_vars = NULL; char *expanded_vars = NULL;
if (globals.shutdown) { if (globals.shutdown) {
@ -389,12 +403,8 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
} }
} }
if (!(log_dir = switch_channel_get_variable(channel, "cdr_pg_csv_base"))) { if (switch_dir_make_recursive(globals.log_dir, SWITCH_DEFAULT_DIR_PERMS, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
log_dir = globals.log_dir; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.log_dir);
}
if (switch_dir_make_recursive(log_dir, SWITCH_DEFAULT_DIR_PERMS, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", log_dir);
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
@ -424,7 +434,7 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
save_cdr(template_str, expanded_vars, log_dir); save_cdr(template_str, expanded_vars);
if (expanded_vars != template_str) { if (expanded_vars != template_str) {
free(expanded_vars); free(expanded_vars);
@ -528,6 +538,8 @@ static switch_status_t load_config(switch_memory_pool_t *pool)
globals.db_table = switch_core_strdup(pool, val); globals.db_table = switch_core_strdup(pool, val);
} else if (!strcasecmp(var, "default-template")) { } else if (!strcasecmp(var, "default-template")) {
globals.default_template = switch_core_strdup(pool, val); globals.default_template = switch_core_strdup(pool, val);
} else if (!strcasecmp(var, "spool-format")) {
globals.spool_format = switch_core_strdup(pool, val);
} }
} }
} }
@ -563,6 +575,9 @@ static switch_status_t load_config(switch_memory_pool_t *pool)
globals.default_template = switch_core_strdup(pool, "default"); globals.default_template = switch_core_strdup(pool, "default");
} }
if (zstr(globals.spool_format)) {
globals.spool_format = switch_core_strdup(pool, "csv");
}
return status; return status;
} }