Конфигурация Log4j - разные журналы для разных файлов
Это может быть очень простым вопросом для некоторых, но лично я считаю, что конфигурация Log4j является кошмарно трудной и что обучение выполнению операций на головном мозге может быть менее сложным.
Я пытаюсь запустить несколько журналов регистрации в разные файлы.
Вот что я имею в файле log4j.properties:
# Root logger option
log4j.rootLogger=INFO, file, admin
# Direct log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=/home/nick/logging/file.log
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=1
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n
log4j.appender.admin=org.apache.log4j.RollingFileAppender
log4j.appender.admin.File=/home/nick/logging/admin.log
log4j.appender.admin.MaxFileSize=1MB
log4j.appender.admin.MaxBackupIndex=1
log4j.appender.admin.layout=org.apache.log4j.PatternLayout
log4j.appender.admin.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n
И вот мое (очень простое) приложение Java, используемое для проверки конфигурации:
public static void main(String[] args) throws Exception {
Properties resource = new Properties();
InputStream in = new FileInputStream("/home/nick/logging/log4j.properties");
resource.load(in);
PropertyConfigurator.configure(resource);
Logger admin = Logger.getLogger("admin");
Logger file = Logger.getLogger("file");
admin.info("hello admin");
file.info("hello file");
}
У меня есть 2 проблемы:
Одна проблема: я всегда получаю исключение в строке PropertyConfigurator.configure(resource);
:
java.io.FileNotFoundException: /home/nick/logging (Is a directory)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:212)
at java.io.FileOutputStream.<init>(FileOutputStream.java:136)
at org.apache.log4j.FileAppender.setFile(FileAppender.java:289)
at org.apache.log4j.RollingFileAppender.setFile(RollingFileAppender.java:167)
at org.apache.log4j.FileAppender.activateOptions(FileAppender.java:163)
at org.apache.log4j.config.PropertySetter.activate(PropertySetter.java:256)
Вторая проблема заключается в том, что оба сообщения записываются в оба журнала. Вот результат фактический:
Администратор файла: журнал:
2014-04-27 11:55:30 INFO admin - hello admin
2014-04-27 11:55:30 INFO file - hello file
Файл file.log:
2014-04-27 11:55:30 INFO admin - hello admin
2014-04-27 11:55:30 INFO file - hello file
Вот результат требуемый:
Администратор файла: журнал:
2014-04-27 11:55:30 INFO admin - hello admin
Файл file.log:
2014-04-27 11:55:30 INFO file - hello file
Что вызывает исключение и как я могу достичь требуемого результата?
Ответы
Ответ 1
Log4J делает различие между регистраторами, которые отвечают за генерирование сообщений журнала, и приложениями, которые несут ответственность за отправку этих сообщений где-нибудь (файл, консоль, база данных и т.д.). Регистраторы формируют иерархию, корневой регистратор - это родительский журнал регистратора с именем admin
, который является родительским элементом admin.component1
и т.д., И вы можете присоединять к любому регистратору в иерархии. По умолчанию регистратор отправляет сообщения всем приятелям, которые прикреплены непосредственно к нему, или любому из его предков в иерархии (поэтому регистраторы обычно называются как классы Java, например, вы можете управлять протоколированием для com.example.Class1
и com.example.subpkg.AnotherClass
путем настройки регистратора com.example
).
Регистраторы и приставки образуют отдельные пространства имен, и это является источником вашей путаницы - регистратор с именем admin
, а appender с именем admin
- это два отдельных объекта.
Конфигурация, заданная вами в вопросе, определяет один регистратор (корневой журнал), который отправляет все сообщения, которые он генерирует, в два отдельных приложения, по одному для каждого из двух файлов. Затем ваш код запрашивает два разных регистратора и генерирует одно сообщение журнала с каждым регистратором. Оба этих регистратора наследуют конфигурацию приложения от корневого регистратора, поэтому оба отправляют свои сообщения в оба настроенных приложения.
![enter image description here]()
Вместо того, чтобы прикреплять два добавителя к корневому журналу, вы должны прикрепить file
appender к регистратору file
и приложению admin
к регистратору admin
:
log4j.rootLogger=INFO
log4j.logger.file=INFO, file
log4j.logger.admin=INFO, admin
Таким образом, регистратор file
отправляет сообщения только на file.log
, регистратор admin
только на admin.log
, и все сообщения от других регистраторов будут отброшены молча, так как нет добавлений, прикрепленных к корню.
![enter image description here]()
Флаг аддитивности является исключением из этого правила - установка логической аддитивности на false существенно отключает стрелку от регистратора до его родителя, поэтому сообщения, сгенерированные этим регистратором (или втекающие в него от одного из его дочерних элементов), не будут идти дальше по дереву, они будут поступать только в приставки, прикрепленные непосредственно к указанному регистратору.
Ответ 2
Чтобы ответить на мой вопрос, это то, что мне нужно:
log4j.logger.file=DEBUG, fileAppender
log4j.logger.admin=DEBUG, adminAppender
log4j.additivity.file=false
log4j.additivity.admin=false
log4j.appender.fileAppender=org.apache.log4j.RollingFileAppender
log4j.appender.fileAppender.File=/home/nick/logging/file.log
log4j.appender.fileAppender.MaxFileSize=1MB
log4j.appender.fileAppender.MaxBackupIndex=1
log4j.appender.fileAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.fileAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n
log4j.appender.adminAppender=org.apache.log4j.RollingFileAppender
log4j.appender.adminAppender.File=/home/nick/logging/admin.log
log4j.appender.adminAppender.MaxFileSize=1MB
log4j.appender.adminAppender.MaxBackupIndex=1
log4j.appender.adminAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.adminAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n
Ответ 3
Вам не нужно загружать файл свойств. Просто поместите его в папку src
, которая будет автоматически добавлена в путь класса.
Пример кода:
public static void main(String[] args) throws Exception {
Logger admin = Logger.getLogger("admin");
Logger file = Logger.getLogger("file");
admin.info("hello admin");
file.info("hello file");
}
Ответ 4
Во-первых: log4j рекомендует использовать файл формата XML для свойств.
Во-вторых: лучше загрузить файл свойств в загрузчик классов.
В-третьих: есть наследование в журнале, но вы можете разрезать его с помощью свойства аддитивности, см. файл log4j.properties - несколько журналов в том же классе