Logging

La clase Logger de la librería estandar de Ruby nos ayuda a escribir mensajes a un log en el sistema de archivos. Soporta la rotación de logs basada en tiempo o en tamaño. Se pueden asignar niveles a los mensajes y sólo los mensajes con un nivel igual o superior al nivel del nivel del objeto logger actual son registrados.

Cuando escribes código, simplemente asumes que todos los mensajes van a ser registrados. En tiempo de ejecución, puedes obtener un log mas o menos detallado al cambiar el nivel del log. Una aplicación en producción usualmente tiene un nivel de Logger::INFO o Logger::WARN. De menos a más severo, los métodos de instancia son: Logger.debug, Logger.info, Logger.warn, Logger.error y Logger.fatal.

El nivel DEBUG es útil para obtener diagnósticos paso a paso de una tarea compleja. El nivel ERROR con frecuencia se utiliza para manejar excepciones: si el programa no puede resolver un problema, registra la excepción en lugar de detener la ejecución y es pera que un administrador atienda el problema. El nivel FATAL sólo debe ser usado cuando un programa no puede solucionar un problema y está a apunto de detener la ejecución.

Si tu log está siendo guardado en un archivo, puedes hacer que Logger rote o substituya el archivo cuando sea demasiado grande o cierto tiempo haya pasado:

 1 require "logger"
 2 
 3 # Guardar informacion solo del mes actual
 4 Logger.new('mes_actual.log', 'monthly')
 5 
 6 # Guardar informacion solo de los ultimos 20 dias
 7 Logger.new('applicacion.log', 20, 'daily')
 8 
 9 # Substituir el archivo log cuando exceda 100 MB
10 Logger.new('application.log', 0, 100 * 1024 * 1024)

El código siguiente utiliza un obeto Logger para mostrar un mensaje debugging y, cuando tiene un nivel más alto de severidad, como parte del código para menjar errores:

 1 require "logger"
 2 
 3 $LOG = Logger.new('archivo_log.log', 'monthly')
 4 
 5 def divide(numerador, denominador)
 6   $LOG.debug("Numerador: #{numerador}, Denominador: #{denominador}")
 7   
 8   begin
 9     resultado = numerador / denominador
10   rescue  => e
11     $LOG.error "Error en la division: #{e}"
12     result = nil
13   end
14   return result
15 end
16 
17 divide(10,0)

El contenido del archivo 'archivo_log.log' después de la primeras ejecución del programa es:

# Logfile created on Mon Jun 23 14:46:05 -0500 2008 by /
D, [2008-06-23T14:46:05.380904 #60025] DEBUG -- : Numerador: 10, Denominador: 2

Si llamamos al mismo método de la siguiente manera:

1 divide(10,0)

El contenido de 'archivo_log.log' es:

# Logfile created on Mon Jun 23 14:46:05 -0500 2008 by /
D, [2008-06-23T14:46:05.380904 #60025] DEBUG -- : Numerador: 10, Denominador: 2
D, [2008-06-23T14:52:20.703330 #60838] DEBUG -- : Numerador: 10, Denominador: 0
E, [2008-06-23T14:52:46.856787 #60910] ERROR -- : Error en la division: divided by 0

Para camibar el nivel del logger:

1 $LOG.level = Logger::ERROR

Ahora nuestro logger va a ignorar todos los mensajes excepto aquellos con un nivel de severidad ERROR o FATAL. El contenido de archivo_log.log es en este caso:

E, [2008-06-23T15:02:03.790196 #62130] ERROR -- : Error en la division: divided by 0