Reference:Call Detail Record CDR
This article is about the now deprecated "gateway level CDRs". For a newer and now recommended CDR scheme see: Reference13r3:Concept_Call_Detail_Record_CDR_PBX.
What is a CDR?
A CDR's purpose is to facilitate billing of customers for calls performed through a gateway running on a particular innovaphone IP gateway. A CDR is defined as a sequence of entries which in total describes a single call as far as billing is considered.
What is the mechanism CDRs are provided by the IP gateways?
The CDR's log entries are provided using a dedicated channel which is technically equal to the version 3 log mechanism of the innovaphone IP gateways. This is to de-couple CDR entries from other possible log entries. The transport mechanisms are as follows:
- syslog
- deliver entries to (unix-ish) syslogd. Entries are sent to a configured syslog demon using the syslog class specified.
- raw tcp
- deliver entries to specified host and port in raw text-based tcp stream. The IP 400/3000 will open a TCP socket to the specified IP address and port and write each entry to this stream. If the stream is closed for any reason, it will be re-opened again. Entries are separated by CR/NL.
- raw tcp incoming
- retrieve entries in raw text-based tcp stream by connecting to a specified TCP port of the gateway. As before except that the gateway waits for an incoming connect.
- http
- deliver entries by HTTP 1.0 GET request to specified web server with query part in URL (e.g. http://path?log=msg)
Can CDRs get lost?
Yes. Currently, only CDRs sent with HTTP are buffered (that is, kept until the corresponding "200 OK" is received). That is, when a CDR is generated and there is no active and functional CDR delivery mechanism at this point in time, only CDRs sent by HTTP are re-tried, all others get lost. Also, CDRs are NOT buffered permanently, so they will get lost when the box restarts (because of this, the box will postpone a reset request until all CDRs are sent).
Thus, you must make sure that the mechanism is always in place.
The amount of memory dedicated for buffering CDRs depends on the gateway model. Models with big memory (such as e.g. IP800/IP3000/IP6000/IPxx10/IPxx11) buffer up to 2000 CDRs of max. 300kB total size, others (such as e.g. IP400 and IP202) only up to 330 of max 50kB total size. A CDR is of variable size, but as a rule of thumb, 200 bytes per Gateway CDR should be a valid average. PBX CDRs may be much larger.
How many CDRs are generated per call and when?
Unless you have ticked “Send only billing CDR’s” in the gateways CDR configuration, you will see a single CDR for each event on the call.
Here are the events for a typical straight call:
event=A:Call src_cgpn=32 src_cdpn=7300961321 event=B:Call src_cgpn=32 src_cdpn=7300961321 dst_cdpn=7300961321 dst_cgpn=32 event=B:Call src_cgpn=32 src_cdpn=7300961321 dst_cdpn=7300961321 dst_cgpn=32 event=B:Proceed src_cgpn=32 src_cdpn=7300961321 dst_cdpn=7300961321 dst_cgpn=32 event=B:Alert src_cgpn=32 src_cdpn=7300961321 dst_cdpn=7300961321 dst_cgpn=32 event=B:Connect src_cgpn=32 src_cdpn=7300961321 dst_cdpn=7300961321 dst_cgpn=32 event=B:Disc src_cgpn=32 cause=02_80_90 src_cdpn=7300961321 dst_cdpn=7300961321 dst_cgpn=32 event=A:Rel src_cgpn=32 cause=02_80_90 src_cdpn=7300961321 dst_cdpn=7300961321 dst_cgpn=32 event=B:Rel src_cgpn=32 cause=02_80_90 src_cdpn=7300961321 dst_cdpn=7300961321 dst_cgpn=32
With reduced CDRs for billing purposes, you will see only the final events:
event=A:Rel src_cgpn=32 cause=02_80_90 src_cdpn=7300961321 dst_cdpn=7300961321 dst_cgpn=32 event=B:Rel src_cgpn=32 cause=02_80_90 src_cdpn=7300961321 dst_cdpn=7300961321 dst_cgpn=32
See chapter 9 for more detailed exampled of CDRs. So if you are interested in billing purposes only, you should configure billing CDRs only to reduce traffic and to increase the number of calls being buffered in case of a CDR link failure (see above). The CDR generation is done by the gateway process. This has the advantage that billing is available even if there is no PBX installed, however it has the disadvantage that for PBX-internal calls (including calls in-between different locations of the same PBX net) no CDRs are generated (since these calls are not seen by the gateway process).
Each event is prefixed by a leg identifier (either A or B). To understand this, consider the following example:
- A PBX user (extension 32) calls an external user in the PSTN (07300932)
- The PBX is registered with the gateway process with the GW1 voice interface
- The call is sent to the PSTN through an ISDN interface PRI1
When the call arrives from the PBX at GW1, the GW1 interface mappings (if any) are evaluated. Then
the call is sent to the routing engine. This end of the call is known as “leg A”. All events originating
at this leg are prefixed with “A:”. Depending on the routing table configuration cdpn/cgpn mappings
are performed, then the call is routed to an outgoing interface. This end of the call is known as “leg
B”. All events originating at this end are prefixed with “B:”.
In the CDR, you will find the numbers after the mapping at the source interface but before the
mapping defined by the routing table as src_cgpn and src_cdpn respectively. The numbers after the
mappings defined by the routing table but before performing the mappings defined for the destination
interface are shown as dst_cgpn and dst_cdpn respectively. These numbers are always in sync on the
A and B leg. However, please note that the numbers (especially the dst_* numbers) may change due
to settings in the routing table (e.g. if least cost routing is configured and multiple call by call
providers are tried to place the call). Also, the interfaces may change (e.g. if a trunk line bundle is
used and one line is busy clearing the call with a “no b channel available” cause code, then another
interface may be tried and thus seen as dst_if). Please note also that, after a call transfer, the src_if
(which actually is the interface used by the A leg) may be used for an outgoing call (and the dst_if
may be used for an incoming call), depending on the value of the dir attribute.
Initially, the A-leg is incoming (as seen from the routing engine), the B-leg is outgoing. However,
after a call transfer, both legs may be incoming or both legs may be outgoing or the A-leg may be
outgoing and the B-leg incoming. This may be significant for billing purposes. Each event has a “dir”
attribute which is either “in” or “out”. So if there is an event for the A-leg and the “dir” attribute has
the value “out”, then the call direction of the A-leg is outgoing (as seen from the routing engine).
When a call transfer happens, it is reflected in an A:X or B:X event. If 2 calls are merged by a
transfer, then one of the call legs receives an X event with an xref/xleg attribute which points to the
call being merged.
All CDRs created by a single call, regardless of the leg the respective event originates from, share the
same ref field.
Depending on the billing strategy, the src/dst_dgpn (diverting party number) may be of interest.
How do I tell internal from external calls?
From the gateway process’ point of view (and thus from the CDR’s point of view), there is no distinction between internal and external calls. Any call travelling through the gateway process is a call for which CDRs are generated. As said before, internal calls from the PBX’s point of view currently do not create CDRs at all. For all others, the interpretation of being “internal” or “external” must be done by the receiving application. Usually, such applications have a configuration dialog to define the interface names (which are seen as dst_if or src_if) which are considered “external”. As a rule of thumb, most ISDN interfaces can be regarded “external” normally3. These names include TEL1, TEL2, TEL3, TEL4, PPP, PRI14.
In some cases, ISDN interfaces are used for connectivity to internal entities. This is e.g. if a second
PBX is connected via a tie line or the gateway is looped-in to the trunk line of the legacy PBX. The
PRI2 interface is usually used in that way.
Note though that all interfaces may be configured individually and thus in a specific installation may
be used for different purposes.
How does a single CDR log entry look like?
A particular log entry has several fields. A field has a name tag and a value. Fields can appear in an arbitrary order within the entry. Not all fields appear in every log entry.
Name tags include:
- cause
Cause code for call termination. These are coded <size>_<coding-standard/location>_<causecode>[_<diagnostics>]. The individual octets (separated by ‘_’ are hex-numbers). Size is usually 0x2.
The example cause translates to “unallocated number”:
cause=02_82_81
- bcaps
Bearer capabilities as received in the incoming call. Coded as hexadecimal octet string according to Q.931. Octets are separated by ’_’. Bearer capabilities are used to describe the type of calls (voice, fax, data, etc).
bcaps=03_80_90_a3
- ref
Call destination. This is a per-call unique identifier and shall not occur twice.
ref=b8a9051be909d311b5fd009033000190
- dst_cdpn
The called party number as dialled on the outgoing interface.
dst_cdpn=01727250457
- dst_cgpn
The calling party number as presented on the outgoing interface.
dst_cgpn=53
- dst_dgpn
The diverting party number as presented on the outgoing interface. This field occurs on calls that have been diverted after passing the gateway.
dst_dgpn=70
- dst_name
The called H.323 alias name as presented on the outgoing interface.
dst_name=NVphone
- dir
The direction of the call-leg the event is posted for. E.g. if the record has an event=B:Connect and dir=out, then the direction of the B call leg is outgoing (as seen at the destination interface given as dst_if). Either in or out.
dir=out
- xref
The ref of the call being merged into the current call due to a call transfer.
xref=b8a9051be909d311b5fd009033000190
- xleg
The leg of the call referenced by xleg that is merged in. Either A or B.
xleg=A
- event
The event triggering this particular CDR entry. Valid events are (more may be added in the future, so ignore unknowns!):
Eventname | Description |
A:Call | The calling party initiates a call. |
B:Call | The called party is called. |
B:Proceed | A call proceeding is received from the calling parties network (or a transit). |
Media | A media channel has been established. |
B:Alert | The called party is alerted. |
B:Connect | The called party is connected. |
A:X | The calling party transfers the call. Following events will display a different calling party. |
B:X | The called party transfers the call. Following events will display a different called party. |
A:Disc | The calling party disconnects the call. |
B:Disc | The called party disconnects the call. |
A:Rel | The calling party releases the call. |
B:Rel | The called party releases the call. |
No-Route | The gateway routing process has no route for the call. |
event=A:Call
- src_cdpn
The called party number as received in the incoming call.
src_cdpn=01727250457
- src_cgpn
The calling party number of the calling party as received in the incoming call.
src_cgpn=53
- src_dgpn
The diverting party number as received in the incoming call. This field occurs on calls that have been diverted before passing the gateway.
src_dgpn=70
- src_name
The H.323 alias name of the calling party as received in the incoming call.
src_name=NVphone
- src_reg_name
The H.323 alias name of the calling party as defined by the gatekeeper.
src_reg_name=NVphone
- src_if
The originating interface of the call. E.g. GW2 can be a Gatekeeper interface.
src_if=GW2
- dst_if
The destination interface of the call. E.g. PPP is a physical Isdn interface.
dst_if=PPP
- time
A time-stamp in 1 second resolution since 01.01.1970 (UTC). The time base does not change during a call (it might change between calls due to clock settings).
time=95985
- ts (since 12r2)
A timestamp since start of the gateway. Format: <seconds>.<milliseconds>
ts=123.045
- alert_time
A time-stamp in 1 second resolution since 01.01.1970 (UTC). This timestamp is comprised within a CONNECT CDR, in order to ease the duration calculation of the alerting phase. : alert_duration=time(CONNECT) – alert_time
alert_time=95985
- connect_time
A time-stamp in 1 second resolution since 01.01.1970 (UTC). This timestamp is comprised within a DISC or REL CDR, in order to ease the duration calculation of the phase a call was in the connected state. :
connect_duration=time(DISC) – connect_time
connect_time=95985
- disc_time
A time-stamp in 1 second resolution since 01.01.1970 (UTC). This timestamp is comprised within a REL CDR, in order to ease the calculation of the amount of time it took to completely release a call.:
release_duration=time(REL) – disc_time
disc_time=95985
- date
The "human readable" date and time: 4 digit year, 2 digit month, 2 digit day of month, 2 digit hours (24h clock), 2 digit minutes, 2 digit seconds. This is not implemented in beta III software.
date=20000101-000000
- charge_units
The accumulated charging units at the end of a call. This complies to the Aoc-E PDU or Aoc-D(total) PDU of Q.956. Clause 2. The example shows how charges would be presented in Germany.
charge_units=3
- charge_amount and charge_curr
The accumulated charge amount at the end of a call. This complies to the Aoc-E PDU of Q.956. Clause 2 . The example shows how charges would be presented in Denmark.
charge_amount=0.80&charge_curr=kr.
- xcoder
The media codec being applied in transmit direction. If present, the info conveyed is:
v6: Codec[string],Framesize[ms](Receive Jitter[ms],Roundtrip Delay[ms])
v7: Codec[string],Framesize[ms](RoundTripAverage[ms],JitterMaximum[ms],PacketLoss[ms])
Currently, the following coders are defined:
G711A, G711u, G723-53, G723-63, G729, G729A, G729B, G729AB, G726-40, G726-32, G726-24, G726-16, T38TCP, T38UDP, XPARENT, HDLC (Although HDLC will currently never happen)
xcoder=G729AB,60c(0,0,0)
- rcoder
The media codec being applied in receive direction. If present, the info conveyed is:
v6: Codec[string],Framesize[ms](Receive Jitter[ms],Roundtrip Delay[ms])
v7: Codec[string],Framesize[ms](RoundTripAverage[ms],JitterMaximum[ms],PacketLoss[ms])
rcoder=G729AB,60(0,0,0)
- xstats
The media statistics of the outgoing audio stream as measured on the remote party. The five fields are: Average Roundtrip Delay, Maximum Roundtrip Delay, Average Jitter, Maximum Jitter, Packet Loss.
xstats=0+0+0+0+0
- rstats
The media statistics of the received audio stream. The five fields are: Average Roundtrip Delay, Maximum Roundtrip Delay, Average Jitter, Maximum Jitter, Packet Loss.
rstats=0+0+0+0+0
- srv_id
The server id. The purpose is to provide a constant unique id serving as an originator address for CDRs. The actual aim is to support billing applications.
srv_id=00-90-33-01-00-7a
How are CDR entries encoded?
CDR entries come in 8-bit ASCII character set.
CDR entries are URL-encoded. URL-encoding translates all reserved characters in a string to the format %HH, where HH is the hexadecimal equivalent of the character’s ASCII value. Spaces are translated to "+".
Example: If src_name is equal to "Mike O’Brien" then it will be encoded as Mike+O%27Brien".
Fields are separated by ampersand (’&’). Each entry starts with a question mark. Example:
?event=A:Disc&time=24&ref=GW12:b5ed3f90e909d3119d37009033000048&src_cgpn=32&src_cdpn=10&dst_cgpn=32
there are slight variations depending on the delivery mechanism:
- syslog
- a log class is added.
- raw-tcp
- each CDR entry is prefixed by a time and date value. this is formatted as described above for the
date
tag (e.g. 19700101-000024)
- raw-tcp incoming
- formatted as above. when connecting to the IP Gateway, it says
Log started
. This line has to be ignored by the CDR analysis.
- http
- the CDR data is presented to the web server as FORM data which can be passed to CGI-interfaces, Active-X controls etc. Tag names are used as form-field names. note that the CGI program receiving the data must return content to the web server to satisfy the GET command used. this content however usually is empty.
Appendix: Sample Active Server Page
This example outlines the storage of CDRs using an ASP-enabled Web Service (tested with MS’s IIS5).
The application lives in the URL /cdr. It will by default create logfiles named "cdrlog_date_srcip.txt" in a subdirectory "CDR" underneath /cdr. Thus, a logfile may be found on \\webserver\webroot\cdr\cdr\cdrlog_20010208_195.226.104.135.txt.
The application is made up of 3 files that you can download here cdr_sample_application.zip:
- global.asa
- Initialises system parameter.
- cdrwrite.asp
- Actually writes the CDR entries to the log file
- cdrform.htm
- Sample HTML form to debug the installation
- copy all files into root your web servers in "/cdr" directory
- create a subdirectory called "CDR"
- make sure your web server processes ASP applications in the "/cdr" directory
- Point your browser to the server and open "/cdr/cdrform.htm". You should see a form
- Enter your name, then click the Submit button.
- Fill in the fields and submit the form
- Event:
A:Disc
- CDR LOG Entry saved to \\webserver\wwwroot\cdr\CDR\cdrlog_20070828_127.0.0.1.txt
- Tag:
time = 100
- Tag:
event = A:Disc
- CDR ENTRY(082829 time=’100’ event=’A:Disc’ )
- Done.
- to configure CDR write destination on IP-Gateway open web interface and go to Gateway->CDR0:

- set CDR-Logging parameters appropriately
- Click OK
Appendix: Sample billing records
As noted in chapter 7, the actual coding of the CDRs depends on the transport mechanism used. For a better understanding of the CDRs, the following lists the CDR events generated in a few standard cases. The CDR content is giving in a suitable pseudo notation, it is not what is received via the wire. For convenience, a packet capture (in pcap format, see Wireshark (formerly Ethereal)) of the same CDRs is also provided.
The data can be found in the .zip file: cdr_sample_records.zip
Call Scenarios captured
The sample scenario includes 5 parties:
- the first external user e1=070317300932
- the second external user e2=07033529969
- the first internal (a.k.a. PBX) user i1=44
- the second internal user i2=55
- the switchboard[1] has extension switchboard=10 and is called from extern via -0
The PBXs trunk access code is 0. The ISDN trunk interface is PPP. The PBX interface is GW1.
Index | Scenario | Initiator | Details | Result |
1 | Incoming call | E1 calls i1 | ||
2 | Forwarded incoming call. | E1 calls i1 | I1 has call forwarding (CFNR) to i2. | E1 calls i2. |
3 | Transferred incoming call | E1 calls i1 | I1 calls i2. I1 transfers i2 to e1 |
E1 calls i2 |
4 | Blindly transferred incoming call | E1 calls i1 | I1 blindly xfers to i2 | E1 calls i2 |
5 | Incoming call forwared to extern | E1 calls i1 | I1 has call forwarding (CFNR) to e2 | E1 calls e2 |
6 | Incoming call blindly xfered to extern | E1 calls i1 | I1 blindly xfers to e2 | E1 calls e2 |
7 | Incoming call xfered to extern | E1 calls i1 | I1 calls e2. I1 xfers to e2 |
E1 calls e2 |
8 | Outgoing external calls joined | I1 calls e1 I1 calls e2 |
I1 xfers e1 to e2 | E1 calls e2 |
9 | Incoming external calls joined | E1 calls i1 E2 calls i1 |
I1 xfers e1 to e2 | E1 calls e2 |
10 | Internal call forwarded to extern | I1 calls i2 | I2 has forwarding (CFNR) to e2 | I1 calls e2 |
11 | Outgoing call | I1 calls e1 | ||
12 | Incoming call to switchboard | E1 calls switchboard | i1 picks up | E1 calls i1 |
- ↑ Calls to the switchboard are sent to both i1 and i2, either of them picks up