Имена файлов журнала log4j?

У нас есть несколько задач, которые выполняются одновременно и должны использовать одну и ту же информацию о конфигурации для log4j. Все они выгружают журналы в один файл, используя один и тот же аппендер. Есть ли способ, чтобы каждое задание динамически именовало свой файл журнала, чтобы они оставались отдельными?

Спасибо Том

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
14
0
32 873
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

Вы можете программно настроить log4j при инициализации задания.

Вы также можете установить файл log4j.properties во время выполнения через системное свойство. Из руководство:

Set the resource string variable to the value of the log4j.configuration system property. The preferred way to specify the default initialization file is through the log4j.configuration system property. In case the system property log4j.configuration is not defined, then set the string variable resource to its default value "log4j.properties".

Предполагая, что вы запускаете задания из разных команд Java, это позволит им использовать разные файлы log4j.properties и разные имена файлов для каждого из них.

Без конкретных знаний о том, как выполняется ваша работа, трудно сказать!

Вы можете указать и дополнения для каждой работы. Предположим, у вас есть 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>

Если имена заданий известны заранее, вы можете включить имя задания при выполнении вызова getLogger (). Затем вы можете привязать разные приложения к разным регистраторам с разными именами файлов (или другими местами назначения).

Если вы не можете заранее узнать имя задания, вы можете настроить регистратор во время выполнения вместо использования файла конфигурации:

FileAppender appender = new FileAppender();
appender.setFileName(...);
appender.setLayout(...);
Logger logger = Logger.getLogger("com.company.job."+jobName);
logger.addAppender(appender);
Ответ принят как подходящий

Можете ли вы передать системное свойство Java для каждого задания? Если это так, вы можете параметризовать следующим образом:

java -Dmy_var=somevalue my.job.Classname

А затем в вашем log4j.properties:

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

Вы можете заполнить системное свойство Java значением из среды хоста (например), которое однозначно идентифицирует экземпляр задания.

Вы можете написать свой собственный аппендер, который составляет свое собственное имя файла, возможно, используя метод [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, чтобы верните тот, который вы выберете на основе любых новых свойств, которые вы хотите добавить.

Вы можете настроить каждое задание NDC или MDC, а затем написать приложение, имя которого будет варьироваться в зависимости от значения NDC или MDC. Создать новый аппендер не так уж сложно. В песочнице log4j также может быть приложение, которое будет соответствовать всем требованиям. Начать поиск в http://svn.apache.org/viewvc/logging/log4j/trunk/contribs/

вы можете реализовать следующее:

  • Держатель ThreadLocal для идентификации вашей работы.
  • Расширьте FileAppender, ваш FileAppender должен хранить карту, содержащую QuietWriter для каждого идентификатора задания. В методе subAppend вы получаете идентификатор своей работы из ThreadLocal, вы просматриваете (или создаете) QuietWriter и пишете в него ...

Если хотите, я могу отправить вам код по почте ...

У нас в системе реализовано нечто подобное. Мы храним определенные регистраторы в 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, что может не работать, если вы запустите то же задание на сервере, который всегда включен, но это дает общее представление о том, как это можно работай.

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

Это еще один способ выполнить эту задачу .. здесь com.foo.admin - полное имя пакета

Основываясь на ответе шадит. Если каждое задание можно определить по тому, главный метод какого класса был запущен, вы можете использовать системное свойство 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, я получаю новый файл журнала для каждого нового процесса, который я запускаю, идентифицируемый именем класса с основным методом и временем его запуска.

Другие вопросы по теме