log4j日志文件名?

时间:2008-09-17 14:37:46

标签: java logging log4j

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

感谢
汤姆

10 个答案:

答案 0 :(得分:21)

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

java -Dmy_var=somevalue my.job.Classname

然后在你的log4j.properties中:

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

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

答案 1 :(得分:3)

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

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

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

答案 2 :(得分:3)

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

以下是一个例子:

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

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

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

答案 3 :(得分:2)

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

答案 4 :(得分:1)

您可以编写自己的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方法,根据您要添加的新属性返回您选择的方法。

答案 5 :(得分:1)

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

答案 6 :(得分:0)

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

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

  

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

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

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

答案 7 :(得分:0)

汤姆,你可以为每项工作指定和追加。假设你有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>

答案 8 :(得分:0)

您可以实施以下内容:

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

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

答案 9 :(得分:0)

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

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