Java >> Java tutorial >  >> Tag >> Log4j

Brug af MDC i log4j til dynamisk at navngive logfilen

Dette kan opnås i Logback, efterfølgeren til Log4J.

Logback er tænkt som en efterfølger til det populære log4j-projekt, der fortsætter, hvor log4j stopper.

Se dokumentationen til Sifting Appender

SiftingAppender er unik i sin kapacitet til at referere og konfigurere indlejrede appenders. I ovenstående eksempel vil der i SiftingAppender være indlejrede FileAppender-forekomster, hver forekomst identificeret ved værdien forbundet med "brugerid" MDC-nøglen. Hver gang "brugerid" MDC-nøglen tildeles en ny værdi, vil en ny FileAppender-instans blive bygget fra bunden. SiftingAppender holder styr på de appenders, den opretter. Vedhæng, der ikke har været brugt i 30 minutter, lukkes automatisk og kasseres.

I eksemplet genererer de en separat logfil for hver bruger baseret på en MDC-værdi. Andre MDC-værdier kan bruges afhængigt af dine behov.


Dette er også muligt med log4j. Du kan gøre dette ved at implementere din egen appender. Jeg gætter på, at den nemmeste måde er at underklasse AppenderSkeleton.

Alle logningshændelser ender i append(LoggingEvent event) metode, du skal implementere.

I den metode kan du få adgang til MDC'en med event.getMDC("nameOfTheKeyToLookFor");

Så kan du bruge disse oplysninger til at åbne filen for at skrive til. Det kan være nyttigt at se på implementeringen af ​​standardtillæggene som RollingFileAppender for at finde ud af resten.

Jeg brugte selv denne tilgang i et program til at adskille logfilerne fra forskellige tråde i forskellige logfiler, og det fungerede meget godt.


Jeg kæmpede i et stykke tid for at finde SiftingAppender-lignende funktionalitet i log4j (vi kunne ikke skifte til logback på grund af nogle afhængigheder), og endte med en programmatisk løsning, der fungerer ret godt, ved at bruge en MDC og tilføje loggere under runtime:

//  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");

Filteret, der er tilføjet ovenfor, kontrollerer kun for et specifikt proces-id:

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;
  }
}

Håber dette hjælper lidt.


Java tag