【问题标题】:log4j log file names?log4j 日志文件名?
【发布时间】:2010-09-10 04:19:50
【问题描述】:

我们有几个同时运行的作业,它们必须为 log4j 使用相同的配置信息。他们都使用相同的附加程序将日志转储到一个文件中。有没有办法让每个作业动态命名其日志文件,以便它们保持独立?

谢谢
汤姆

【问题讨论】:

    标签: java logging log4j


    【解决方案1】:

    shadit 的回答为基础。如果可以通过启动哪个类的 main 方法来识别每个作业,则可以使用包含启动的类的全名的系统属性sun.java.command。比如这样:

    log4j.appender.LOGFILE.File=${sun.java.command}.log
    

    我将它与TimestampFileAppender 一起使用,如下所示:

    log4j.appender.LOGFILE=TimestampFileAppender
    log4j.appender.LOGFILE.TimestampPattern=yyyy_MM_dd__HH_mm
    log4j.appender.LOGFILE.File=${sun.java.command}_{timestamp}.log
    

    这样,当我在 Eclipse 中进行开发时,我会为我运行的每个新进程获得一个新的日志文件,由具有 main 方法的类的类名和它的启动时间来标识。

    【讨论】:

      【解决方案2】:

      log4j.logger.com.foo.admin=,AdminFileAppender log4j.logger.com.foo.report=,ReportFileAppender

      这是完成此任务的另一种方法.. 这里 com.foo.admin 是完整的包名

      【讨论】:

        【解决方案3】:

        我们的系统中实现了类似的功能。我们将特定的记录器存储在 HashMap 中,并根据需要为每个记录器初始化附加程序。

        这是一个例子:

        public class JobLogger {
        private static Hashtable<String, Logger> m_loggers = new Hashtable<String, Logger>();
        private static String m_filename = "...";  // Root log directory
        
        public static synchronized void logMessage(String jobName, String message)
        {
            Logger l = getJobLogger(jobName);
            l.info(message);
        }
        
        public static synchronized void logException(String jobName, Exception e)
        {
            Logger l = getJobLogger(partner);
            l.info(e.getMessage(), e);
        }
        
        private static synchronized Logger getJobLogger(String jobName)
        {
            Logger logger = m_loggers.get(jobName);
            if (logger == null) {
                Layout layout = new PatternLayout("...");
                logger = Logger.getLogger(jobName);
                m_loggers.put(jobName, logger);
                logger.setLevel(Level.INFO);
                try {
                    File file = new File(m_filename);
                    file.mkdirs();
                    file = new File(m_filename + jobName + ".log");
                    FileAppender appender = new FileAppender(layout, file.getAbsolutePath(), false);
                    logger.removeAllAppenders();
                    logger.addAppender(appender);
            }
                catch (Exception e)
            { ... }
            }
            return logger;
        }
        }
        

        然后要在你的工作中使用它,你只需要使用这样的一行条目:

        JobLogger.logMessage(jobName, logMessage);
        

        这将为每个作业名称创建一个日志文件,并将其放入其自己的文件中,并在您指定的任何目录中使用该作业名称。

        您可以摆弄其他类型的附加程序等,如所写,它将继续附加,直到 JVM 重新启动,如果您在始终处于启动状态的服务器上运行相同的作业,这可能无法正常工作,但这给出了一般的想法它是如何工作的。

        【讨论】:

          【解决方案4】:

          您可以实现以下功能:

          • 您的工作身份的 ThreadLocal 持有者。
          • 扩展 FileAppender,您的 FileAppender 必须为每个工作身份保留一个包含 QuietWriter 的 Map。在 subAppend 方法中,您从 ThreadLocal 获取工作的标识,查找(或创建)QuietWriter 并向其写入...

          如果您愿意,我可以通过邮件向您发送一些代码...

          【讨论】:

            【解决方案5】:

            您可以让每个作业设置 NDC 或 MDC,然后编写一个附加程序,根据 NDC 或 MDC 值改变名称。创建一个新的 appender 并不难。在 log4j 沙箱中也可能有一个符合要求的附加程序。开始寻找http://svn.apache.org/viewvc/logging/log4j/trunk/contribs/

            【讨论】:

              【解决方案6】:

              您可以编写自己的附加程序来组成自己的文件名,也许使用 [File.createTempFile](http://java.sun.com/j2se/1.5.0/docs/api/java/io/File.html#createTempFile(java.lang.String,%20java.lang.String)) 方法。如果 FileAppender 类编写正确,您应该能够扩展它 - 或 @ 987654323@ — 并覆盖 getFile 方法以返回您根据要添加的任何新属性选择的方法。

              【讨论】:

                【解决方案7】:

                您可以在初始化作业时以编程方式配置 log4j。

                您还可以通过系统属性在运行时设置 log4j.properties 文件。来自manual

                将资源字符串变量设置为 log4j.configuration 系统属性的值。指定默认初始化文件的首选方法是通过 log4j.configuration 系统属性。如果未定义系统属性 log4j.configuration,则将字符串变量资源设置为其默认值“log4j.properties”。

                假设您从不同的 java 命令运行作业,这将使它们能够使用不同的 log4j.properties 文件和每个文件的不同文件名。

                如果不了解您的作业是如何运行的,这很难说!

                【讨论】:

                  【解决方案8】:

                  您可以为每个作业传递一个 Java 系统属性吗?如果是这样,您可以像这样进行参数化:

                  java -Dmy_var=somevalue my.job.Classname
                  

                  然后在你的 log4j.properties 中:

                  log4j.appender.A.File=${my_var}/A.log
                  

                  您可以使用主机环境中的值(例如)填充 Java 系统属性,该值将唯一标识作业的实例。

                  【讨论】:

                    【解决方案9】:

                    如果提前知道作业名称,您可以在调用 getLogger() 时包含作业名称。然后,您可以使用不同的文件名(或其他目标)将不同的附加程序绑定到不同的记录器。

                    如果您无法提前知道作业名称,您可以在运行时配置记录器,而不是使用配置文件:

                    FileAppender appender = new FileAppender();
                    appender.setFileName(...);
                    appender.setLayout(...);
                    Logger logger = Logger.getLogger("com.company.job."+jobName);
                    logger.addAppender(appender);
                    

                    【讨论】:

                      【解决方案10】:

                      Tom,您可以为每个作业指定和附加程序。假设你有 2 个作业对应于两个不同的 java 包 com.tom.firstbatch 和 com.tom.secondbatch,你会在 log4j.xml 中有这样的东西:

                         <category name="com.tom.firstbatch">
                            <appender-ref ref="FIRST_APPENDER"/>
                         </category>
                         <category name="com.tom.secondtbatch">
                            <appender-ref ref="SECOND_APPENDER"/>
                         </category>
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2014-11-17
                        • 2011-05-23
                        • 1970-01-01
                        • 1970-01-01
                        • 2019-02-04
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多