[英]Java Logger usage
我使用java.util.logging
為我的項目制作了一個自定義記錄器:
public class SpotifyLogger {
private static final Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
public SpotifyLogger(String loggerFilePath) throws IOException {
Logger myLogger = Logger.getLogger("");
// suppress console messaging
Handler[] handlers = myLogger.getHandlers();
if (handlers[0] instanceof ConsoleHandler) { //exception occurs here
myLogger.removeHandler(handlers[0]);
}
// set level
LOGGER.setLevel(Level.SEVERE);
// create a txt handler
FileHandler textFileHandler = new FileHandler(loggerFilePath);
SimpleFormatter simpleFormatter = new SimpleFormatter();
textFileHandler.setFormatter(simpleFormatter);
LOGGER.addHandler(textFileHandler);
}
public void log(String user, Exception e) {
LOGGER.log(Level.SEVERE, user, e);
}
}
對於程序的客戶端和服務器部分,我創建了兩個單獨的 Logger 對象:
// class member initialized as null, because of exception handling
private SpotifyLogger logger = null;
//...
//in constructor:
this.logger = new SpotifyLogger(LOGGER_FILE_NAME); // the LOGGER_FILE_NAME is different for the client and the server
當我手動測試我的程序時,記錄器似乎可以工作(兩個日志文件包含我造成的異常)。 然后,我編寫了自動測試。 對於我正在測試的每個 class(總共 5 個),我創建了一個具有不同目標路徑的單獨記錄器 object。 測試(以先出現的 class 為准)工作正常。 所有其他測試都失敗了,因為當我為那個特定的 class 初始化記錄器時,我得到了一個ArrayIndexOutOfBoundsException
。原因是我試圖訪問handlers[0]
,當handlers
的長度為 0 時。 根據我搜索 web 后的理解,這是因為記錄器正在使用父處理程序。 我試過這個:
public SpotifyLogger(String loggerFilePath) throws IOException {
Logger myLogger = Logger.getLogger("");
// suppress console messaging
myLogger.setUseParentHandlers(false);
Handler[] handlers = myLogger.getHandlers();
if (handlers.length > 0) {
if (handlers[0] instanceof ConsoleHandler) {
myLogger.removeHandler(handlers[0]);
}
}
//etc
}
我不再有異常,但日志記錄不起作用。 我究竟做錯了什么?
如果您想要不同的Logger
,則需要為每個提供不同的名稱。 因此,您的這一行代碼(在SpotifyLogger
構造函數中)始終返回相同的Logger
。
Logger myLogger = Logger.getLogger("");
這實際上返回java.util.logging.LogManager.RootLogger
,它有一個Handler
,它是ConsoleLogger
的一個實例。 隨后,您在第一次調用SpotifyLogger
構造函數時刪除了該Handler
程序,因此在每次后續調用中,方法getHandlers
返回一個空數組。
由於您只將Handler
添加到全局Logger
,因此每次調用SpotifyLogger
構造函數時都會將另一個FileHandler
添加到全局記錄器。 我尚未驗證,但我相信Logger
將使用方法getHandlers
返回的數組中的第一個適當的Handler
程序,因此您看到的行為是僅寫入第一個日志文件,即您傳遞給的文件第一次調用SpotifyLogger
構造函數。
請注意,您沒有提供可重現的示例,因此我無法根據您的上下文驗證上述任何內容。 我只測試了您問題中的代碼以達到上述目的。
考慮以下對 class SpotifyLogger
的重寫——包括僅用於測試目的的main
方法。
import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
public class SpotifyLogger {
private static final String[] NAMES = {"First", "Second"};
private static int count;
private int index;
public SpotifyLogger(String loggerFilePath) throws IOException {
index = count;
Logger myLogger = Logger.getLogger(NAMES[count++]);
myLogger.setUseParentHandlers(false);
// set level
myLogger.setLevel(Level.SEVERE);
// create a txt handler
FileHandler textFileHandler = new FileHandler(loggerFilePath);
SimpleFormatter simpleFormatter = new SimpleFormatter();
textFileHandler.setFormatter(simpleFormatter);
myLogger.addHandler(textFileHandler);
}
public void log(String user, Exception e) {
Logger myLogger = Logger.getLogger(NAMES[index]);
myLogger.log(Level.SEVERE, user, e);
}
public static void main(String[] args) {
try {
SpotifyLogger x = new SpotifyLogger("spotifyx.log");
SpotifyLogger y = new SpotifyLogger("spotifyy.log");
x.log("George", new Exception());
y.log("Martha", new RuntimeException());
}
catch (IOException x) {
x.printStackTrace();
}
}
}
請注意,關於父Handler
s,您是正確的,因此上面代碼中的以下行:
myLogger.setUseParentHandlers(false);
運行上述代碼后,文件spotifyx.log的內容為:
Feb 12, 2022 2:12:28 PM javalogp.SpotifyLogger log
SEVERE: George
java.lang.Exception
at javalogp/javalogp.SpotifyLogger.main(SpotifyLogger.java:38)
文件spotifyy.log的內容是:
Feb 12, 2022 2:12:28 PM javalogp.SpotifyLogger log
SEVERE: Martha
java.lang.RuntimeException
at javalogp/javalogp.SpotifyLogger.main(SpotifyLogger.java:39)
並且沒有日志消息寫入控制台。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.