log4j日志文件名?

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

谢谢
汤姆

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

java -Dmy_var=somevalue my.job.Classname 

然后在你的log4j.properties中:

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

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

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

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

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

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

这是一个例子:

 public class JobLogger { private static Hashtable m_loggers = new Hashtable(); 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); 

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

你可以摆弄其他类型的appender等,因为它会继续附加,直到JVM重新启动,如果你在一个总是运行的服务器上运行相同的工作,这可能不起作用,但这给出了它如何能够大致的概念工作。

您可以将每个作业设置为NDC或MDC,然后编写一个根据NDC或MDC值更改名称的appender。 创建一个新的appender并不是太难。 可能还有一个适合log4j沙箱中的帐单的appender。 开始查看http://svn.apache.org/viewvc/logging/log4j/trunk/contribs/

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

以shadit的答案为基础。 如果可以通过启动哪个类的main方法来识别每个作业,则可以使用系统属性sun.java.command ,该属性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中开发时,我为每个运行的新进程获取一个新的日志文件,由类的类名以主方法和启动时间标识。

汤姆你可以为每项工作指定和追加。 假设你有2个作业对应两个不同的java包com.tom.firstbatch和com.tom.secondbatch,你会在log4j.xml中有这样的东西:

        

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

您还可以通过系统属性在运行时设置log4j.properties文件。 从手册 :

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

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

如果没有关于你的工作如何运作的具体知识,很难说!

你可以实现以下:

  • ThreadLocal持有人,用于识别您的工作。
  • 扩展FileAppender,您的FileAppender必须为每个作业标识保留一个包含QuietWriter的Map。 在方法subAppend中,您从ThreadLocal获取作业的标识,您查找(或创建)QuietWriter并写入它…

如果你愿意,我可以通过邮件发给你一些代码……

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

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