Log4J, SMTPAppender: Envio de trazas de log por email

2
17617

Log4J, SMTPAppender: Envio de trazas de log por email

Una tarea fundamental en todo proyecto informático es la generación de log o trazas, generalmente para detectar y solucionar los posibles errores
que pudieran producirse.

Aunque normalmente estos logs suelen dejarse en archivos de texto, en determinadas situaciones puede ser
necesario enterarse rápidamente de los errores sin tener que esperar a que el usuario nos lo notifique.
Una posible solución podría ser que el sistema nos enviase esos errores a una cuenta de correo electrónico.

En este tutorial vamos a aprender como hacerlo, para ello nos basaremos en una sencilla aplicación que genera errores por correo electrónico cuando una simulada compra de productos falla.

BuyCard: Simula un carrito de compra.

package com.autentia.tutoriales.log4j;


import java.util.ArrayList;
import java.util.Random;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/**
 * Carrito de compra
 * @author Carlos García. Autentia
 * @see http://www.mobiletest.es
 */
public class BuyCard {
	private static Log log = LogFactory.getLog(BuyCard.class);
	private java.util.ArrayList pedido; 
	
	
	/**
	 * Constructor
	 */
	public BuyCard(){
		this.pedido = new ArrayList();
	}
	
	/**
	 * Añade un producto al carrito de la compra
	 * @param code Código del producto
	 * @throws java.util.NoSuchElementException En caso de que el producto no exista o no hay unidades dispobibles en stock
	 */
	public void appendProduct(String code) throws java.util.NoSuchElementException {
		if (! this.isAvailable(code)){
			if (log.isDebugEnabled()){
				log.debug("Se ha solicitado un producto que no existe: " + code);
			}
			throw new java.util.NoSuchElementException(code);
		}
		
		pedido.add(code);
		
		if (log.isDebugEnabled()){
			log.debug("El producto ha sido agregado al carrito correctamente: " + code);
		}		
	}
	
	/**
	 * @param code Código del producto
	 * @return Indica un producto está en stock
	 */
	public boolean isAvailable(String code){
		Random	rnd		= new Random();
		int		nRnd	= rnd.nextInt(100); // Generamos número aleatorio entre 0-100
		boolean exists	= (nRnd >= 5);      // Probabilidad baja de que el producto no exista.
		
		if (log.isDebugEnabled()){
			log.debug("Producto " + code + ", dispobibilidad: " + exists);
		}	
		
		return exists;
	}
	
	/**
	 * Realiza el proceso de compra
	 */
	public boolean processBuy() {
		if (log.isDebugEnabled()){
			log.debug("Realizando la compra");
		}
		
		Random	rnd	 = new Random();
		int		nRnd = rnd.nextInt(100); // Generamos número aleatorio entre 0-100 
		boolean ok	 = (nRnd >= 50);     // 50% de probabilidad de que el proceso de compra compra falle.
		
		if (log.isDebugEnabled()){
			log.debug("compra realizada correctamente: " + ok);
		}			
		
		return ok;
	}
}

La siguiente aplicación de consola simula un proceso de compra de varios productos.

package com.autentia.tutoriales.log4j;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.xml.DOMConfigurator;

/**
 * Ejemplo del tutorial 
 * @author Carlos García. Autentia.
 * @see http://www.mobiletest.es
 */
public class EjemploLog {
	
	/**
	 * Punto de entrada a la aplicación
	 */
	public static void main(String[] args) {
		// Cargamos la configuración de Log4J desde un archivo accesible via CLASSPATH
		DOMConfigurator.configure(EjemploLog.class.getClassLoader().getResource("autentiaLog4jSmtp.xml"));
		
		// Obtenemos el Log para esta clase.
		Log log  = LogFactory.getLog(EjemploLog.class);
		
		BuyCard compra = new BuyCard();
		
		try {
			// Solicitamos unos productos
			compra.appendProduct("98HG");
			compra.appendProduct("73DD");
			compra.appendProduct("671A");
		
			if (compra.processBuy()){
				log.debug("La compra se ha realizado correctamente");
			} else {
				Log smtp = LogFactory.getLog("soporteCompras");
				smtp.info("No saldrá en el email por por el valor LevelMin del filtro LevelRangeFilter");
				smtp.error("Se ha producido un error grave al realizar el proceso de compra");
			}
		} catch (Exception ex){
			log.warn("Error en la compra:", ex);
		}
	}
}

Si observa, en las líneas 35 y 36 se ve como la aplicación selecciona el Logger soporteCompras para notificar el error por correo.

Dependencias necesarias para ejecutar la aplicación:

	// Para el sistema de logs necesitamos:
	log4j-X.Y.jar
	commons-logging-X.Y.jar
	
	// Para el envio de correos necesitamos:
	mail-X.Y.jar
	activation-X.Y.jar	

Archivo de configuración de Log4j: autentiaLog4jSmtp.xml




	
		
		
		

		
			
		
	

    
        
        
        
        
        
        
        
        
		
       
            
            
        
        		        
    		
    			
    		
    
    	
	
		 
	

	
 		
		

  • BufferSize: Número de eventos de log que serán enviados por email, (por motivos de rendimiento).
  • Si observa en las líneas 16-20 debemos poner la configuración necesaria para realizar la conexión al servidor SMTP y enviar el correo electrónico.
  • Por defecto SMTPAppender almacenará en memoria todos eventos y los enviará cuando se reporte algún evento de nivel ERROR o superrior.
    En este ejemplo debido al valor de LevelMin sólo saldrán las trazas de error o superior.

En el archivo autentiaLog4jApp.log la aplicación deja todas las trazas que genera la aplicación.

2008-04-18 16:18:01 [DEBUG] [com.autentia.tutoriales.log4j.BuyCard.isAvailable(BuyCard.java:58)] 
Producto 98HG, dispobibilidad: true

2008-04-18 16:18:01 [DEBUG] [com.autentia.tutoriales.log4j.BuyCard.appendProduct(BuyCard.java:44)] 
El producto ha sido agregado al carrito correctamente: 98HG

2008-04-18 16:18:01 [DEBUG] [com.autentia.tutoriales.log4j.BuyCard.isAvailable(BuyCard.java:58)] 
Producto 73DD, dispobibilidad: true

2008-04-18 16:18:01 [DEBUG] [com.autentia.tutoriales.log4j.BuyCard.appendProduct(BuyCard.java:44)] 
El producto ha sido agregado al carrito correctamente: 73DD

2008-04-18 16:18:01 [DEBUG] [com.autentia.tutoriales.log4j.BuyCard.isAvailable(BuyCard.java:58)] 
Producto 671A, dispobibilidad: true

2008-04-18 16:18:01 [DEBUG] [com.autentia.tutoriales.log4j.BuyCard.appendProduct(BuyCard.java:44)] 
El producto ha sido agregado al carrito correctamente: 671A

2008-04-18 16:18:01 [DEBUG] [com.autentia.tutoriales.log4j.BuyCard.processBuy(BuyCard.java:69)] 
Realizando la compra

2008-04-18 16:18:01 [DEBUG] [com.autentia.tutoriales.log4j.BuyCard.processBuy(BuyCard.java:77)] 
compra realizada correctamente: false

2008-04-18 16:18:01 [ERROR] [com.autentia.tutoriales.log4j.EjemploLog.main(EjemploLog.java:36)] 
Se ha producido un error grave al realizar el proceso de compra

Además de la salida que se observa en el log, la aplicación habrá enviado un correo electrónico con la información que aparecen en las líneas 25 y 26.

Tenga en cuenta que registrar un evento por correo es mucho más costoso en términos de rendimiento que hacerlo a un archivo, por lo que sería bueno realizar esta tarea en de forma asíncrona.

Conclusiones

La gestión de trazas es una parte fundamental de toda aplicación, por lo que es recomendable establecer alguna política o pautas al respecto dentro del proyecto.

Recordar que la mayor parte del dinero de un sistema informático se va en mantenimientos, así que un buen sistema de logs nos hará la vida más fácil y nos permitirá ahorrar muchos esfuerzos (dinerito).

Referencias y enlaces de interés

Carlos García Pérez. Creador de MobileTest, un complemento educativo para los profesores y sus alumnos.

cgpcosmad@gmail.com

2 COMENTARIOS

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad