Java log4j rootLogger 似乎继承了其他记录器的日志级别。为什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2453010/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
log4j rootLogger seems to inherit log level of other logger. Why?
提问by AndrewR
I've got a log4J setup in which the root logger is supposed to log ERROR level messages and above to the console and another logger logs everything to syslog.
我有一个 log4J 设置,其中根记录器应该将 ERROR 级别的消息和更高级别的消息记录到控制台,另一个记录器将所有内容记录到 syslog。
log4j.properties is:
log4j.properties 是:
# Root logger option
log4j.rootLogger=ERROR,R
log4j.appender.R=org.apache.log4j.ConsoleAppender
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d %p %t %c - %m%n
log4j.logger.SGSearch=DEBUG,SGSearch
log4j.appender.SGSearch=org.apache.log4j.net.SyslogAppender
log4j.appender.SGSearch.SyslogHost=localhost
log4j.appender.SGSearch.Facility=LOCAL6
log4j.appender.SGSearch.layout=org.apache.log4j.PatternLayout
log4j.appender.SGSearch.layout.ConversionPattern=[%-5p] %m%n
In code I do
在代码中我做
private static final Logger logger = Logger.getLogger("SGSearch");
.
.
.
logger.info("Commencing snapshot index [" + args[1] + " -> " + args[2] + "]");
What is happening is that I get the console logging for all logging levels. What seems to be happening is that the level for SGSearch overrides the level set for the root logger somehow. I can't figure it out.
发生的事情是我获得了所有日志记录级别的控制台日志记录。似乎正在发生的事情是 SGSearch 的级别以某种方式覆盖了为根记录器设置的级别。我想不通。
I have confirmed that Log4J is reading the properties file I think it is, and no other (via the -Dlog4j.debug
option)
我已经确认 Log4J 正在读取我认为是的属性文件,没有其他(通过-Dlog4j.debug
选项)
采纳答案by Adriaan Koster
The way Log4j chaining works is a bit counter intuitive (to me at least). See the log4j manual. If the request level is equal to or above the threshold of the most specific matching logger, it is accepted. Once the request is accepted, it gets handled by the complete chain of ancestors regardless of their thresholds!
Log4j 链接的工作方式有点反直觉(至少对我而言)。请参阅log4j 手册。如果请求级别等于或高于最具体的匹配记录器的阈值,则接受。一旦请求被接受,无论阈值如何,它都会由完整的祖先链处理!
To suppress the chaining behavior, add:
要抑制链接行为,请添加:
log4j.additivity.SGSearch=false
This will cause requests handled by logger SGSearch to no longer be passed up the chain.
这将导致记录器 SGSearch 处理的请求不再向上传递。
One other suggestion: don't name your logger and appender the same, because at some point in the future you, or a colleague will mix them up. The logger name should indicate which type of logging is handled, the appender name should specify where the logging goes. So in this case I would think 'SGSearch' could be the logger name, and the appender should be called something like 'LocalSysLog'.
另一个建议:不要将您的 logger 和 appender 命名为相同的名称,因为在未来的某个时候,您或您的同事会将它们混淆。记录器名称应指示处理哪种类型的日志记录,附加程序名称应指定日志记录的位置。所以在这种情况下,我认为“SGSearch”可能是记录器名称,而附加程序应该被称为“LocalSysLog”。
BTW: In my opinion you are doing the right thing by restricting the root logger with a high threshold, and lowering it for specific loggers. This avoids clutter from loud libraries (Apache has a few notorious ones).
顺便说一句:在我看来,您通过使用高阈值限制根记录器并降低特定记录器的阈值来做正确的事情。这避免了嘈杂的库造成的混乱(Apache 有一些臭名昭著的库)。
回答by Buhake Sindi
Quick information about Levels
有关级别的快速信息
Log4J Levels
Loggers may be assigned levels. The set of possible levels, that is DEBUG, INFO, WARN, ERROR and FATAL are defined in the org.apache.log4j.Level class.
If a given logger is not assigned a level, then it inherits one from its closest ancestor with an assigned level.
The root logger resides at the top of the logger hierarchy. It always exists and always has an assigned level.
Log4J 级别
记录器可以被分配级别。在 org.apache.log4j.Level 类中定义了一组可能的级别,即 DEBUG、INFO、WARN、ERROR 和 FATAL。
如果给定的 logger 没有被分配一个级别,那么它会从它最近的祖先那里继承一个级别。
根记录器位于记录器层次结构的顶部。它始终存在并且始终具有指定的级别。
I've changed your sample log4j configuration to work this way:
我已将您的示例 log4j 配置更改为以这种方式工作:
# Root logger option
log4j.rootLogger=ALL,R
log4j.appender.R=org.apache.log4j.ConsoleAppender
log4j.appender.R.Target=System.out
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d %p %t %c - %m%n
log4j.appender.R.Threshold=ERROR
log4j.appender.SGSearch=org.apache.log4j.net.SyslogAppender
log4j.appender.SGSearch.SyslogHost=localhost
log4j.appender.SGSearch.Facility=LOCAL6
log4j.appender.SGSearch.layout=org.apache.log4j.PatternLayout
log4j.appender.SGSearch.layout.ConversionPattern=[%-5p] %m%n
log4j.appender.SGSearch.Threshold=DEBUG
I hope this helps you.
我希望这可以帮助你。
回答by Michael
setting the threshold on a per-appender basis is key here:
在每个附加程序的基础上设置阈值是这里的关键:
log4j.appender.SGSearch.Threshold=DEBUG
log4j.appender.SGSearch.Threshold=DEBUG
and
和
log4j.appender.R.Threshold=ERROR
log4j.appender.R.Threshold=ERROR
this is a far better solution than the suggestion to disable "additivity" - the problem with that is that anything you want multipleappenders to handle will be defeated by it - so you cannot, for example, send anything which is an ERROR
level message to boththe console and syslog if you set additivity to false
...
这是一个比禁用“可加性”的建议更好的解决方案 - 问题在于您希望多个附加程序处理的任何内容都将被它击败 - 因此您不能,例如,向两者发送任何ERROR
级别消息如果您将可加性设置为...false