CDR details

CDRs (Call Detail Records) are generated by cdrbuild and cdrfile Yate modules (loaded by default in YateUCN and YateSMSC equipment)

  • Configuration files can be found on: /etc/yate/ucn/cdrbuild.conf and /etc/yate/ucn/cdrfile.conf (/etc/yate/smsc/cdrbuild.conf ; /etc/yate/smsc/cdrfile.conf )
  • They are stored by default in /var/log/yate-ucn-cdr.tsv ; /var/log/yate-smsc-cdr.tsv files, which are rotated by logrotate utility.
    » These locations can be changes and you should check that these new files are log rotated -
    » See file '/etc/logrotate.d/yate-ucn'; '/etc/logrotate.d/yate-ucn'
  • We have three on top services to handle Yate products CDR logs.
    ✔ yate-cdrpush → provides a CDR FIFO and JSON despooler for Yate based products
    ✔ yate-cdrfifo → provides a script for pushing CDRs to a remote SFTP server for Yate based products
    ✔ yate-cdrenrich → provides a CDR enricher for YateUCN and YateSMSC that makes JSON requests to YateHSS

CDR files format

Question: Are the records in the CDR files always mixed ?
Answer: Yes, the CDR files are always mixed, there is no warranty regarding the order they are written in the file, you should correlate them by billid.
The records are always build as described in cdrfile.conf file.
This is the header of the table. If a certain value is missing, it won’t be added to CDRs and there will be spaces instead of it.

[root@yate-ucn /etc/yate/ucn]# cat cdrfile.conf 
format=${time}  ${route_type$call}      ${component}${connection_id}  ${billid}      ${chan} ${address}      ${caller}       ${called}    \
 ${billtime}    ${ringtime}     ${duration}     ${direction}    ${status}       ${reason}       ${rtp_stats}    \
 ${charging_id} ${imsi} ${imeisv}       ${nsapi}        ${qci}  ${qos}  ${ipv4} ${ipv6} \
 ${inp_pkt}     ${inp_oct}      ${out_pkt}      ${out_oct}      ${rat_type}     ${plmn} ${loc_info}
[root@yate-ucn /etc/yate/ucn]#

Question: How can we add new fields in the CDR files? (Usage: To record the caller number when he is anonymous)

Answer: First you should add parameter in the cdrfile.conf (the name of the field) and the ‘name_of_variable’
Ex: ,${asserted_caller},${rn},

Then also add that parameter name in cdrbuild.conf

echo "asserted_caller=true" >> /etc/yate/ucn/cdrbuild.conf
echo "rn=true" >> /etc/yate/ucn/cdrbuild.conf

Then assure that these params are copied from other Yate modules.

Any extra parameters can be added in [parameters] section of cdrbuild.conf file

  » rn=true -> updates everytime if it is present

  » rn=false -> it is freezed like this, first time when will be found and is not empty

cdrbuild module will store it when it appears in different monitored messages.
For this to appear in chan.startup of each outbound chan – we should set copyparams=rn from call.route or call.execute

If copyparams already contains some other parameters, we should keep those also, so set like this:


It is alright to have some extra commas.

: In CRDs, the records with same billid are they calculated like one SMS? Answer: Yes. In the example below there are two call legs: incoming and outgoing
Is comming through MAP in the SMSC (40744003001) and is sent over HTTP to

[root@yate-smsc old-cdr]# grep 1543926687-18 core_server2__2018-12-04_15-59-11__yate-smsc-cdr.tsv
1543934906.092  msg     SMSC    1543926687-18   MAP     40740003001     40746820086     40744003001     0.002   incoming                                001010302000035
1543934907.104  msg     SMSC    1543926687-18   HTTP      40746820086     40744003001     0.080   outgoing        4
[root@yate-smsc old-cdr]#


Question: The ‘billid’ is always unique? In which cases there is only one row for a call?
Answer: Yes, the billid is always uniq.
For Voice and SMSes CDRs: It is composed of a timestamp (date when Yate service was started) + uniq ID (which is growing incrementally)

[root@yate-ucn old-cdr]# seelogs core_server1__2018-11-29_13-08-57__yate-ucn-cdr.tsv
2018-11-29_13:08:54.249 call    fixed     1543418964-26   sip/51      +40747553298    +40747735711     0.000   0.000   3.565   incoming        progressing     Request Terminated                
2018-11-29_13:08:54.250 call    mvno    1543418964-26   sip/52      +40747553298    +40747735711     0.000   0.000   3.567   outgoing        progressing     Cancelled                         
[root@yate-ucn old-cdr]# seelogs core_server1__2018-11-27_11-59-07__yate-ucn-cdr.tsv
2018-11-27_11:58:56.399 call    mvno    1542795110-172  sip/343      +40746008701    +40745300058    5.686   2.948   11.196  incoming        answered                                          
2018-11-27_11:58:56.400 call    mno     1542795110-172  sip/344      +40746008701    +40745300058    5.691   2.948   11.200  outgoing        answered                                          
[root@yate-ucn old-cdr]#

For data: Is composed of timestamp (UNIX start time of yate in hexa) – name of GTP-C EP – TEI-C in hexa

[root@yate-ucn old-cdr]# seelogs core_server1__2018-11-28_18-51-14__yate-ucn-cdr.tsv
2018-11-28_18:45:22.028 call    f2m     1543418964-2    sip/3      +40742211451    +40741456923     0.000   0.000   4.934   incoming        progressing     Request Terminated                
2018-11-28_18:45:22.029 call    mvno    1543418964-2    sip/4      +40742211451    +40741456923     0.000   0.000   4.938   outgoing        progressing     Cancelled                         
2018-11-28_18:47:00.233 call    m2m     1543418964-3    sip/6      +40744600870    +40740300058    3.130   4.748   13.704  outgoing        answered                                          
2018-11-28_18:47:00.232 call    mvno    1543418964-3    sip/5      +40744600870    +40740300058    3.135   4.748   13.710  incoming        answered                                          
2018-11-28_18:50:18.309 data    PGW     5bfeb454-pgw0-c/6b2e28f2        pgw0-u/0/6c320ba  40744600870     internet_apn      56.370          56.370  incoming                                113451194  001010302010072 3579990570930006        6       9       1b921f7396fefe74831040006400              0       0       0       0       1       00101   0192f41000651eb9
[root@yate-ucn old-cdr]#

Question: Some details about ${loc_info}? Is supposed to be decodable then for extra location information.

Answer: ${loc_info} holds the 3GPP-User-Location-Info, please see TS 29.06116.4.7.2 (3GPP Type: 22) for the encoding used in RADIUS and Diameter.

If you want to decode the loc_info field (User Location Info in binary format), take a look at the examples below:

01 = Contains CGI (GSM)
CGI: 3+2+2 octets
130062 = PLMN 310-260
2775 = LAC 0x2775 = 10101
5aca = Cell ID 0x5aca = 23242

82 = Contains TAI and ECGI (LTE)
TAI: 3 + 2 octets
32f401 = TAI PLMN 234-10
1080 = TAC 0x1080 = 4224
ECGI: 3 + 4 octets
32f401 = ECGI PLMN 234-10
0 = unused
7a2417c = E-UTRAN Cell 0x7a2417c = 128074108

82 = Contains TAI and ECGI (LTE)
TAI: 3 + 2 octets
32f401 = TAI PLMN 234-10
1080 = TAC 0x1080 = 4224
ECGI: 3 + 4 octets
32f401 = ECGI PLMN 234-10
0 = unused
7a24178 = E-UTRAN Cell 0x7a24178 = 128074104

If you just want a Serving PLMN ID you can skip first octet (type) / 2 characters, take the following 3 octets / 6 characters and do a bit of swapping.
The order of nibbles / characters is:

  1. MCC digit 2
  2. MCC digit 1
  3. MNC digit 3 (or F if MNC is 2 digits long)
  4. MCC digit 3
  5. MNC digit 2
  6. MNC digit 1

So if the string is xxABCDEFxxx… the PLMN will be BAD-FEC or BAD-FE

Question: If sms is successfully delivered, the reason field is not filled in the log file (empty). Why?


Answer: Empty reason is actually used to indicate success. CDRs for delivery may look like:

attempt#1 tries:10 reason:failure
attempt#2 tries:9 reason:absent
attempt#3 tries:8 (no reason = success)

or maybe

attempt#10 tries:1 reason:absent
attempt#11 tries:0 reason:absent (final because tries left is zero)


Question: Is there more that two rows for one call ?

  • A normal call will be 1 row for each channel (call leg)
  • coming to Yate (incoming)
  • going out from Yate (outgoing)
  • on a forwarded call there are 3 rows (assuming Q is calling X, and X has Call Forwarding to Z)
  • 1 incoming: Q is calling X (through Yate)
  • 2 outgoing: Yate to X (X has CF to Z) and Yate to Z

Question: Why is the time different. Should it be billtime + ringtime = duration, if this is the case why ringtime is 0.000
Answer: Signaling (session negotiation) till 180 Ringing is received; signaling is not ringtime
Voice: if there is no billtime, there is no bill.

  • To bill the called party, you need to bill only one call leg (incoming or outgoing)
  • To bill the caller party, you bill (billtime of incoming)
  • In the scenario you want to bill both caller and called
  • assuming A-MVNO user is roaming in Spain -> and B-MVNO user is calling A (in Spain) -> and you want bill both A (as is called in roaming) and B (as it calls to roaming)
  • you need to bill both incoming and outgoing. This it won’t work if called is not your MVNO subscriber


Question: Can we get all the scenarios for the status column and reason too?

one of incoming, outgoing, ringing, answered or connected, reflecting the current state of the call referred to by this CDR
a (mostly) human readable reason for this CDR.
  • Usually reason is sent by the protocol used there (voice = SIP, sms = MAP, data = MAP/DRA)


[root@yate-smsc smsc]# cat cdrfile.conf
format=${time}  ${route_type$msg}       ${component}${connection_id}    \
 ${billid}      ${protocol}     ${address}      ${caller}       ${called}       \
 ${duration}    ${direction}    ${retries}      ${reason}       \
 ${charging_id} ${imsi}
[root@yate-smsc smsc]# 

Question: The column that is +1 in the CDR files always has value of 4 what is that value?
Answer: This value of 4 is the ${retries} initial value, it begins with 4 (meaning that has maximum 4 retries), if does not succeed, goes to 3, then to 2, then to 1

  • /etc/yate/smsc/yatesmsc.conf:
    ;sms_attempts=3 (by default is 4, this line is commented)
  • Can be configured from MMI -> Equipment -> SMSC-equipment -> SMSC
  • SMS Attempts:: Optional, integer, range [1,30]. How many attempts to make to deliver each SMS. Taken from Extra params if missing.

Question: Is there any way to count the characters of the message so we could incorporate in our billing payment for more than 1 message?
Answer: Below are the CDRs for one SMS that was longer than 160 chars. “just sent sms from +40745867112 to +40747827112”
You don’t need to make anything special (the SMSC dispatch the long SMSes as two messages and bills them separately)
For each SMS there is a CDR entry, for long SMSes there are two/or more entries in the CDRs each with different billid

${time} ${route_type$msg} ${component} ${connection_id} ${billid} ${protocol} ${address} ${caller} ${called} ${duration} ${direction} ${retries} ${reason} ${charging_id} ${imsi}

receiving SMSes by SMSC from your_MNO
2018-11-29_14:56:02.315 msg     SMSC    1541755391-105  MAP     40744003001     40745867112     40747827112     0.002   incoming                                001010302000034
2018-11-29_14:56:02.467 msg     SMSC    1541755391-106  MAP     40744003001     40745867112     40747827112     0.002   incoming                                001010302000034

sending SMSes:
2018-11-29_14:56:03.277 msg     SMSC    1541755391-105  MAP     40744003001     40745867112     40747827112     1.448   outgoing        4                       001010302000036
2018-11-29_14:56:04.727 msg     SMSC    1541755391-106  MAP     40744003001     40745867112     40747827112     0.156   outgoing        4                       001010302000036

sending delivery report:
2018-11-29_14:56:27.158 msg     SMSC    1541755391-107  MAP     40740003001     40744600869     40744600867     0.002   incoming                                001010302000036
2018-11-29_14:56:28.327 msg     SMSC    1541755391-107  MAP     40740003001     40744600869     40744600867     0.692   outgoing        4                       001010302000034

Default Values

Question: What is the default value of the CDR closing interval?
Answer: Taken from the configuration file: /etc/yate/yateucn.conf.sample:

; Minimum interval in seconds between interim (status) data CDR messages
; Can be overridden by MME, SGSN or PGW
; Valid values 30 – 86400, default 0 which disables status CDRs
; Maximum interval in seconds at which to finalize a CDR and start a new one
; Can be overridden by MME, SGSN or PGW
; Valid values 300 – 2678400 (31 days), default 0 which disables restarting CDRs

Our solutions