CEL Overview
A CEL record contains information about a system event including a partial dump of the Primary's state and may contain data relevant to that specific record type such as channel names, bridge unique identifiers, channel variable values, or other miscellaneous information. The CEL engine tracks changes in individual channel state and guarantees ordering of records for a given Primary, but does not guarantee ordering of records in relation to other Primaries. The exception to this record ordering occurs with meta-records which occur adjacent to the events they describe. Applicable event ordering is provided in the descriptions below. CEL output does not describe interaction with MeetMe conferences other than MeetMe as an application.
Record Types
The records produced by the CEL engine can be grouped in to three general categories.
- Stand-Alone Records
- Interaction Records
- Meta-Records
Stand-Alone Records
These records convey a channel event on the channel that does not involve channels or bridges other than the Primary.
Channel Start
An AST_CEL_CHANNEL_START record is generated when a channel is created. This record introduces a new Primary and is the first record available for all Primaries.
Channel End
An AST_CEL_CHAN_END record is generated when a channel is destroyed. This record indicates that a Primary is going away and that there will be no further records for this Primary with the exception of AST_CEL_LINKEDID_END.
Answer
An AST_CEL_ANSWER record is generated when a channel is answered. Depending on the state transitions that occur on a Primary, this record may not be generated.
Hangup
An AST_CEL_HANGUP record is generated when a channel is hung up. This record will occur on every Primary prior to channel destruction.
Application Start
An AST_CEL_APP_START record is generated when a channel enters an application. This record will always be generated before its corresponding AST_CEL_APP_END.
Application End
An AST_CEL_APP_END record is generated when a channel exits an application. This record will be generated after its corresponding AST_CEL_APP_START, but is not guaranteed to be generated on hangup.
User Defined
An AST_CEL_USER_DEFINED record is generated when a channel enters the CELGenUserEvent application. The application sets the user defined name field and additional information in the extra field in the "extra" key.
Linked ID End
An AST_CEL_LINKEDID_END record is generated when the last channel using the given linked ID is destroyed or the last instance of a linked ID is overwritten by a different linked ID. This is the only type of record that may occur after AST_CEL_CHANNEL_END.
Interaction Records
These records convey the Primary's interactions with other channels or bridges.
Bridge Enter
An AST_CEL_BRIDGE_ENTER record is generated when a channel enters a bridge. The entering channel is the Primary for this event. Additional information is conveyed in the extra field under the "bridge_id" key. The "bridge_technology" key is available in Asterisk 13+. All other channels in the bridge at the time of entry are available in the peer field as a comma-separated list.
Bridge Exit
An AST_CEL_BRIDGE_EXIT record is generated when a channel exits a bridge. The leaving channel is the Primary for this event. Additional information is conveyed in the extra field under the "bridge_id" key. The "bridge_technology" key is available in Asterisk 13+. All other channels in the bridge at the time of exit are available in the peer field as a comma-separated list.
Forward
An AST_CEL_FORWARD record is generated when a dialing channel is forwarded elsewhere by a dialed channel. The dialing channel is the Primary for this event. Additional information is conveyed in the extra field under the "forward" key.
Park Start
An AST_CEL_PARK_START record is generated when a channel is parked. The parked channel is the Primary for this event. Additional information is conveyed in the extra field under the keys "parker_dial_string" and "parking_lot".
Park End
An AST_CEL_PARK_START record is generated when a channel is unparked. The unparked channel is the Primary for this event. Additional information is conveyed in the extra field under the "reason" key and the "retriever" key when available. This record always occurs after its corresponding AST_CEL_PARK_START.
Pickup
An AST_CEL_PICKUP record is generated when a channel is picked up. The picked up channel (also known as the target) is the Primary for this record. The name of the channel that is picking up is conveyed in the extra field under the "pickup_channel" key.
These records convey additional context relating to surrounding CEL records
Blind Transfer
An AST_CEL_BLINDTRANSFER record is generated when a blind transfer feature is activated on a bridge. The initiating channel is the Primary for this record. Additional information is conveyed in the extra field under the "extension", "context", and "bridge_id" keys.
Attended Transfer
An AST_CEL_ATTENDEDTRANSFER record is generated when an attended transfer is successfully performed.
Bridge-Bridge Attended Transfers
This type of attended transfer occurs when both involved channels are bridged. The initiating channel is the Primary for this record. Additional information is conveyed in the extra field under the "bridge1_id", "channel2_name", "bridge2_id", "transferee_channel_name", and "transfer_target_channel_name" keys.
The records associated with this type of transfer will vary depending on the configuration of the bridges involved and the number of channels involved. Possible methods of accomplishing the transfer include (but are not limited to) channel swap, bridge merge, and bridge link via a local channel.
Bridge-App Attended Transfers
This type of attended transfer occurs when one involved channel is bridged while the other is running an application. The bridged channel is the Primary for this record. Additional information is conveyed in the extra field under the "bridge1_id", "channel2_name", and "app" keys.
App-App Attended Transfers
Attended transfers involving only channels that are running applications are not currently possible. This is not possible with internal transfers since there is no bridge involved to handle the feature codes and any externally initiated attended transfer that attempts to bridge two app-bound channels will fail.
Local Channel Optimization
An AST_CEL_LOCAL_OPTIMIZE record is generated when a local channel optimization attempt completes successfully. The semi-one (local channel ending in ';1') channel is the Primary for this event. The name of the semi-two (local channel ending in ';2') channel is conveyed in the extra field under the "local_two" key.
Removed Records
The following record types are no longer available as of Asterisk 12:
AST_CEL_BRIDGE_START
AST_CEL_BRIDGE_END
AST_CEL_CONF_START
AST_CEL_CONF_END
AST_CEL_CONF_ENTER
AST_CEL_CONF_EXIT
AST_CEL_HOOKFLASH
AST_CEL_3WAY_START
AST_CEL_3WAY_END
AST_CEL_BRIDGE_UPDATE
AST_CEL_TRANSFER
Record Fields
Primary Fields
These fields are populated exclusively from their corresponding fields on the Primary in a consistent manner for every CEL record.
CallerID Name
The name identifying the caller for this channel.
CallerID Number
The number identifying the caller for this channel.
CallerID ANI
Automatic Number Identification caller information provided for this channel.
CallerID RDNIS
Redirecting information for this channel.
CallerID DNID
Dialed Number Identification for this channel.
Extension
The extension in which this channel is currently executing.
Context
The context in which this channel is currently executing.
Channel Name
The name of this channel.
Application Name
The name of the application that this channel is currently executing.
Application Data
The data provided to the application being executed.
Account Code
The account code used for billing.
Peer Account Code
The peer channel's account code.
Unique ID
This channel's instance unique identifier.
Linked ID
This channel's current linked ID which is affected by bridging operations. This identifier starts as the channel's unique ID.
AMA Flags
This channel's Automated Message Accounting flags.
Record Type Specific Fields
These fields vary or may be blank depending on the CEL record type.
User Defined Name
This field is only used for AST_CEL_USER_DEFINED and conveys the user-specified event type.
This field contains a JSON blob describing additional record-type-specific information.
Logging Backends
CEL provides several methods of logging records to be processed at a later time. CEL only publishes record types to backends that are enabled in the general CEL configuration. Sample configurations are provided with the Asterisk 12 source for all of these backends.
Custom
The Custom CEL output module provides logging capability to a CSV file in a format described in the configuration file. This module is configured in cel_custom.conf.
Manager
The manager CEL output module publishes records over AMI as CEL events with the record type published under the "EventName" key. This module is configured in cel.conf in the [manager] section.
ODBC
The ODBC CEL output module provides logging capability to any ODBC-compatible database. This module is configured in cel_odbc.conf.
PGSQL
The PGSQL CEL output module provides logging capability to PostgreSQL databases when it is desirable to avoid the ODBC abstraction layer. This module is configured in cel_pgsql.conf.
RADIUS
The RADIUS CEL output module allows the CEL engine to publish records to a RADIUS server. This module is configured in cel.conf in the [radius] section.
SQLite
The SQLite CEL output module provides logging capability to a SQLite3 database in a format described in its configuration file. This module is configured in cel_sqlite3_custom.conf.
TDS
The TDS CEL output module provides logging capability to Sybase or Microsoft SQL Server databases when it is desirable to avoid the ODBC abstraction layer. This module is configured in cel_tds.conf.
Example Scenarios
For the following scenarios, assume the CEL engine is configured to generate the following record types:
AST_CEL_CHANNEL_START
AST_CEL_CHAN_END
AST_CEL_BRIDGE_ENTER
AST_CEL_BRIDGE_EXIT
Two-Participant Bridge
The following scenario demonstrates channel creation, channel destruction, bridge start, and bridge end:
Event | Record | Primary | Extra |
---|
Channel Alice is created | AST_CEL_CHANNEL_START | Alice | |
Channel Bob is created | AST_CEL_CHANNEL_START | Bob | |
Bridge Link is created | | | |
Alice enters bridge Link | AST_CEL_BRIDGE_ENTER | Alice | {"bridge_id": "Link"} |
Bob enters bridge Link | AST_CEL_BRIDGE_ENTER | Bob | {"bridge_id": "Link"} |
Bob exits bridge Link | AST_CEL_BRIDGE_EXIT | Bob | {"bridge_id": "Link"} |
Bob is destroyed | AST_CEL_CHAN_END | Bob | |
Alice exits bridge Link | AST_CEL_BRIDGE_EXIT | Alice | {"bridge_id": "Link"} |
Alice is destroyed | AST_CEL_CHAN_END | Alice | |
Multi-participant Conference
The following scenario demonstrates conversion of a bridge to a multi-participant conference:
Event | Record | Primary | Extra |
---|
Channel Alice is created | AST_CEL_CHANNEL_START | Alice | |
Channel Bob is created | AST_CEL_CHANNEL_START | Bob | |
Channel Charlie is created | AST_CEL_CHANNEL_START | Charlie | |
Channel David is created | AST_CEL_CHANNEL_START | David | |
Bridge Link is created | | | |
Alice enters bridge Link | AST_CEL_CONF_ENTER | Alice | {"bridge_id", "Link"} |
Bob enters bridge Link | AST_CEL_CONF_ENTER | Bob | {"bridge_id", "Link"} |
Charlie enters bridge Link | AST_CEL_CONF_ENTER | Charlie | {"bridge_id", "Link"} |
David enters bridge Link | AST_CEL_CONF_ENTER | David | {"bridge_id", "Link"} |
Alice exits bridge Link | AST_CEL_CONF_EXIT | Alice | {"bridge_id", "Link"} |
Alice is destroyed | AST_CEL_CHAN_END | Alice | |
Bob exits bridge Link | AST_CEL_CONF_EXIT | Bob | {"bridge_id", "Link"} |
Bob is destroyed | AST_CEL_CHAN_END | Bob | |
Charlie exits bridge Link | AST_CEL_CONF_EXIT | Charlie | {"bridge_id", "Link"} |
Charlie is destroyed | AST_CEL_CHAN_END | Charlie | |
David exits bridge Link | AST_CEL_CONF_EXIT | David | {"bridge_id", "Link"} |
David is destroyed | AST_CEL_CHAN_END | David | |
Dial Nominal
For this scenario, assume that AST_CEL_ANSWER, AST_CEL_HANGUP, AST_CEL_APP_START, and AST_CEL_APP_END are configured in addition to the aforementioned record types and that "Dial" is configured to be watched.
The following scenario demonstrates a Dial that results in an answer followed by bridging and hangup:
Event | Record | Primary | Extra |
---|
Channel Alice is created | AST_CEL_CHANNEL_START | Alice | |
Alice executes Dial(SIP/Bob) | AST_CEL_APP_START | Alice | |
Channel Bob is created | AST_CEL_CHANNEL_START | Bob | |
Bob answers | AST_CEL_ANSWER | Bob | |
Alice answers | AST_CEL_ANSWER | Alice | |
Bridge Link is created | | | |
Alice enters bridge Link | AST_CEL_BRIDGE_ENTER | Alice | {"bridge_id": "Link"} |
Bob enters bridge Link | AST_CEL_BRIDGE_ENTER | Bob | {"bridge_id": "Link"} |
Bob initiates hangup, exits bridge Link | AST_CEL_BRIDGE_EXIT | Bob | {"bridge_id": "Link"} |
Bob completes hang up | AST_CEL_HANGUP | Bob | {"hangupcause":16,"dialstatus":"","hangupsource":"Bob"} |
Bob is destroyed | AST_CEL_CHAN_END | Bob | |
Alice exits bridge Link | AST_CEL_BRIDGE_EXIT | Alice | {"bridge_id": "Link"} |
Alice is hung up | AST_CEL_HANGUP | Alice | {"hangupcause":16,"dialstatus":"ANSWER","hangupsource":""} |
Alice is destroyed | AST_CEL_CHAN_END | Alice | |
Dial Busy
For this scenario, assume that AST_CEL_ANSWER, AST_CEL_HANGUP, AST_CEL_APP_START, and AST_CEL_APP_END are configured in addition to the aforementioned record types and that "Dial" is configured to be watched. The following scenario demonstrates a Dial that results in a busy:
Event | Record | Primary | Extra |
---|
Channel Alice is created | AST_CEL_CHANNEL_START | Alice | |
Alice executes Dial(SIP/Bob) | AST_CEL_APP_START | Alice | |
Channel Bob is created | AST_CEL_CHANNEL_START | Bob | |
Bob responds BUSY | AST_CEL_HANGUP | Bob | {"hangupcause":21,"dialstatus":"","hangupsource":""} |
Bob is destroyed | AST_CEL_CHAN_END | Bob | |
Alice is hung up | AST_CEL_HANGUP | Alice | {"hangupcause":17,"dialstatus":"BUSY","hangupsource":""} |
Alice is destroyed | AST_CEL_CHAN_END | Alice | |
For this scenario, assume that AST_CEL_HANGUP is configured in addition to the aforementioned record types. The following scenario demonstrates a blind transfer:
For this scenario, assume that AST_CEL_ANSWER and AST_CEL_HANGUP are configured in addition to the aforementioned record types. The following scenario demonstrates a channel-swapping attended transfer:
Note that the ATTENDEDTRANSFER event does not necessarily occur before or after the records it is related to.
2 Comments
Craig Sheahan
Noticed a few things that should to be fixed or improved in this article.
> An AST_CEL_CHAN_END record is generated when a channel is destroyed. This record indicates that a Primary is going away and that there will be no further records for this Primary with the exception of AST_CEL_LINKEDID_END.
> For the following scenarios, assume the CEL engine is configured to generate the following record types:
> AST_CEL_CHANNEL_START
> AST_CEL_CHAN_END
Should these not be AST_CEL_CHANNEL_END instead of AST_CEL_CHAN_END? The Asterisk enumeration has 'CHANNEL' instead of 'CHAN', but the database gets the event logged as 'CHAN'. Seems maybe someone got the two confused, or it was corrected in a later commit. The tables that show example events already use the correct enumeration name.
> An AST_CEL_PARK_START record is generated when a channel is unparked. The unparked channel is the Primary for this event. Additional information is conveyed in the extra field under the "reason" key and the "retriever" key when available. This record always occurs after its corresponding AST_CEL_PARK_START.
Should this not be AST_CEL_PARK_END in the first sentence? The event type in the CEL table is PARK_END, the AST_CEL_PARK_END enumeration does exist in include/asterisk/cel.h, and it doesn't really make sense to log a second start record when a park is ending.
The CDR specification article contains a list of fields with database data types for each. Any chance someone can add the same sort of table to this article? It's a bit annoying to have to go to third party sites or dig into the source code to determine which database fields should be in the CEL table and to determine how the fields have changed with an Asterisk upgrade.
This article is missing what the CEL event types are when logged to a database, there is some discrepancy in the naming compared to the internal Asterisk CEL enumerations. For ease of reference, here are the Asterisk 12/13 event types as logged to the database (pulled from main/cel.c): CHAN_START, CHAN_END, ANSWER, HANGUP, APP_START, APP_END, PARK_START, PARK_END, USER_DEFINED, BRIDGE_ENTER, BRIDGE_EXIT, BLINDTRANSFER, ATTENDEDTRANSFER, PICKUP, FORWARD, LINKEDID_END, LOCAL_OPTIMIZE
Craig Sheahan
Actually, it does seem some of the example tables incorrectly use AST_CEL_CHAN_END instead of AST_CEL_CHANNEL_END .