[Asterisk-code-review] funcs/func cdr: Correctly report high precision values for d... (asterisk[master])

Joshua Colp asteriskteam at digium.com
Wed Jan 20 10:33:27 CST 2016


Joshua Colp has submitted this change and it was merged.

Change subject: funcs/func_cdr: Correctly report high precision values for duration and billsec
......................................................................


funcs/func_cdr: Correctly report high precision values for duration and billsec

When CDRs were refactored, func_cdr's ability to report high precision values
for duration and billsec (the 'f' option) was broken. This was due to func_cdr
incorrectly interpreting the duration/billsec values provided by the CDR engine
in milliseconds, as opposed to seconds. Since the CDR engine only provides
duration and billsec in seconds, and does not expose either attribute with
sufficient precision to merely pass back the underlying value, this patch fixes
the bug by re-calculating duration and billsec with microsecond precision based
on the start/answer/end times on the CDR.

ASTERISK-25179 #close

Change-Id: I8bc63822b496537a5bf80baf6102c06206bee841
---
M funcs/func_cdr.c
1 file changed, 33 insertions(+), 8 deletions(-)

Approvals:
  Mark Michelson: Looks good to me, but someone else must approve
  Anonymous Coward #1000019: Verified
  Joshua Colp: Looks good to me, approved



diff --git a/funcs/func_cdr.c b/funcs/func_cdr.c
index 8d98479..ae15f6a 100644
--- a/funcs/func_cdr.c
+++ b/funcs/func_cdr.c
@@ -221,6 +221,26 @@
 STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_write_message_type);
 STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_prop_write_message_type);
 
+static struct timeval cdr_retrieve_time(struct ast_channel *chan, const char *time_name)
+{
+	struct timeval time;
+	char *value = NULL;
+	char tempbuf[128];
+
+	if (ast_strlen_zero(ast_channel_name(chan))) {
+		/* Format request on a dummy channel */
+		ast_cdr_format_var(ast_channel_cdr(chan), time_name, &value, tempbuf, sizeof(tempbuf), 1);
+	} else {
+		ast_cdr_getvar(ast_channel_name(chan), time_name, tempbuf, sizeof(tempbuf));
+	}
+
+	if (sscanf(tempbuf, "%ld.%ld", &time.tv_sec, &time.tv_usec) != 2) {
+		ast_log(AST_LOG_WARNING, "Failed to fully extract '%s' from CDR\n", time_name);
+	}
+
+	return time;
+}
+
 static void cdr_read_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
 {
 	struct cdr_func_payload *payload = stasis_message_data(message);
@@ -268,16 +288,21 @@
 
 	if (ast_test_flag(&flags, OPT_FLOAT)
 		&& (!strcasecmp("billsec", args.variable) || !strcasecmp("duration", args.variable))) {
-		long ms;
-		double dtime;
+		struct timeval start = cdr_retrieve_time(payload->chan, !strcasecmp("billsec", args.variable) ? "answer" : "start");
+		struct timeval finish = cdr_retrieve_time(payload->chan, "end");
+		double delta;
 
-		if (sscanf(tempbuf, "%30ld", &ms) != 1) {
-			ast_log(AST_LOG_WARNING, "Unable to parse %s (%s) from the CDR for channel %s\n",
-				args.variable, tempbuf, ast_channel_name(payload->chan));
-			return;
+		if (ast_tvzero(finish)) {
+			finish = ast_tvnow();
 		}
-		dtime = (double)(ms / 1000.0);
-		snprintf(tempbuf, sizeof(tempbuf), "%lf", dtime);
+
+		if (ast_tvzero(start)) {
+			delta = 0.0;
+		} else {
+			delta = (double)(ast_tvdiff_us(finish, start) / 1000000.0);
+		}
+		snprintf(tempbuf, sizeof(tempbuf), "%lf", delta);
+
 	} else if (!ast_test_flag(&flags, OPT_UNPARSED)) {
 		if (!strcasecmp("start", args.variable)
 			|| !strcasecmp("end", args.variable)

-- 
To view, visit https://gerrit.asterisk.org/2044
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I8bc63822b496537a5bf80baf6102c06206bee841
Gerrit-PatchSet: 3
Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Owner: Matt Jordan <mjordan at digium.com>
Gerrit-Reviewer: Anonymous Coward #1000019
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Mark Michelson <mmichelson at digium.com>



More information about the asterisk-code-review mailing list