Using CDR for billing (billsec accuracy)

Hello All,

We are using CDR for billing and we are now comparing billing information from Asterisk CDR and billing information bringed by our PSTN operator.

We have to face a minor but critical issue regarding the billsec value accuracy.

For some calls, the billsec value bringed by the operator is 1s more than the billsec value reported by Asterisk in CDR.

On the PSTN operator side, the billing process charges any second that has been initiated. Meaning that for a call that took (billsec) 62.3 s (62 s and 300 ms) the operator will report and charge a billsec value of 63.

At the same time, it looks like (as I can read in the source code) Asterisk is not managing ms in call timestamps… and therefore in the billsec calculation process (I undestand that billsec = hangup timestamp in sec - answer timestamp in sec). Meaning that for the call that took 62.3s, the billsec value reported will be 62 or 63, depending on the rounding process that have been applied on the call timestamps…

Also, is there any workaround or addon patch that can be applied on Asterisk in order to :

  • manage call timestamps in ms, and
  • get billsec in ms or control the billsec rounding rule ?

Thanks for any response.


PTOs and ITSPs will in 99.99% of cases round up to the nearest second or in some cases nearest 30 seconds.

As to rounding I would expect asterisk to follow the normal rules as i said and always roundup.



We have exactly the same problem. All of our calls is 1 second less than that of our providers.(Even 2 seconds in some cases.) Can someone confirm if Asterisk does indeed round the billsec up? Any idea where one can change this behavior?


Ended up the the problem was with our provider’s software. Can you believe it. We were the first people to complain and they traced the fault on there software. :smiley:

At least that is the reason that they gave you :wink:. There is a lot of dishonesty in the telephony world.


I have checked the core code from Asterisk source and found the following in main/cdr.c :

cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec;
cdr->billsec = ast_tvzero(cdr->answer) ?
0 : cdr->end.tv_sec - cdr->answer.tv_sec;

So it looks like there is no rounding process applied on the billsec calculation : the billsec calculation does not take in account at all the ms and also (billsec = end(s) - answer(s)).

It would be more accurate to add the following line (or somelike, I’m not a C developer) :

cdr->billsec += cdr->end.tv_usec > cdr->answer.tv_usec ? 1 : 0;

Meaning that we would have to add 1s in case the fractional part from end time (in µs) is greater than the fractional part from answer time (in µs too).

I will make a post on the developer forum…


Dev team said that billsec accuracy has been improved in Asterisk 1.6 as billsec and duration have been correct down to millisecond.

as indicated :
Note that this is only available on CDR drivers which support the new accuracy (most of the stock drivers, actually) and on database tables which allow either decimals or floats in the duration/billsec columns.


I use Asterisk 15.6.1. How can I get call duration rounded to full second in cdr?
We conduct tests with the operator and his system works in this way…

Add one to the values reported.

Generally, though, you should not expect the provider to agree exactly on the time of answer and clear. For a start, these involve time of flight considerations for the signalling used.

For something that accounts for either rounding to nearest, or a bias in the measured time, rather than adding 1, you could probably change and recompile. However, I haven’t researched this fully and there may be other places where similar calculations are performed.

I tried to make changes in the place you suggested. I also tried in the cdr_object_get_billsec function, but I do not see any effects.

The installation procedure was done as follows:
make menuselect
make install
make samples
make config
make install-logrotate

Am I doing something wrong?

I may not have found all the places where it is calculated, but otherwise there is nothing obviously wrong.

why you not using cdr_custom ?
billsec in cdr_custom is in millisecond

Great, in the folder CDR-custom I have data with milliseconds. Thanks!
However, currently the billing information is stored in the database.
How to force the storage of these custom data in PostgreSQL?

I think you are going to have to go through the code, to find out why my suggestion wasn’t right. I don’t think you will need any deep understanding, and the changes needed should be safe, but you need to put more time into it than I can give.

You can use res_odbc and func_odbc to insert “manually” value in cdr_custom into database.
In my case, I call the func_odbc in “h” extension.

Works beautifuly. But I can’t get ${CDR(answer, u)}
(and end, and billsec and …) in this configuration:

exten => _X.,1,Progress()

exten => _X.,n,Wait(1)

exten => _X.,n,Set(SQL_WRITECDR(${CDR(start, u)})=) ;printing ok

exten => _X.,n,Set(SQL_WRITECDR(${CDR(answer, u)})=) ;is empty

exten => _X.,n,ConfBridge(${EXTEN}, default_bridge, admin_user)

;exten => _X.,n,Set(SQL_WRITECDR(${CDR(answer, u)})=) ;is empty to

exten => _X.,n,Hangup()

How can I get billing data?