diff --git a/conf/autoload_configs/cdr_pg_csv.conf.xml b/conf/autoload_configs/cdr_pg_csv.conf.xml index e17809780c..2f2efa9b26 100644 --- a/conf/autoload_configs/cdr_pg_csv.conf.xml +++ b/conf/autoload_configs/cdr_pg_csv.conf.xml @@ -9,6 +9,8 @@ + + diff --git a/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c b/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c index 9da7c9dfcb..fba5f86728 100644 --- a/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c +++ b/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c @@ -67,6 +67,7 @@ static struct { cdr_leg_t legs; char *db_info; char *db_table; + char *spool_format; PGconn *db_connection; int db_online; 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) { cdr_fd_t *fd = NULL; + char *log_line_lf = NULL; unsigned int bytes_in, bytes_out; 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); } + 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); - bytes_out = (unsigned) strlen(log_line); + bytes_out = (unsigned) strlen(log_line_lf); if (fd->fd < 0) { do_reopen(fd); @@ -169,7 +180,7 @@ static void write_cdr(const char *path, const char *log_line) 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); do_rotate(fd); switch_yield(250000); @@ -184,7 +195,7 @@ static void write_cdr(const char *path, const char *log_line) 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 *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 (') * for correct PostgreSQL syntax, and replace semi-colon with space to - * prevent SQL injection attacks. + * prevent SQL injection attacks */ values = strdup(cdr); for (p = values; *p; ++p) { @@ -309,9 +320,7 @@ static switch_status_t save_cdr(const char * const template, const char * const values = nullValues; free(tp); - //----------------------------- END_OF_PATCH ------------------------------- - - sql = switch_mprintf("INSERT INTO %s (%s) VALUES (%s);\n", globals.db_table, columns, values); + sql = switch_mprintf("INSERT INTO %s (%s) VALUES (%s);", globals.db_table, columns, values); assert(sql); free(columns); 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); /* SQL INSERT failed for whatever reason. Spool the attempted query to disk */ - path = switch_mprintf("%s%scdr-spool.sql", log_dir, SWITCH_PATH_SEPARATOR); - assert(path); - write_cdr(path, sql); + if (!strcasecmp(globals.spool_format, "sql")) { + path = switch_mprintf("%s%scdr-spool.sql", globals.log_dir, SWITCH_PATH_SEPARATOR); + assert(path); + 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(sql); return SWITCH_STATUS_FALSE; - } static switch_status_t my_on_reporting(switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_status_t status = SWITCH_STATUS_SUCCESS; - const char *log_dir = NULL, *template_str = NULL; + const char *template_str = NULL; char *expanded_vars = NULL; 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"))) { - log_dir = 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); + if (switch_dir_make_recursive(globals.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", globals.log_dir); return SWITCH_STATUS_FALSE; } @@ -424,7 +434,7 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) return SWITCH_STATUS_FALSE; } - save_cdr(template_str, expanded_vars, log_dir); + save_cdr(template_str, expanded_vars); if (expanded_vars != template_str) { 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); } else if (!strcasecmp(var, "default-template")) { 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"); } + if (zstr(globals.spool_format)) { + globals.spool_format = switch_core_strdup(pool, "csv"); + } return status; }