Skip to content

CEL Specification

Introduction

Channel Event Logging (CEL) provides a series of records describing the state of channels in Asterisk to any of several event recording back-ends. CEL records provide substantially more information than CDRs and thus allow an Asterisk User to construct their own more complex billing system.

As a result of the bridging work done for Asterisk 12, CEL behavior has changed for several events that occur in the system. The most significant changes are:

  • AST_CEL_BRIDGE_ENTER and AST_CEL_BRIDGE_EXIT have been introduced to denote participant changes in bridges.
  • AST_CEL_BRIDGE_START and AST_CEL_BRIDGE_END have been removed as they no longer applies to the new bridging framework.
  • AST_CEL_BRIDGE_UPDATE has been removed as it no longer applies to the new bridging framework.
  • AST_CEL_LOCAL_OPTIMIZE has been added to describe local channel optimizations that occur.
  • All linkedid accounting and record generation is now handled within the CEL engine.
  • The peer field is only used in BRIDGE_ENTER and BRIDGE_EXIT records.

Scope

This CEL specification applies to Asterisk 12 and above. While some portions of this specification are applicable to prior versions of Asterisk, other portions are specific to Asterisk 12 and their counterparts in prior versions are not discussed.

Terminology

Term Definition
CEL Channel Event Logging. The focus of this documentation.
CEL record An individual event record produced by the CEL engine.
CDR Call Detail Record. An alternative method of extracting billing information from Asterisk. Simpler, but less flexible.
Stasis The internal message bus in Asterisk that conveys state to the CEL engine.
Primary The channel around which a CEL record is focused.
AMI Asterisk Manager Interface
CSV Comma Separated Values.  A format commonly used for tabular data when stored outside of a database.

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.

Meta-Records

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.

Field Description
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.

Field Description
User Defined Name This field is only used for AST_CEL_USER_DEFINED and conveys the user-specified event type.
Extra 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

Blind Transfer

For this scenario, assume that AST_CEL_HANGUP is configured in addition to the aforementioned record types. The following scenario demonstrates a blind transfer:

Event Record Primary Extra
Channel Alice is created AST_CEL_CHANNEL_START Alice
Channel Bob is created AST_CEL_CHANNEL_START Bob
Alice answers AST_CEL_ANSWER Alice
Bob answers AST_CEL_ANSWER Bob
Bridge Link is created
Bob enters bridge Link AST_CEL_BRIDGE_ENTER Bob {"bridge_id":"Link"}
Alice enters bridge Link AST_CEL_BRIDGE_ENTER Alice {"bridge_id":"Link"}
Alice initiates a blind transfer to exten@context AST_CEL_BLINDTRANSFER Alice {"bridge_id":"Link","extension":"exten","context":"context"}
Alice exits bridge Link AST_CEL_BRIDGE_EXIT Alice {"bridge_id":"Link"}
Alice is hung up AST_CEL_HANGUP Alice {"hangupcause":16,"dialstatus":"","hangupsource":""}
Alice is destroyed AST_CEL_CHANNEL_END Alice
A local channel pair is created to handle dialplan AST_CEL_CHANNEL_START Local1
AST_CEL_CHANNEL_START Local2
Local1 enters bridge Link AST_CEL_BRIDGE_ENTER Local1 {"bridge_id":"Link"}
Local2 executes dialplan at exten@context
Local2 is eventually hung up by the dialplan AST_CEL_HANGUP Local2 {"hangupcause":16,"dialstatus":"","hangupsource":""}
Hangup is initiated on Local1, exiting bridge Link AST_CEL_BRIDGE_EXIT Local1 {"bridge_id":"Link"}
Local1 is hung up AST_CEL_HANGUP Local1 {"hangupcause":16,"dialstatus":"","hangupsource":""}
Local1 is destroyed AST_CEL_CHANNEL_END Local1
Local2 is destroyed AST_CEL_CHANNEL_END Local2
Bob is the last channel and so is hung up AST_CEL_HANGUP Bob {"hangupcause":16,"dialstatus":"","hangupsource":""}
Bob is destroyed AST_CEL_CHANNEL_END Bob

Attended 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:

Event Record Primary Extra
Channel Alice is created AST_CEL_CHANNEL_START Alice
Channel Bob is created AST_CEL_CHANNEL_START Bob
Alice answers AST_CEL_ANSWER Alice
Bob answers AST_CEL_ANSWER Bob
Bridge Link1 is created
Bob enters bridge Link1 AST_CEL_BRIDGE_ENTER Bob {"bridge_id":"Link1"}
Alice enters bridge Link1 AST_CEL_BRIDGE_ENTER Alice {"bridge_id":"Link1"}
Channel Charlie is created AST_CEL_CHANNEL_START Charlie
Channel David is created AST_CEL_CHANNEL_START David
Charlie answers AST_CEL_ANSWER Charlie
David answers AST_CEL_ANSWER David
Bridge Link2 is created
David enters bridge Link2 AST_CEL_BRIDGE_ENTER Bob {"bridge_id":"Link2"}
Charlie enters bridge Link2 AST_CEL_BRIDGE_ENTER Alice {"bridge_id":"Link2"}
An attended transfer between Alice and David begins
Bob exits bridge Link1 AST_CEL_BRIDGE_EXIT Bob {"bridge_id":"Link1"}
Bob enters bridge Link2 AST_CEL_BRIDGE_ENTER Bob {"bridge_id":"Link2"}
David exits bridge Link2 AST_CEL_BRIDGE_EXIT David {"bridge_id":"Link2"}
David is hung up AST_CEL_HANGUP David {"hangupcause":16,"dialstatus":"","hangupsource":""}
David is destroyed AST_CEL_CHANNEL_END David
Alice and David execute an attended transfer  AST_CEL_ATTENDEDTRANSFER Alice {"bridge1_id":"Link1","channel2_name":"David","bridge2_id":"Link2"}
Alice exits bridge Link1 AST_CEL_BRIDGE_EXIT Alice {"bridge_id":"Link1"}
Alice is hung up AST_CEL_HANGUP Alice {"hangupcause":16,"dialstatus":"","hangupsource":""}
Alice is destroyed AST_CEL_CHANNEL_END Alice
Bob exits bridge Link2 AST_CEL_BRIDGE_EXIT Bob {"bridge_id":"Link2"}
Charlie exits bridge Link2 AST_CEL_BRIDGE_EXIT Charlie {"bridge_id":"Link2"}
Bob is hung up AST_CEL_HANGUP Bob {"hangupcause":16,"dialstatus":"","hangupsource":""}
Bob is destroyed AST_CEL_CHANNEL_END Bob
Charlie is hung up AST_CEL_HANGUP Charlie {"hangupcause":16,"dialstatus":"","hangupsource":""}
Charlie is destroyed AST_CEL_CHANNEL_END Charlie

Note that the ATTENDEDTRANSFER event does not necessarily occur before or after the records it is related to.