Joven hacker sonriendo

Hackeamos su software

cero falsos positivos

Inteligencia experta + automatización eficaz

Registrar Eventos en Bitácoras

Nuestros ethical hackers explican cómo programar adecuadamente en Scala al registrar eventos importantes en bitácoras. Esto facilita la labor de identificar fallas y ataques potenciales, así como realizar un seguimiento detallado de los archivos e información afectada.

Necesidad

Registrar eventos en las bitácoras de una aplicación Scala

Contexto

A continuación se describen las circunstancias bajo las cuales la siguiente solución tiene sentido:

  1. Se esta desarrollando una aplicación en lenguaje de programación Scala v2.10.4.

  2. Se desea minimizar el número de dependencias externas de la aplicación (uso de frameworks de logging).

Solución

  1. Cada evento que desea grabarse en la bitácora tiene un nivel, que indica la prioridad o urgencia de dicho evento. Los niveles en orden descendente de urgencia son [2]:

    • SEVERE

    • WARNING

    • INFO

    • CONFIG

    • FINE

    • FINER

    • FINEST

  2. Adicionalmente existen los siguientes niveles, con significado solo en tiempo de configuración o despliegue, y que permiten deshabilitar por completo el registro de evento o por el contrario habilitar el registro de eventos de todos los niveles. [2]

    • OFF

    • ALL

  3. El API estándar de bitácoras de Java, se forma principalmente por el concepto de logger, que corresponde a un nombre de estructura jerárquica similar a la de los paquetes y clases y que representa una configuración particular para grabar eventos.

  4. En el código fuente, el objeto logger correspondiente, es obtenido mediante:

    1
    2
    3
    ...
    val logger = Logger.getLogger(this.getClass().getName())
    ...
    
  5. Para grabar eventos asociados al logger existen dos opciones. La primera, mas corta, involucra el nivel del evento en el nombre de la función:

    logger.scala
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ...
      logger.severe("evento")
      logger.warning("evento")
      logger.info("evento")
      logger.config("evento")
      logger.fine("evento")
      logger.finer("evento")
      logger.finest("evento")
    ...
    
  6. El segundo involucra el nivel como un parámetro adicional.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    ...
      logger.log(Level.SEVERE, "evento")
      logger.log(Level.WARNING, "evento")
      logger.log(Level.INFO, "evento")
      logger.log(Level.CONFIG, "evento")
      logger.log(Level.FINE, "evento")
      logger.log(Level.FINER, "evento")
      logger.log(Level.FINEST, "evento")
    ...
    
  7. Se recomienda el uso de la primera opción, por su mantenibilidad y legibilidad. Adicionalmente, para cualquiera de las dos alternativas, existen versiones de las funciones que reciben como parámetro las excepciones generadas en una clausula try-catch.

    1
    2
    3
    4
    ...
      logger.warning("evento", e)
      logger.log(Level.WARNING, "evento", e)
    ...
    
  8. A continuación se presenta un ejemplo de uso completo del API de bitácoras en cuestión:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    import java.util.logging.{Logger,Level}
    
    object Main {
        val logger = Logger.getLogger(this.getClass().getName())
        def main(args: Array[String])
        {
            logger.setLevel(Level.WARNING)
            logger.warning("Comenzando el main")
            try {
                println("Hola")
                var i = 0/0;
            } catch {
                case e: Exception => logger.severe("Problemas dentro del main")
            }
            logger.info("No se mostrará por no tener nivel WARNING o superior: Finalizando el main")
        }
    }
    
  9. Se observa la salida:

    1
    2
    3
    4
    5
    6
    % scala LogEvents.scala
    dic 23, 2015 3:19:34 PM Main$ main
    WARNING:: Comenzando el main
    Hola
    dic 23, 2015 3:19:35 PM Main$ main
    SEVERE: Problemas dentro del main
    
  10. Nótese que sólo los mensajes con nivel de depuración de INFO o superiores, como es el caso de SEVERE, fueron mostrados.

  11. La configuración de los loggers se define primero por los valores por defecto que se encuentran en lib/logging.properties en el directorio del JRE. Adicionalmente se pueden definir loggers particulares mediante la invocación de la máquina virtual con los siguientes parámetros:

    1
    2
    3
    ...
    scala -Djava.util.logging.config.file=mylogging.properties <class>
    ...
    
  12. Este archivo de propiedades que determina la configuración de cada logger permite determinar el nivel de los eventos que efectivamente se registrarán para cada logger en dicho momento. El siguiente ejemplo muestra como se define que se registren todos los eventos para el logger en cuestión:

    1
    2
    3
    ...
    com.FLUIDSignal.level = ALL
    ...
    
  13. En ambientes de desarrollo la recomendación anterior es ideal, sin embargo para ambientes de producción se recomienda utilizar niveles que contengan solo el nivel de detalle necesario y que no incluyan eventos de depuración. Esta recomendación ayudará a mantener el rendimiento de la aplicación y el tamaño de las bitácoras en valores apropiados.




Haz un comentario

Estado de los servicios - Términos de Uso