我总是想知道是否可以在pr线程级别上以编程方式设置java.util.logging的日志级别。
用例是在Web服务器中。如果我的代码检测到某个用户的错误级别异常,我想为该客户启用跟踪日志记录。
我正在考虑使用servletfilter执行此操作,并将其绑定到其会话ID。但据我所知,我可以在appender上设置的日志级别不是线程仿射。即如果我将根级别设置为FINE,它将影响系统中的所有线程,并且日志将填满其他200个同步用户流量。当然,我之后可以过滤日志,但无论如何都会出现性能损失。
有没有人有这方面的经验?
答案 0 :(得分:1)
我总是想知道是否可以在pr线程级别上以编程方式设置java.util.logging的日志级别。
创建log filter以捕获用户上下文并将过滤对象的级别设置为ALL:
public class UserFilter implements Filter {
private final Level lvl;
private final Object userContext;
public UserFilter(Level originalLevel, Object userContext) {
this.lvl = originalLevel;
this.userContext = userContext;
}
@Override
public boolean isLoggable(LogRecord record) {
if (!belongsTo(record, userContext)) {
int levelValue = this.lvl.intValue();
if (record.getLevel().intValue() < levelValue
|| levelValue == Level.OFF.intValue()) {
return false;
}
}
return true;
}
private boolean belongsTo(LogRecord record) {
/**
* Insert logic here.
*/
//return ((Integer) this.userContext) == record.getThreadId();
return true;
}
}
对于您的用例,您应该能够创建一个servlet过滤器:
答案 1 :(得分:0)
好吧,你应该总是能够直接调用log(level, message);
并通过使用一些线程本地映射来获得实际级别。
您也可以编写一些包装器来处理这个问题,例如:
public void debugExceptCritical(Logger l, String message) {
//critical would be your per-thread flag,
//just make sure to reset it when it is no longer used, e.g. in a servlet filter
l.log( critical ? ERROR : DEBUG, message );
}
或者你可以尝试获取调用它的类(我在某个地方做了但不记得细节,所以我必须查找它)并使用此信息来获取方法内的记录器。
查询来电者:
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
for( StackTraceElement elem : stackTrace ) {
//look for the debugExceptCritical method or maybe just the class it contains
//if found take the class name of the next element to look up the correct logger
}
另一种方法是,根据您实际使用的日志框架,可能会挂钩一些每线程过滤器/ appender /其中的任何内容。在Log4J中,我要么尝试添加自己的appender,然后检查critical
标志并更改日志事件的级别,或者始终记录关键操作,并使用每线程过滤器,当{{1}时拒绝这些日志事件没有设置标志。