2016-02-12 4 views
5

Die folgenden 3 Posts bieten Antworten zur Verwendung eines Zwischenprotokollierungshilfeprogramms und zum Abrufen der zugrunde liegenden Protokollfunktion aus dem Verfahren von einem Client zu, dass die Protokollierung Helfer (und nicht die Protokollierungshilfsmethode als Quelle Reporting):Java-Protokollierung: Log4j Version2.x: zeigt die Methode eines Endclient-Aufrufers an (keine Zwischenprotokollierungs-Hilfsmethode)

Aber die scheinen nur Antworten zu bieten für Log4j 1.2, die heute nicht mehr existierenden bietet:

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

Es scheint nicht für Logger in the log4J 2.5 API ein offensichtliches Äquivalent zu sein.

Kann jemand eine Antwort anbieten, die mit der direkten Verwendung von Log4J 2.x kompatibel ist?

Antwort

3

Für Log4j2 wird die Antwort vollständig durch die Verwendung von Logger-Wrappern bereitgestellt, wie im Log4j2-Handbuch unter Example Usage of a Generated Logger Wrapper beschrieben. Man kann einfach (unter Verwendung der dort dargestellten org.apache.logging.log4j.core.tools.Generate $ ExtendedLogger-Tools) einen Logger-Wrapper mit einer einzelnen STUB-Ebene generieren und diesen dann anpassen, um benutzerdefinierte Protokollierungsmethoden zu erstellen, die die Verwendung von logIfEnabled nachahmen (FQCN, LEVEL, Marker, Nachricht, Throwable) - möglicherweise ignorieren die STUB-Ebene und die regulären verwenden - dann, wenn gewünscht, löschen und kommentieren die STUB-Ebene und ihre Methoden. Zu diesem Zweck kann die FormatierteMessage hilfreich sein.

Beispiel:

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

dann die generierte Klasse anpassen (die meisten Unterstützung Methoden weggelassen):

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

Dann in einer Client-Klasse wird nun log sie "im Namen" des Client korrekt über die Hilfsmethoden des Loggers, in diesem Fall das Formatierungsbeispiel echo (Name, Wert):

Einfache Pattern:

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

Ausgang:

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

Sobald Sie den Dreh mit logger.logIfEnabled (FQCN, ...) hat mit dem FQCN (die Suche nach in dem Stack-Trace LOG4J) Vielleicht möchten Sie die stub (..) Methoden und STUB Ebene löschen oder auskommentieren, wenn Sie keine zusätzliche Ebene verwenden.

0

Wenn Sie ein neues System erstellen, bleiben Sie bei Webels Antwort.

Wenn Sie ein vorhandenes System haben, das Sie zu log4j2 migrieren, sollten Sie wahrscheinlich noch die generate-Methoden ausführen (aber ich schließe eine minimale Arbeitsklasse ein), und Sie können diese Funktion hinzufügen, die die alte 1 bietet.2 callerFQCN Art und Weise Dinge (Art) zu tun:

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

Dann aus Ihrem bestehenden Log-Wrapping-Klassen, können Sie etwas tun:

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

Ich war zufällig ein Bündel löschen von anderen generierten Funktionen verwende ich nicht, da ich plante, eine einfache Shim für ein schlecht entworfenes (benutzerdefiniertes) Logging-System zu machen. Ich habe einige create() Methoden gelöscht, die ich nicht verwenden wollte. Also hier ist eine Arbeiterklasse (die Teile im Wert von Sharing):

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

Ich sollte anmerken, dass ich dies berücksichtigen eine Beilage - es ist etwas zu Ihnen durch, aber ich würde weiterhin dringend empfohlen, von der alten wegzubewegen Logging-System, sobald Sie die Shim an Ort und Stelle haben. Auf diese Weise können Sie mehr inkrementelle Codeänderungen durchführen, ohne sofort eine vollständige Migration durchführen zu müssen.