Skip to main content.

17 Octubre 2009

Log en Asterisk

A menudo cuando una centralita tiene alta carga, ver la consola o los logs que genera Asterisk en /var/log/asterisk/messages no es suficiente. Porque se genera gran cantidad de información, porque al tener muchas llamadas concurrentes seguir una llamada en concreto a través de saltos en un fichero es complicado, porque a medida que integramos más y más herramientas con Asterisk las llamadas ya no se controlan o se localizan en un único punto…

Lo que vamos a intentar es tener controlado el log de todo el sistema, incluyendo Asterisk, su dialplan, los agis y cualesquira herramientas que usemos. Los objetivos son claros:

En este post vamos a ver un ejemplo de cómo hacer esto con un criterio arbitrario. Se pretende que cualquira pueda adaptar este ejemplo a sus necesidades. En este ejemplo vamos a querer:

  1. Los logs generales del sistema para ver que todo es correcto. Esto es, el syslog. Deberemos filtrar cúales de los servicios del sistema que loguean al syslog queremos ver y cuáles no.
  2. Los logs relacionados con el flujo de una llamada. En este caso vamos a suponer que dialplan y agis.

Todo esto lo vamos a hacer a través del syslog del sistema y las opciones que nos brinda para filtrar y etiquetar los logs.  ¡Manos a la obra!

Logger de Asterisk

Asterisk tiene una herramienta para configurar los logs que genera. Se configura en el fichero logger.conf. En el fichero podemos configurar los niveles de log que queremos que asterisk muestre en consola, en el fichero messages y en el syslog. Independientemente de lo que habilitemos para consola y para el fichero messages -nunca hay suficientes logs- vamos a activar y configurar el logging a syslog de tal forma que asterisk loguee ahí los errores y los warnigs. No nos interesa más información porque el log de los flujos de llamada lo vamos a gestionar de forma manual a fin de tener la información que nosotros deseamos de una forma más limpia.

  1. [general]
  2. [logfiles]
  3. console => notice,warning,error,verbose
  4. messages => notice,warning,error,verbose,debug,dtmf
  5. syslog.local5 => warning,error

Como se puede ver, las dos primeras líneas hacen referencia al CLI y al log normal de Asterisk. La última línea, que es la que usaremos, indica a Asterisk que loguee los mensajes de severidad Error y Warning a syslog con la facility Local5. De esta forma ya podremos ver en el syslog errores de parseo, de los channels, si no hemos cerrado un paréntesis y demás. Pero no podremos seguir el flujo de las llamadas ya que no tenemos ni verbose ni debug.

Este sería un ejemplo de lo que aparece en syslog cuando se hace un dialplan reload de Asterisk:

Oct 16 09:51:35 callcenter asterisk[15238]: WARNING[15309]: pbx_config.c:2276 in pbx_load_config: No closing parenthesis found? 'Macro(setgroup-in'

En vez de ver todo el reload en la consola con todas las extensiones, veo que me he dejado un paréntesis sin cerrar en el dialplan. Lo mismo pasaría para el resto de errores y warnings comunes durante las llamadas.

Log de los Agis

Cada vez más, a medida que desarrollamos nuestro Asterisk para darle más funcionalidades, debemos ejecutar más Agis. Los Agis son parte normal del flujo de una llamada y por tanto es de esperar que si queremos seguir la pista a cuanto ocurre en las llamadas de la centralita, sepamos lo que pasa dentro de esos Agi.

Todos los leguajes de programación tienen sus funciones para loguear a syslog. En este ejemplo vamos a usar Agis escritos en PHP. Generamos una pequeña clase que gestione los logs tal y como queremos que aparezcan en nuestros ficheros:

  1. class ivLogger {
  2.  
  3.         public static function doLog($uid, $file, $ref, $level, $str = "") {
  4.                 $ftmp = explode("/", $file);
  5.                 $f = $ftmp[count($ftmp)-1];
  6.                 if (empty($uid)) {
  7.                         $logmsg = "[$f][$ref] $str";
  8.                 } else {
  9.                         $logmsg = "[$uid][$f][$ref] $str";
  10.                 }
  11.                 openlog("ivozlog", LOG_ODELAY, LOG_LOCAL6);
  12.                 @syslog($level, $logmsg);
  13.                 closelog();
  14.                 if ($level != LOG_DEBUG) {
  15.                         $host = file_get_contents("/etc/hostname");
  16.                         @mail("vozip@irontec.com", "i::voz Logger [".trim($host)."]", $logmsg);
  17.                 }
  18.         }
  19. }

Tenemos una función doLog a la que podremos llamar para que loguee lo que nosotros le pasemos como parámetro al Syslog. Además, enviará un correo por todo mensaje que no sea de tipo DEBUG para avisar de que algo no funciona como debería. Sólo queda ver hacer llamadas de log en los Agi para tener el flujo controlado y logueado. Por ejemplo:

  1. define("CHK_KARMA", "1");
  2. define("DB_CON", "asterisk");
  3. require_once("lib/autoload.php");
  4. $uniqueid = $fastagi->request[‘agi_uniqueid’];
  5.  
  6. /* En FastAGI no tenemos que instanciar el AGI, nos viene dado en $fastagi */
  7. if (count($argx) != 1) {
  8.         ivLogger::doLog($uniqueid,__FILE__,__LINE__,LOG_ERR,"El número de parámetros no coincide. Se han pasado ".count($argx)." parámetros.");
  9.         exit(1);
  10. }
  11. $usuario = $argx[‘usuario’];
  12. $fastagi->set_variable("EXISTE_USUARIO", "NO");
  13. $sql = "SELECT id_usuario FROM tablausuarios WHERE login = ‘".$usuario."’ LIMIT 1";
  14. $con = new con($sql, DB_CON);
  15. if (!$con->getError()) {
  16.         if ($con->getNumRows() == 1) {
  17.                 $fastagi->set_variable("EXISTE_USUARIO", "SI");
  18.                 ivLogger::doLog($uniqueid,__FILE__,__LINE__,LOG_DEBUG,"Existe el usuario ".$usuario.".");
  19.                 exit(0);
  20.         }
  21.         else {
  22.                 ivLogger::doLog($uniqueid,__FILE__,__LINE__,LOG_DEBUG,"No existe el usuario ".$usuario.".");
  23.                 exit(0);
  24.         }
  25. }
  26. else {
  27.         ivLogger::doLog($uniqueid,__FILE__,__LINE__,LOG_WARNING,"Ha ocurrido un error en la conexión a la base de datos en la consulta ".$sql."El error devuelto ha sido ".$con->getError());
  28.         exit(1);
  29. }
  30. ivLogger::doLog($uniqueid,__FILE__,__LINE__,LOG_WARNING,"Hemos llegado a un punto del AGI al que probablemente no deberíamos haber llegado…");
  31. exit(1);

Este sencillo Agi, comprueba si un usuario dado como parámetro existe en la tabla tablausuarios y setea la variable de canal EXISTE_USUARIO a “SI” o “NO”. Como podemos ver, se hacen múltiples llamadas a la clase de log a lo largo del Agi para poder seguir el flujo de la llamada en el mismo y no hacer que éste sea una caja negra desde que se le llama en el Dialplan hasta que termina y devuelve el control. Las llamadas a la función de log reciben como parámetros:

Una vez tenemos los Agi bien comentados y las llamadas al log bien pensadas, podemos ver cuanto pasa en un Agi mirando el Syslog:

  1. Oct 16 10:34:53 callcenter ivozlog: [1255682093.0][pbx_DoesUserExist.php][40] No existe el usuario

Como podemos ver, hemos llamado al Agi y le hemos preguntado por un usuario que no existe. En el log podemos ver:

Como podemos ver, tenemos toda la información necesaria para poder ver el flujo que ha seguido una llamada en concreto en los Agi por los que ha pasado. Sin embargo, no hemos terminado con los Agi ya que sólo hemos controlado errores de programación y de conexión. Tenemos controlados los errores y los flujos pero no estamos aún preparados para los errores incontrolados tales como excepciones.

La librería de Agi más popular es sin duda phpagi. Esta librería permite además avisar de errores incontrolados y fallos en la comunicación con Asterisk mediante un correo electrónico. Es muy sencillo modificar la función de manejo de errores de phpagi.php para que loguee a syslog con el tag y el facility que nosotros queramos:

  1.      if(ini_get(‘error_reporting’) == 0) return; // this happens with an @
  2.  
  3. +    openlog("phpagi", LOG_ODELAY, LOG_LOCAL6);
  4. +    @syslog(LOG_WARNING, $file . ‘[' . $line . ']: ‘ . $message);
  5. +    closelog();
  6.  
  7.      global $phpagi_error_handler_email;

Y por fin lo único que quedaría sería decir al propio PHP que loguease los errores propios del lenguaje en syslog para de esta forma terminar de controlar todo lo que puede pasar en un AGI. Esto ya es propio de cada instalación de php en cada distribución así que símplemente lo dejamos como comentario.

Log del dialplan de Asterisk

Como hemos comentado, sólo tenemos de Asterisk los errores y los warnings. No tenemos información detallada de lo que pasa con una llamada ya que en alta carga el log de Asterisk y la consola se vuelven a efectos prácticos, inusables. Casi todos hemos usado la aplicación NoOp para ir poniendo mensajes que más tarde nos ayuden a debuguear visualmente el flujo de las llamadas. En este caso y dado que lo que queremos es unificar los logs en el syslog, vamos a reemplazar Noop por una aplicación que loguee a Syslog.
Asterisk dispone de la aplicación Log, que usa el logger de Asterisk para hacer sus cosas. Sin embargo, esta función nos deja poco control y es poco flexible para nuestras necesidades. En su lugar vamos a usar una aplicación  que aunque no es oficial de asterisk,  es fácilmente integrable en cualquier asterisk 1.4 y además ya viene se serie en asterisk-es-rsp: app_syslog.
La función app_syslog se pensó para poder loguear al Syslog directamente desde dialplan. Acepta gran cantidad de parámetros y al llamar directamente a Syslog y no usar el log de asterisk es enormemente rápida, ligera y flexible. Para instalarla símplemente hay que copiar el app_syslog.c a la carpeta apps de Asterisk (a no ser que tengamos las últimas versiones del branch principal de asterisk-es-rsp) y escoger su compilación al hacer “make menuconfig”, ya que al no ser una aplicación oficial de asterisk se decidió que no se compilase por defecto.

El uso de la aplicación es bastante sencilla:

  1.  -= Info about application ‘Syslog’ =-
  2.  
  3. [Synopsis]
  4. Syslog a given text
  5.  
  6. [Description]
  7. Syslog(message|[severity|facility|syslogtag|setuniqueid])
  8.   severity must be one of ERROR, WARNING, NOTICE, DEBUG, INFO, CRIT, ALERT, EMERG. Defaults to DEBUG
  9.   facility must be local0…local7. Defaults to USER
  10.   syslogtag if not present defaults to "asterisk"
  11.   setuniqueid is a 0-1 boolean that prepends or not channel’s uniqueid to logging message. Defaults to 0

En este caso, no vamos a cambiar de facility, ni de tag… por lo que los parámetros los guardaremos en variables globales y haremos las llamadas a Syslog desde nuestro dialplan de forma sencilla:

  1. exten => s,1,Syslog(Macro de llamar a usuario ${ARG1},${SYSLOG_SEVERITY},${SYSLOG_FACILITY},${SYSLOGTAG},${SYSLOG_SETUNIQUEID})
  2. exten => s,n,AGI(agi://${FASTAGI_SERVER}/pbx_DoesUserExist.php?usuario=${ARG1})
  3. exten => s,n,GotoIf($["${EXISTE_USUARIO}" != "SI"]?nouser)

Y El resultado en el Syslog sería tal que:

  1. Oct 16 08:07:44 callcenter asterisk: [1255673264.14291] Macro de llamar a usuario 22109
  2. Oct 16 08:07:44 callcenter ivozlog: [1255673264.14291][pbx_DoesUserExist.php][36] Existe el usuario 22109.
  3. Oct 16 08:07:44 callcenter ivozlog: [1255673264.14291][pbx_CheckStatusUsuario.php][42] SET de DESVIO_INCONDICIONAL a NO
  4. Oct 16 08:07:44 callcenter ivozlog: [1255673264.14291][pbx_CheckStatusUsuario.php][52] SET de DESVIO_NOANSWER a NO
  5. Oct 16 08:07:44 callcenter ivozlog: [1255673264.14291][pbx_CheckStatusUsuario.php][61] SET de DESVIO_BUSY a NO
  6. Oct 16 08:07:44 callcenter ivozlog: [1255673264.14291][pbx_CheckStatusUsuario.php][68] SET de DND a NO
  7. Oct 16 08:07:44 callcenter ivozlog: [1255673264.14291][pbx_CheckStatusUsuario.php][69] SET de USERTIMEOUT a 40
  8. Oct 16 08:07:44 callcenter ivozlog: [1255673264.14291][pbx_CheckStatusUsuario.php][70] SET de MAX_CALLS a 2
  9. Oct 16 08:07:44 callcenter ivozlog: [1255673264.14291][pbx_CheckStatusUsuario.php][71] SET de IDUSER a 759
  10. Oct 16 08:07:44 callcenter ivozlog: [1255673264.14291][pbx_CheckStatusUsuario.php][72] SET de VOICEMAIL_HABILITADO a 1
  11. Oct 16 08:07:44 callcenter ivozlog: [1255673264.14291][pbx_CheckStatusUsuario.php][89] Buscando interfaces para el usuario…
  12. Oct 16 08:07:44 callcenter ivozlog: [1255673264.14291][pbx_CheckStatusUsuario.php][93] Encontradas 1 interfaces
  13. Oct 16 08:07:44 callcenter ivozlog: [1255673264.14291][pbx_CheckStatusUsuario.php][100] SET de INTERFACES a SIP/telf0459
  14. Oct 16 08:07:55 callcenter asterisk: [1255673264.14291] Colgando en contexto macro de llamar usuario

De tal forma que ahora sí que podemos seguir un flujo de llamada de forma ordenada desde el Syslog del sistema.

Poniendo orden en el Syslog

Hemos hecho que nuestra centralita loguee todo al Syslog del sistema. Tenemos enormes cantidades de información en el fichero /var/log/syslog, pero esa información únicamente está marcada. Aún nos queda poder filtrarla (sin greps por favor), y tenerla en tamaños manejables ya que la inspección del fichero de syslog va a ser un caos mucho mayor que mirar la consola de asterisk, cosa que queríamos evitar desde un inicio.
Como herramienta de Syslog vamos a usar rsyslog, el programa de viene por defecto en Debian. Vamos a repartir los logs entre diferentes ficheros de tal forma que tengamos todo un poco más repartido. ¿Repartido? ¿No queríamos unificar todo?
En estos momentos tenemos los siguientes logs marcados de la siguiente manera:

Vamos a hacer que los errores (Local6) vayan a un fichero y los mensajes de flujo de llamadas (Local5) vayan a otro fichero. De esta forma tendremos más separado lo que es el error incontrolado de lo que es un debug o error controlado (que por otra parte ya se nos notifica por correo).

En el fichero /etc/rsyslog.conf tenemos la configuración por defecto de un syslog. No vamos a comentar todo lo que hace el sistema ya que el manejo de syslog es algo que todos los administradores de sistemas conocen a la perfección. Símplemente modificaremos las líneas necesarias para que los logs con determinada facility sean desviados a otros ficheros y no aparezcan en el log principal mezclados con todo lo demás.
Localizamos la línea

  1. *.*;auth,authpriv.none          -/var/log/syslog

Y la reemplazamos por

  1. *.*;auth,authpriv.none;local6.none;local5.none;local0.none            -/var/log/syslog
  2. local6.*                        -/var/log/ivozng/dialplan.log
  3. local5.*                        -/var/log/ivozng/asterisk.log
  4. local0.*                        -/var/log/ivozng/terminales.log

De esta forma hacemos que todos los logs con facility Local5, Local6, Local0 no aparezcan en el fichero de syslog y cada uno se escriba en su propio fichero. Tenemos las cosas más separadas pero aún así podemos ver el flujo de llamadas y errores de forma ordenada y cada uno en su sitio.
¡No hemos acabado! Tenemos ingentes cantidades de información que van a generar ficheros enormes que van a acabar por hacerse demasiado pesados amén de llenarnos el disco duro. Los logs hay que rotarlos. Nada más sencillo que crear unas rotaciones con el fichero /etc/logrotate.d/asterisk :

  1. root@callcenter:/etc/logrotate.d# cat ivozng
  2. /var/log/ivozng/dialplan.log {
  3.       daily
  4.       missingok
  5.       rotate 60
  6.       compress
  7.       copytruncate
  8.       notifempty
  9.       create 640 root adm
  10. }
  11.  
  12. /var/log/ivozng/asterisk.log {
  13.       daily
  14.       missingok
  15.       rotate 60
  16.       compress
  17.       copytruncate
  18.       notifempty
  19.       create 640 root adm
  20. }
  21.  
  22. /var/log/ivozng/terminales.log {
  23.       daily
  24.       missingok
  25.       rotate 60
  26.       compress
  27.       copytruncate
  28.       notifempty
  29.       create 640 root adm
  30. }
  31. /var/log/asterisk/messages {
  32.         daily
  33.         missingok
  34.         rotate 30
  35.         compress
  36.         copytruncate
  37.         notifempty
  38.         create 640 root adm
  39. }

Esto ya va tomando forma :)
Del mismo modo que hemos marcado y desviado los logs de Asterisk y de nuestra programación, podemos hacer lo propio con otros servicios de tal forma que la ingente cantidad de información -nunca hay demasiada- pueda ser más manejable y tratable. Podemos quedarnos aquí o podemos ir a hacerlo mejor:

Syslog a Mysql

¿No sería mucho más manejable disponer de todos los logs en una base de datos? De esta forma podríamos integrar visores y filtros en webs de gestión de una forma mucho más sencilla, amén de hacer todas las tareas de mantenimiento más sencillas al pobre administrador que no va a tener que lidiar con docenas de ficheros o dar acceso a los logs a gente que no debe tener acceso al sistema.
Rsyslog hace esto sencillo. Lo que vamos a necesitar es:

  1. Dar soporte mysql a rsyslog.
  2. Crear la base de datos y hacer que rsyslog escriba en ella lo que nosotros queramos.
  3. Hacer que la base de datos sea manejable.

Lo primero no puede ser más sencillo:
apt-get install rsyslog-mysql

Durante la instalación de rsyslog-mysql nos saldra un “ncurses” donde nos preguntará si queremos configurar una bases de datos … le decimos que no, que lo haremos manualmente ya que nos vamos a crear una tabla normal sino una tabla del tipo merge. Esto lo explicamos más adelante.

Vamos a crear digamos 28 tablas se1-se28 idénticas en todo excepto en el nombre, en una base de datos llamada log y creada para este propósito:

  1. CREATE TABLE `se1` (
  2.   `ID` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  3.   `CustomerID` bigint(20) DEFAULT NULL,
  4.   `ReceivedAt` datetime DEFAULT NULL,
  5.   `DeviceReportedTime` datetime DEFAULT NULL,
  6.   `Facility` smallint(6) DEFAULT NULL,
  7.   `Priority` smallint(6) DEFAULT NULL,
  8.   `FromHost` varchar(60) DEFAULT NULL,
  9.   `Message` text,
  10.   `NTSeverity` int(11) DEFAULT NULL,
  11.   `Importance` int(11) DEFAULT NULL,
  12.   `EventSource` varchar(60) DEFAULT NULL,
  13.   `EventUser` varchar(60) DEFAULT NULL,
  14.   `EventCategory` int(11) DEFAULT NULL,
  15.   `EventID` int(11) DEFAULT NULL,
  16.   `EventBinaryData` text,
  17.   `MaxAvailable` int(11) DEFAULT NULL,
  18.   `CurrUsage` int(11) DEFAULT NULL,
  19.   `MinUsage` int(11) DEFAULT NULL,
  20.   `MaxUsage` int(11) DEFAULT NULL,
  21.   `InfoUnitID` int(11) DEFAULT NULL,
  22.   `SysLogTag` varchar(60) DEFAULT NULL,
  23.   `EventLogType` varchar(60) DEFAULT NULL,
  24.   `GenericFileName` varchar(60) DEFAULT NULL,
  25.   `SystemID` int(11) DEFAULT NULL,
  26.   PRIMARY KEY  (`ID`)
  27. ) ENGINE=MyISAM DEFAULT CHARSET=utf8

Después creamos la tabla SystemEvents que es una tabla merge de las 28 anteriores:

  1. CREATE TABLE `SystemEvents` (
  2.   `ID` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  3.   `CustomerID` bigint(20) DEFAULT NULL,
  4.   `ReceivedAt` datetime DEFAULT NULL,
  5.   `DeviceReportedTime` datetime DEFAULT NULL,
  6.   `Facility` smallint(6) DEFAULT NULL,
  7.   `Priority` smallint(6) DEFAULT NULL,
  8.   `FromHost` varchar(60) DEFAULT NULL,
  9.   `Message` text,
  10.   `NTSeverity` int(11) DEFAULT NULL,
  11.   `Importance` int(11) DEFAULT NULL,
  12.   `EventSource` varchar(60) DEFAULT NULL,
  13.   `EventUser` varchar(60) DEFAULT NULL,
  14.   `EventCategory` int(11) DEFAULT NULL,
  15.   `EventID` int(11) DEFAULT NULL,
  16.   `EventBinaryData` text,
  17.   `MaxAvailable` int(11) DEFAULT NULL,
  18.   `CurrUsage` int(11) DEFAULT NULL,
  19.   `MinUsage` int(11) DEFAULT NULL,
  20.   `MaxUsage` int(11) DEFAULT NULL,
  21.   `InfoUnitID` int(11) DEFAULT NULL,
  22.   `SysLogTag` varchar(60) DEFAULT NULL,
  23.   `EventLogType` varchar(60) DEFAULT NULL,
  24.   `GenericFileName` varchar(60) DEFAULT NULL,
  25.   `SystemID` int(11) DEFAULT NULL,
  26.   PRIMARY KEY  (`ID`)
  27. ) ENGINE=MRG_MyISAM DEFAULT CHARSET=utf8 INSERT_METHOD=FIRST UNION=(`se1`,`se2`,`se3`,`se4`,`se5`,`se6`,`se7`,`se8`,`se9`,`se10`,`se11`,`se12`,`se13`,`se14`,`se15`,`se16`,`se17`,`se18`,`se19`,`se20`,`se21`,`se22`,`se23`,`se24`,`se25`,`se26`,`se27`,`se28`)

¿Qué hemos hecho? Hemos creado una tabla que es una unión de otras 28 tablas. Cuando hagamos un SELECT de la tabla SystemEvents, estaremos buscando en las 28 tablas y cuando hagamos un INSERT en la tabla estremos escribiendo en la tabla se1 (la primera).
Ya tenemos la tabla, ahora toca hacer que rsyslog escriba en ella los logs del sistema que nosotros queremos. Para ello vamos a crear un fichero de configuración aparte /etc/rsyslog.d/mysql.conf. Lo primero de todo es decirle a rsyslog que incluya la configuración de ese fichero. Vamos al final del fichero /etc/rsyslog.conf y añadimos (si no la tenemos ya) la línea
$IncludeConfig /etc/rsyslog.d/*.conf
En el nuevo fichero le diremos a rsyslog que cargue el módulo mysql y que loguee ciertas cosas a la base de datos log, tabla SystemEvents:

  1. $template tp1,"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values (’%msg%’, %syslogfacility%, ‘%fromhost%’, %syslogpriority%, ‘%timereported:::date-mysql%’, ‘%timegenerated:::date-mysql%’, %iut%, ‘%syslogtag%’)",SQL
  2.  
  3. $ModLoad ommysql
  4. *.*;auth,authpriv.none;local6.none;local5.none;cron.none;local0.none :ommysql:127.0.0.1,log,rsysloguser,rsyslogpass;tp1
  5. local6.* :ommysql:127.0.0.1,log,rsysloguser,rsyslogpass;tp1
  6. local5.* :ommysql:127.0.0.1,log,rsysloguser,rsyslogpass;tp1

Este fichero loguea todo lo que iría al fichero normal de syslog más los facility 5 y 6 a la base de datos. Se podría haber hecho todo en una sola línea y el uso del template no es en realidad necesario (ya que usamos el esquema estandar para las tablas, el que rsyslog usa por defecto) pero de esta forma se puede tocar después de una forma más cómoda. En la web de rsyslog hay mucha documentación acerca de cómo configurar este comportamiento.
Sólo nos queda dar permisos al usuario “rsysloguser” con contraseña “rsyslogpass” en la base de datos “log” para poder reiniciar rsyslog y ver los logs en la base de datos.
¡Tampoco hemos terminado!
Por lo que hemos visto, los INSERT de Mysql se hacen en la tabla se1, por lo que las otras 27 tablas están vacías y no sirven de nada. Además, a medida que pasa el tiempo y los logs se acumulan, la tabla SystemEvents se va haciendo más y más grande y el rendimiento empieza a degradarse. Para eso hemos hecho 28 tablas: Al igual que rotamos los ficheros de log vamos a rotar las tablas de log de tal forma que todos los días vamos a:

De esta forma consevaremos en base de datos los logs de las últimas 4 semanas siempre, una tabla por cada día. Además borrar una tabla es mucho más eficiente que borrar sus registros. Un pequeño script puesto en cron nos va a permitir hacer esto de forma automática:

  1. #!/bin/bash
  2. #Rotar tablas merge del syslog
  3.  
  4. PATH="/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin"
  5. export PATH
  6.  
  7. ROTATION=28
  8.  
  9. SQL="mysql -ursysloguser -prsyslogpass log -Be"
  10.  
  11. $SQL "DROP TABLE se$ROTATION;"
  12. let ROTATION=$ROTATION-1
  13.  
  14. while  [ $ROTATION -ge 1 ];
  15. do
  16.         let X=$ROTATION+1;
  17.         $SQL "ALTER TABLE se$ROTATION RENAME TO se$X;"
  18.         let ROTATION=$ROTATION-1
  19. done
  20.  
  21. $SQL "CREATE TABLE se1 LIKE se2;"
  22. $SQL "FLUSH TABLES;"

Nota: El usuario rsyslog ha de tener el privilegio global RELOAD para que esta rotación funcione correctamente.

¿Hemos acabado ya? Realmente… sí.
Ya sólo nos quedaría usar una aplicación que nos permita ver y filtrar los logs de una forma sencilla. Podemos usar nuestra propia aplicación o usar alguna ya hecha a tal efecto como phplogcon. Este programa, no vamos a meternos en su instalación ya que es bastante sencilla y sería repetir lo que ya está explicado en su web, dispone de una potente interfaz para ver y gestionar los logs. Cada uno que use el que más le guste :)

phplogcon

phplogcon

Posted by Jon Bonilla in Asterisk, General, Howto

Esta entrada se publicó el Sábado, Octubre 17th, 2009 a las 11:31 y está archivada bajo la categoría Asterisk, General, Howto. Puede seguir cualquier comentario a esta entrada a través del feed RSS 2.0 . Puede dejar un comentario, o trackback desde su propio sitio.

7 comentarios to “Log en Asterisk”

  1. Maik says:

    Vaya pedazo how-to Jon, muy currado!!

    :)

  2. » Cómo organizar y controlar los logs de Asterisk SinoLogic says:

    [...] Podeis ver el tutorial aquí: http://blog.voz-ip.com/2009/log-en-asterisk/ [...]

  3. Elio Rojano says:

    Ya te digo… muy, muy interesante, aunque lo de guardar los logs en una base de datos no me parece tan interesante… ¿eso no consume demasiado en comparación con el beneficio que tiene?

  4. Jon Bonilla says:

    Aupa Elio

    En realidad te sorprendería de lo ligero que es todo esto. En un server corriente de hoy día ni te enteras de la carga de esto.

    Generalmente las centralitas van sobredimensionadas. Un server de hoy día va muy sobrado para correr un asterisk y una base de datos. Además, si va a ser realmente grande, se puede tener el syslog en remoto, la base de datos en remoto y hasta los AGI en remoto. Si tienes una instalación en la que un servidor normal no da para tener los logs en mysql entonces es que REALMENTE necesitas tener los logs ordenados y te merece la pena un server más grande o un server con algunos servicios remotos.

    Pruébalo y vas a ver lo fino que va :)

  5. Saúl Ibarra says:

    Wow! Como mola Manwe! Posteas poco, pero cuando posteas te sales eh!

  6. Logs en Asterisk - Cosas del curro says:

    [...] http://blog.voz-ip.com/2009/log-en-asterisk/ [...]

  7. Organizar y controlar los logs de Asterisk « Asterisk CR says:

    [...] Estaba leyendo en sinologic.net que Jon Bonilla ha publicado un estupendo tutorial sobre cómo organizar el log de Asterisk, realmente imprescindible para sistemas de alta carga o que generan muchos mensajes y que necesitamos controlar para saber qué está haciendo Asterisk en ese momento. Estos es estupendo para los que tenemos que lidear con grandes cantidades de Logs, por ejemplo si tenemos que verificar los gateways H323 y el log esta creciendo constantemente en tiempo real se hará muy complicado, chequeen esta solución aquí [...]

Deje un comentario

XHTML: Puede emplear estos tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

2005 © Irontec S.L. :: Powered by Irontec & Wordpress
[ IRONTEC S.L. - C.I.F. B-95274890 ]
[ Ctra. Basurto-Kastrexana nº70 / Enpresaldea ]
[ 48002 - Bilbao - Bizkaia ]