Logback - программная установка имени файла журнала

Я использую логбэк и пытаюсь программно установить имя файла журнала в своей программе на Java (аналогично Программная установка пути Logback Appender), и я попытался адаптировать это решение следующим образом:

В logback-test.xml:

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
  <file>log/${log_file_name}.log</file>
  ...

И снова в моей программе на Java:

String logFileName = "" + System.currentTimeMillis(); // just for example
System.setProperty("log_file_name", logFileName);

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
ContextInitializer ci = new ContextInitializer(lc);
lc.reset();
try
{
    // I prefer autoConfig() over JoranConfigurator.doConfigure() so I
    // wouldn't need to find the file myself.
    ci.autoConfig();
}
catch (JoranException e)
{
    // StatusPrinter will try to log this
    e.printStackTrace();
}
StatusPrinter.printInCaseOfErrorsOrWarnings(lc);

Однако результатом являются два журнала, один полный и назван так, как я хотел, например, «1319041145343.log», а другой пустой и назван «log_file_name_IS_UNDEFINED.log». Как мне остановить создание этого другого пустого файла журнала?


person conorsomahony    schedule 19.10.2011    source источник
comment
Единственная проблема вашего кода, похоже, заключается в том, что вы слишком поздно устанавливаете System.setProperty("log_file_name", logFileName);. Выполните его до того, как будет выполнена автоконфигурация Logback, и у вас будет то, что вы хотите.   -  person Robert    schedule 30.01.2013
comment
На самом деле это можно сделать намного проще, чем в вашем фрагменте кода: stackoverflow.com/a/21886071/709537   -  person Evgeniy Berezovsky    schedule 25.11.2016


Ответы (4)


Я считаю, что следующее будет ближе к тому, что вы хотите.

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.util.StatusPrinter;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;

public class Main {
  public static void main(String[] args) {
    LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();

    FileAppender fileAppender = new FileAppender();
    fileAppender.setContext(loggerContext);
    fileAppender.setName("timestamp");
    // set the file name
    fileAppender.setFile("log/" + System.currentTimeMillis()+".log");

    PatternLayoutEncoder encoder = new PatternLayoutEncoder();
    encoder.setContext(loggerContext);
    encoder.setPattern("%r %thread %level - %msg%n");
    encoder.start();

    fileAppender.setEncoder(encoder);
    fileAppender.start();

    // attach the rolling file appender to the logger of your choice
    Logger logbackLogger = loggerContext.getLogger("Main");
    logbackLogger.addAppender(fileAppender);

    // OPTIONAL: print logback internal status messages
    StatusPrinter.print(loggerContext);

    // log something
    logbackLogger.debug("hello");
  }
}

Если все, что вам нужно, это добавить отметку времени имени файла журнала, возврат уже поддерживает элемент отметки времени. Таким образом, вам вообще не нужен специальный код.

person Ceki    schedule 19.10.2011
comment
спасибо за вашу помощь, я попробую. (Я просто использовал метку времени в качестве примера, фактическое имя файла будет другим) - person conorsomahony; 20.10.2011
comment
Спасибо, это работает - в logback-test.xml я больше не указываю файловый аппендер, а в java-коде я создаю его и прикрепляю к «корневому» регистратору. - person conorsomahony; 20.10.2011
comment
Смысл slf4j не в том, чтобы избежать импорта ch.qos.logback.classic.Logger - person Zombies; 02.11.2012
comment
@Zombies: Да, это так. Однако предполагается, что slf4j должен быть простым, как следует из названия, поэтому API slf4j не предлагает никакого контроля над выводом журнала. Если вам нужен этот элемент управления, вы должны напрямую разговаривать (и зависеть от) используемой вами структуры ведения журнала. - person sleske; 07.07.2015

Чтобы разделить / отсеять сообщения журнала по разным файлам в зависимости от атрибута времени выполнения, вы можете использовать ch .qos.logback.classic.sift.SiftingAppender.

Вкратце, это позволяет вам настроить FileAppender (или любое другое приложение) с <file>${userid}.log</file>, где ${userId} заменяется на основе MDC (сопоставленный диагностический контекст) (например, MDC.put("userid", "Alice");). См. Первую ссылку для полного примера.

person simon04    schedule 18.04.2013

Вот что вы можете сделать, чтобы игнорировать создание лишних файлов. Ниже находится файл конфигурации.

<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<!-- "application-name" is a variable -->
<File>c:/logs/${application-name}.log</File>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d %p %t %c - %m%n</Pattern>
</layout>
</appender>
<root level="debug">
<appender-ref ref="FILE"/>
</root>
</configuration>  

Вот часть java,

LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
JoranConfigurator jc = new JoranConfigurator();
jc.setContext(context);
context.reset(); // override default configuration
// inject the name of the current application as "application-name"
// property of the LoggerContext
context.putProperty("application-name", NAME_OF_CURRENT_APPLICATION);
jc.doConfigure("/path/to/the/above/configuration/file.xml");

Я получил это отсюда http://logback.qos.ch/faq.html#sharedConfiguration

person Sneha Mohan    schedule 04.10.2012
comment
Другой способ - инициализировать все системные переменные перед вызовом Logger. Это тоже работает. - person Sneha Mohan; 04.10.2012
comment
Закончился использованием System.setProperty (..) вместо сброса контекста. Мне кажется чище. Спасибо за напр. - person Steven Levine; 15.01.2016
comment
К сожалению, использование свойств системы не может работать, если вы хотите поделиться конфигурацией. - person Brice; 09.06.2016

Похоже, логгер инициализирован дважды. В первый раз, вероятно, когда приложение загружается и не может разрешить ошибку ${log_file_name}. Если вы запустите приложение с -Dlog_file_name=*something*, вы можете проверить это поведение, если оно создаст другой файл журнала с именем *something*

person srkavin    schedule 19.10.2011
comment
Что вы можете сделать, чтобы программно установить имя файла, так это создать экземпляр файлового приложения с необходимой конфигурацией (имя, категорию, пакет и т. Д.) И добавить его в иерархию приложений. - person srkavin; 19.10.2011
comment
Спасибо, я добавил ровно -Dlog_file_name=verify к аргументам виртуальной машины, и я действительно получил пустой журнал с именем verify.log - Есть ли способ остановить запуск регистратора дважды? - person conorsomahony; 20.10.2011