Как создать файловый аппендер

Обновлено: 06.07.2024

Я новичок в log4j. Может ли кто-нибудь объяснить, как создать свой собственный Appender? т.е. как реализовать классы и интерфейсы и как их переопределить?

задан 20 мая '11, 13:05

вам необходимо реализовать интерфейс приложения. но вам, вероятно, следует создать подкласс одного из существующих дополнений и переопределить методы, например doAppend (LoggingEvent), в соответствии с вашими потребностями. - happymeal

что, если существующий аппендер окончательный? - Gaurav

4 ответы

Вам следует расширить класс AppenderSkeleton, который (цитируя javadoc) «предоставляет код для общих функций, таких как поддержка пороговой фильтрации и поддержка общих фильтров».

Если вы прочитаете код AppenderSkeleton, вы увидите, что он обрабатывает почти все, оставляя вам только:

  1. защищенное пустое добавление (событие LoggingEvent)
  2. public void close ()
  3. public boolean requiresLayout ()

Основной метод - добавление. Помните, что вам не нужно реализовывать в нем логику фильтрации, потому что она уже реализована в doAppend, который, в свою очередь, вызывает append. Здесь я создал (совершенно бесполезный) класс, который хранит записи журнала в ArrayList, просто в качестве демонстрации.

Хорошо, давайте протестируем:

ответ дан 24 мая '11, 11:05

Я использовал вышеуказанный класс, без ошибок, .. как я могу определить, что новый Appender будет создан? Как я могу его использовать? - неизвестный

от logging.apache.org/log4j/1.2/manual.html,"A запрос журнала уровня p в регистраторе с (назначенным или унаследованным, в зависимости от того, что подходит) уровнем q, включен, если p> = q ". Запрос журнала имеет уровень" трассировка ", в то время как регистратор имеет уровень, установленный на" отладка "который выше, чем трассировка, поэтому не будет регистрироваться. Помните, что регистратору не назначен уровень, поэтому он наследует уровень корневого регистратора. Чтобы журнал регистратора также отслеживал запросы уровня (максимальная детализация!), вы можете установить либо программно (l.setLevel (Level.TRACE);), либо (лучше) через файлы свойств уровень «регистратора» или корневого регистратора. - AgostinoX

Это не то, что вы задали в своем первоначальном вопросе. Если у вас есть собственный подкласс Appender, вы должны предоставить код для записи на диск. Возможно, вам не нужен был собственный класс Appender, вам нужен только FileAppender, который автоматически регистрируется на диске. Вы просто указываете имя файла. - AgostinoX

@Elakkiya: пожалуйста. Вы решили свою проблему с log4j? Вы расширили AppenderSkeleton или использовали какой-нибудь предоставленный Appender? - AgostinoX

Если вы хотите совершить какие-то манипуляции или решения, вы можете сделать это так:

Интерфейс Appender

Конкретные реализации класса AppenderSceleton

Вывод в консоль

Кроме кодировок для данного вида аппендера можно назначить поток вывода в свойстве Target( имеет два значения "System.out" и "System.err"). Устанавливается значение данного свойства аналогично назначению кодировки.

Аппендеры записи в файл

Перед рассмотрением файловых аппендеров небольшое замечание о использовании. Так-как запись ведётся в файл, то необходимо указать его имя. Есть три способа указать имя файла: абсолютный адрес в файловой системе, указать URL, задать относительное имя файла. В третьем случае имя файла указывается относительно директории запуска JVM. Если приложение запускается из командной строки - проблем нет, если это делает IDE придётся поискать в файловой системе место создания файла. Другим моментом, общим для всех видов файловых аппендеров является требование прикрепления компоновщика(layout).

  • FileAppender - производит запись в файл.
  • RollingFileAppender - производит запись в несколько файлов поочерёдно.
  • DailyRollingFileAppender - меняет файл записи по достижении указанного срока.
  • ExternallyRolledFileAppender - меняет файл записи при получении сигнала.

FileAppender - ведётся запись в файл. Если файл не существует, то будет создан. В этом классе событие системы логгирования вставляется в поток FileOutputStream и в итоге будет записано в файл. Раз запись ведётся в файл, то естественно есть настройки работы с файлом и потоком записи. Рассматриваю свойства:

Переходм к примеру. Он состоит из двух файлов java-класса и файла свойств. Класс объявляет логгер и производит запись в него:

Второй частью является файл свойств - log4j.properties:

Запустив пример получаем следующий вывод:
[ 11:45:46 Main5 ] Hello
Чтобы посмотреть как влияет на запись в файл назначение свойства "append" нужно несколько раз запустить программу с данным файлом конфигурации. Изменить свойство append на true и снова запустить его несколько раз. Не забудьте сохранить новый файл конфигурации или не увидите изменений.

RollingFileAppender - тоже предназначен для записи в файл. Запись предыдущим аппендером проста, но обратной стороной простоты является некоторое неудобство. Например имеем большое приложение или приложение долго работает(на сервере), в таком случае размер log-файла значительно разрастается, искать что-либо в нём становится трудно. Класс RollingFileAppender расширяет возможности FileAppender и имеет возможность усекать размер записываемого файла и создавать, при необходимости новые. RollingFileAppender в дополнение к свойствам своих родителей ещё имеет:

MaxBackupIndex (int) Максимальное число файлов хранения информации. Желательно иметь от 1 до 10 файлов. Большее число файлов приводит к значительному падению производительности системы.
MaxFilesize (String) Строка содержит максимальное значение размера файла. Может дополняться уточнением KB, MB, GB(размер измерять в килобайтах, мегабайтах, гигабайтах). По умолчанию размер будет 10MB.

При ведении записи в RollingFileAppender учитывается размер файла заданный в MaxFilesize, если после проведения записи в файл(для определённости назовём его logFile) окажется, что размер файла превышает указанную величину, то файл будет переименован в logFile1. При следующем обращении для записи в RollingFileAppender будет создан файл logFile и всё пойдёт в него. Когда окажется, что файл logFile превысил значение MaxFilesize произойдёт следующее переименование logFile в logFile1, logFile1(он уже был создан ранее) переименуется в logFile2. Далее процесс пойдёт аналогично до достижения индексом logFile значения MaxBackupIndex. В последнем случае файл с индексом MaxBackupIndex будет удалён, а его место займёт файл с индексом MaxBackupIndex-1 и так далее. Т.е как только будет создано MaxBackupIndex файлов, при следующей смене имён наиболее старый файл будет удалён.

Конфигурационный файл не имеет комментариев из-за того,что он почти такой-же как предыдущий, просто дополнен настройками размера файлов и их количества .

Запустив пример нужно открыть директорию запуска и смотреть что происходит при очередной записи в лог( количество файлов, их размер и содержание). Можно посмотреть что будет происходить изменив настройки файла конфигурации. Если подходить к этому примеру с точки зрения производительности , то вставка кода журналирования в цикл никуда не годное дело и в реальных приложениях этого следует избегать. В нашем случае определяющим будет всё-же время ответа пользователя.

В дополнение к RollingFileAppender есть ещё ExternallyRolledFileAppender его непосредственный потомок.

ExternallyRolledFileAppender - расширение класса RollingFileAppender. Автоматически получает все свойства предков. Дополнительно слушает заданный порт компьютера, при получении на данный порт строки "RollOver" сменит имена файлов подобно RollingFileAppender и отправит строку подтверждения-"OK" обратно(строки прописаны в константах класса ExternallyRolledFileAppender и лучше пользоваться ими). Смотрим индивидуальные свойства класса ExternallyRolledFileAppender:

Port Назначает номер порта прослушиваемого данным аппендером.Если попробовать назначить данное свойство в файле *.properties программа окажется неработоспособной. Записи в файл производятся, но назначенный порт прослушиваться не будет со всеми вытекающими последствиями.

Если запустить пример с log4j.xml и поэкспериментировать, то разница с примером RollingFileAppender будет только в том, что здесь нет вывода на консоль. Что-бы посмотреть действие сигнала RollOver нужно запустить отдельную программу отсылающую данный сигнал. Для демонстрации работы ExternallyRolledFileAppender в log4j есть класс Roller, посылаюший такой сигнал. Посмотреть содержимое Roller(а) можно в исходных кодах, внутри папки src/main/java/org/apache/log4j/varia входящей в поставку log4j.

DailyRollingFileAppender - расширение FileAppender. Если RollingFileAppender меняет имя файла по достижении предельного размера, то DailyRollingFileAppender меняет название файла по достижении определённого момента времени. Имеет весь набор свойств предка и дополнительно:


Данный аппендер производит записи в файл, указанный в свойстве File. Когда приходит время в назначенное в DatePattern к имени файла прибавляется дата записи, в форме указанной в DatePattern и файл переименовывается в соответствии с новым именем. Далее записи ведутся в файл с именем в свойстве File и всё повторяется. Возьмём для определённости что запись ведётся в файл с именем myLog и в PatternLayout заданo '.'yyyy-MM-dd. Начинались записи, допустим 05.01.10г. Тогда в полночь с 05.01.10г на 06.01.10г файл myLog будет переименован в myLog.2010-01-05, будет создан файл myLog и запись будет вестись в него. В следующую полночь всё повторится, если приложение не будет закрыто.

Работающего примера не привожу. Можно взять класс из предыдущего и добавить к нему изменённый файл конфигурации(в нём вместо RollingFileAppender назначьте DailyRollingFileAppender и желательно, в свойстве DatePattern указать замену каждую минуту, иначе придётся очень долго ждать). Запустить пример и понажимать разные буквы. После посмотреть результат.

Аппендеры удалённой записи

Т.к. данный апендер работает с сетью логично предположить, что он имеет настройки работы с сетью . Это:

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

  • Log4j должен быть установлен и на передающей, и на принимающей стороне.
  • Кто принимает LoggingEvent должен позаботиться о том как поступить с полученной информацией( произвести десериализацию, извлечь информацию и предоставить её в удобочитаемой форме).

Файл конфигурации описывает практически все дополнительные настройки для SyslogAppender. Всё готово. Можно запускать пример: java ".:path/to/log4j" Main
Посмотреть результат можно в файле /var/log/messages. Файл большой сразу идите в конец и ищите там.

  1. Строится файл конфигурации по аналогии с предыдущими. Обязательным будет определение порта.
  2. Запускается программа Telnet.
  3. Запускается приложение.
  4. В программе Telnet смотрим результат

Запись в базы данных

Так-как JDBCAppender предназначен для работы с БД он имеет свои дополнительные настройки. Это:

Начинаем с базы данных. В java, начиная с 1.6 уже имеется встроенная база - JavaDB(это Apache Derby только называется по другому), поэтому пример будет с ней. Если в вашей системе установлена другая БД придётся проводить аналогичные шаги для неё. Многие БД могут работать в трёх режимах embedded(встроенная в приложение), in memory(база целиком находится в оперативной памяти компьютера), server(база обслуживает запроосы от локальных или удалённых пользователей). Первый и второй режимы имеют функциональность схожую с работой самого log4j, имеется в виду локальная запись и один владелец БД для embedded режима, что походит на запись в файл. Для in memory режима закрытие приложения БД приведёт к потере данных. Использовать эти режимы можно, но не имеет особого смысла. Так, что рассматриваем режим работы server.

Многие базы данных имеют инструмент для непосредственной работы с ними. В случае Derby это ij. Первое, что надо сделать - проверить настройки системы, для этого открываем терминал и вводим ij, если получаем в ответ command not found(команда не найдена) или что-то похожее значит в системе не указан путь к БД. Это можно преодолеть вызывая не только имя команды, но и полный путь к ней. Например путь к БД будет c:\Program Files\sun\javadb, тогда утилиту можно запустить набрав в командной строке "c:\Program Files\Sun\javadb\bin\ij". В Linux можно поступить аналогично, а можно создать ссылку на файл ij и поместить её в папку bin домашней директории. Можно так-же прописать в системе пути к исполняемым файлам базы данных. Для этого в Windows в свойствах системы открывают окно редактирования переменных системы и вводят новую переменную DERBY_HOME с значением пути к папке bin в примере это c:\Program Files\sun\javadb, к переменной PATH добавляют ";DERBY_HOME/bin". Linux-пользователи могут проделать аналогичные действия, отредактировав файл .bashrc домашней директории:
DERBY_HOME=/путь/к/директории/bin/базы/данных
export DERBY_HOME
PATH=$PATH:$DERBY_HOME/bin
export PATH
Повторно вводим ij в командной строке. Если всё нормально получим в ответ:
версия ij .
ij >
Теперь с Derby можно работать:

Windows-пользователи должны в приведённом выше коде переменную среды обозначать как %DERBY_HOME%. Всё может работать и без назначения переменной среды DERBY_HOME. В таком случае все относительные пути заменяются на полный путь к соответствующему файлу(jar-файлы или ij).

В примере надо создать несколько записей в DB. Я пошёл путём сокращения работы при создании Main6 класса, за что поплатился делая записи в журнал внутри цикла - в реальных приложениях так делать не стоит.

Буферизация вывода.

Давайте разберем реальные случаи, в которых логирование решало бы проблему. Вот пример из моей работы. Есть точки приложений, которые интегрируются с другими сервисами. Я использую логирование этих точек для “алиби”: если интеграция не сработает, будет легко разобраться, с какой стороны возникла проблема. Еще желательно логировать важную информацию, которая сохраняется в базу данных. Например создание пользователя администратора. Это как раз то, что хорошо бы логировать.

Инструменты для логирования в Java

  • log4j
  • JUL — java.util.logging
  • JCL — jakarta commons logging
  • Logback
  • SLF4J — simple logging facade for java

System.err.println

Первоначально был, разумеется, System.err.println (вывод записи в консоль). Его и сейчас используют для быстрого получения лога при дебаге. Конечно, говорить о каких-то настройках здесь не приходится, поэтому просто запомним его и пойдем дальше.

Log4j

Это уже было полноценное решение, которое создавалось из потребностей разработчиков. Получился действительно интересный инструмент, который можно использовать. В силу разных обстоятельств это решение так и не попало в JDK, чем очень расстроило все комьюнити. В log4j были возможности по конфигурации таким образом, чтобы можно было включить логирование в пакете com.example.type и выключить его в подпакете com.example.type.generic . Это позволяло быстро отсечь то, что нужно логировать, от того, что не нужно. Здесь важно отметить, что есть две версии log4j: 1.2.х и 2.х.х, которые несовместимы друг с другом. log4j добавил такое понятие как appender, то есть инструмент, с помощью которого записываются логи и layout — форматирование логов. Это позволяет записывать только то, что нужно и как нужно. Больше о appender поговорим чуть позже.

JUL — java.util.logging

Одно из ключевых преимуществ это решения — JUL включен в JDK (Java development kit). К сожалению, при его разработке за основу взяли не популярный log4j, а решение от IBM, что и повлияло на его развитие. По факту на данный момент JUL есть, но им никто не пользуется. Из “такого себе”: в JUL уровни логирования отличаются от того, что есть в Logback, Log4j, Slf4j, и это ухудшает понимание между ними. Создание логгера более менее похожее. Для этого нужно сделать импорт: Имя класса специально передается для того, чтобы знать, откуда идет логирование. Начиная с Java 8, можно передавать Supplier<String> . Это помогает считать и создавать строку только в тот момент, когда это действительно нужно, а не каждый раз, как это было до этого. Только с выходом Java 8 разработчики решили важные проблемы, после чего JUL по-настоящему стало возможно в использовании. А именно, методы с аргументом Supplier<String> msgSupplier , как показано ниже:

JCL — jakarta commons logging

Из-за того, что долгое время не было промышленного стандарта в логировании и был период, когда многие создавали свой кастомный логгер, решили выпустить JCL — общую обертку, которая использовалась бы над другими. Почему? Когда в проект добавлялись какие-то зависимости, они могли использовать логгер, отличный от логгера на проекте. Из-за этого они транзитивно добавлялись в проект, что создавало реальные проблемы при попытке все это собрать воедино. К сожалению, обертка была очень бедна на функциональность и никаких дополнений не вносила. Наверное, было бы удобно, если бы все использовали JCL для работы. Но на деле так не получалось, поэтому на данный момент применять JCL — не лучшая идея.

Logback

  • улучшена производительность;
  • добавлена нативная поддержка slf4j;
  • расширена опция фильтрации.

SLF4J — simple logging facade for java

Что нужно логировать

  1. Начало/конец работы приложения. Нужно знать, что приложение действительно запустилось, как мы и ожидали, и завершилось так же ожидаемо.
  2. Вопросы безопасности. Здесь хорошо бы логировать попытки подбора пароля, логирование входа важных юзеров и т.д.
  3. Некоторые состояния приложения. Например, переход из одного состояния в другое в бизнес процессе.
  4. Некоторая информация для дебага, с соответственным уровнем логирования.
  5. Некоторые SQL скрипты. Есть реальные случаи, когда это нужно. Опять-таки, умелым образом регулируя уровни, можно добиться отличных результатов.
  6. Выполняемые нити(Thread) могут быть логированы в случаях с проверкой корректной работы.

Популярные ошибки в логировании

  1. Избыток логирования. Не стоит логировать каждый шаг, который чисто теоретически может быть важным. Есть правило: логи могут нагружать работоспособность не более, чем на 10%. Иначе будут проблемы с производительностью.
  2. Логирование всех данных в один файл. Это приведет к тому, что в определенный момент чтение/запись в него будет очень сложной, не говоря о том, что есть ограничения по размеру файлов в определенных системах.
  3. Использование неверных уровней логирования. У каждого уровня логирования есть четкие границы, и их стоит соблюдать. Если граница расплывчатая, можно договориться какой из уровней использовать.

Уровни логирования

  • OFF: никакие логи не записываются, все будут проигнорированы;
  • FATAL: ошибка, после которой приложение уже не сможет работать и будет остановлено, например, JVM out of memory error;
  • ERROR: уровень ошибок, когда есть проблемы, которые нужно решить. Ошибка не останавливает работу приложения в целом. Остальные запросы могут работать корректно;
  • WARN: обозначаются логи, которые содержат предостережение. Произошло неожиданное действие, несмотря на это система устояла и выполнила запрос;
  • INFO: лог, который записывает важные действия в приложении. Это не ошибки, это не предостережение, это ожидаемые действия системы;
  • DEBUG: логи, необходимые для отладки приложения. Для уверенности в том, что система делает именно то, что от нее ожидают, или описания действия системы: “method1 начал работу”;
  • TRACE: менее приоритетные логи для отладки, с наименьшим уровнем логирования;
  • ALL: уровень, при котором будут записаны все логи из системы.

Запись и отправка логов: Appender

  • для записи в файл — решение DailyRollingFileAppender;
  • для получения данных в консоль приложения — ConsoleAppender;
  • для записи логов в базу данных — JDBCAppender;
  • для контроля передачи через TCP/IP — TelnetAppender;
  • для того, чтобы запись логов не била по быстродействию — AsyncAppender.

Узлы логирования

Думаю, ни для кого не секрет, что такое логгеры и для чего они нужны. За время существования java было создано немало фреймворков логгирования. Среди самых известных можно выделить:

  • JUL — java.util.logging
  • log4j
  • JCL — jakarta commons logging
  • Logback
  • SLF4J — simple logging facade for java

System.err.println

Первым и самым примитивным способом логгирования был метод System.err.println. Думаю, комментарии излишние, достаточно взглянуть на приведенный ниже код:

Java.util.logging

Данный фреймворк включен в стандарт и поставляется вместе с JDK, поэтому ничего дополнительно скачивать и подключать вам не надо. JUL имеет следующие уровни логгирования по возрастанию: FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE, а так же ALL и OFF, включающий и отключающий все уровни соответственно.
Логгер создается вызовом одного из статических методов класса java.util.logging.Logger:


Вторая группа методов имеет следующие вариации:


Для того что бы JUL применил данную конфигурацию нужно передать параметр -Djava.util.logging.config.file = <путь до файла>, либо при старте приложения выполнить код:

Log4j

Данный фреймворк на текущий момент имеет уже вторую версию, которая увы не совместима с первой. Поскольку первая версия log4j существует достаточно давно и, в виду ее большой популярности, существует не мало статей на просторах интернета, сегодня мы рассмотрим вторую. Для использования log4j2 вам необходимо подключить библиотеки log4j-api-2.x и log4j-core-2.x. Log4j имеет несколько отличное от JUL именование уровней логгирования: TRACE, DEBUG, INFO, WARN, ERROR, FATAL, а так же ALL и OFF включающий и отключающий все уровни соответственно.
Логгер создается вызовом статического метода класса org.apache.logging.log4j.Logger:


Логгер умеет принимать помимо привычных нам String, Object и Throwable еще два новых типа — MapMessage и Marker:


В классическом для логгеров стиле методы делятся на два типа: совпадающие с названием уровня логгирования и методы log, принимающие уровень логгирования в качестве параметра. Первые имеют вид:


Методы log в log4j2 выглядят так:

  • BurstFilter
  • CompositeFilter
  • DynamicThresholdFilter
  • MapFilter
  • MarkerFilter
  • RegexFilter
  • StructuredDataFilter
  • ThreadContextMapFilter
  • ThresholdFilter
  • TimeFilter
  • AsyncAppender
  • ConsoleAppender
  • FailoverAppender
  • FileAppender
  • FlumeAppender
  • JDBCAppender
  • JMSAppender
  • JPAAppender
  • MemoryMappedFileAppender
  • NoSQLAppender
  • OutputStreamAppender
  • RandomAccessFileAppender
  • RewriteAppender
  • RollingFileAppender
  • RollingRandomAccessFileAppender
  • RoutingAppender
  • SMTPAppender
  • SocketAppender
  • SyslogAppender

Commons-logging

Довольно старый проект, который представляет собой обертку над JUL и log4j, не привносящая никакого дополнительного функционала. Уровни логгирования у JCL совпадают с log4j, а в случае взаимодействия с JUL происходит следующее сопоставление:


Для использования JCL подключаем commons-logging-1.x.jar. Создаем логгер вызовом метода фабрики:


Методы JCL очень простые, совпадают с названием уровней логгирования, принимают только объекты и исключения и имеют две вариации:


Указать файл конфигурации JCL можно следующим образом:

Logback

Данный фреймворк используется только в связке с оберткой SLF4J, которую мы будем рассматривать позднее. Для начала работы вам необходимы logback-core-1.x.jar и logback-classic-1.x.x.jar, а также slf4j-api-1.x.x.jar.
Взаимодействие с логгером мы будем осуществлять через API предоставляемый оберткой SLF4J. Уровни логгирования совпадают с log4j. Создание логгера в таком случае выглядит следующим образом:


Названия методов совпадают с уровнями логгирования и имеют вид:

SLF4J

Хотя файлы журналов часто содержат полезную информацию, они, естественно, со временем увеличиваются в размерах, и, если им позволено расти бесконечно, их размер может стать проблемой.

Библиотеки ведения журнала решают эту проблему с помощью добавляющих файлов, которые автоматически «прокручивают» или архивируют текущий файл журнала и возобновляют запись в новый файл при возникновении определенных предопределенных условий, тем самым предотвращая нежелательные простои.

В этой статье мы рассмотрим, как настроить добавляемые файлы в некоторых из наиболее широко используемых библиотек журналов - Log4j, Log4j2 и Slf4j.

Мы покажем, как свернуть файлы журнала в зависимости от размера, даты / времени и комбинации размера и даты / времени. Мы также продемонстрируем, как настроить каждую библиотеку для автоматического сжатия и последующего удаления старых файлов журнала, что избавит нас от написания утомительного служебного кода.

2. Наш образец приложения

Мы будем использовать этот пример, чтобы продемонстрировать несколько функций различных типов добавляемых файлов.

3. Прокрутка файловых приложений в Log4j

3.1. Зависимости Maven

Прежде всего, чтобы использовать Log4j в вашем приложении, добавьте эту зависимость в файл pom.xml вашего проекта :

Чтобы использовать дополнительные приложения, предоставляемые apache-log-extras, которые мы будем использовать в следующих примерах, добавьте следующую зависимость, обязательно используя ту же версию, которую мы объявили для Log4j, чтобы обеспечить полную совместимость:

Вы можете найти последний выпуск Log4j и Apache Log4j Extras на Maven Central.

3.2. Прокрутка в зависимости от размера файла

В Log4j, как и в других библиотеках журналирования, прокрутка файлов делегируется приложению. Давайте посмотрим на конфигурацию приложения для роликового файла в Log4j, которое запускается в зависимости от размера файла:

Здесь мы настроили Log4j для прокрутки файла журнала, когда его размер достигнет 5 КБ, используя параметр MaxFileSize . Мы также проинструктировали Log4j хранить максимум два свернутых файла журнала с помощью параметра MaxBackupIndex .

При запуске нашего примера приложения мы получили следующие файлы:

Затем, после того как новый app.log превысил ограничение в 5 КБ , этот процесс прокатки был повторен. На этот раз app.log.1 был перемещен в app.log.2, освободив место для другого нового, пустого app.log .

Процесс прокрутки повторялся несколько раз во время выполнения, но, поскольку мы настроили наш appender для хранения не более двух свернутых файлов, нет ни одного файла с именем app.log .

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

Для этого мы собираемся использовать другие более мощные, гибкие и настраиваемые приложения Log4j, которые поставляются в специальном пакете под названием apache-log4j-extras .

Дополнения, содержащиеся в этом артефакте, предлагают множество опций для точной настройки прокрутки журнала, а также представляют различные концепции запуска политики и политики прокрутки . Политика запуска описывает, когда должна произойти прокрутка, а политика прокрутки описывает, как следует выполнять прокрутку . Эти две концепции являются ключевыми для скользящих файлов журналов и используются более или менее явно и другими библиотеками, как мы скоро увидим.

3.3. Прокатка с автоматическим сжатием

Вернемся к примеру с Log4j и улучшим нашу настройку, добавив автоматическое сжатие свернутых файлов для экономии места:

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

Также отметим, что FileNamePattern оканчивается расширением « .gz» . Каждый раз, когда мы используем расширение, связанное с поддерживаемым сжатым форматом, мы будем сжимать старые свернутые файлы без каких-либо дополнительных усилий с нашей стороны.

Теперь, когда мы запускаем приложение, мы получаем другой набор файлов журнала:

The file app.current.log is where the last logs occurred. Previous logs have been rolled and compressed when their size reached the set limit.

3.4. Rolling Based on Date and Time

In other scenarios, you may want to configure Log4j to roll the files based on the date and time of the log messages instead of the size of the file. In a web application, for instance, you may want to have all the log messages issued in one day in the same log file.

To do that, you can use the TimeBasedRollingPolicy. With this policy, it is mandatory to specify a template for the path of the log file that contains a time-related placeholder. Each time a log message is issued, the appender verifies what the resulting log path would be, and if it differs from the last used path, then a roll will occur. Here's a quick example that configures such an appender:

3.5. Rolling Based on Size and Time

Combining the SizeBasedTriggeringPolicy and the TimeBasedRollingPolicy, you can obtain an appender that rolls based on date/time, and when the size of the file reaches the set limit, it rolls based on size too:

When we ran our application with this setup, we obtained the following log files:

The file app.19-26.1481393470902.log is where current logging takes place. As you can see, all the logs in the interval between 19:25 and 19:26 are stored in multiple compressed log files with names starting with “app.19-25″. The “%i” placeholder is replaced by an ever increasing number.

4. Rolling File Appenders in Log4j2

4.1. Maven Dependencies

To use Log4j2 as our preferred logging library, we need to update our project's POM with the following dependency:

As usual, you can find the latest version on Maven Central.

4.2. Rolling Based on File Size

Let's change our example application to use the Log4j2 logging libraries and let's explore now how we can set up file rolling based on the size of the log file in the log4j2.xml configuration file:

In the Policies tag, we specified all the triggering policies we want to apply. OnStartupTriggeringPolicy triggers a roll every time the application starts, which could be useful for stand-alone applications. We then specified a SizeBasedTriggeringPolicy stating that a roll should occur whenever the log file reaches 5KB.

4.3. Rolling Based on Date and Time

Using the policies offered by Log4j2, let's set up an appender to roll and compress the log file based on time:

Here the key is the use of TimeBasedTriggeringPolicy that allows us to use time-related placeholders in the template of the rolled file names. Note that since we needed only a single triggering policy, we do not have to use the Policies tag as we did in the previous example.

4.4. Rolling Based on Size and Time

As previously described, a more compelling scenario is to roll and compress log files based on both time and size. Here is an example of how we can set up Log4j2 for this task:

With this configuration, we stated that a roll should occur based on time and size. The appender is able to understand what time interval we're referring to because of the pattern used for the file name, “app.%d.%i.log.gz”, which implicitly sets a roll to occur every minute and compresses the rolled file.

We also added a DefaultRolloverStrategy to delete old rolled files matching certain criteria. We configure ours to delete files that match the given pattern when they are older than 20 days.

4.5. Maven Dependencies

To use Log4j2 as our preferred logging library, we need to update our project's POM with the following dependency:

As usual, you can find the latest version on Maven Central.

5. Rolling File Appenders in Slf4j

5.1. Maven Dependencies

When you want to use Slf4j2 with a Logback backend as logging libraries, add this dependency to your pom.xml:

As usual, you can find the latest version on Maven Central.

5.2. Rolling Based on File Size

Let's see now how to use Slf4j instead, with its default back-end Logback. Let's explore how we can set up file rolling in the configuration file logback.xml, which is placed in the application's classpath:

Again we encounter the concept of rolling policy. The basic mechanism is the same as that used by Log4j and Log4j2. The FixedWindowRollingPolicy allows us to use an index placeholder in the name pattern of the rolled file.

When the size of the log file grows over the configured limit, a new file is allocated, and the old content is stored as the first file of the list, shifting the existing ones one place further.

5.3. Rolling Based on Time

In Slf4j, we can roll a log file based on time using the provided TimeBasedRollingPolicy. This policy allows us to specify the template name of the rolling file using time and date related placeholders:

5.4. Rolling Based on Size and Time

If you need to roll a file both based on both time and size, you can use the provided SizeAndTimeBasedRollingPolicy. When using this policy, you must specify both a time-related placeholder and an index placeholder.

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

6. Заключение

Как мы видели, использование библиотеки журналов для сворачивания файлов избавляет вас от бремени ручного управления файлами журналов, позволяя сосредоточиться на разработке бизнес-логики. Прокручивающиеся файловые приложения - ценный инструмент, который должен быть в наборе инструментов каждого разработчика.

Как обычно, вы найдете исходники на GitHub, где примеры приложений, представленные в этой статье, настроены для ведения журнала с использованием нескольких различных скользящих настроек, чтобы вы могли найти хорошую базовую конфигурацию для дальнейшей настройки в соответствии с вашими потребностями.

Читайте также: