2016-02-12 32 views
5

I seguenti 3 post offrono risposte su come utilizzare un helper di registrazione intermedio e ottenere comunque il logger sottostante da segnalare dal metodo di un client per la registrazione che helper (piuttosto che riferire il metodo di registrazione di supporto come la fonte):Registrazione Java: Log4j Versione2.x: mostra il metodo di un chiamante del client finale (non un metodo di supporto intermedio di registrazione)

Ma l'sembrano offrire solo risposte per Log4j 1.2, che offre la ormai defunta:

Category.log(String callerFQCN, Priority level, Object message, Throwable t). 

Non sembra essere un equivalente ovvia per Logger in the log4J 2.5 API.

Qualcuno può offrire una risposta compatibile con l'uso diretto di Log4J 2.x?

risposta

3

Per Log4j2 la risposta è fornita completamente dall'utilizzo di wrapper logger come descritto nel manuale Log4j2 sotto Example Usage of a Generated Logger Wrapper. Si può semplicemente generare (usando gli strumenti org.apache.logging.log4j.core.tools.Generate $ ExtendedLogger qui illustrati) un wrapper del registratore con un singolo livello STUB, e quindi adattarlo per creare metodi di registrazione personalizzati che imitano l'uso di logIfEnabled (FQCN, LEVEL, Marker, message, Throwable) - possibilmente ignorando il livello di STUB e usando quelli regolari - quindi, se lo si desidera, eliminando o commentando il livello STUB ei suoi metodi). A tale scopo, FormattedMessage può essere utile.

Esempio:

java -cp log4j-core-2.5.jar org.apache.logging.log4j.core.tools.Generate\$ExtendedLogger com.mycomp.ExtLogger STUB=350 > com/mycomp/ExtLogger.java 

Poi adattare la classe generata (la maggior parte dei metodi di supporto omessi):

public final class ExtLogger extends ExtendedLoggerWrapper { 
... 
private final ExtendedLoggerWrapper logger; 

private static final String FQCN = ExtLogger.class.getName(); 
private static final Level STUB = Level.forName("STUB", 350); 
//Delete this afterwards if level not used. 

private ExtLogger(final Logger logger) { 
    super((AbstractLogger) logger, logger.getName(), logger.getMessageFactory()); 
    this.logger = this; 
} 

/** 
* Returns a custom Logger with the name of the calling class. 
* 
* @return The custom Logger for the calling class. 
*/ 
public static ExtLogger create() { 
    final Logger wrapped = LogManager.getLogger(); 
    return new ExtLogger(wrapped); 
} 

/** 
* Returns a custom Logger using the fully qualified name of the Class as 
* the Logger name. 
* 
* @param loggerName The Class whose name should be used as the Logger name. 
*   If null it will default to the calling class. 
* @return The custom Logger. 
*/ 
public static ExtLogger create(final Class<?> loggerName) { 
    final Logger wrapped = LogManager.getLogger(loggerName); 
    return new ExtLogger(wrapped); 
} 

... 

/** 
* Logs a message object with the {@code STUB} level. 
* 
* @param message the message object to log. 
*/ 
public void stub(final String message) { 
    logger.logIfEnabled(FQCN, STUB, null, message, (Throwable) null); 
} 


/** 
* Example: Adapt with custom formatting. 
* Here DEBUG level is used just as an example. 
* 
* @param name 
* @param value 
*/ 
public void echo(final String name, Object value) { 
    Message m = new FormattedMessage("echo: %s(%s)",name,value); 
    logger.logIfEnabled(FQCN, Level.DEBUG, null, m, (Throwable) null); 
} 
... 
} 

Poi in una classe cliente sarà ora log "per conto" di quel cliente in modo corretto tramite metodi di supporto del registratore, in questo caso la formattazione esempio eco (nome, valore):

public class TestLog4j { 

private static final ExtLogger extLogger = ExtLogger.create(TestLog4j.class); 

public static void elseWhere() { 
    extLogger.echo("aVariableName", 4); 
} 

public static void main(String[] args) { 
     extLogger.echo("aStringVariableName","from main"); 
     elseWhere(); 
} 
} 

PatternLayout Semplice:

<PatternLayout pattern=" %-5level [%C{1}::%M(%L)] %logger{36} - %msg%n"/> 

uscita:

DEBUG [TestLog4j::main(63)] testlogging.TestLog4j - echo: aStringVariableName(from main) 
DEBUG [TestLog4j::elseWhere(42)] testlogging.TestLog4j - echo: aVariableName(4) 

Una volta che hai il blocco di utilizzare logger.logIfEnabled (FQCN, ...) con la FQCN (che Log4J ricerche per la traccia dello stack) potresti voler cancellare o commentare i metodi di stub (..) e il livello di STUB se non usi un livello addizionale.

0

Se si sta costruendo un nuovo sistema, attenersi alla risposta di Webel.

Se si dispone di un sistema esistente durante la migrazione a log4j2, è comunque consigliabile eseguire i metodi di generazione (ma includo una classe di lavoro minima di seguito) ed è possibile aggiungere questa funzione che fornisce il vecchio 1.2 callerFQCN modo di fare le cose (o quasi):

public void log(Class ignoreClassFQCN, Level level, Marker marker, String msg, Throwable throwable){  
    logger.logIfEnabled(ignoreClassFQCN.getName(), level, marker, msg, throwable); 
} 

Poi, dalle vostre esistenti classi log-avvolgimento, si può fare qualcosa di simile:

// inside ThisClass.java, denoting an old logger such as one that used log4j 1.2 with the callerFQCN parameter, or just an old logger that's naive and custom built. 
private static final MyLog4j2WrapperClass newLogger = MyLog4j2WrapperClass.create(); 

public static void debug(String message) { 
    // basic example 
    newLogger.log(ThisClass.class, Level.DEBUG, null, message, null); 
} 

public static void logFailure(String message) { 
    // example of using a custom log level 
    newLogger.log(ThisClass.class, MyLog4j2WrapperClass.FAILURE, null, message, null); 
} 

mi è capitato di eliminare un gruppo di altre funzioni generate che non sto utilizzando, dal momento che avevo pianificato di realizzare un semplice shim per un sistema di registrazione mal progettato (personalizzato). Ho eliminato un sacco di metodi create() che non avevo intenzione di usare. Così qui è una classe operaia (le parti vale la pena condividere):

public final class MyLog4j2WrapperClass extends ExtendedLoggerWrapper { 
    private static final long serialVersionUID = 1L; 
    private final ExtendedLoggerWrapper logger; 

    private static final String FQCN = MyLog4j2WrapperClass.class.getName(); 
    public static final Level FAILURE = Level.forName("FAILURE", 150); 

    public void log(Class ignoreClass, Level level, Marker marker, String msg, Throwable throwable){ 
     logger.logIfEnabled(ignoreClass.getName(), level, marker, msg, throwable); 
    } 

    private MyLog4j2WrapperClass(final Logger logger) { 
     super((AbstractLogger) logger, logger.getName(), logger.getMessageFactory()); 
     this.logger = this; 
    } 

    /** 
    * Returns a custom Logger with the name of the calling class. 
    * 
    * @return The custom Logger for the calling class. 
    */ 
    public static MyLog4j2WrapperClass create() { 
     final Logger wrapped = LogManager.getLogger(); 
     return new MyLog4j2WrapperClass(wrapped); 
    } 

Vorrei sottolineare che considero questo uno spessore - è qualcosa di farti da parte, ma vi consiglio vivamente di continuare ad allontanarsi dalla vecchia sistema di registrazione una volta che hai lo shim in atto. Ciò ti consentirà di eseguire più modifiche incrementali del codice senza dover eseguire immediatamente una migrazione completa.

Problemi correlati