我希望我的记录器在每条消息上添加一个文本字符串作为前缀,因为我需要识别一个类的实例已记录消息。我怎么能做到这一点?
我不想记得在每个日志记录方法调用中添加前缀,所以我正在寻找一个更像是插件的解决方案。当然,记录器本身不再是静态的,否则就是正常情况。
我已经调查了Fomatter
和Handler
的使用情况,但未能解决这个特定用例的问题。 JUL几乎是为类级别的记录器设计的,而不是实例级记录器。也许我会以错误的方式解决这个问题?
想留在JUL。
答案 0 :(得分:1)
我已经研究过使用Fomatters和Handlers,但是还没能为这个特殊的用例破解坚果。 JUL几乎是为类级别的记录器设计的,而不是实例级记录器。也许我会以错误的方式解决这个问题?
JUL只包含两个格式化程序。 XMLFormatter包含记录器名称。 SimpleFormatter包含一个format属性,可以将其设置为包含记录器名称。这是一个测试程序,以确保您正确设置所有内容。
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)。
在您的申请中加入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()));
}
}
您只需在首次使用时修改记录器。