[英]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);
}
順便說一下: Level , MDC和Logger類都是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):
參數:
請參閱: 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.