自定义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的风险。具体修复如下:
- 修复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() ); } });
删除多余的方法重写
父类Logger已经实现了warning、severe、info等方法,你的重写完全多余,还可能破坏原有流程,直接删除这些重写代码。避免重复添加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); }
- 关闭父类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
相关产品推荐
相关产品推荐

