Go to Chapter 2    :  Chapter 4        Contents

3. Getting the CDR's (Call Detail Records)

It's a no-brainer, if you can monitor in real-time, you can most certainly log what is being happening. Still, a few questions must be answered:

Most of the real-time information goes into the CDR's, yet some variables, like call duration, byte and packet counts and disconnection causes, must be read from the gateway history log to get re real final counts. Also real-time  instant values of Gap and Latency must turn into averages for the call before they go into the CDR, this information is also in the history log. Under heavy call volume the permanence of a call in the history buffer gets smaller and at some point, depending on how fast is the GW_Relay link to the gateway, it may happen it can not get to log the call before it disappears from the buffer. In this case, the call is logged with the last real-time info, that, for the above mentioned reasons, may not be fully accurate. This event generates an alarm like for instance:

10/27/03 07:38 AM ---#12-Error parsing, CDR with last known data 1F8 :

If this happens too frequently, it may be a good idea to setup a larger buffer at the gateway.

3.1 what to log?

Gateways produce an overwhelming volume of information about a call, should we log them all and let the user sort out what's relevant. This approach has a few disadvantages: it burdens the users with with the task of field selection; it will use up a lots of disk space in useless information; eyeballing through the CDR's without a previous query becomes a useless exercise. Big Bro will release you from that burden, it has already selected the fields that would, most likely, be relevant. Also, gateways report separately the two legs of a call, but what you need are Call Detail Records not Leg Detail records, because you don't charge for leg but for call, if a leg fails a call fails, so Big Bro figures that records must refer to that two legged unit known as the "call". 20 values have been selected for Big Bro's CDR:

CallID Setup NoChargT ChargeT dnis ani ChNum Cause Codec PSTN_2_IP IP ...
135937792 9/1/03 5:50:46 PM 13290 586 0914522912   424 4112 g729r8 0 ...
135937778 9/1/03 5:32:59 PM 15830 1154 0913883828 9083544962 405 4112 g729r8 0 ...
135937779 9/1/03 5:33:14 PM 8910 1157 30185113883828   211 4112 g729r8 0 ...
135937790 9/1/03 5:46:35 PM 10940 377 30185112582164   224 11308 g729r8 1 ...
cont ...
CallID ... PeerID Gap_2_pl rtt IsFax PacketsIn BytesIn PacketsOut BytesOut GW_Name
135937792 ... 3652 0.03 116 0 15015 300300 24825 488995 NTK_LMA_2
135937778 ... 3652 0.04 105 0 26350 527000 51252 995742 NTK_LMA_2
135937779 ... 3018 0.03 221 0 0 0 26684 533680 NTK_LMA_2
135937790 ... 3018 0.03 221 0 0 0 12690 253800 NTK_LMA_2


3.1.1 CallID

The purpose of this field is to provide a unique number for every call, unique...not in the Galaxy, just in the gateway, so a 32 bit number would do perfectly. Gateways provide a 16 bit call number. The number will repeat every 65535 calls, but is quite unlikely to happen in an hour, because it would take, for instance, every channel in an 8 E1 gateway to average over 273 attempts per hour. So, to get a unique number, Big Bro adds to this mentioned gateway's ID, the count of hours from a fixed date multiplied by 65536 to the moment the call finishes. And what would be that "fixed date", well... what we at #include has considered to be Big Bro's birthday, 8/24/2003.


3.1.2 Setup

Is a string with the setup date-time of the call in the same format that has been set in the gateway. If the CDR are being saved to a Microsoft SQL server using the stored procedure "proc_GW_CDR" provided by include, this field is converted to a datetime type variable.

3.1.3 NoChargeT

Non chargeable time: is that interval from setup to connection, also known in standard telephony as PDD or Post Dial Delay.  It expressed in milliseconds.

3.1.4 ChargeT

Chargeable time: the interval from connection to call drop, the duration of the call. It is expressed in seconds.

3.1.5 DNIS

Dialed Number Identification Service: actually is just a string with the Called Number. To be even more precise, it is the number labeled as "called" in the gateway's "calltracker service", it some time may include some extra prefixes for peer matching.

3.1.6 ANI

Automatic Number Identification: actually is just a string with the Calling Number. To be even more precise, it is the number labeled as "calling" in the gateway's "calltracker service",

3.1.7 ChNum

A number that identifies the DS0 channel being used in a call. The number is Span Number x 100 + channel number. Both the span and the channels are numbered from 1, so the first channel of the first span is 101.

3.1.8 Cause

Contains the Q.931 call termination cause code. Since there are two disconnections for every call, one for each leg,  Answer or Originate. A way must be found to express this in most meaningful way. Here's how we do it in 16 bits: The sign will tell which leg terminated the call, positive will mean that the "Answer" leg terminated the call. The cause of the terminating leg, whichever it may be, Answer or Originate, will go in the 7 less significant bits of the absolute value of the field, while the cause of the last to drop will go from the ninth to the fifteenth. For example (0x stands for Hexadecimal expression)

Cause = 4112 =  (+1) x (0x1010) means Caller hung up, since it is positive and 0x10 (16) stands for normal clearing

When calls terminate normally, only the sign carries some information. Upon failure, it is the terminating leg that may carry information because the other will bear a trivial cause. Trivial as being the same if dropped by the gateway or just normal termination if by the party. The relevant information should always be found in the lower 7 bits and the the sign. (See a reference with the Q.931 disconnect cause descriptions

3.1.9 CODEC

The string read from the gateway is supplied without further processing.

3.1.10 PSTN_2_IP

This is Boolean field, is TRUE if the inbound call comes into a DS0 from the PSTN and FALSE  if from the IP network. The case of a PSTN to PSTN call, will also render a TRUE, since the inbound is a DS0.

3.1.11 IP

A string with the IP in the aaa.bbb.ccc.ddd format. In case of a PSTN to PSTN call, it will carry a string with the ChNum of the outbound DS0. This is important information because it identifies the client or the provider.

3.1.12 PeerID

A 32 bit number with the "Originate" leg Peer ID. The "Answer" peer ID doesn't bear too much information, it involves no matching and it is not related to the caller in any way.

3.1.13 Gap_2_pl

Average Gap to Playback ratio expressed as a floating point percentage number with two digits after de decimal point. In a perfect IP world, all packets are received in time and so they are played back, but in the real word packets may be late, in which case the CODEC will have to fill that gap, with either silence or with extrapolated data. Early packets is just as bad,  the buffer may overflow and forcing packets to be discarded, when the time comes to playback those discarded packets, the gap must be filled again with, either silence or interpolated data. The bigger the gap time, the poorer the sound. The ratio Gap time to Playback time is a figure of merit to the lack of quality of the sound.

When the silence suppression feature is activated in a gateway, the CODEC will insert silences after a command instead of playing back silent packets. This saves considerable bandwidth, but the gap is no longer related to sound quality but to the nature of the feature. Fortunately in these cases, gap time can be greater than play time when a party is listening, indicating to the GW_Relay that the mentioned feature is being used. In this case, total packet loss to received packet count ratio will be used instead. 

3.1.14 RTT

Round Trip Time in milliseconds. One of the elements in the quality of a connection is the Latency, or the response time to caller's prompting of the other party. A long latency can make a real mess of a phone conversation, if you have to wait too long for a reply, you are prone to repeat the question, this starts an undetermined sequence of misunderstandings. Good values are under 300 ms, fair values, under 700, the rest are poor. 

3.1.15 IsFax

This is a Boolean field that is TRUE if the call is a FAX.

3.1.16 PacketsIn

Inbound packet count. A comment here about the packets an byte count: The ratio from packets to bytes depends on the packet payload and on the header compression. The fewer packets the better use of the bandwidth, even with the same CODEC, the payload size is negotiated with the remote party, a wrong setting on any of the two gateways involved in a call can use more bandwidth that it is really necessary. On the other hand, bigger payloads cause bigger gaps when packets are lost, so it your link has an unstable return time and sound quality is important, you may want to have smaller payloads.

3.1.17 BytesIn

Inbound Byte count

3.1.18 PacketsOut

Outbound packet count

3.1.19 BytesOut

Outbound byte count

3.1.20 GW_Name

It is string variable with the name of the gateway. Exactly, it is the text in the prompt of a TELNET session without the ">" or the "#".  This field becomes very important when CDR's from more than one gateway are making it into the same table. Actually is must belong to the primary key of the CDR table.

3.2 where to log?

3.2.1 In a Database?

GW_Relay can connect with any database by ODBC. The name to the ODBC DSN can be specified in the GW_Relay.ini with the parameter ODBC_DSN_SRC A direct ODBC connection to the database would be a very straight forward choice. A table could be created with the fields described in 3.1.  GW_Relay calls a stored procedure proc_GW_CDR and sends the fields above as parameters. A sample script for that stored procedure for a Microsoft SQL server is:


@CallID int,  @Setup datetime, @NoChargT int, @ChargeT int, 

@dnis varchar(50), @ani varchar(50),
@ChNum int, @Cause int, @Codec varchar(20), 

@PSTN_2_IP int, @IP varchar(15), @PeerID int,
@Gap_2_pl float, @rtt int, @IsFax int, 

@PacketsIn int, @BytesIn int, @PacketsOut int, @BytesOut int,
@GW_Name varchar(20) 


if exists (Select * from CDR_Table WHERE   GW_Name = @GW_Name AND 

                                             Setup = @Setup AND 

                                             ChNum = @ChNum) return 0

    @CallID, @Setup, @NoChargT, @ChargeT, @dnis, @ani,
    @ChNum, @Cause, @Codec, @PSTN_2_IP, @IP, @PeerID,
    @Gap_2_pl, @rtt, @IsFax, @PacketsIn, @BytesIn, @PacketsOut, @BytesOut,
return 0

It is possible that there is already a billing system in exploitation and data must be reformatted into a different table than the one described or even into a Database like, for example, an Oracle server. In this case, a different procedure that includes data transformation must be devised. #include can offer you this service.


Another problem arises when the server carrying the accounting is not in the same building, same subnet, same city, state or country. Solution to this is to create a local Microsoft SQL server (could be the free licensed MSDE from Microsoft) and use #include Replication Scheme to send CDR's reliably to any place in the world. Setting up this replication system involve some licensing, contact #include if interested.

3.2.2  In Text files?


This requires almost no set up, you just need to specify a directory in parameter CDR_TXT_PATH of the GW_Relay.ini file. These files can then be imported to other billing systems.


3.3 When to Log?


In the case of a direct connection to a database, logging takes place as soon as a call is ended, the log is almost real-time. If using the Replication Scheme, calls go to the pending replication table as soon as they end, but replication may or may not happen immediately. If the link between the ReplSrc and the SQLReplic is good, then you get, for all practical purposes, a real-time log, but if the link happens to slow down or even go down, then the Log_PendingRepl will do as a huge buffer for this event. The only thing lost is the real-time feature, but not a single record and this is the beauty of the scheme.


Logging to text files, is different. Even though records are written to files as soon as calls terminate, they can not be copied or opened if the GW_Relay has them opened, this is one of the reasons why al the CDR's can not go into a single text file, the same way they go into a single table. By default, GW_Relay will close a CDR file at the top of the hour sharp, so there is going to be a file for every hour. The name to such files will have the following format:




If you are not planning on hourly file transfers, then you may consider the daily choice a better one, set FILE_INTERVAL to "d". Naming format for these files is:




Daily file close at midnight.


3.3 Who will process the log?


The most likely answer is...yourself. If you already have a billing system, you may integrate Big Bro's CDR's into this system of yours. If you don't have a Billing system, the OmniBilling may be customized to suit your operation by mapping the fields in Big Bro's CDR to those in OmniBilling's Log_CDR..


Also, #include offers to process the CDR's for you, this meaning, to render periodic reports like invoices, provider payments, disputes, performance, etc  Charges for this service will depend on its volume and will be quoted on each case. 


3.4 How about the licensing issues?


Big Bro has several licensing levels, there's the Basic Big Bro License which includes all the features except the CDR's; there is a License for the CDR's that includes even the use of the Replication Scheme and BigBroBill, but installation is not, since it may involve more or less work depending on the your operation. The CDR feature is licensed by spans, this license can be bought, but also paid monthly. The idea behind this monthly license is to let you try the system with a minimum investment. If you take #include's reporting service, you don't need to purchase the CDR license because it will go in the service fee. Check the current offer.