【问题标题】:How to give dynamic file name in the appender in log4j.xml如何在 log4j.xml 的 appender 中给出动态文件名
【发布时间】:2011-02-18 03:35:30
【问题描述】:

我正在使用 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/。如何动态更改日志文件的名称?

【问题讨论】:

    标签: java log4j dynamic-data


    【解决方案1】:

    执行以下操作要容易得多:

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

    设置完成后,您可以继续正常获取记录器,它们将记录到动态文件中(注意那些在主方法执行之前创建记录器的静态记录器)。

    【讨论】:

    • 如果我在 .properties 文件中给出值,它会支持/接受吗?即,我可以在 .properties 文件中定义它,而不是在 JVM 的开头定义值吗?
    • 如果你使用 System.setProperty("logfilename", "a_cool_logname");确保在记录任何内容之前设置此设置
    • 如果您使用的是 log4j2,我相信您需要在 XML 中使用${sys:logfilename}
    • 我们能否在文件名中也给出路径,如“D:/Test/my_fancy_filename”,以便它可以在指定目录中创建my_fancy_filename.log?
    【解决方案2】:

    以下是我使用 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!!");
    

    快乐编码。

    【讨论】:

      【解决方案3】:

      使用您自己的类扩展FileAppender 更有意义,在该类中您覆盖setOptions() 方法。然后在你的log4j.properties 中配置root 登录到yourpackage.yourFileAppender,这样更干净。

      【讨论】:

        【解决方案4】:

        在包含 main 方法的类中,将类的名称设置为某个系统属性。在以下示例中,我使用 log_dir 作为属性名称。

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

        并且在您的 log4j.xml 文件中,在 File 参数的 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>
        

        像魅力一样工作

        【讨论】:

          【解决方案5】:

          在执行任何操作之前,log4j 会彻底检查 log4j.xml 配置文件的类路径。假设碰巧,如果您在项目中引用的库 jar 中有任何 log4j.xml 配置文件,log4j 会将该文件加载为配置文件并开始记录。在这种情况下,当您按照@Big B 的建议通过从系统属性中获取值来动态设置 FileAppender 中的日志文件位置时,它将不起作用,因为 log4j 已经加载了它首先发现的配置文件。

          为了防止这种情况,您可以使用DOMConfigurator 通知 log4j 它应该加载什么配置文件以及何时加载。因此,只要您在程序中设置了 LogFileLocation 的系统属性,就可以使用 DOMConfigurator 通过以下方式加载预期的属性文件:

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

          通过这种方式,您将在程序中设置系统属性 LogFileLocation 后加载 log4j.xml。 (它也会覆盖已经加载的配置)

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-11-08
            • 2014-12-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多