2011-11-03 29 views

Respuesta

10

Esto se puede lograr en Logback, el sucesor de Log4J.

Logback está diseñado como un sucesor del popular proyecto log4j, retomando donde lo deja log4j.

consulte la documentación de Sifting Appender

El SiftingAppender es único en su capacidad para hacer referencia y configurar appenders anidados. En el ejemplo anterior, dentro de SiftingAppender habrá instancias FileAppender anidadas, cada instancia identificada por el valor asociado con la clave MDC "ID de usuario". Siempre que a la clave MDC "userid" se le asigne un nuevo valor, se generará una nueva instancia de FileAppender desde cero. SiftingAppender realiza un seguimiento de los apéndices que crea. Los apéndices que no se usen durante 30 minutos se cerrarán automáticamente y se descartarán.

En el ejemplo, generan un archivo de registro separado para cada usuario basado en un valor de MDC. Se pueden usar otros valores de MDC según sus necesidades.

+0

Pero el uso de Logback significaría que todas las instrucciones de registro deben cambiarse ¿verdad? ' –

+1

Consulte el enlace de API heredadas en http://slf4j.org/legacy.html – Ceki

9

Esto también es posible con log4j. Puedes hacer esto implementando tu propio appender. Supongo que la forma más fácil es subclase AppenderSkeleton.

Todos los eventos de registro terminan en el método append(LoggingEvent event) que debe implementar.

En ese método se puede acceder al MDC por event.getMDC("nameOfTheKeyToLookFor");

A continuación, puede utilizar esta información para abrir el archivo para escribir. Puede ser útil echar un vistazo a la implementación de los appenders estándar como RollingFileAppender para descubrir el resto.

Utilicé este enfoque yo mismo en una aplicación para separar los registros de diferentes subprocesos en diferentes archivos de registro y funcionó muy bien.

+0

No estoy utilizando RollingFileAppender. ¿Es posible en FileAppender? –

+0

Mencioné RollingfileAppender solo como ejemplo de cómo implementar un appender.Básicamente puedes hacer lo que quieras en el método de agregar. – Wolfgang

5

Luché por un tiempo para encontrar la funcionalidad de SiftingAppender en log4j (no pudimos cambiar a logback debido a algunas dependencias), y terminé con una solución programática que funciona bastante bien, usando un MDC y agregando loggers en tiempo de ejecución:

// this can be any thread-specific string 
String processID = request.getProcessID(); 

Logger logger = Logger.getRootLogger(); 

// append a new file logger if no logger exists for this tag 
if(logger.getAppender(processID) == null){ 

    try{ 
    String pattern = "%d{yy/MM/dd HH:mm:ss} %p %c{2}: %m%n"; 
    String logfile = "log/"+processID+".log"; 

    FileAppender fileAppender = new FileAppender(
     new PatternLayout(pattern), logfile, true); 
    fileAppender.setName(processID); 

    // add a filter so we can ignore any logs from other threads 
    fileAppender.addFilter(new ProcessIDFilter(processID)); 

    logger.addAppender(fileAppender); 
    }catch(Exception e){ 
    throw new RuntimeException(e); 
    } 
} 

// tag all child threads with this process-id so we can separate out log output 
MDC.put("process-id", processID); 

//whatever you want to do in the thread 
LOG.info("This message will only end up in "+processID+".log!"); 

MDC.remove("process-id"); 

El filtro anexa anteriormente simplemente comprueba para un ID de proceso específico:

public class RunIdFilter extends Filter { 

    private final String runId; 

    public RunIdFilter(String runId) { 
    this.runId = runId; 
    } 

    @Override 
    public int decide(LoggingEvent event) { 
    Object mdc = event.getMDC("run-id"); 

    if (runId.equals(mdc)) { 
     return Filter.ACCEPT; 
    } 

    return Filter.DENY; 
    } 
} 

Hope esto ayuda un poco.

+0

¿Cómo escribo el mismo filtro en Log4j 2? –

+0

donde agregar el código en el primer bloque? – NaiveCoder

+0

@NaiveCoder en cualquier lugar donde desee iniciar el filtrado de MDC. – bpodgursky

Cuestiones relacionadas