diff options
author | snuffy <snuffy@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-06-08 23:48:17 +0000 |
---|---|---|
committer | snuffy <snuffy@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-06-08 23:48:17 +0000 |
commit | b9d2b2684d6dfde3759cbbc84dfb6aa11d0e3b60 (patch) | |
tree | b9c0a6d9e565124104804ec2cb1e31a3c6b5ea41 /cdr | |
parent | 6db8e08fa31bc24296db13621a207e435834fdcd (diff) |
Add High Resolution Times to CDRs for Asterisk
People expressed an interest in having access to the exact length of calls to a finer degree than seconds. See the CHANGES and UPGRADE.txt for usage also updated the sample configs to note the change.
Patch by snuffy.
(closes issue #16559)
Reported by: cianmaher
Tested by: cianmaher, snuffy
Review: https://reviewboard.asterisk.org/r/461/
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@269153 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'cdr')
-rw-r--r-- | cdr/cdr_adaptive_odbc.c | 34 | ||||
-rw-r--r-- | cdr/cdr_odbc.c | 28 | ||||
-rw-r--r-- | cdr/cdr_pgsql.c | 4 | ||||
-rw-r--r-- | cdr/cdr_sqlite.c | 29 | ||||
-rw-r--r-- | cdr/cdr_tds.c | 71 |
5 files changed, 158 insertions, 8 deletions
diff --git a/cdr/cdr_adaptive_odbc.c b/cdr/cdr_adaptive_odbc.c index 3c52658d4..50577db7e 100644 --- a/cdr/cdr_adaptive_odbc.c +++ b/cdr/cdr_adaptive_odbc.c @@ -611,6 +611,23 @@ static int odbc_log(struct ast_cdr *cdr) continue; } else { double number = 0.0; + + if (!strcasecmp(entry->cdrname, "billsec")) { + if (!ast_tvzero(cdr->answer)) { + snprintf(colbuf, sizeof(colbuf), "%lf", + (double) (ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0)); + } else { + ast_copy_string(colbuf, "0", sizeof(colbuf)); + } + } else if (!strcasecmp(entry->cdrname, "duration")) { + snprintf(colbuf, sizeof(colbuf), "%lf", + (double) (ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0)); + + if (!ast_strlen_zero(colbuf)) { + colptr = colbuf; + } + } + if (sscanf(colptr, "%30lf", &number) != 1) { ast_log(LOG_WARNING, "CDR variable %s is not an numeric type.\n", entry->name); continue; @@ -628,6 +645,23 @@ static int odbc_log(struct ast_cdr *cdr) continue; } else { double number = 0.0; + + if (!strcasecmp(entry->cdrname, "billsec")) { + if (!ast_tvzero(cdr->answer)) { + snprintf(colbuf, sizeof(colbuf), "%lf", + (double) (ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0)); + } else { + ast_copy_string(colbuf, "0", sizeof(colbuf)); + } + } else if (!strcasecmp(entry->cdrname, "duration")) { + snprintf(colbuf, sizeof(colbuf), "%lf", + (double) (ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0)); + + if (!ast_strlen_zero(colbuf)) { + colptr = colbuf; + } + } + if (sscanf(colptr, "%30lf", &number) != 1) { ast_log(LOG_WARNING, "CDR variable %s is not an numeric type.\n", entry->name); continue; diff --git a/cdr/cdr_odbc.c b/cdr/cdr_odbc.c index e0f830c2a..fde134fa8 100644 --- a/cdr/cdr_odbc.c +++ b/cdr/cdr_odbc.c @@ -53,6 +53,7 @@ enum { CONFIG_LOGUNIQUEID = 1 << 0, CONFIG_USEGMTIME = 1 << 1, CONFIG_DISPOSITIONSTRING = 1 << 2, + CONFIG_HRTIME = 1 << 3, }; static struct ast_flags config = { 0 }; @@ -96,8 +97,23 @@ static SQLHSTMT execute_cb(struct odbc_obj *obj, void *data) SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dstchannel), 0, cdr->dstchannel, 0, NULL); SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastapp), 0, cdr->lastapp, 0, NULL); SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastdata), 0, cdr->lastdata, 0, NULL); - SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->duration, 0, NULL); - SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->billsec, 0, NULL); + + if (ast_test_flag(&config, CONFIG_HRTIME)) { + double hrbillsec = 0.0; + double hrduration; + + if (!ast_tvzero(cdr->answer)) { + hrbillsec = (double) ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0; + } + hrduration = (double) ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0; + + SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_FLOAT, 0, 0, &hrbillsec, 0, NULL); + SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_FLOAT, 0, 0, &hrduration, 0, NULL); + } else { + SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->duration, 0, NULL); + SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->billsec, 0, NULL); + } + if (ast_test_flag(&config, CONFIG_DISPOSITIONSTRING)) SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(ast_cdr_disp2str(cdr->disposition)) + 1, 0, ast_cdr_disp2str(cdr->disposition), 0, NULL); else @@ -203,6 +219,14 @@ static int odbc_load_module(int reload) ast_debug(1, "cdr_odbc: Logging in local time\n"); } + if (((tmp = ast_variable_retrieve(cfg, "global", "hrtime"))) && ast_true(tmp)) { + ast_set_flag(&config, CONFIG_HRTIME); + ast_debug(1, "cdr_odbc: Logging billsec and duration fields as floats\n"); + } else { + ast_clear_flag(&config, CONFIG_HRTIME); + ast_debug(1, "cdr_odbc: Logging billsec and duration fields as integers\n"); + } + if ((tmp = ast_variable_retrieve(cfg, "global", "table")) == NULL) { ast_log(LOG_WARNING, "cdr_odbc: table not specified. Assuming cdr\n"); tmp = "cdr"; diff --git a/cdr/cdr_pgsql.c b/cdr/cdr_pgsql.c index eae092642..53e957c26 100644 --- a/cdr/cdr_pgsql.c +++ b/cdr/cdr_pgsql.c @@ -211,12 +211,12 @@ static int pgsql_log(struct ast_cdr *cdr) } else if (strncmp(cur->type, "float", 5) == 0) { struct timeval *when = cur->name[0] == 'd' ? &cdr->start : &cdr->answer; LENGTHEN_BUF2(31); - ast_str_append(&sql2, 0, "%s%f", first ? "" : ",", (double)cdr->end.tv_sec - when->tv_sec + cdr->end.tv_usec / 1000000.0 - when->tv_usec / 1000000.0); + ast_str_append(&sql2, 0, "%s%f", first ? "" : ",", (double) (ast_tvdiff_us(cdr->end, *when) / 1000000.0)); } else { /* Char field, probably */ struct timeval *when = cur->name[0] == 'd' ? &cdr->start : &cdr->answer; LENGTHEN_BUF2(31); - ast_str_append(&sql2, 0, "%s'%f'", first ? "" : ",", (double)cdr->end.tv_sec - when->tv_sec + cdr->end.tv_usec / 1000000.0 - when->tv_usec / 1000000.0); + ast_str_append(&sql2, 0, "%s'%f'", first ? "" : ",", (double) (ast_tvdiff_us(cdr->end, *when) / 1000000.0)); } } else if (strcmp(cur->name, "disposition") == 0 || strcmp(cur->name, "amaflags") == 0) { if (strncmp(cur->type, "int", 3) == 0) { diff --git a/cdr/cdr_sqlite.c b/cdr/cdr_sqlite.c index 5a3a4b2ba..d871e8a8a 100644 --- a/cdr/cdr_sqlite.c +++ b/cdr/cdr_sqlite.c @@ -49,8 +49,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/utils.h" #include "asterisk/paths.h" -#define LOG_UNIQUEID 0 -#define LOG_USERFIELD 0 +#define LOG_UNIQUEID 0 +#define LOG_USERFIELD 0 +#define LOG_HRTIME 0 /* When you change the DATE_FORMAT, be sure to change the CHAR(19) below to something else */ #define DATE_FORMAT "%Y-%m-%d %T" @@ -74,8 +75,13 @@ static const char sql_create_table[] = "CREATE TABLE cdr (" " start CHAR(19)," " answer CHAR(19)," " end CHAR(19)," +#if LOG_HRTIME +" duration FLOAT," +" billsec FLOAT," +#else " duration INTEGER," " billsec INTEGER," +#endif " disposition INTEGER," " amaflags INTEGER," " accountcode VARCHAR(20)" @@ -101,6 +107,10 @@ static int sqlite_log(struct ast_cdr *cdr) char *zErr = 0; char startstr[80], answerstr[80], endstr[80]; int count; +#if LOG_HRTIME + double hrbillsec = 0.0; + double hrduration; +#endif ast_mutex_lock(&sqlite_lock); @@ -108,6 +118,13 @@ static int sqlite_log(struct ast_cdr *cdr) format_date(answerstr, sizeof(answerstr), &cdr->answer); format_date(endstr, sizeof(endstr), &cdr->end); +#if LOG_HRTIME + if (!ast_tvzero(cdr->answer)) { + hrbillsec = (double) ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0; + } + hrduration = (double) ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0; +#endif + for(count=0; count<5; count++) { res = sqlite_exec_printf(db, "INSERT INTO cdr (" @@ -126,7 +143,11 @@ static int sqlite_log(struct ast_cdr *cdr) "'%q', '%q', '%q', '%q', " "'%q', '%q', '%q', '%q', " "'%q', '%q', '%q', " +#if LOG_HRTIME + "%f, %f, %d, %d, " +#else "%d, %d, %d, %d, " +#endif "'%q'" # if LOG_UNIQUEID ",'%q'" @@ -138,7 +159,11 @@ static int sqlite_log(struct ast_cdr *cdr) cdr->clid, cdr->src, cdr->dst, cdr->dcontext, cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata, startstr, answerstr, endstr, +#if LOG_HRTIME + hrduration, hrbillsec, cdr->disposition, cdr->amaflags, +#else cdr->duration, cdr->billsec, cdr->disposition, cdr->amaflags, +#endif cdr->accountcode # if LOG_UNIQUEID ,cdr->uniqueid diff --git a/cdr/cdr_tds.c b/cdr/cdr_tds.c index c615400d3..ab0f0659c 100644 --- a/cdr/cdr_tds.c +++ b/cdr/cdr_tds.c @@ -87,6 +87,7 @@ struct cdr_tds_config { AST_STRING_FIELD(table); AST_STRING_FIELD(charset); AST_STRING_FIELD(language); + AST_STRING_FIELD(hrtime); ); DBPROCESS *dbproc; unsigned int connected:1; @@ -149,7 +150,36 @@ retry: } if (settings->has_userfield) { - erc = dbfcmd(settings->dbproc, + if (settings->hrtime) { + double hrbillsec = 0.0; + double hrduration; + + if (!ast_tvzero(cdr->answer)) { + hrbillsec = (double)(ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0); + } + hrduration = (double)(ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0); + + erc = dbfcmd(settings->dbproc, + "INSERT INTO %s " + "(" + "accountcode, src, dst, dcontext, clid, channel, " + "dstchannel, lastapp, lastdata, start, answer, [end], duration, " + "billsec, disposition, amaflags, uniqueid, userfield" + ") " + "VALUES " + "(" + "'%s', '%s', '%s', '%s', '%s', '%s', " + "'%s', '%s', '%s', %s, %s, %s, %lf, " + "%lf, '%s', '%s', '%s', '%s'" + ")", + settings->table, + accountcode, src, dst, dcontext, clid, channel, + dstchannel, lastapp, lastdata, start, answer, end, hrduration, + hrbillsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid, + userfield + ); + } else { + erc = dbfcmd(settings->dbproc, "INSERT INTO %s " "(" "accountcode, src, dst, dcontext, clid, channel, " @@ -168,8 +198,37 @@ retry: cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid, userfield ); + } } else { - erc = dbfcmd(settings->dbproc, + if (settings->hrtime) { + double hrbillsec = 0.0; + double hrduration; + + if (!ast_tvzero(cdr->answer)) { + hrbillsec = (double)(ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0); + } + hrduration = (double)(ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0); + + erc = dbfcmd(settings->dbproc, + "INSERT INTO %s " + "(" + "accountcode, src, dst, dcontext, clid, channel, " + "dstchannel, lastapp, lastdata, start, answer, [end], duration, " + "billsec, disposition, amaflags, uniqueid" + ") " + "VALUES " + "(" + "'%s', '%s', '%s', '%s', '%s', '%s', " + "'%s', '%s', '%s', %s, %s, %s, %lf, " + "%lf, '%s', '%s', '%s'" + ")", + settings->table, + accountcode, src, dst, dcontext, clid, channel, + dstchannel, lastapp, lastdata, start, answer, end, hrduration, + hrbillsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid + ); + } else { + erc = dbfcmd(settings->dbproc, "INSERT INTO %s " "(" "accountcode, src, dst, dcontext, clid, channel, " @@ -187,6 +246,7 @@ retry: dstchannel, lastapp, lastdata, start, answer, end, cdr->duration, cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid ); + } } if (erc == FAIL) { @@ -502,6 +562,13 @@ static int tds_load_module(int reload) ast_string_field_set(settings, table, "cdr"); } + ptr = ast_variable_retrieve(cfg, "global", "hrtime"); + if (ptr && ast_true(ptr)) { + ast_string_field_set(settings, hrtime, ptr); + } else { + ast_log(LOG_NOTICE, "High Resolution Time not found, using integers for billsec and duration fields by default.\n"); + } + mssql_disconnect(); if (mssql_connect()) { |