簡體   English   中英

Java 記錄器使用

[英]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 myLogger = Logger.getLogger("")

參考: Oracle java文檔

如果您想要不同的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.

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