我已经调查了 Fomatters 和 Handlers 的使用,但无法解决这个特定用例的问题。 JUL 几乎是为类级记录器设计的,而不是实例级记录器。也许我的做法是错误的?
JUL 仅包含两个格式化程序。 XMLFormatter 包括记录器名称。 SimpleFormatter 包含一个可以设置为包含记录器名称的格式属性。这是一个测试程序,可确保您已正确设置所有内容。
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
public class SimpleFormatTest {
public static void main(String[] args) throws Exception {
//final String format = "%1$ta %1$tb %1$td, %1$tY %1$tl:%1$tM:%1$tS.%1$tL %1$Tp %2$s%n%4$s: %5$s%n";
final String format = "%1$tc %2$s%n%3$s %4$s: %5$s%6$s%n";
final String key = "java.util.logging.SimpleFormatter.format";
test(format);
test(System.getProperty(key, format));
test(LogManager.getLogManager().getProperty(key));
}
private static void test(String format) {
if (format != null) {
System.out.println("============");
LogRecord record = new LogRecord(Level.INFO, "msg");
record.setLoggerName("logger.name");
record.setSourceClassName(SimpleFormatTest.class.getName());
record.setSourceMethodName("test");
System.out.println(String.format(format,
new java.util.Date(record.getMillis()),
record.getSourceClassName(),
record.getLoggerName(),
record.getLevel().getLocalizedName(),
record.getMessage(),
record.getThrown() == null ? "" : record.getThrown()));
System.out.println("============");
}
}
}
但我正在寻找一种在消息文本中包含前缀的解决方案。我不知道用户想要使用什么 Formatter,他可能会选择不记录记录器名称(相比之下,没有人会创建省略消息文本的 Formatter)。
在您的应用程序中包含logging.properties。您可以添加一个前提条件检查,使您的代码完全无法工作。这将迫使用户设置配置。
public class NoStart {
public static void main(String[] args) throws IOException {
String id = "logger.name";
LogRecord record = new LogRecord(Level.INFO, "msg");
record.setLoggerName(id);
File f = File.createTempFile("test", ".tmp");
try {
FileHandler fh = new FileHandler(f.getCanonicalPath(), false);
try {
Formatter fmt = fh.getFormatter();
String r = fmt.format(record);
if (!r.contains(id)) {
throw new IllegalStateException("Formatter must contain logger name.");
}
} finally {
fh.close();
}
} finally {
f.delete();
}
}
}
否则,您可以创建自定义过滤器来修改 LogRecord 消息。
public class PrefixMessageFilter implements Filter {
private final String instanceId;
private final Filter target;
public PrefixMessageFilter(final String instanceId, final Filter target) {
this.instanceId = instanceId;
this.target = target;
}
@Override
public boolean isLoggable(LogRecord record) {
record.setMessage(instanceId + ' ' + record.getMessage());
return target == null || target.isLoggable(record);
}
//Example code to setup filter.
private Logger logger = Logger.getLogger(toString());
{
logger.setFilter(new PrefixMessageFilter(toString(), logger.getFilter()));
}
}
您只需在首次使用时修改记录器。