CDR Support

mpermar edited this page Sep 1, 2011 · 2 revisions

Rayo lets you configure how you want to store your CDRs. Basically there is four different storage options:

  • Filesystem
  • JMS destinations
  • XMPP PubSub nodes
  • AMQP destinations


This is a sample CDR. Note that Rayo is currently under ongoing development so this structure may be slightly changed at the time of reading this.

A Rayo CDR is typically made of a set of attributes that define the call and a complete transcript that shows how the call has gone through the system. This is an example:

<?xml version="1.0"?>
<cdr xmlns="" xmlns:cdr=""
  start="2011-10-06 12:17:42.20+0200" 
  end="2011-10-06 12:17:42.31+0200" state="DISCONNECTED">
  <offer xmlns="urn:xmpp:ozone:1" to="sip:userc@" from="sip:martin@" cdr:ts="2011-10-06 12:17:42.20+0200">
    <header name="Max-Forwards" value="70"/>
    <header name="Subject" value="Phone call"/>
    <header name="Content-Length" value="406"/>
    <header name="Contact" value="&lt;sip:martin@;"/>
    <header name="Allow" value="INVITE"/>
    <header name="To" value="PrismLocal &lt;sip:userc@;"/>
    <header name="CSeq" value="20 INVITE"/>
    <header name="User-Agent" value="Linphone/3.3.2 (eXosip2/3.3.0)"/>
    <header name="Via" value="SIP/2.0/UDP;rport=6089;branch=z9hG4bK223660164;received="/>
    <header name="Call-ID" value="1083438027"/>
    <header name="Content-Type" value="application/sdp"/>
    <header name="From" value="&lt;sip:martin@;;tag=1790499602"/>
  <answer xmlns="urn:xmpp:ozone:1" cdr:ts="2011-10-06 12:17:42.20+0200"/>
  <say xmlns="urn:xmpp:ozone:say:1" cdr:ts="2011-10-06 12:17:42.20+0200">
    <audio xmlns="" src=""/>
  <todo cdr:ts="2011-10-06 12:17:42.20+0200">TODO: Empty IQ Result</todo>
  <ref xmlns="urn:xmpp:ozone:1" jid="eed317db-b126-4ed7-83b5-ac2007132015@localhost/e2765ecc-1624-45c2-9f74-5787aa656d13" cdr:ts="2011-10-06 12:17:42.20+0200"/>
  <complete xmlns="urn:xmpp:ozone:say:1" reason="HANGUP" cdr:ts="2011-10-06 12:17:42.20+0200"/>
  <end xmlns="urn:xmpp:ozone:1" cdr:ts="2011-10-06 12:17:42.20+0200">

Configuring CDR storage

CDR storage configuration is done via editing the rayo-context.xml Spring configuration file. The following snippet shows a sample configuration that has enabled all the different types of supported CDR storages.

    <bean id="cdrErrorHandler" class="com.rayo.server.cdr.DefaultErrorHandler"/>
    <bean id="cdrManager" class="com.rayo.server.CdrManager">
        <property name="errorHandler" ref="cdrErrorHandler"/>
        <property name="storageStrategies">
                <ref bean="fileCdrStorageStrategy"/>
                <ref bean="jmsCdrStorageStrategy"/> 
                                <ref bean="xmppCdrStorageStrategy"/>
                                <ref bean="amqpCdrStorageStrategy"/>

Let's go through that file. The first line defines an error handler that will be used to handle exceptions. Rayo comes with a default error handler that logs every error to the console, but you can provide your own error handlers should you want to.

The second bean configured is the CDR Manager. First we set up the error handler, and the second part of the bean is a list of storage strategies. In this example, we are enabling all the available storage strategies that come bundled with Rayo, a filesystem-based storage strategy, a JMS-based storage strategy, an XMPP PubSub storage strategy and an AMQP CDR storage strategy. But, again, you can create your own implementations of the CdrStorageStrategy interface if you need it.

When multiple storage strategies are set, Rayo will deliver the CDR to all strategies. In the example above, Rayo would first store the CDR in an audit log using the fileCdrStorageStrategy, then it would send the CDR to a JMS queue using the jmsCdrStorageStrategy, third it would send the CDR to a PubSub node within an XMPP server and finally it would deliver the CDR to an AMQP destination.

Below you will learn how to enable all the individual CDR storage strategies:

Filesystem based CDR storage

The file system based storage lets you specify a file where your CDRs will stored. The definition is as follows:

    <bean id="fileCdrStorageStrategy" class="com.rayo.server.cdr.FileCdrStorageStrategy" 
        <property name="path" value="/tmp/test.log"/>

There is two properties that you can specify:

  • path: The path for the file where the CDRs will be stored
  • append: You can specify whether you want to append information to the file or not. This field is optional. The default value is true.

JMS based CDR storage

The JMS based CDR storage lets you send CDRs to any JMS queue. You only need to define the JMS server connection and queue details in the configuration file. Here is an example:

        <util:map id="env" map-class="java.util.HashMap" key-type="java.lang.String" value-type="java.lang.String">
            <key><util:constant static-field="javax.naming.Context.INITIAL_CONTEXT_FACTORY"/></key>
            <key><util:constant static-field="javax.naming.Context.PROVIDER_URL"/></key>

    <bean id="jmsCdrStorageStrategy" class="com.rayo.server.cdr.JMSCdrStorageStrategy" 
        <property name="environment" ref="env"/>
        <property name="connectionFactory" value="QueueConnectionFactory"/>
        <property name="queue" value="example.A"/>

Don't let the verbosity of this configuration to scare you. It is fairly simple. First there is a map of configuration options defined by the util:map block of code. In that map you need to define two options:

  • Initial Context Factory: You need to define the class that is used to create connections with your JMS server. This value depends on the application server you are going to use. Please also remember that whatever connection factory you use, you will need to include a JAR file with that class in your application. So for example, on the above example you would have to include activemq-core.jar in your WEB-INF/lib folder when deploying Rayo's WAR file.
  • Provider URL: The URL of your JMS Server like for example tcp://localhost:61616

Finally, in the bean section you need to define a couple of extra variables:

  • Connection Factory name: The JNDI name of the connection factory you are going to use. So for example if you are going to send messages to an ActiveMQ queue you would use the JNDI name QueueConnectionFactory.
  • Queue name: The JNDI name of the queue where the CDR messages will be sent.

XMPP PubSub based CDR storage

The XMPP based CDR storage lets you publish CDRs to any PubSub destination. You will only have to define the connection settings for the XMPP server and the name of the node where the CDRs will be sent. Here is an example:

    <bean id="xmppCdrStorageStrategy" class="com.rayo.server.cdr.XmppCdrStorageStrategy"
          <property name="server" value="yourxmppserverhere"/>
          <property name="port" value="5222"/>
          <property name="username" value="admin"/>
          <property name="password" value="admin"/>
          <property name="node" value="rayo-cdr"/>

So, as you can see on the code above, you only need to define a few variables:

  • Server: Name or IP of the XMPP Server.
  • Port: The port where that XMPP server is listening to.
  • Username: The username that will connect to the server.
  • Password: The password for that username.
  • Node: This is the name of the PubSub node where messages will be published. Any consumers subscribed to that node will receive the CDRs.

AMQP based CDR storage

The AMQP based CDR storage lets you publish CDRs to any AMQP destination. You will only have to define the connection settings for the XMPP server and the name of the node where the CDRs will be sent. Here is an example that uses RabbitMQ:

    <bean id="amqpCdrStorageStrategy" class="com.rayo.server.cdr.AmqpCdrStorageStrategy"
          <property name="server" value="localhost"/>
          <property name="port" value="5672"/>
          <property name="username" value="guest"/>
          <property name="password" value="guest"/>
          <property name="exchange" value="rayo-exchange"/>
          <property name="route" value="rayo-route"/>

So, as you can see on the code above, you only need to define a few variables:

  • Server: Name or IP of the AMQP Server.
  • Port: The port where that AMQP server is listening to.
  • Username: The username that will connect to the server.
  • Password: The password for that username.
  • Exchange: The name of the exchange where messages will be sent to.
  • Route: The name of the route where messages will be sent to.

And that is it. Any consumer subscribed to the specified exchange and route will receive the CDRs.

Viewing active CDRs in real time

You can view active CDRs in real time by using JMX. Check out the JMX Rayo Monitoring wiki page to find out how.

Configuring CDR storage in real time

Some CDR storage services can be configured by using JMX. Be sure to check out the JMX Rayo Monitoring wiki page to find out how.