简体   繁体   English

如何在 log4j.xml 的 appender 中给出动态文件名

[英]How to give dynamic file name in the appender in log4j.xml

I am using log4j to log information.我正在使用 log4j 来记录信息。 I have used a log4j.xml file for creating log files.我使用了log4j.xml文件来创建日志文件。 I have given the absolute path for each log file as a param tag value.我已将每个日志文件的绝对路径作为param标记值给出。

Eg:例如:

<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>

I do not want to write "GPreprocessor.log" directly.我不想直接写“GPreprocessor.log”。 Actually, that file name is dynamic, based on my project's name.实际上,该文件名是动态的,基于我的项目名称。 For example, if I run the program ABC.java, logging should go to D:/logFiles/ABC.log , but if I run XYZ.java, logging should go to D:/logFiles/XYZ.log .例如,如果我运行程序 ABC.java,日志记录应该 go 到D:/logFiles/ABC.log ,但是如果我运行 XYZ.java,日志记录应该 go 到D:/logFiles/XYZ.log The file's location will always remain the same: D:/logFiles/ .该文件的位置将始终保持不变: D:/logFiles/ How can I change the log file's name dynamically?如何动态更改日志文件的名称?

It's much easier to do the following:执行以下操作要容易得多:

In log4j.xml define variable as ${variable}:在 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>

Then make sure you set the system property when you start your JVM such as:然后确保在启动 JVM 时设置系统属性,例如:

java -Dlogfilename=my_fancy_filename  example.Application

That will create a dynamic log file name: my_fancy_filename.log这将创建一个动态日志文件名: my_fancy_filename.log

Alternatively, you can set the system property in code so long as you do it before you create a logger (this is useful if you want your PID in your logs for instance).或者,您可以在代码中设置系统属性,只要您在创建记录器之前进行设置(例如,如果您希望在日志中包含 PID,这将很有用)。 Such as:如:

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

Once that is set you can go ahead and get your loggers as normal and they will log to the dynamic file (be careful of those static Loggers that create loggers before your main method executes).一旦设置好,您就可以继续正常获取记录器,它们将记录到动态文件中(注意那些在主方法执行之前创建记录器的静态记录器)。

Below is my code for using Log4J for dynamically generate filename.下面是我使用 Log4J 动态生成文件名的代码。 It changes its name according to input file name and current date-time.它根据输入文件名和当前日期时间更改其名称。 (So helpful in case you run same file multiple times.) (如果您多次运行同一个文件,这很有帮助。)

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

Now whenever you want to use logger in your program, Just write these two lines :现在每当你想在你的程序中使用记录器时,只需写这两行:

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

Happy Coding.快乐编码。

It makes more sense to extend FileAppender with your own class, in which you override setOptions() method.使用您自己的类扩展FileAppender更有意义,您可以在其中覆盖setOptions()方法。 Then in your log4j.properties you configure root to log to yourpackage.yourFileAppender , which is much cleaner.然后在您的log4j.properties您将 root 配置为登录到yourpackage.yourFileAppender ,这要干净得多。

In your class containing main method set the name of your class to some system property.在包含 main 方法的类中,将类的名称设置为某个系统属性。 In following example I used log_dir as property name.在以下示例中,我使用log_dir作为属性名称。

class ABC{
 public static void main(String s[]){
  System.setProperty("log_dir", ABC.class.getSimpleName());
 }
}

And in your log4j.xml file use log_dir property in File param's value attribute在你的 log4j.xml 文件中,在 File param 的 value 属性中使用log_dir属性

<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>

Works like a charm奇迹般有效

Before executing anything, log4j thoroughly checks the class path for log4j.xml configuration file.在执行任何操作之前,log4j 会彻底检查 log4j.xml 配置文件的类路径。 Let'say, by chance, if there is any log4j.xml configuration file in the library jars you referenced in your project, log4j loads that file as the configuration file and starts logging.假设,如果您在项目中引用的库 jar 中有任何 log4j.xml 配置文件,log4j 会将该文件作为配置文件加载并开始记录。 In this context, when you are setting log file location in your FileAppender dynamically by getting the value from System properties as suggested by @Big B, it will not work since log4j had already loaded the configuration file it discovered first.在这种情况下,当您通过从系统属性中获取@Big B 建议的值来动态设置 FileAppender 中的日志文件位置时,它将不起作用,因为 log4j 已经加载了它首先发现的配置文件。

To prevent this, you can use DOMConfigurator to inform log4j what configuration file it should load and when it should load.为了防止这种情况,您可以使用DOMConfigurator通知 log4j 它应该加载什么配置文件以及它应该何时加载。 So, as soon as you set the system property of LogFileLocation in your program use DOMConfigurator to load intended properties file in the following way:因此,一旦您在程序中设置了 LogFileLocation 的系统属性,就可以使用 DOMConfigurator 按以下方式加载预期的属性文件:

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

By doing this way, you will load log4j.xml after you set the system property LogFileLocation in your program.通过这种方式,您将在程序中设置系统属性 LogFileLocation 后加载 log4j.xml。 (It will also override the already loaded configuration) (它也会覆盖已经加载的配置)

Inside the log4j.xml configuration, you set the file location in the param tag 'File':在 log4j.xml 配置中,您在参数标记“文件”中设置文件位置:

<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>

To understand whatever I said better, provide -Dlog4j.debug=true in your VM arguments and see the log of log4j execution in your console.为了更好地理解我所说的内容,请在您的 VM 参数中提供-Dlog4j.debug=true并在您的控制台中查看 log4j 执行的日志。

For me it worked only after I used ${sys: ... as below.对我来说,只有在我使用 ${sys: ... 之后它才起作用,如下所示。 Without that it was not picking up that variable set in java command.否则它不会获取 java 命令中设置的变量。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM