Enviar logs a un syslog centralizado con Symfony2 y Monolog

Recientemente me vi en la necesidad de enviar los logs de un sistema hecho con Symfony2 al syslog de la empresa y la sorpresa es que ni en la documentación de Symfony ni en la documentación de Monolog hay mucha información sobre este tema, así que voy a ver de documentar las pruebas aquí para que sirva de referencia a quiénes lo intenten.

La configuración de monolog en Symfony es un poco confusa, no tanto por como configurarlo sino porque hay que conocer varios conceptos e ir probando.

En uno de los cookbooks del sitio oficial de Symfony se puede encontrar este artículo que explica como usar diferentes handlers para tratar los logs. En el ejemplo se puede ver el siguiente código yml:

monolog:
    handlers:
        applog:
            type: stream
            path: /var/log/symfony.log
            level: error
        main:
            type: fingers_crossed
            action_level: warning
            handler: file
        file:
            type: stream
            level: debug
        syslog:
            type: syslog
            level: error

En la última parte del código se muestra como se utiliza el SyslogHandler que figura dentro de la documentación de la cuenta de github oficial de monolog pero solo se cita su existencia. De todas formas es bien sencilla su interpretación ya que como dice el tipo es “syslog” y lo que hace es enviar los registros de errores directamente al syslog de la máquina en donde se encuentra la aplicación· Hay que notar que por así decirlo, se hereda también la configuración del key “main” donde se utiliza el handler especial FingersCrossed de monolog que lo que hace es que cuando ocurra un error no solo tome en cuenta la línea del error sino un poco más del contexto para interpretar mejor el problema.

Hasta aquí es fácil, pero según las pruebas, este handler “syslog”, como comento arriba, envía los logs al archivo por defecto configurado por en el syslog de la máquina, que dependiendo del sistema operativo podrían ser por ejemplo: /var/log/syslog (debian), /var/log/messages (redhat) o /var/log/system.log.

El problema es que si tenemos varias aplicaciones distribuidas en distintos servidores o incluso varias instancias balanceadas de la misma aplicación en varios servidores, cada aplicación queda con el log en su servidor y cuando hablamos de varios servidores es un problema no contar con los logs de forma centralizada. Por lo tanto, la necesidad sería más bien enviar a un syslog remoto donde sean centralizados y administrados todos los logs de los sistemas y con este handler aparentemente no se puede hacer esto.

Luego de mucho probar e investigar, encontré en la documentación de monolog, también a nivel de cita nada más ya que no encontré ejemplos de uso, una sección específica para tratar con handlers que permiten enviar los logs a través de la red. Aquí encontré el handler llamado: SyslogUdpHandler.

Para conocer como configurarlo busqué dentro del archivo Symfony\Bundle\MonologBundle\DependencyInjection\MonologExtension que se encuentra entre los vendors de Symfony en la carpeta vendors/symfony/monolog-bundle/DependencyInjection/MonologExtension.php, que es donde el bundle de monolog sabe como leer las configuraciones y aquí se puede encontrar a “syslogudp” con las siguientes configuraciones válidas:

case 'syslogudp':
    $definition->setArguments(array(
        $handler['host'],
        $handler['port'],
        $handler['facility'],
        $handler['level'],
        $handler['bubble'],
    ));
    break;

Con esta información pude realizar la configuración para el ambiente de producción de la aplicación quedando de la siguiente manera:

monolog:
    handlers:
        main:
            type:         fingers_crossed
            action_level: error
            handler:      syslog
        syslog:
            type:         syslogudp
            host:         '%syslog.host%'
            level:        error

Como se puede notar, en la línea 6 digo que el handler a utilizar va a ser el llamado “syslog” que se encuentra configurado en las líneas 9-12. Ahora si el tipo usado ya es “syslogudp” y el “host” que contiene la IP del servidor de logs centralizados lo dejo como un parámetro definido en app/config/parameters.yml.dist para que los encargados de producción la definan. También es posible definir el puerto en el que estará escuchando el syslog pero como es el 514 que es el por defecto no hizo falta.

Con esta sencilla configuración ya podemos entrar por SSH al servidor remoto y hacer una prueba con algún error de la aplicación como por ejemplo una página que no se encuentre definida lo que daría un 404 por dejar de agregar algún punto y coma al final de una línea dentro de un controller 😛 lo que daría un error 500.

Comenta este artículo