# Asterisk Project : Asterisk 12 CEL Specification

Added by kmoore , edited by kmoore on Aug 20, 2013

Asterisk 12 has not yet been released - this specification is still in draft form.

# Introduction

Channel Event Logging (CEL) provides a series of records describing the state of channels in Asterisk to any of several event recording backends. 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 no longer available due to the changes in the bridging system.

## Scope

This CEL specification applies to Asterisk 12. 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

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.

### 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.

### 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. 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", and "bridge2_id" 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 in 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.

### 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.