[Home]

Summary:ASTERISK-16475: CDR user fields not updated and CDR() returns invalid data when using Queue with "c" flag
Reporter:Kirill Katsnelson (kkm)Labels:
Date Opened:2010-07-29 19:52:10Date Closed:2015-03-27 15:36:47
Priority:MinorRegression?No
Status:Closed/CompleteComponents:CDR/General
Versions:Frequency of
Occurrence
Related
Issues:
Environment:Attachments:
Description:When Queue() is called with the "c" flag (continue dialplan after agent hangup):
# assignments made to CDR(...) values from the h extension are not written to the database; these are the userfield and all additional custom fields (used with  adaptive_odbc).
# {{CDR()}} fields are reset to defaults. These are {{CDR(billsec)}}, {{CDR(duration)}}, {{CDR(disposition)}} -- possibly more.

*STEPS TO REPRODUCE*

{code}
context cdr-bug {
 777 => {
   QUEFLAGS = "ct";

   CDR(userfield)="before queue";
   Verbose(1, Before Queue: QS:${QUEUESTATUS} T:${CDR(billsec)}/${CDR(duration)} D:${CDR(disposition)} A:${CDR(amaflags)});

   Queue(QTest,${QUEFLAGS});

   CDR(userfield)="after queue";
   Verbose(1, After Queue: QS:${QUEUESTATUS} T:${CDR(billsec)}/${CDR(duration)} D:${CDR(disposition)} A:${CDR(amaflags)});
 }

 h => {
   CDR(userfield)="hangup";
   Verbose(1, Hangup: T:${CDR(billsec)}/${CDR(duration)} D:${CDR(disposition)} A:${CDR(amaflags)});
 }
}
{code}

Send a call to 777@cdr-bug ("Customer" originates). Have a device in the queue QTest answer (this is the "Agent"). set core verbose 1 to see Verbose() output from the script.

Test1: "Customer" hangs up 10 seconds into the call.
 Before Queue: QS: T:0/0 D:NO ANSWER A:DOCUMENTATION
 Hangup: T:0/0 D:NO ANSWER A:DOCUMENTATION
Values of 0/0 and "NO ANSWER" are wrong.
CDR userfield set in the database to "before queue" -- expected "hangup".

Test2: "Agent" hangs up 10 seconds into the call. The same problem.
Agent hangup, CT
 Before Queue: QS: T:0/0 D:NO ANSWER A:DOCUMENTATION
 After Queue: QS:CONTINUE T:0/0 D:NO ANSWER A:DOCUMENTATION
 Hangup: T:0/0 D:NO ANSWER A:DOCUMENTATION
userfield: "before queue"

Control. Change QUEFLAGS to "t" (remove the c flag), and the same 2 tests act normally.

Customer hangup
 Before Queue: QS: T:0/0 D:NO ANSWER A:DOCUMENTATION
 Hangup: T:10/10 D:ANSWERED A:DOCUMENTATION
Userfield:hangup

Agent hangup
 Before Queue: QS: T:0/0 D:NO ANSWER A:DOCUMENTATION
 Hangup: T:8/8 D:ANSWERED A:DOCUMENTATION
Userfield:hangup

All values are present and database is updated with the correct value.

*ADDITIONAL INFORMATION*

I think that Dial() with the g flag has the same problem.
Comments:By: Leif Madsen (lmadsen) 2010-08-05 14:25:51

I asked Tilghman on IRC about this issue, and here is some of the discussion and his thoughts. It seems you're going to be better off with CEL in Asterisk 1.8 than us modifying the CDRs again here, because when we knock one gopher down another pops up, especially in edge cases like this.


<Corydon76-dig> Oh, I know what it is

<Corydon76-dig> Murf changed how CDRs are generated, and in that case, he's looking at the bridge CDR

<Corydon76-dig> There should be an additional CDR after the bridge, but because it's reset, there isn't

<Corydon76-dig> although I'm confused why the "h" extension values aren't getting set, because the bridge explicitly calls the "h" extension at the conclusion of the bridge

<Corydon76-dig> probably what he means is that the "h" extension isn't getting called AGAIN after the dialplan continues

<leifmadsen> hmm, ya that makes sense

<leifmadsen> I guess he's expecting it to be called for the hungup channel and again after the other channel hangs up?

<Corydon76-dig> How to resolve this, though, is going to be a major PITA.  Best way would probably be to redirect him to CEL

<Corydon76-dig> Well, the CDR is only ever posted from the controlling channel

<Corydon76-dig> except in the case of a bridge, in which case, it's called from the bridge code

<Corydon76-dig> It's even further complicated by this being a Queue

<Corydon76-dig> what was fun is that we put in a ton of effort into making sure that the "h" extension will never run a second time for a single call

<Corydon76-dig> so once it's called for the bridge, see ya, so long, no more...

By: Kirill Katsnelson (kkm) 2010-08-05 14:50:38

I traced code some time ago, when first discovered that, and yes, it seems to me that the bridge is involved heavily. I also remember having not even a glimpse of an idea how to fix that... :-(

What is the position of CEL/CDR? Is CDR going legacy, and CEL is the way to go? I am almost sure I cannot fix the present issue by myself; should I refresh my memory and find the exact location where the CDR update is bypassed due to the flag, or there is no use even doing that?

By: Leif Madsen (lmadsen) 2010-08-06 13:44:05

Well the thing with CDRs is that we're trying not to change them anymore. Everytime we "fix" something for one person, we break CDRs for someone else.

CDRs were never designed for the complex call flows that some people expect to use them for. CEL was designed for that very issue, so for complex call scenarios like the one described here, CEL is a much better option.

By: Leif Madsen (lmadsen) 2010-08-06 13:48:45

The resolution to this issue, at a minimum, is to provide some sort of documentation to explain why this can't be resolved as-is, and to explain why you can't expect CDRs to work as might be expected.

We need to make sure that when these types of issues come up, we document and explain why CDRs are not designed for this type of call flow instead of just closing them.

Bottom line: don't close this issue unless you've provided documentation to the Asterisk source tree explaining why this can't be done ;)

By: Kirill Katsnelson (kkm) 2010-08-06 18:08:58

“Well the thing with CDRs is that we're trying not to change them anymore. Everytime we "fix" something for one person, we break CDRs for someone else.”

Amen to that! I've seen some subtle changes in the past with upgrades.

And internally, in our software we have couple of such poisonous features as well. :-)

By: André Emerich (aemerich) 2012-08-01 16:44:35.881-0500

I have a tip to turn around this problem..
Put this before Queue:
exten => _X.,n,Set(STARTCALL=${CDR(start)})
exten => _X.,n,Set(ANSWERTIME=${CDR(answer)})

And in h exten, I had put:
exten => h,n,Set(DURATION=$[${EPOCH} - ${STRPTIME(${STARTCALL},,%Y-%m-%d %H:%M:%S)}])
exten => h,n,Set(BILLSEC=$[${EPOCH} - ${STRPTIME(${ANSWERTIME},,%Y-%m-%d %H:%M:%S)}])

It was enough to me to "cheat" this problem.

I hope it helps.

By: Matt Jordan (mjordan) 2015-03-27 15:36:40.848-0500

I'm going to go ahead and close this out as "Won't Fix."

First, Leif and Tilghman were absolutely right in their assessment of CDRs. "Thar be dragons in that thar code."

Second, we fundamentally changed CDRs in 12+. In some ways, the behaviour as described above is now, well, by design. You will get multiple records depending on what the call does, and they may have different durations. The assumption of CDRs is that once you hit a particular point of complexity, you are going to have to post-process your records. Asterisk is too complex and allows a user to do too many things to pretend like it can provide one consistent picture of the world. Sometimes the best it can do is present you with what happened, and let you go make a billing record out of it.

At any rate, we won't lose information in 12+.