Настроювання журналів Log4j програмно


191

Я намагаюся використовувати SLF4J (з log4jприв’язкою) вперше.

Я хотів би налаштувати 3 різних іменованих реєстраторів, які можуть бути повернуті LoggerFactory, які будуть реєструвати різні рівні та надсилати повідомлення до різних додатків:

  • Logger 1 "FileLogger" записує журнал DEBUG і додає до DailyRollingFileAppender
  • Журнал 2 "TracingLogger" записує журнал TRACE + та додає до JmsAppender
  • Журнал 3 "ErrorLogger" реєструє ERROR + та додає до іншого JmsAppender

Крім того, я хочу, щоб вони були налаштовані програмно (на Java, на відміну від XML або log4j.propertiesфайлу).

Я думаю, що, як правило, я б визначав їх Loggerдесь у якомусь завантажувальному коді, як init()метод. Однак, оскільки я хочу використовувати slf4j-log4j, я плутаюсь щодо того, де я міг би визначити реєстратори та зробити їх доступними для classpath.

Я не вірю, що це порушення основної мети SLF4J (як фасаду), оскільки мій код, що використовує API SLF4J, ніколи не дізнається, що ці реєстратори існують. Мій код просто робить звичайні дзвінки до API SLF4J, який потім пересилає їх до Log4j Loggers, який він знаходить на classpath.

Але як я конфігурую ці Log4j Loggers на classpath ... на Java ?!



3
Для log4j 1.x використовувати загальноприйнятий відповідь нижче 2.x см logging.apache.org/log4j/2.x/manual/customconfig.html
earcam

Відповіді:


279

Ви можете додати / вилучити Програму програмно до Log4j:

  ConsoleAppender console = new ConsoleAppender(); //create appender
  //configure the appender
  String PATTERN = "%d [%p|%c|%C{1}] %m%n";
  console.setLayout(new PatternLayout(PATTERN)); 
  console.setThreshold(Level.FATAL);
  console.activateOptions();
  //add appender to any Logger (here is root)
  Logger.getRootLogger().addAppender(console);

  FileAppender fa = new FileAppender();
  fa.setName("FileLogger");
  fa.setFile("mylog.log");
  fa.setLayout(new PatternLayout("%d %-5p [%c{1}] %m%n"));
  fa.setThreshold(Level.DEBUG);
  fa.setAppend(true);
  fa.activateOptions();

  //add appender to any Logger (here is root)
  Logger.getRootLogger().addAppender(fa);
  //repeat with all other desired appenders

Я б запропонував вам покласти його в init () десь там, де ви впевнені, що це буде виконано раніше, ніж будь-що інше. Потім можна видалити всі наявні додатки в кореневому журналі

 Logger.getRootLogger().getLoggerRepository().resetConfiguration();

і почніть з додавання власного. Звичайно, для цього вам потрібен log4j на уроці класу.

Зауваження:
Ви можете взяти будь-яке, Logger.getLogger(...)що хочете, щоб додати додавання. Я щойно взяв кореневий реєстратор, оскільки він знаходиться внизу всіх речей і буде обробляти все, що передається через інші додатки в інших категоріях (якщо не налаштовано інше, встановивши прапор добавки).

Якщо вам потрібно знати, як працює лісозаготівля та як вирішено, де записуються журнали, прочитайте цей посібник, щоб дізнатися більше про це.
Коротко:

  Logger fizz = LoggerFactory.getLogger("com.fizz")

дасть вам реєстратор категорії "com.fizz".
Для наведеного вище прикладу це означає, що все, що зареєстровано в ньому, буде передано до консолі та додатку файлу в кореневому журналі.
Якщо додати до appender'у в Logger.getLogger ( «com.fizz»). AddAppender (newAppender) , то вхід з fizzбуде оброблятися алле в appenders від кореневого реєстратора а newAppender.
Ви не створюєте Logger з конфігурацією, ви просто надаєте обробники для всіх можливих категорій у вашій системі.


2
Дякую! Швидке запитання - я помітив, що ви додаєте додатки до кореневого журналу. Чи є для цього причина?
IAmYourFaja

І, що ще важливіше, мені потрібно буде вказати, який Logger отримати з LoggerFactory SLF4J. Чи можна запитати SLF4J для кореневого реєстратора log4j?
IAmYourFaja

3
@AdamTannon Ви можете взяти будь-який Logger.getLogger (...), який вам подобається. Я щойно взяв кореневий реєстратор, оскільки він знаходиться внизу всіх речей і буде обробляти все, що передається через інші додатки в інших категоріях (якщо не налаштовано інше). Дивіться ієрархію
лісорубів

@AdamTannon ви не можете використовувати завод sl4j, щоб отримати кореневий реєстратор log4j. SL4j - фасад лісозаготівель. Ви нічого не отримаєте від нього log4j.
oers

2
oers - Я ціную ваші чудові відгуки, але я просто не з'єдную тут усі точки. Чи можете ви змінити свій приклад, щоб показати додавання нового Logger (не кореневого реєстратора), який після додавання до системи буде доступний для будь-якого іншого класу, який запитує його? Наприклад, Logger, до якого зазвичай можна отримати доступ, скажімо, Logger fizz = LoggerFactory.getLogger("com.fizz");Спасибі!
IAmYourFaja

47

Здається, ви намагаєтеся використовувати log4j з "обох кінців" (споживчий кінець та кінець конфігурації).

Якщо ви хочете кодувати проти aplf slf4j, але визначити достроково (і програмно) конфігурацію Log4j Loggers, яку поверне classpath, вам абсолютно необхідно мати якусь адаптацію журналу, яка використовує ліниву побудову.

public class YourLoggingWrapper {
    private static boolean loggingIsInitialized = false;

    public YourLoggingWrapper() {
        // ...blah
    }

    public static void debug(String debugMsg) {
        log(LogLevel.Debug, debugMsg);
    }

    // Same for all other log levels your want to handle.
    // You mentioned TRACE and ERROR.

    private static void log(LogLevel level, String logMsg) {
        if(!loggingIsInitialized)
            initLogging();

        org.slf4j.Logger slf4jLogger = org.slf4j.LoggerFactory.getLogger("DebugLogger");

        switch(level) {
        case: Debug:
            logger.debug(logMsg);
            break;
        default:
            // whatever
        }
    }

    // log4j logging is lazily constructed; it gets initialized
    // the first time the invoking app calls a log method
    private static void initLogging() {
        loggingIsInitialized = true;

        org.apache.log4j.Logger debugLogger = org.apache.log4j.LoggerFactory.getLogger("DebugLogger");

        // Now all the same configuration code that @oers suggested applies...
        // configure the logger, configure and add its appenders, etc.
        debugLogger.addAppender(someConfiguredFileAppender);
    }

При такому підході вам не потрібно турбуватися про те, де / коли налаштовуються ваші реєстратори log4j. Перший раз, коли класовий шлях просить їх, вони ліниво будуються, передаються назад і стають доступними через slf4j. Сподіваюся, це допомогло!


2
Прибила його! Дуже дякую за корисний приклад! @Oers - дякую за те, що ти намагався направляти мене в правильному напрямку - я збираюся дати тобі зелений чек на твою відданість, але мушу дати жарві щедрості, бо це було саме те, що я шукав. Ще раз дякую всім!
IAmYourFaja

4

У випадку, якщо ви визначили додаток у властивостях log4j і хочете його програмно оновити, встановіть ім’я у властивостях log4j та отримайте його за назвою.

Ось приклад запису log4j.properties:

log4j.appender.stdout.Name=console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.Threshold=INFO

Щоб оновити його, виконайте наступне:

((ConsoleAppender) Logger.getRootLogger().getAppender("console")).setThreshold(Level.DEBUG);

1

Якщо хтось шукає програмне налаштування log4j2 на Java, то це посилання може допомогти: ( https://www.studytonight.com/post/log4j2-programmatic-configuration-in-java-class )

Ось основний код конфігурації придатника консолі:

ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();

builder.setStatusLevel(Level.DEBUG);
// naming the logger configuration
builder.setConfigurationName("DefaultLogger");

// create a console appender
AppenderComponentBuilder appenderBuilder = builder.newAppender("Console", "CONSOLE")
                .addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
// add a layout like pattern, json etc
appenderBuilder.add(builder.newLayout("PatternLayout")
                .addAttribute("pattern", "%d %p %c [%t] %m%n"));
RootLoggerComponentBuilder rootLogger = builder.newRootLogger(Level.DEBUG);
rootLogger.add(builder.newAppenderRef("Console"));

builder.add(appenderBuilder);
builder.add(rootLogger);
Configurator.reconfigure(builder.build());

Це дозволить перенастроїти rootLogger за замовчуванням, а також створить нове додаток .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.