簡體   English   中英

使用log4j包裝器在日志語句中打印“source”類

[英]Printing the “source” class in a log statement with a log4j wrapper

我的應用程序有一個自制日志記錄類,我正在遷移到使用log4j。 但是,由於我使用自制程序類將應用程序的其余日志語句傳遞給log4j,因此輸出語句將記錄為來自包裝類而不是源類。

除了為每個日志語句創建新的org.apache.log4j.Logger實例之外,還有辦法確保顯示“正確”的源嗎? 我也嘗試過使用Logger.log(String callerFQCN,Priority level,Object message,Throwable t)方法,但它似乎不起作用,例如:

public class Logger2 {

    public static org.apache.log4j.Logger log4JLogger = org.apache.log4j.Logger.getLogger(Logger2.class);

    public static void warning(Object source, String message) {

        log(source, message, Level.WARN, null)
    }

    private static void log(Object source, String message, Level level, Throwable t) {

        String className = source.getClass().getName();
        System.out.println("Logging class should be " + className);
        log4JLogger.log(className, loggingLevel, message, t);
    }
}

被召喚時:

public void testWarning() {
    Logger2.warning(new Integer(3), "This should warn");
}

打印:

Logging class should be java.lang.Integer
2010-05-25 10:49:57,152 WARN                              test.Logger2 - This should warn

我的自制日志記錄解決方案使用log4j的LocationInfo類來查找源代碼信息。

使用此解決方案, locationInfo對象包含來自使用loggerName調用記錄器的對象的信息。

這是我使用log4j記錄的記錄器的簡化版本:

public void log(Level level, String message) {
    LocationInfo locationInfo = new LocationInfo(new Throwable(),
            loggerName);

    MDC.put(LINE_NUMBER, locationInfo.getLineNumber());
    MDC.put(FILE_NAME, locationInfo.getFileName());
    MDC.put(CLASS_NAME, locationInfo.getClassName());
    MDC.put(METHOD_NAME, locationInfo.getMethodName());
    MDC.put(FQMETHOD_NAME, locationInfo.getClassName() + "."
            + locationInfo.getMethodName());

    logger.log(level, message);

    MDC.remove(LINE_NUMBER);
    MDC.remove(FILE_NAME);
    MDC.remove(CLASS_NAME);
    MDC.remove(METHOD_NAME);
    MDC.remove(FQMETHOD_NAME);
}

順便說一下: LevelMDCLogger類都是log4j類。

對評論的回復:

MDC對象存儲在ThreadLocal對象中,可供log4j記錄器訪問。

從MDC Java文檔:

MDC基於每個線程進行管理。

這應該這樣做:

class Logger2 {

  Logger _log4JLogger;

  public void log(Object msg) {
    _log4JLogger.log(Logger2.class.getName(), Priority.INFO, msg, null);
  }

}

在關於Logger.log的Log4J API中(String callerFQCN,優先級,對象消息,Throwable t):

參數:

  • callerFQCN - 包裝類的完全限定類名。
  • level - 日志記錄請求的級別。
  • message - 日志記錄請求的消息。
  • t - 日志記錄請求的throwable可能為null。

請參閱: Log4J API

我知道很奇怪,參數被稱為“callerFQCN”,它接近調用者對象類,但是(muajaja!)它實際上是“包裝器”類(來自MyClass.class.getName())。

實際上,我認為調用者是通過Throwable論證獲得的。 不確定,還沒有檢查實現。

當你離開Throwable參數為null時,我認為必須在下面發生這樣的事情:

StackTraceElement[] stack = (new Throwable()).getStackTrace();
String caller = stack[something, meaby 1].getClassName();

如果要創建Logger包裝器,則需要執行以下操作:

public static void myWarn(String message) {
    myLogger.log(MyWrapper.class.getName(), message, Level.WARN, null);
}

這項工作沒有問題作為包裝。

或者,如果您絕對需要維護下面顯示的界面,請執行以下操作:

// Warning: Pseudocode
public static void myWarn(Object source, String message) {
    String sourceClass = source.class.GetName();
    StackTraceElement[] stack = (new Throwable()).getStackTrace();
    stack[1, or meaby 2... or 0?] = new whatever(sourceClass);
    myLogger.log(MyWrapper.class.getName(), message, Level.WARN, myStack);
}

希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM