The CDR system in Asterisk is used to log the history of calls in the system. In some deployments, these records are used for billing purposes. In others, call records are used for analyzing call volumes over time. They can also be used as a debugging tool by Asterisk administrators.
A CDR has a number of fields that are included by default. Table 24.2, “Default CDR fields” lists them.
Table 24.2. Default CDR fields
Option | Value/Example | Notes |
---|---|---|
accountcode | 12345 | An account ID. This field is user-defined and is empty by default. |
src | 12565551212 | The calling party’s caller ID number. It is set automatically and is read-only. |
dst | 102 | The destination extension for the call. This field is set automatically and is read-only. |
dcontext | PublicExtensions | The destination context for the call. This field is set automatically and is read-only. |
clid | "Big Bird" <12565551212> | The full caller ID, including the name, of the calling party. This field is set automatically and is read-only. |
channel | SIP/0004F2040808-a1bc23ef | The calling party’s channel. This field is set automatically and is read-only. |
dstchannel | SIP/0004F2046969-9786b0b0 | The called party’s channel. This field is set automatically and is read-only. |
lastapp | Dial | The last dialplan application that was executed. This field is set automatically and is read-only. |
lastdata | SIP/0004F2046969,30,tT | The arguments passed to the lastapp . This field is set
automatically and is read-only. |
start | 2010-10-26 12:00:00 | The start time of the call. This field is set automatically and is read-only. |
answer | 2010-10-26 12:00:15 | The answered time of the call. This field is set automatically and is read-only. |
end | 2010-10-26 12:03:15 | The end time of the call. This field is set automatically and is read-only. |
duration | 195 | The number of seconds between the start and end times for the call. This field is
set automatically and is read-only. |
billsec | 180 | The number of seconds between the answer and end times for the call. This field is
set automatically and is read-only. |
disposition | ANSWERED | An indication of what happened to the call. This may be
NO ANSWER , FAILED , BUSY , ANSWERED , or UNKNOWN . |
amaflags | DOCUMENTATION | The Automatic Message Accounting (AMA) flag associated
with this call. This may be one of the following: OMIT , BILLING , DOCUMENTATION , or Unknown . |
userfield | PerMinuteCharge:0.02 | A general-purpose user field. This field is empty by default and can be set to a user-defined string.[a] |
uniqueid | 1288112400.1 | The unique ID for the src channel. This field is set
automatically and is read-only. |
[a] The |
All fields of the CDR record can be
accessed in the Asterisk dialplan by using the CDR()
function. The CDR()
function is also used to set the fields
of the CDR that are user-defined.
exten => 115,1,Verbose(Call start time: ${CDR(start)}) same => n,Set(CDR(userfield)=zombie pancakes)
In addition to the fields that are always
included in a CDR, it is possible to add custom fields. This is done in
the dialplan by using the Set()
application with the CDR()
function:
exten => 115,1,NoOp() same => n,Set(CDR(mycustomfield)=coffee) same => n,Verbose(I need some more ${CDR(mycustomfield)})
If you choose to use custom CDR variables, make sure that the CDR backend that you choose is capable of logging them.
To view the built-in documentation for
the CDR()
function, run the following
command at the Asterisk console:
*CLI>
core show function CDR
In addition to the CDR()
function, there are some dialplan
applications that may be used to influence CDR records. We’ll look at
these next.
There are a few dialplan applications that can be used to influence CDRs for the current call. To get a list of the CDR applications that are loaded into the current version of Asterisk, we can use the following CLI command:
*CLI> core show applications like CDR
-= Matching Asterisk Applications =-
ForkCDR: Forks the Call Data Record.
NoCDR: Tell Asterisk to not maintain a CDR for the current call
ResetCDR: Resets the Call Data Record.
-= 3 Applications Matching =-
Each application has documentation built into the Asterisk application, which can be viewed using the following command:
*CLI>
core show application
<application name>
The cdr.conf
file has
a [general]
section that contains
options that apply to the entire CDR system. Additional optional
sections may exist in this file that apply to specific CDR logging
backend modules. Table 24.3, “cdr.conf [general] section” lists the
options available in the [general]
section.
Table 24.3. cdr.conf [general] section
Option | Value/Example | Notes |
---|---|---|
enable | yes | Enable CDR logging. The default is yes . |
unanswered | no | Log unanswered calls. Normally, only answered calls
result in a CDR. Logging all call attempts can result in a large
number of extra call records that most people do not care about.
The default value is no . |
end before hexten | no | Close out CDRs before running the h extension in the Asterisk dialplan.
Normally CDRs are not closed until the dialplan is completely
finished running. The default value is no . |
initiated seconds | no | When calculating the billsec field, always round up. For
example, if the difference between when the call was answered
and when the call ended is 1 second and 1 microsecond, billsec will be set to 2 seconds. This
helps ensure that Asterisk’s CDRs match the behavior used by
telcos. The default value is no . |
batch | no | Queue up CDRs to be logged in batches instead of logging
synchronously at the end of every call. This prevents CDR
logging from blocking the completion of the call teardown
process within Asterisk. The default value is no , but we recommend turning it
on.[a] |
size | 100 | Set the number of CDRs to queue up before they are logged
during batch mode. The default value is 100 . |
time | 300 | Set the maximum number of seconds that CDRs will wait in
the batch queue before being logged. The CDR batch logging
process will run at the end of this time period, even if
size has not been reached.
The default value is 300
seconds. |
scheduler only | no | Set whether CDR batch processing should be done by
spawning a new thread, or within the context of the CDR batch
scheduler. The default value is no , and we recommend not changing
it. |
safe shutdown | yes | Block Asterisk shutdown to ensure that all queued CDR
records are logged. The default is yes , and we recommend leaving it that
way, as this option prevents important data loss. |
[a] The disadvantage of enabling this option is that if
Asterisk were to crash or die for some reason, the CDR
records would be lost, as they are only stored in memory
while the Asterisk process exists. See |
Asterisk CDR backend modules provide a way to log CDRs. Most CDR backends require specific configuration to get them going.
As the name suggests, the cdr_adaptive_odbc
module allows CDRs to be
stored in a database through ODBC. The “adaptive” part of the name
refers to the fact that it works to adapt to the table structure:
there is no static table structure that must be used with this module.
When the module is loaded (or reloaded), it reads the table structure.
When logging CDRs, it looks for a CDR variable that matches each
column name. This applies to both the built-in CDR variables and
custom variables. If you want to log the built-in channel
CDR variable, just create a column
called channel
.
Adding custom CDR content is as simple
as setting it in the dialplan. For example, if we wanted to log the
User-Agent
that is provided by a
SIP device, we could add that as a custom CDR variable:
exten => 105,n,Set(CDR(useragent)=${CHANNEL(useragent)})
To have this custom CDR variable
inserted into the database by cdr_adaptive_odbc
, all we have to do is
create a column called useragent
.
Multiple tables may be configured in
the cdr_adaptive_odbc
configuration
file. Each goes into its own configuration section. The name of the
section can be anything; the module does not use it. Here is an
example of a simple table configuration:
[mytable] connection = asterisk table = asterisk_cdr
A more detailed example of setting up a database for logging CDRs can be found in the section called “Storing Call Detail Records (CDRs)”.
Table 24.4, “cdr_adaptive_odbc.conf table configuration options”
lists the options that can be specified in a table configuration
section in the cdr_adaptive_odbc.conf
file.
Table 24.4. cdr_adaptive_odbc.conf table configuration options
Option | Value/Example | Notes |
---|---|---|
connection | pgsql1 | The database connection to be used. This is a reference
to the configured connection in res_odbc.conf . This field is
required. |
table | asterisk_cdr | The table name. This field is required. |
usegmtime | no | Indicates whether to log timestamps using GMT instead
of local time. The default value for this option is no . |
In addition to the key/value pair
fields that are shown in the previous table, cdr_adaptive_odbc.conf
allows for a few
other configuration items. The first is a column alias. Normally, CDR
variables are logged to columns of the same name. An alias
allows the variable name to be mapped
to a column with a different name. The syntax is:
alias<CDR variable>
=><column name>
Here is an example column mapping using
the alias
option:
alias src => source
It is also possible to specify a content filter. This allows you to specify criteria that must match for records to be inserted into the table. The syntax is:
filter<CDR variable>
=><content>
Here is an example content filter:
filter accountcode => 123
Finally, cdr_adaptive_odbc.conf
allows static
content for a column to be defined. This can be useful when used along
with a set of filter
s. This static
content can help differentiate records that were inserted into the
same table by different configuration sections. The syntax for static
content is:
static<"Static Content Goes Here">
=><column name>
Here is an example of specifying static content to be inserted with CDRs:
static "My Content" => my_identifier
The cdr_csv
module is
a very simple CDR backend that logs CDRs into a CSV (comma separated
values) file. The file is /var/log/asterisk/cdr-csv/Master.csv
. As
long as CDR logging is enabled in cdr.conf
and this module has been loaded,
CDRs will be logged to the Master.csv
file.
While no options are required to get
this module working, there are some options that customize its
behavior. These options, listed in Table 24.5, “cdr.conf [csv] section options”, are placed in the [csv]
section of cdr.conf
.
Table 24.5. cdr.conf [csv] section options
The order of CDR variables in CSV files
created by the cdr_csv
module
is:
<accountcode
>,<src
>,<dst
>,<dcontext
>,<clid
>,<channel
>,<dstchannel
>,<lastapp
>, \ <lastadata
>,<start
>,<answer
>,<end
>,<duration
>,<billsec
>,<disposition
>, \ <amaflags
>[,<uniqueid
>][,<userfield
>]
This CDR backend allows for custom formatting of CDR
records in a log file. This module is most commonly used for
customized CSV output. The configuration file used for this module is
/etc/asterisk/cdr_custom.conf
. A
single section called [mappings]
should exist in this file.
The [mappings]
section contains
mappings between a filename and the custom template for a CDR. The
template is specified using Asterisk dialplan functions.
The following example shows a sample
configuration for cdr_custom
that
enables a single CDR log file, Master.csv
. This file will be created as
/var/log/asterisk/cdr-custom/Master.csv
.
The template that has been defined uses both the CDR()
and CSV_QUOTE()
dialplan functions. The CDR()
function
retrieves values from the CDR being logged. The CSV_QUOTE()
function ensures that the values
are properly escaped for the CSV file format:
[mappings] Master.csv => ${CSV_QUOTE(${CDR(clid)})},${CSV_QUOTE(${CDR(src)})}, ${CSV_QUOTE(${CDR(dst)})},${CSV_QUOTE(${CDR(dcontext)})}, ${CSV_QUOTE(${CDR(channel)})},${CSV_QUOTE(${CDR(dstchannel)})}, ${CSV_QUOTE(${CDR(lastapp)})},${CSV_QUOTE(${CDR(lastdata)})}, ${CSV_QUOTE(${CDR(start)})},${CSV_QUOTE(${CDR(answer)})}, ${CSV_QUOTE(${CDR(end)})},${CSV_QUOTE(${CDR(duration)})}, ${CSV_QUOTE(${CDR(billsec)})},${CSV_QUOTE(${CDR(disposition)})}, ${CSV_QUOTE(${CDR(amaflags)})},${CSV_QUOTE(${CDR(accountcode)})}, ${CSV_QUOTE(${CDR(uniqueid)})},${CSV_QUOTE(${CDR(userfield)})}
The cdr_manager
backend emits CDRs as events on the Asterisk Manager Interface (AMI),
which we discussed in detail in Chapter 20, Asterisk Manager Interface (AMI). This
module is configured in the /etc/asterisk/cdr_manager.conf
file.
The first section in this file is the [general]
section, which contains a single
option to enable this module (the default value is no
):
[general] enabled = yes
The other section in cdr_manager.conf
is the [mappings]
section. This allows for adding
custom CDR variables to the manager event. The syntax is:
<CDR variable>
=><Header name>
Here is an example of adding two custom CDR variables:
[mappings] rate => Rate carrier => Carrier
With this configuration in place, CDR records will appear as events on the manager interface. To generate an example manager event, we will use the following dialplan example:
exten => 110,1,Answer() same => n,Set(CDR(rate)=0.02) same => n,Set(CDR(carrier)=BS&S) same => n,Hangup()
This is the command used to execute this extension and generate a sample manager event:
*CLI>
console dial 110@testing
Finally, this is an example manager event produced as a result of this test call:
Event: Cdr Privilege: cdr,all AccountCode: Source: Destination: 110 DestinationContext: testing CallerID: Channel: Console/dsp DestinationChannel: LastApplication: Hangup LastData: StartTime: 2010-08-23 08:27:21 AnswerTime: 2010-08-23 08:27:21 EndTime: 2010-08-23 08:27:21 Duration: 0 BillableSeconds: 0 Disposition: ANSWERED AMAFlags: DOCUMENTATION UniqueID: 1282570041.3 UserField: Rate: 0.02 Carrier: BS&S
This module allows posting of CDRs to a MySQL database.
We recommend that new installations use cdr_adaptive_odbc
instead.
This module enables the legacy ODBC interface for CDR
logging. New installations should use cdr_adaptive_odbc
instead.
This module allows posting of CDRs to a PostgreSQL
database. We recommend that new installations use cdr_adaptive_odbc
instead.
The cdr_radius
backend allows posting of CDRs to a RADIUS server. When using this
module, each CDR is reported to the RADIUS server as a single stop
event. This module is configured in the /etc/asterisk/cdr.conf
file. Options for
this module are placed in a section called [radius]
. The available options are listed
in Table 24.6, “cdr.conf [radius] section options”.
Table 24.6. cdr.conf [radius] section options
This module allows posting of CDRs to a SQLite database using SQLite version 2. Unless you have a
specific need for SQLite
version 2 as opposed to version 3, we recommend that all new
installations use cdr_sqlite3_custom
.
This module requires no configuration
to work. If the module has been compiled and loaded into Asterisk, it
will insert CDRs into a table called cdr
in a database located at /var/log/asterisk/cdr.db
.
This CDR backend inserts CDRs into a SQLite database using SQLite version 3. The database created
by this module lives at /var/log/asterisk/master.db
. This module
requires a configuration file, /etc/asterisk/cdr_sqlite3_custom.conf
. The
configuration file identifies the table name, as well as customizes
which CDR variables will be inserted into the database:
[master] table = cdr ; ; List the column names to use when inserting CDRs. ; columns => calldate, clid, dcontext, channel, dstchannel, lastapp, lastdata, duration, billsec, disposition, amaflags, accountcode, uniqueid, userfield, test ; ; Map CDR contents to the previously specified columns. ; values => '${CDR(start)}','${CDR(clid)}','${CDR(dcontext)}','${CDR(channel)}', '${CDR(dstchannel)}','${CDR(lastapp)}','${CDR(lastdata)}','${CDR(duration)}', '${CDR(billsec)}','${CDR(disposition)}','${CDR(amaflags)}', '${CDR(accountcode)}','${CDR(uniqueid)}','${CDR(userfield)}','${CDR(test)}'
This module allows logging of CDRs using syslog. To enable
this, first add an entry to the system’s syslog
configuration file, /etc/syslog.conf
. For example:
local4.* /var/log/asterisk/asterisk-cdr.log
The Asterisk module has a configuration
file, as well. Add the following section to /etc/asterisk/cdr_syslog.conf
:
[cdr] facility = local4 priority = info template = "We received a call from ${CDR(src)}"
Here is an example syslog entry using this configuration:
$ cat /var/log/asterisk/asterisk-cdr.log
Aug 12 19:17:36 pbx cdr: "We received a call from 2565551212"
We will use the cdr_custom
module to illustrate some example
CDR records for different call scenarios. The configuration used for
/etc/asterisk/cdr_custom.conf
is
shown in the section called “cdr_custom”.
In this example, we’ll show what a CDR looks like for a
simple one-party call. Specifically, we will use the example of a user
calling in to check her voicemail. Here is the extension from
/etc/asterisk/extensions.conf
:
exten => *98,1,VoiceMailMain(@${GLOBAL(VOICEMAIL_CONTEXT)})
This is the CDR from /var/log/asterisk/cdr-custom/Master.csv
that was created as a result of calling this extension:
"""Console"" <2565551212>","2565551212","*98","UserServices","Console/dsp","", "VoiceMailMain","@shifteight.org","2010-08-16 01:08:44","2010-08-16 01:08:44", "2010-08-16 01:08:53","9","9","ANSWERED","DOCUMENTATION","","1281935324.0","",0
For this next example, we show what a CDR looks like for a simple two-party call. We’ll have one SIP phone place a call to another SIP phone. The call is answered and then hung up after a short period of time. Here is the extension that was dialed:
exten => 101,1,Dial(SIP/0000FFFF0002)
Here is the CDR that was logged to
Master.csv
as a result of this
call:
"""Console"" <2565551212>","2565551212","101","LocalSets","Console/dsp", "SIP/0000FFFF0002-00000000","Dial","SIP/0000FFFF0002","2010-08-16 01:16:10", "2010-08-16 01:16:16","2010-08-16 01:16:29","19","13","ANSWERED", "DOCUMENTATION","","1281935770.2","",2
The CDR system in Asterisk works very well for fairly simple call scenarios. However, as call scenarios get more complicated, involving calls to multiple parties, transfers, parking, and other such features, the CDR system starts to fall short. Many users report that the records do not show all of the information that they expect. Many bug fixes have been made to address some of the issues, but the cost of regressions or changes in behavior when making changes in this area is very high since these records are used for billing.
As a result, the Asterisk development team has become increasingly resistant to making additional changes to the CDR system. Instead, a new system, channel event logging (CEL), has been developed that is intended to help address logging of more complex call scenarios. Bear in mind that call detail records are simpler and easier to consume, though, so we still recommend using CDRs if they suit your needs.