我想在某个阈值后记录我的应用程序的消息。在10条消息后说。我读了关于内存处理程序并使用它。但是我发现它会立即记录消息而不是像文档中所说的那样缓冲它们。这是代码
Handler h = new FileHandler('/var/tmp/process.log',Level.INFO);
Handler h2 = new MemoryHandler(h, 10, Level.ALL);
logger.addHandler(h2);
for(int i=0; i<10; i++) {
logger.log(Level.INFO, "Sample message");
Thread.sleep(1000);
}
此代码即时添加上述消息。我错过了什么?我的目的是不要让太多的磁盘I / O发生。请帮忙
答案 0 :(得分:2)
中的第三个构造函数参数
Handler h2 = new MemoryHandler(h, 10, Level.ALL);
定义推送级别,即如果记录了给定级别或更高级别的消息,则MemoryHandler会将其推送到配置的下游处理程序(jdk documentation)。
我不认为,MemoryHandler适合您想达到的目的。您可以使用固定大小的缓冲区创建自己的MemoryHandler实现,只要缓冲区已满,就会刷新。但请考虑这种方法的缺点:当应用程序终止时,日志消息可能会丢失,刷新可能涉及阻塞I / O,并且您无法确定哪个线程必须执行该I / O.
或者,您可以考虑使用另一个经过验证的日志记录框架,例如logback或log4j2。这些通常提供更高级的功能。我建议寻找异步日志记录。
答案 1 :(得分:2)
您必须扩展MemoryHandler以提供自定义推送行为。您可以通过将推送级别设置为ALL
来覆盖推送方法或将推送级别设置为OFF
,然后从push方法手动发出publish来执行此操作。
如果您只想在看到许多日志记录后开始记录,那么您需要创建类似的内容:
public class PopoffHandler extends MemoryHandler {
private long count;
private final long size;
public PopoffHandler(Handler target, int size) {
super(target, size, Level.ALL);
this.size = size;
}
@Override
public synchronized void push() {
if (count == size) {
super.push();
} else {
++count;
}
}
@Override
public void setPushLevel(Level newLevel) {
if (newLevel == null) {
throw new NullPointerException();
}
super.setPushLevel(Level.ALL);
}
}
如果要在组中记录记录,则需要执行以下操作:
public class ChunkedHandler extends MemoryHandler {
private long count;
private final long size;
public ChunkedHandler(Handler target, int size) {
super(target, size, Level.OFF);
this.size = size;
}
@Override
public synchronized void publish(LogRecord record) {
super.publish(record);
if (++count % size == 0L) {
super.push();
}
}
@Override
public void setPushLevel(Level newLevel) {
if (newLevel == null) {
throw new NullPointerException();
}
super.setPushLevel(Level.OFF);
}
}