Java Log4j 配置 - 不同的日志到不同的文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23322602/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 21:53:53  来源:igfitidea点击:

Log4j config - different logs to different files

javalogginglog4j

提问by NickJ

This might be a very easy question for some, but personally I find Log4j config to be nightmarishly difficult and that learning to perform brain surgery might be less challenging.

对于某些人来说,这可能是一个非常简单的问题,但就我个人而言,我发现 Log4j 配置非常困难,而且学习进行脑部手术可能不那么具有挑战性。

I am trying to lave multiple loggers logging into different files. Here is what I have in my log4j.properties file:

我试图让多个记录器登录到不同的文件。这是我的 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

And here is my (very simple) Java app used to test the config:

这是我用于测试配置的(非常简单的)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");
}

I have 2 problems:

我有两个问题:

One problem I always get an exception in the line PropertyConfigurator.configure(resource);:

一个问题我总是在行中遇到异常PropertyConfigurator.configure(resource);

java.io.FileNotFoundException: /home/nick/logging (Is a directory)
 at java.io.FileOutputStream.open(Native Method)
 at java.io.FileOutputStream.<init>(FileOutputStream.java:212)
 at java.io.FileOutputStream.<init>(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)

The 2nd problem is that both messages are written to both logs. Here is the actualresult:

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

File admin:log:

文件管理员:日志:

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

File file.log:

文件file.log:

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

Here is the requiredresult:

这是所需的结果:

File admin:log:

文件管理员:日志:

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

File file.log:

文件file.log:

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

What is causing the exception, and how can I achieve the required result?

导致异常的原因是什么,我如何才能达到所需的结果?

回答by Braj

You don't need to load the properties file. Just place it inside the srcfolder that will automatically added in class path.

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

Sample code:

示例代码:

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");
}

回答by spopoff

First: log4j recommands to use xml format file for properties.

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

Second: its better to load the properties file in the classloader.

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

Third: there is inheritance in logger, but you can cut it with additivity property see log4j.properties file - multiple loggers in same class

第三:记录器中有继承,但您可以使用可加性属性对其进行切割,请参见log4j.properties 文件 - 同一类中的多个记录器

回答by NickJ

To answer my own question, this is what I needed:

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

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

回答by Ian Roberts

Log4J makes a distinction between loggers, which are responsible for generating log messages, and appenders, which are responsible for sending those messages somewhere (a file, the console, a database, etc.). Loggers form a hierarchy, the root logger is the parent of the logger named admin, which is the parent of admin.component1, etc., and you can attach appenders to any logger in the hierarchy. By default a logger will send messages to all appenders that are attached directly to it, or to any of its ancestors in the hierarchy (this is why loggers are conventionally named like Java classes, e.g. you can control logging for com.example.Class1and com.example.subpkg.AnotherClassby configuring the com.examplelogger).

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

Loggers and appenders form separate namespaces and this is the source of your confusion - the logger named adminand the appender named adminare two separate entities.

记录器和附加器形成单独的命名空间,这是您混淆的根源 - 记录器命名admin和附加器命名admin是两个独立的实体。

The configuration you have given in the question defines one logger (the root logger) which sends all the messages it generates to two separate appenders, one for each of the two files. Your code then requests two different loggersand generates one log message with each logger. Both these loggers inherit the appender configuration from the root logger, so they both send their messages to bothof the configured appenders.

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

enter image description here

在此处输入图片说明

Instead of attaching the two appenders to the root logger, you should attach the fileappender to the filelogger and the adminappender to the adminlogger:

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

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

This way the filelogger will send messages only to file.log, the adminlogger only to admin.log, and all messages from otherloggers will be silently discarded, as there are no appenders attached to the root.

这样file记录器将只发送消息到file.logadmin记录器只发送到admin.log,并且来自其他记录器的所有消息都将被静默丢弃,因为没有附加到根的附加程序。

enter image description here

在此处输入图片说明



The additivityflag is the exception to this rule - setting a logger's additivity to false essentially disconnects the arrow from a logger up to its parent, so messages generated by that logger (or flowing into it from one of its children) will not go any further up the tree, they will only go to appenders attached directlyto the logger in question.

加性标志是此规则的一个例外 - 将记录器的可加性设置为 false 基本上会断开从记录器到其父级的箭头,因此该记录器生成的消息(或从其子代之一流入)将不会再进一步在树上,它们只会转到直接附加到相关记录器的附加程序。