jueves, 24 de noviembre de 2011

Asterisk 1.6.2.X, cdr_adaptive y calidad de llamadas

Un cliente llama y se queja de la calidad de las llamadas “escucho entrecortado”, “tengo eco” y un largo etcétera. ¿Cómo podemos darle una respuesta fiable y anexarle un reporte de la calidad de sus llamadas? Trabajando con el modulo cdr_adaptive de Asterisk y creando una tabla personalizada donde guardar los datos que nos interesa.



Prerrequisitos: Haber compilado Asterisk con el soporte ODBC


El modulo cdr_adaptive permite crear tablas personalizadas de CDR y guardar los datos en una base de datos a través del conector ODBC. Pero ¿Qué datos vamos a guardar? En esto nos ayuda la función CHANNEL de Asterisk. Entre los distintos valores que podemos leer de un canal activo, están:



  • peerip: la IP de origen del canal

  • rtpqos: permite leer distintas informaciones acerca de la calidad de la llamada. Entre ellas:

    • local_lostpackets: los paquetes audio/video perdidos a lo largo de la llamada

    • local_count: numero total de paquetes audio/video recibidos

    • local_jitter: Jitter local de la llamada

    • remote_lostpackets: los paquetes audio/video perdidos entre los trasmitidos

    • remote_count: numero total de paquetes audio/video trasmitidos

    • remote_jitter: jitter remoto para la llamada



  • useragent: el dispositivo utilizado para la llamada (telefono SIP; Softphone; PBX, etc)

  • audioreadformat: codec audio del canal

  • audiowriteformat: codec audio saliente


Además de estos valores, vamos a escribir en la tabla otros:



  • accountcode: el código o cuenta del cliente

  • hangupcause: variable generada por la aplicación Dial que contiene un código que nos dice como y porque ha terminado la llamada

  • calldate: la fecha de la llamada

  • dst: el numero de destino de la llamada

  • billsec: duración de la llamada desde que ha sido contestada


Algunos de estos campos los escribe Asterisk en automático ya que son parte de las variables predefinidas del CDR (Call Data Record). Otros hay que declararlos en el dialplan. Con estos datos vamos a crear la base de datos (o utilizar una existente) y la tabla correspondiente.


mysql -u root -ppassword


mysql> create database asterisk;


mysql> use asterisk


mysql>  CREATE TABLE `cdr2` ( 
  `id` bigint(20) NOT NULL auto_increment, 
  `calldate` datetime NOT NULL default '0000-00-00 00:00:00', 
  `accountcode` varchar(20) default NULL, 
  `dst` varchar(80) NOT NULL default '0', 
  `billsec` varchar(80) NOT NULL default '0', 
  `peerip` varchar(80) NOT NULL default '', 
  `useragent` varchar(80) NOT NULL default '', 
  `codec1` varchar(80) NOT NULL default '', 
  `codec2` varchar(80) NOT NULL default '', 
  `tlp` int(15) NOT NULL default '0', 
  `llp` int(15) NOT NULL default '0', 
  `porlp` decimal(6,3) unsigned zerofill NOT NULL default '000.000', 
  `trp` int(15) NOT NULL default '0', 
  `rlp` int(15) NOT NULL default '0', 
  `porrp` decimal(6,3) unsigned zerofill NOT NULL default '000.000', 
  `ljitter` varchar(20) NOT NULL default '', 
  `rjitter` varchar(32) NOT NULL default '', 
   `hangupcause` varchar(80) NOT NULL default '', 
   PRIMARY KEY  (`id`) 
   );


Si se fijan hay dos campos de que no hemos hablado:



  • porlp: este campo contendrá el porcentaje de paquetes locales perdidos cuyo calculo se hará a través de una operación matemática muy sencilla

  • porrp: este campo contendrá el porcentaje de paquetes remotos perdidos cuyo calculo se hará a través de una operación matemática muy sencilla


Ahora creamos los permisos para la base de datos asterisk, desde local:


mysql> GRANT ALL PRIVILEGES ON asterisk.* TO 'asterisk'@'localhost' IDENTIFIED BY 'sesamo';


desde remoto:


mysql> GRANT ALL PRIVILEGES ON asterisk.* TO 'asterisk'@'%' IDENTIFIED BY 'sesamo';


actualizamos los permisos:


mysql> flush privileges;


salimos del cliente MySQL:


mysql> quit


Ahora creamos una conexión a la base de datos MySQL con ODBC. Si es la primera vez que utilizan ODBC hay que seguir estos pasos:


nano /etc/odbcinst.ini


Para CentOS 5.7 32 bit debe contener:


[MySQL] 
Description = ODBC for MySQL 
Driver = /usr/lib/libmyodbc3.so 
Setup = /usr/lib/libodbcmyS.so 
FileUsage = 1


nano /odbc.ini


[cdr2] 
Description = MySQL CDR2 
Driver = MySQL 
Database = asterisk 
Server = localhost 
User = asterisk 
Password = sesamo 
Port = 3306 
Option = 3


El bloque de arriba crea una conexión a la base de datos MySQL “asterisk” utilizando como usuario asterisk y como contraseña sesamo. Terminada la configuración de ODBC falta la parte Asterisk donde hay que modificar tres archivos:



  • res_odbc.conf

  • cdr_adaptive_odbc.conf

  • extensions.conf


El primer archivo es él que normalmente se utiliza para la configuración de Asterisk Realtime. Se abre:


nano /etc/asterisk/res_odbc.conf


y al final del archivo se copian las siguientes líneas:


[cdr2] 
enabled => yes 
dsn => cdr2 
username => asterisk 
password => sesamo 
pre-connect => yes 
sanitysql => select 1 
idlecheck => 3600 
connect_timeout => 10


En dsn hay que poner el nombre de la etiqueta que define el bloque creado en odbc.ini. Se guardan los cambios y se continua con cdr_adaptive.conf


nano /etc/asterisk/cdr_adaptive_odbc.conf


al final del archivo se pone;


[cdr2] 
connection=cdr2 
table=cdr2 
alias start => calldate


los datos:



  • [cdr2]: un nombre que se le asigna a la conexión

  • connection=cdr2: en este parámetro hay que poner la etiqueta que define el bloque creado en res_odbc.conf

  • table=cdr2: la tabla MySQL donde se guardarán los datos

  • alias start => calldate: en cdr_adaptive hay tres campos donde se guardan diferentes momentos de la llamada: cuando inicia, cuando se contesta y cuando se termina. Los nombres de estos  campos son respectivamente start, answer y end. El campo calldate no existe. Por este motivo para que este campo contenga un valor hay que escoger unos de los tres que crea cdr_adaptive. Esto se hace indicando un alias y definiendo que el campo calldate contendrá el valor del campo start de cdr_adaptive (cuando la llamada inicia).


Se guardan los cambios y se pasa al dialplan. Si queremos monitorear todas las llamadas salientes y para ellas utilizamos un proveedor SIP, en el contexto correspondiente ponemos:


[salientes] 
exten => _00.,1,Noop(llamadas salientes) 
same => n,Dial(SIP/ProveedorSIP/${FILTER(0-9,${EXTEN})}) 
same => n,Hangup() 
exten => h,1,set(CDR(hangupcause)=${HANGUPCAUSE}) 
exten => h,n,set(CDR(accountcode)=${CDR(accountcode)}) 
exten => h,n,set(CDR(peerip)=${CHANNEL(peerip)}) 
exten => h,n,set(CDR(useragent)=${CHANNEL(useragent)}) 
exten => h,n,set(CDR(codec1)=${CHANNEL(audioreadformat)}) 
exten => h,n,set(CDR(codec2)=${CHANNEL(audiowriteformat)}) 
exten => h,n,set(CDR(tlp)=${CHANNEL(rtpqos,audio,local_count)}) 
exten => h,n,set(CDR(llp)=${CHANNEL(rtpqos,audio,local_lostpackets)}) 
exten => h,n,set(CDR(porlp)=$[{CHANNEL(rtpqos,audio,local_lostpackets)} / ${CHANNEL(rtpqos,audio,local_count)} * 100]) 
exten => h,n,set(CDR(trp)=${CHANNEL(rtpqos,audio,remote_count)}) 
exten => h,n,set(CDR(rlp)=${CHANNEL(rtpqos,audio,remote_lostpackets)}) 
exten => h,n,set(CDR(porrp)=$[{CHANNEL(rtpqos,audio,remote_lostpackets)} / ${CHANNEL(rtpqos,audio,remote_count)} * 100]) 
exten => h,n,set(CDR(ljitter)=${CHANNEL(rtpqos,audio,local_jitter)}) 
exten => h,n,set(CDR(rjitter)=${CHANNEL(rtpqos,audio,remote_jitter)}) 
exten => h,n,Hangup


Como Asterisk guarda los datos en el CDR cuando finaliza la llamada, podemos utilizar la extensión h para los nuestros. Si se fijan en porlp ý porrp la operación matemática es muy sencilla: se multiplican los paquetes perdidos por los paquetes totales y el resultado se divide por 100. De esta forma se saca el porcentaje de paquetes perdidos.


Se sacan unas cuantas llamadas y se mira que pasa en la tabla CDR2:


mysql -u root -ppassword


mysql> use asterisk


mysql> select calldate,useragent,codec1,codec2,tlp,llp,porlp,trp,rlp,porrp from cdr2;


Captura


mysql> quit


Fuente: Voztovoice.org

No hay comentarios.:

Publicar un comentario