Log4j настройка вывода в файл
Думаю, ни для кого не секрет, что такое логгеры и для чего они нужны. За время существования 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
Первый источник это Wikipedia, в ней мы сможем почерпнуть достаточно скудную информацию лишь о компании разработчике и целях проекта.
Log4j — библиотека журналирования Java программ, часть общего проекта «Apache Logging Project».
Log4j первоначально развивался в рамках зонтичного Apache Jakarta Project, ответственного за все Java-проекты Apache, но впоследствии выделился в отдельный, очень популярный проект журналирования (стандарт де-факто).
Собственно русскоязычный ресурс компании разработчика, на нем тоже есть описание целей и задач, основных возможностей и небольшие примеры использования.Ознакомившись с двумя предыдущими источниками подключить и выполнить примеры Вы конечно же сможете, но что это нам даст, спросите Вы, вряд ли кто то будет выкладывать у себя примеры со сложными реализациями. Да примеры и должны быть простыми, сразу возразят поклонники простоты и лаконичности. Но как это обычно бывает, все примитивные примеры носят мало практической пользы и любой «шаг вправо или шаг влево» повлечет за собой поиски новых источников с описанием настроек и подводных камней. Принимая во внимание все выше сказанное, начнем сначала.
- Выбор хранилища – консоль, файл, СУБД;
- Конфигурация хранилища – именование хранилища, объем хранилища, путь к хранилищу, сохранение конфигурации;
- Форматирование записей журнала – дата/время, класс/метод и т.д., гибкое форматирование.
- загрузить библиотеку фреймворка;
- создать конфигурационный файл с параметрами журналирования;
- создать объект журнала (лога) в своем приложении;
- воспользоваться методами для записи в журнал.
Каким образом хранить конфигурацию журналирования?
Есть два типа конфигурационных файлов формат XML и формат PROPERTIES. В случае одноименных файлов выше приоритет у файлов XML.Как конфигурировать файл log4j.properties или log4j.xml?
log4j.properties
1 log4j.rootCategory=DEBUG, console
4 log4j.appender.console.layout.ConversionPattern= %p %c: %m%n
<? xml version= "1.0" encoding= "UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
< log4j:configuration xmlns:log4j= "http://jakarta.apache.org/log4j/" >
< appender name= "console" class= "org.apache.log4j.ConsoleAppender" >
< param name= "Target" value= "System.out" />
< layout class= "org.apache.log4j.PatternLayout" >
< param name= "ConversionPattern" value= "%p %c: %m%n" /> </ layout >
</ appender >
<!-- Корневой logger-->
< root > < priority value = "debug" />
< appender-ref ref= "console" />
</ root >
</ log4j:configuration >
Советы по использованию Log4J
- Определите События, подлежащие записи в журнал;
- Определите ключевые Параметры, для каждого События;
- Определите Источники Событий – это самое важное, иначе ваша система логирования превратится в свалку не нужных Событий с таким же перечнем ненужных Параметров;
- Не старайтесь разделить системы логирования по приоритетам (FATAL or INFO), разделите по функциональным модулям или ключевым Объектам системы;
- Выполняйте логирование жизненного цикла Объекта;
Журналирование событий это лишь часть функциональности Вашего приложения, не стоит ставить приоритет этой задачи выше приоритета основной функциональности.
Как использовать Log4J в Java приложениях?
Для использования всех функциональных возможностей фрейворка необходимо создать объект журнала.
public static void main(String[] args) throws FileNotFoundException, IOException 1:String nameFile = "log4j.properties";
2:PropertyConfigurator.configure(nameFile);
/*1*/Logger LOG = Logger.getRootLogger();
/*2*/Logger localLog2 = Logger.getLogger("logfile");
/*3*/Enumeration append = LOG.getAllAppenders();
/*3*/while (append.hasMoreElements())
/*3*/LOG.info("Available appender " + append.nextElement());
/*3*/>
log4j.rootLogger = TRACE, console log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout.ConversionPattern=[%p] %d (%F:%M:%L)%m %n%n
log4j.appender.logfile.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
Вывод на консоль :
1: [INFO] 10:07:06 (Main.java:main:43)Available appender org.apache.log4j.ConsoleAppender@10b4199
2: [INFO] 10:07:06 (Main.java:main:45)Hi Logger info!
3: [DEBUG] 10:07:06 (Main.java:main:47)osdebug write!
4: [WARN] 10:07:06 (Main.java:main:48)logfile write!
Вывод в лог-файл D:\infolog.txt:
2009-09-15 10:07:06,811 [main] WARN logfile - logfile write!
Вывод в лог-файл D:\debuglog.txt:
2009-09-15 10:07:06,811 [main] DEBUG osdebug - osdebug write!
В строке 1 перечислены типы категорий, которые были указаны в глобальном объекте.
localLog.debug("osdebug write!");
localLog2.warn("logfile write!");
Вывод перенаправленный в лог файл, форматируется по отдельным правилам , которые указаны в категории log4.j.logger.logfile=INFO, logfile , а строка форматируется на основании шаблона
log4j.appen der.logfile.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
В файле конфигураций указана категория log4.j.logger.logfile=INFO, logfile
но вывод не будет направлен, даже если Вы замените строку вызова Logger localLog = Logger.getLogger("logfile");
В примере создано два объекта журнала, строки помечены как /*1*/ и /*2*/ , оба они ссылаются на разные объекты! В строках /*3*/ создаётся объект enumeration ? если вы вдруг просто слили чей-то конфиг и хотите посмотреть что и как внутри , он выведет все доступные(описанные) в файле конфигураций объекты appender.
Будьте внимательны при указании приоритета в вызове объекта журнала, при указании приоритета ,который не соответствует описанному в конфигурации, данные не будут записаны в журнал. Пример такого описания:
Давайте научимся следить за выполнением логики в нашей программе, для этого мы научимся использовать логирование, поймем зачем оно и где используется.
Шаг 0. Обзор
Зачем нужно логирование и что оно даёт?
Вы, как человек который администрирует магазин начнет разбераться в чем же проблема. Неопытный человек будет долго искать проблему, а опытный сразу полезет в логи сервера, но там все логи сервера и найти то что нужно вам сложно.
В этом случае решение следующее, выводить нужные вам логи в отдельный файл. Но как понять, какие из всех логов, которые сыпятся в общий лог сервера нужны вам? Для этого нужно реализовать свою систему логирования, где вы сможите указать какие логи куда выводить, или же настроить уровни логирования.
В данном уроке мы рассмотрим как сконфигурировать и начать использовать Log4j.
Шаг 1. Создаем проект и добавляем завимости
Запускаем всеми любимую Intellij IDEA и тыкаем New Project выбираем Maven Module и называем его :
Теперь в pom.xml жлбавим зависимость:
Это все зависимости, которые надо было подключить.
Шаг 2. Создание примитивной логики для примера
Давайте создадим класс в котором была бы бизнес-логика, назовем его OrderLogic:
Хочу обратить ваше внимание на то, что логика данного проекта не важна, так как мы рассматриваем логирование, для этого я и подготовил примитивную логику класса OrderLogic.
И теперь создаем Main класс:
В результате выполнения данного кода, мы получим следующее:
Как видите пока ничего нового.
Шаг 3. Конфигурируем Log4j
Чтобы гибко управлять логированием стоит создать в resources/ файл log4j.properties:
Теперь в этот файл добавим пару строк конфигураций:
Теперь давайте более детальней разберем строку формирования шаблона:
Давайте разберем реальные случаи, в которых логирование решало бы проблему. Вот пример из моей работы. Есть точки приложений, которые интегрируются с другими сервисами. Я использую логирование этих точек для “алиби”: если интеграция не сработает, будет легко разобраться, с какой стороны возникла проблема. Еще желательно логировать важную информацию, которая сохраняется в базу данных. Например создание пользователя администратора. Это как раз то, что хорошо бы логировать.
Инструменты для логирования в 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
Что нужно логировать
- Начало/конец работы приложения. Нужно знать, что приложение действительно запустилось, как мы и ожидали, и завершилось так же ожидаемо.
- Вопросы безопасности. Здесь хорошо бы логировать попытки подбора пароля, логирование входа важных юзеров и т.д.
- Некоторые состояния приложения. Например, переход из одного состояния в другое в бизнес процессе.
- Некоторая информация для дебага, с соответственным уровнем логирования.
- Некоторые SQL скрипты. Есть реальные случаи, когда это нужно. Опять-таки, умелым образом регулируя уровни, можно добиться отличных результатов.
- Выполняемые нити(Thread) могут быть логированы в случаях с проверкой корректной работы.
Популярные ошибки в логировании
- Избыток логирования. Не стоит логировать каждый шаг, который чисто теоретически может быть важным. Есть правило: логи могут нагружать работоспособность не более, чем на 10%. Иначе будут проблемы с производительностью.
- Логирование всех данных в один файл. Это приведет к тому, что в определенный момент чтение/запись в него будет очень сложной, не говоря о том, что есть ограничения по размеру файлов в определенных системах.
- Использование неверных уровней логирования. У каждого уровня логирования есть четкие границы, и их стоит соблюдать. Если граница расплывчатая, можно договориться какой из уровней использовать.
Уровни логирования
- OFF: никакие логи не записываются, все будут проигнорированы;
- FATAL: ошибка, после которой приложение уже не сможет работать и будет остановлено, например, JVM out of memory error;
- ERROR: уровень ошибок, когда есть проблемы, которые нужно решить. Ошибка не останавливает работу приложения в целом. Остальные запросы могут работать корректно;
- WARN: обозначаются логи, которые содержат предостережение. Произошло неожиданное действие, несмотря на это система устояла и выполнила запрос;
- INFO: лог, который записывает важные действия в приложении. Это не ошибки, это не предостережение, это ожидаемые действия системы;
- DEBUG: логи, необходимые для отладки приложения. Для уверенности в том, что система делает именно то, что от нее ожидают, или описания действия системы: “method1 начал работу”;
- TRACE: менее приоритетные логи для отладки, с наименьшим уровнем логирования;
- ALL: уровень, при котором будут записаны все логи из системы.
Запись и отправка логов: Appender
- для записи в файл — решение DailyRollingFileAppender;
- для получения данных в консоль приложения — ConsoleAppender;
- для записи логов в базу данных — JDBCAppender;
- для контроля передачи через TCP/IP — TelnetAppender;
- для того, чтобы запись логов не била по быстродействию — AsyncAppender.
Узлы логирования
Читайте также: