You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义GameLogger日志异常:所有日志均被标记为WARN

问题:自定义Java Logger所有日志级别显示为WARN

我实现了一个继承自java.util.logging.Logger的GameLogger类,代码如下:

package me.retamrovec.thebridge.game;

import org.jetbrains.annotations.NotNull;

import java.util.logging.*;

public class GameLogger extends Logger {

    String prefix;

    public GameLogger(@NotNull Game game) {
        super(getAnonymousLogger().getName(), null);
        prefix = "[TheBridge-GameLogger-" + game.getUniqueId() + "] ";
        Handler handler = new ConsoleHandler();
        handler.setLevel(Level.ALL);
        handler.setFormatter(new SimpleFormatter() {
            private static final String format = "%1$s %n";

            @Override
            public String format(LogRecord record) {
                return String.format(format,
                        record.getMessage()
                        );
            }
        });

        addHandler(handler);
        setLevel(Level.ALL);
    }

    @Override
    public void log(@NotNull LogRecord logRecord) {
        logRecord.setMessage(prefix + logRecord.getMessage());
        super.log(logRecord);
    }

    @Override
    public void warning(String message) {
        log(Level.WARNING, message);
    }

    @Override
    public void severe(String message) {
        log(Level.SEVERE, message);
    }

    @Override
    public void info(String message) {
        log(Level.INFO, message);
    }
}

随后调用以下代码输出不同级别的日志:

gameLogger.info(". Hey! This is " + tick + "/20 game tick.");
gameLogger.fine(".. Hey! This is " + tick + "/20 game tick.");
gameLogger.severe("... Hey! This is " + tick + "/20 game tick.");
gameLogger.warning(".... Hey! This is " + tick + "/20 game tick.");
gameLogger.finest("..... Hey! This is " + tick + "/20 game tick.");
gameLogger.finer("...... Hey! This is " + tick + "/20 game tick.");

问题:所有日志(包括info、fine、severe等级别)均被标记为WARN,但调试时LogRecord的级别显示正确。调用GameLogger#log(Level, String)方法后问题依旧。


解决方案

核心问题有两个:自定义Formatter未输出日志级别,导致误判;多余的方法重写可能干扰父类日志流程,同时存在重复添加Handler的风险。具体修复如下:

  1. 修复Formatter,显示实际日志级别
    你的Formatter只输出了消息内容,看不到级别信息,才会误以为所有日志都是WARN。修改Formatter,加入时间、级别字段:
handler.setFormatter(new SimpleFormatter() {
    private static final String format = "%1$tF %1$tT %2$s %3$s %n";

    @Override
    public String format(LogRecord record) {
        return String.format(format,
                new Date(record.getMillis()),
                record.getLevel().getName(),
                prefix + record.getMessage()
        );
    }
});
  1. 删除多余的方法重写
    父类Logger已经实现了warning、severe、info等方法,你的重写完全多余,还可能破坏原有流程,直接删除这些重写代码。

  2. 避免重复添加Handler
    每次创建GameLogger都新建ConsoleHandler会导致日志重复输出,改为复用已有Handler:

// 获取或创建ConsoleHandler,避免重复添加
ConsoleHandler handler = null;
for (Handler h : getHandlers()) {
    if (h instanceof ConsoleHandler) {
        handler = (ConsoleHandler) h;
        break;
    }
}
if (handler == null) {
    handler = new ConsoleHandler();
    addHandler(handler);
}
  1. 关闭父类Handler复用
    设置setUseParentHandlers(false),避免父类默认Handler重复输出日志。

修复后的完整GameLogger代码:

package me.retamrovec.thebridge.game;

import org.jetbrains.annotations.NotNull;

import java.util.Date;
import java.util.logging.*;

public class GameLogger extends Logger {

    private final String prefix;

    public GameLogger(@NotNull Game game) {
        super("GameLogger-" + game.getUniqueId(), null);
        prefix = "[TheBridge-GameLogger-" + game.getUniqueId() + "] ";
        
        // 获取或创建ConsoleHandler,避免重复添加
        ConsoleHandler handler = null;
        for (Handler h : getHandlers()) {
            if (h instanceof ConsoleHandler) {
                handler = (ConsoleHandler) h;
                break;
            }
        }
        if (handler == null) {
            handler = new ConsoleHandler();
            addHandler(handler);
        }
        
        handler.setLevel(Level.ALL);
        handler.setFormatter(new SimpleFormatter() {
            private static final String format = "%1$tF %1$tT %2$s %3$s %n";

            @Override
            public String format(LogRecord record) {
                return String.format(format,
                        new Date(record.getMillis()),
                        record.getLevel().getName(),
                        prefix + record.getMessage()
                );
            }
        });

        setLevel(Level.ALL);
        // 关闭父类Handler,避免重复输出
        setUseParentHandlers(false);
    }

    @Override
    public void log(@NotNull LogRecord logRecord) {
        logRecord.setMessage(prefix + logRecord.getMessage());
        super.log(logRecord);
    }
}

内容的提问来源于stack exchange,提问作者Jakush

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 14:13:20