如何在log4j.xml的appender中使用动态文件名

24

我正在使用log4j来记录信息。我使用了一个log4j.xml文件来创建日志文件。我已将每个日志文件的绝对路径作为param标签的值提供。

例如:

<appender name="FA" class="org.apache.log4j.DailyRollingFileAppender">
  <param name="DatePattern" value="'_'yyyyMMdd"/>
  <param name="File" value="D:/logFiles/GPreprocessor.log"/>
  <layout class="com.dnb.genericpreprocessor.common.log.AppXMLLayout"/>
</appender>

我不想直接写"GPreprocessor.log"。事实上,该文件名是动态的,基于我的项目名称。例如,如果我运行程序ABC.java,则日志记录应该存储到D:/logFiles/ABC.log,但如果我运行XYZ.java,则日志记录应该存储到D:/logFiles/XYZ.log。该文件的位置始终保持不变:D:/logFiles/。如何动态更改日志文件的名称?

6个回答

81

以下操作更加容易:

在log4j.xml中将变量定义为${variable}:

<appender name="FILE" class="org.apache.log4j.FileAppender">    
    <param name="File" value="${logfilename}.log" />
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d::[%t]::%-5p::%c::%x - %m%n" />
    </layout>       
</appender>

然后,请确保在启动JVM时设置系统属性,例如:

java -Dlogfilename=my_fancy_filename  example.Application

这将创建一个动态的日志文件名: my_fancy_filename.log

作为替代,您可以在代码中设置系统属性,只要在创建记录器之前进行设置(如果您想要在日志中包含您的PID,这很有用)。例如:

System.setProperty("logfilename", "a_cool_logname");

设置好之后,您可以像平常一样获取日志记录器,它们将记录到动态文件中(请注意那些在主方法执行之前创建记录器的静态记录器)。


1
如果我在.properties文件中提供值,它会支持/接受吗?也就是说,我可以在JVM启动时定义值,还是可以在.properties文件中定义它? - SuRa
如果你使用了 System.setProperty("logfilename", "a_cool_logname");,请确保在日志记录之前设置这个。 - James
6
如果您正在使用log4j2,我认为您需要在XML中使用${sys: logfilename} - automaton
我们可以在文件名中同时给出路径吗,例如“D:/Test/my_fancy_filename”,这样它就可以在指定的目录中创建my_fancy_filename.log文件了吗? - manikanta nvsr

10
以下是我使用Log4J动态生成文件名的代码。 它根据输入文件名和当前日期时间更改其名称。(这对于多次运行同一文件非常有帮助。)
public class LogClass {

    private static Logger log =  Logger.getLogger(LogClass.class);
    private static boolean initializationFlag = false;
    private static String fileName;

    private static void intializeLogger(){
        log.setLevel(Level.DEBUG);

        DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
        Date date = new Date();

        RollingFileAppender appender = new RollingFileAppender();
        appender.setAppend(true);
        appender.setMaxFileSize("1MB");
        appender.setMaxBackupIndex(1);
        appender.setFile(fileName + "_" + dateFormat.format(date) + ".log");
        appender.activateOptions();

        PatternLayout layOut = new PatternLayout();
        layOut.setConversionPattern("%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n");
        appender.setLayout(layOut);

        log.addAppender(appender);
    }

    public static Logger getLogger(){
        if(initializationFlag == false){
            intializeLogger();
            initializationFlag = true;
            return LogClass.log;
        }
        else{
            return LogClass.log;
        }
    }

    public static void setFileName(String fileName){
        LogClass.fileName = fileName;
    }
}

现在,无论何时你想在程序中使用记录器,只需要写下这两行代码:

LogClass.setFileName(yourFileName);
LogClass.getLogger().debug("hello!!");

愉快的编码。


4

最好是通过扩展FileAppender来实现自定义类,覆盖setOptions()方法。然后在你的log4j.properties文件中将根日志记录到yourpackage.yourFileAppender,这样更加简洁。


0

在执行任何操作之前,log4j会彻底检查类路径以获取log4j.xml配置文件。假设您在项目中引用的库JAR包中有任何log4j.xml配置文件,log4j将加载该文件作为配置文件并开始记录日志。在这种情况下,当您尝试通过从系统属性中获取值动态设置FileAppender中的日志文件位置时,它将无法工作,因为log4j已经加载了它发现的第一个配置文件。

为了防止这种情况发生,您可以使用DOMConfigurator来告知log4j应该加载哪个配置文件以及何时加载该文件。因此,只要您在程序中设置了LogFileLocation系统属性,请使用以下方式使用DOMConfigurator来加载预期的属性文件:

System.setProperty("LogFileLocation", "D:Test/Logdetails"));
DOMConfigurator.configure("log4j.xml");

通过这种方式,您将在设置系统属性LogFileLocation后加载log4j.xml文件。 (它还将覆盖已加载的配置)
在log4j.xml配置中,您可以在param标签“File”中设置文件位置:
<appender name="fileAppender"
        class="org.apache.log4j.FileAppender">
        <param name="File" value="${LogFileLocation}.log" />
        <param name="Append" value="false" /> 
<!-- false will make the log to override the file. true will make the log to append to the file -->
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern"
                value="%d{dd/MM/yyyy HH:mm:ss} %-5p %c{2} 
        - %m%n" />
        </layout>
    </appender>

为更好地理解我所说的内容,请在您的VM参数中提供-Dlog4j.debug=true,并在控制台中查看log4j执行日志。

0

对我而言,只有在使用如下的 ${sys: ... 之后才能正常工作。如果没有这个,它就无法获取在java命令中设置的变量。

<param name="File" value="${sys:logfilename}.log" />

0
在包含 main 方法的类中,将你的类名设置为一些系统属性。在下面的示例中,我使用了 log_dir 作为属性名称。
class ABC{
 public static void main(String s[]){
  System.setProperty("log_dir", ABC.class.getSimpleName());
 }
}

在你的 log4j.xml 文件中,使用 log_dir 属性作为 File 参数值属性。
<appender name="FA" class="org.apache.log4j.DailyRollingFileAppender">
  <param name="DatePattern" value="'_'yyyyMMdd"/>
  <param name="File" value="D:/logFiles/${log_dir}"/>
  <layout class="com.dnb.genericpreprocessor.common.log.AppXMLLayout"/>
</appender>

非常好用


你有log4j2的类似示例吗? - Abhi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接