Log4j config – 不同的日志到不同的文件

对于一些人来说,这可能是一个非常简单的问题,但我个人认为Log4j配置是噩梦般困难,并且学习进行脑部手术可能不那么具有挑战性。

我正在尝试将多个记录器记录到不同的文件中。 这是我在log4j.properties文件中的内容:

# Root logger option log4j.rootLogger=INFO, file, admin # Direct log messages to a log file log4j.appender.file=org.apache.log4j.RollingFileAppender log4j.appender.file.File=/home/nick/logging/file.log log4j.appender.file.MaxFileSize=1MB log4j.appender.file.MaxBackupIndex=1 log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n log4j.appender.admin=org.apache.log4j.RollingFileAppender log4j.appender.admin.File=/home/nick/logging/admin.log log4j.appender.admin.MaxFileSize=1MB log4j.appender.admin.MaxBackupIndex=1 log4j.appender.admin.layout=org.apache.log4j.PatternLayout log4j.appender.admin.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n 

这是我用来测试配置的(非常简单的)Java应用程序:

 public static void main(String[] args) throws Exception { Properties resource = new Properties(); InputStream in = new FileInputStream("/home/nick/logging/log4j.properties"); resource.load(in); PropertyConfigurator.configure(resource); Logger admin = Logger.getLogger("admin"); Logger file = Logger.getLogger("file"); admin.info("hello admin"); file.info("hello file"); } 

我有两个问题:

一个问题我总是在PropertyConfigurator.configure(resource);遇到exceptionPropertyConfigurator.configure(resource);

 java.io.FileNotFoundException: /home/nick/logging (Is a directory) at java.io.FileOutputStream.open(Native Method) at java.io.FileOutputStream.(FileOutputStream.java:212) at java.io.FileOutputStream.(FileOutputStream.java:136) at org.apache.log4j.FileAppender.setFile(FileAppender.java:289) at org.apache.log4j.RollingFileAppender.setFile(RollingFileAppender.java:167) at org.apache.log4j.FileAppender.activateOptions(FileAppender.java:163) at org.apache.log4j.config.PropertySetter.activate(PropertySetter.java:256) 

第二个问题是两个消息都写入两个日志。 这是实际结果:

文件管理员:日志:

 2014-04-27 11:55:30 INFO admin - hello admin 2014-04-27 11:55:30 INFO file - hello file 

文件file.log:

 2014-04-27 11:55:30 INFO admin - hello admin 2014-04-27 11:55:30 INFO file - hello file 

这是必需的结果:

文件管理员:日志:

 2014-04-27 11:55:30 INFO admin - hello admin 

文件file.log:

 2014-04-27 11:55:30 INFO file - hello file 

导致exception的原因是什么,我如何才能达到要求的结果?

Log4J区分了负责生成日志消息的记录器和负责在某处(文件,控制台,数据库等)发送这些消息的appender 。 记录器形成层次结构,根记录器是名为admin的记录器的父级,它是admin.component1的父级等,您可以将appender附加到层次结构中的任何记录器。 默认情况下,记录器会将消息发送到直接连接到它的所有appender,或者发送给层次结构中的任何祖先(这就是为什么logger通常被命名为Java类,例如你可以控制com.example.Class1com.example.subpkg.AnotherClass通过配置com.example记录器)。

记录器和追加器形成单独的命名空间,这是您混淆的原因 – 名为admin的记录器和名为admin的appender是两个独立的实体。

您在问题中给出的配置定义了一个记录器(根记录器),它将它生成的所有消息发送到两个独立的appender ,每个appender对应两个文件。 然后,您的代码会请求两个不同的记录器,并为每个记录器生成一条日志消息。 这两个记录器都从根记录器inheritanceappender配置,因此它们都将消息发送到两个配置的appender。

在此处输入图像描述

您应该将file appender附加到file记录器,将admin appender附加到admin记录器,而不是将两个appender附加到根记录器:

 log4j.rootLogger=INFO log4j.logger.file=INFO, file log4j.logger.admin=INFO, admin 

这样, file记录器将仅向admin.log发送消息, admin记录器仅发送到admin.log ,并且将以静默方式丢弃来自其他记录器的所有消息,因为没有附加到根的appender。

在此处输入图像描述


additivity标志是此规则的例外 – 将记录器的可加性设置为false实际上将箭头从记录器断开连接到其父记录,因此该记录器生成的消息(或从其子节点流入它的消息)将不再进一步在树上,他们只会直接连接到有问题的记录器。

要回答我自己的问题,这就是我需要的:

 log4j.logger.file=DEBUG, fileAppender log4j.logger.admin=DEBUG, adminAppender log4j.additivity.file=false log4j.additivity.admin=false log4j.appender.fileAppender=org.apache.log4j.RollingFileAppender log4j.appender.fileAppender.File=/home/nick/logging/file.log log4j.appender.fileAppender.MaxFileSize=1MB log4j.appender.fileAppender.MaxBackupIndex=1 log4j.appender.fileAppender.layout=org.apache.log4j.PatternLayout log4j.appender.fileAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n log4j.appender.adminAppender=org.apache.log4j.RollingFileAppender log4j.appender.adminAppender.File=/home/nick/logging/admin.log log4j.appender.adminAppender.MaxFileSize=1MB log4j.appender.adminAppender.MaxBackupIndex=1 log4j.appender.adminAppender.layout=org.apache.log4j.PatternLayout log4j.appender.adminAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n 

您不需要加载属性文件。 只需将其放在src文件夹中,该文件夹将自动添加到类路径中。

示例代码:

 public static void main(String[] args) throws Exception { Logger admin = Logger.getLogger("admin"); Logger file = Logger.getLogger("file"); admin.info("hello admin"); file.info("hello file"); } 

第一:log4j建议使用xml格式文件作为属性。

第二:最好在类加载器中加载属性文件。

第三:在logger中有inheritance,但你可以用additive属性来删除它看到log4j.properties文件 – 同一个类中的多个记录器