Чуть ранее мы рассмотрели библиотеку логирования Pantheios. Пришла очередь ознакомится с более известной Apache log4cxx. Библиотека является имплементаций принципов и механизмов из log4j (библиотека логирования Java) на ��зыке C++. Проект выглядит «мертвым», по крайней мере круных изменений в течение последнего года не наблюдается, впрочем это не повод не посмотреть (а может быть и использовать) эту библиотеку.
Я рассматриваю процесс сборки и работы с библиотекой на платформе Windows, используя VisualStudio 2010 SP1. Логи как обычно хочется иметь как на консоли, так и в файле. Особо стоит подчеркнуть что логи могут содержать симолы национальных алфавитов (читай unicode).
Статья расчитана на начинающих и содержит материал для быстрого старта, а не глубокое изучение библиотеки.
Для начала нам надо скачать зависимости и собственно саму библиотеку. По хорошему, надо бы скачать её с SVN проекта, т.к. судя по коммитам исправлены баги, но я почему-то решил не рисковать и попытать счастья с стабильной версией 0.10.0.
Итак, поехали!
Качаем:
фуф, самое сложное позади…
Распаковываем:
Мне sed на машине не нужен как таковой, но он нужен для скрипта конфигурирования, его надо бы бросить сюда: C:\temp\log4cxx\apache-log4cxx-0.10.0\ и все dll файлы, от которых он зависит рядом положить. Эстеты могут бросить и sed и dll-ки в %SystemRoot%\System32\, если sed им в дальнейшем нужен.
Далее: запускаем командную строку VS2010 и перейдя в каталог C:\temp\log4cxx\apache-log4cxx-0.10.0\ делаем последовательно:
Ошибок быть не должно.
Настала очередь собственно сборки. Тут стоит запустить саму студию (devenv) и открыть в ней c:\temp\log4cxx\apache-log4cxx-0.10.0\projects\log4cxx.dsw. Студия попросит переконвертировать проекты, что нам и надо.
Нажимаем build, но чай пить не идем. Процесс сборки достаточно быстро завершится ~300 ми ошибками. Ругаться будет на LOG4CXX_LIST_DEF макрос. Все такие макросы надо вынести перед классом (они объявлены внутри класса).
После убирания этих ощибок будут ошибки, связанные с неизвестностью std::insert_iterator — просто добавьте #include <iterator> вначале файла.
Далее появится ошибки об неопределенности «KeySet» — на все такие ошибки надо поменять (пример):
(т.к. мы вынесли макрос, формирующий эти самые KeySet вне классов).
После этого «шаманства» сборка пройдет успешно, а вот линковка «завалится» с сообщениями об неопределнности некоторых функций. Это просто студия при конвертации забыла сделать ссылки на нужные файлы в проекте.
Их надо попросту внести в свойства проекте log4cxx (я захардкодил пути для простоты абсолютными, т.к. мне это надо только на период одноразовой сборки):


после чего и линковка заработает.
log4cxx оперирует понятиями appender-ов, layout-ов и target-ами.
appender — определяет набор параметров для получателя (target) потока сообщений (лог строк по сути), содержит в себе ссылку на layout, который в свою очередь определяет правила форматирования сообщения.
Подробнее об архитектуре можно прочесть на сайте проекта.
Я предпочитаю затягивать в свои программы подобные фундаментальные библиотеки через переменные среды (но т.к. работаю с разными версиями библиотек стараюсь не определять их как переменные среды для пользователя). Поэтому запустив коммандную строку VS2010 вбиваем примерно следующее:
(я собирал в дебаг режиме, для release понятное дело пути немного иные).
Далее создадим простой проект C++ Console Application — это и будет наш тестовый проект.
В нём доопределим пути до общих include файлов и библиотек в настройке проекта, согласно нашим переменным среды:

и для линковки:


Пришла очередь добавить нужные нам include-ы:
Теперь надобно сделать конфигурационный файл. Я сделал его таким:
Подробнее можно прочесть в документации к log4j, т.к. форматы файлов «почти совпадают».
Ну и ниже тестовая программа:
Замечу «хитрость» использования:
из цикла «как это работает». Дело в том, что второй аргумент макроса передается на вход в stream, и именно поэтому сюда можно писать несколько сообщений (не только текст), используя operator <<.
Мы посмотрели сборку и базовую настройку log4cxx на простом примере.
Из плюсо�� библиотеки стоит выделить настраиваемость через конфигурационный файл, поддержку unicode «из коробки» (включая различные кодировки выходных файлов).
Из минусов надо заметить относительную сложность сборки, также поговаривают что библиотека течёт и не такая уж и быстрая.
Вне этого топика осталось: advanced конфигурирование, сравнение с другими логгерами, проверка «мифа о течах».
Приятного логирования!
Общие замечания
Я рассматриваю процесс сборки и работы с библиотекой на платформе Windows, используя VisualStudio 2010 SP1. Логи как обычно хочется иметь как на консоли, так и в файле. Особо стоит подчеркнуть что логи могут содержать симолы национальных алфавитов (читай unicode).
Статья расчитана на начинающих и содержит материал для быстрого старта, а не глубокое изучение библиотеки.
Получение библиотеки
- Сайт библиотеки: http://logging.apache.org/log4cxx/index.html
- Лицензия: Apache License, Version 2.0
- Зависит от: Apache Portable Runtime (APR) (http://apr.apache.org/)
- Требуется при сборке: sed (из GNU Utils)
Сборка
Для начала нам надо скачать зависимости и собственно саму библиотеку. По хорошему, надо бы скачать её с SVN проекта, т.к. судя по коммитам исправлены баги, но я почему-то решил не рисковать и попытать счастья с стабильной версией 0.10.0.
Итак, поехали!
Качаем:
исходники: www.apache.org/dyn/closer.cgi/logging/log4cxx/0.10.0/apache-log4cxx-0.10.0.tar.gz
APR: apr.apache.org/download.cgi (качать надо APR 1.4.2, APR-util 1.3.10 , APR iconv 1.2.1)
Sed: sourceforge.net/projects/gnuwin32/files//sed/4.2.1/sed-4.2.1-bin.zip/download
и зависимости для Sed:
sourceforge.net/projects/gnuwin32/files/libintl/0.14.4/libintl-0.14.4-bin.zip/download
sourceforge.net/projects/gnuwin32/files/libiconv/1.9.2-1/libiconv-1.9.2-1-bin.zip/download
sourceforge.net/projects/gnuwin32/files/regex/2.7/regex-2.7-bin.zip/download
фуф, самое сложное позади…
Распаковываем:
- исходники в C:\temp\log4cxx_test\apache-log4cxx-0.10.0\
- APR в C:\temp\log4cxx_test\apr\ (переименовать папку архивную не забудьте)
- APR Util в C:\temp\log4cxx_test\apr-util\ (переименовать папку архивную не забудьте)
- APR в C:\temp\log4cxx_test\apr-util\ (переименовать папку архивную не забудьте)
Мне sed на машине не нужен как таковой, но он нужен для скрипта конфигурирования, его надо бы бросить сюда: C:\temp\log4cxx\apache-log4cxx-0.10.0\ и все dll файлы, от которых он зависит рядом положить. Эстеты могут бросить и sed и dll-ки в %SystemRoot%\System32\, если sed им в дальнейшем нужен.
Далее: запускаем командную строку VS2010 и перейдя в каталог C:\temp\log4cxx\apache-log4cxx-0.10.0\ делаем последовательно:
>configure
>configure-aprutil
Ошибок быть не должно.
Настала очередь собственно сборки. Тут стоит запустить саму студию (devenv) и открыть в ней c:\temp\log4cxx\apache-log4cxx-0.10.0\projects\log4cxx.dsw. Студия попросит переконвертировать проекты, что нам и надо.
Нажимаем build, но чай пить не идем. Процесс сборки достаточно быстро завершится ~300 ми ошибками. Ругаться будет на LOG4CXX_LIST_DEF макрос. Все такие макросы надо вынести перед классом (они объявлены внутри класса).
После убирания этих ощибок будут ошибки, связанные с неизвестностью std::insert_iterator — просто добавьте #include <iterator> вначале файла.
Далее появится ошибки об неопределенности «KeySet» — на все такие ошибки надо поменять (пример):
LoggingEvent::KeySet set;
на
KeySet set;
(т.к. мы вынесли макрос, формирующий эти самые KeySet вне классов).
После этого «шаманства» сборка пройдет успешно, а вот линковка «завалится» с сообщениями об неопределнности некоторых функций. Это просто студия при конвертации забыла сделать ссылки на нужные файлы в проекте.
Их надо попросту внести в свойства проекте log4cxx (я захардкодил пути для простоты абсолютными, т.к. мне это надо только на период одноразовой сборки):


после чего и линковка заработает.
Кратко об архитектуре
log4cxx оперирует понятиями appender-ов, layout-ов и target-ами.
appender — определяет набор параметров для получателя (target) потока сообщений (лог строк по сути), содержит в себе ссылку на layout, который в свою очередь определяет правила форматирования сообщения.
Подробнее об архитектуре можно прочесть на сайте проекта.
Тестируем работу
Я предпочитаю затягивать в свои программы подобные фундаментальные библиотеки через переменные среды (но т.к. работаю с разными версиями библиотек стараюсь не определять их как переменные среды для пользователя). Поэтому запустив коммандную строку VS2010 вбиваем примерно следующее:
>SET LOG4CXX=C:\temp\log4cxx\apache-log4cxx-0.10.0\src\main\include\
>SET LOG4CXXLIB=C:\temp\log4cxx\apache-log4cxx-0.10.0\projects\Debug\
>devnenv
(я собирал в дебаг режиме, для release понятное дело пути немного иные).
Далее создадим простой проект C++ Console Application — это и будет наш тестовый проект.
В нём доопределим пути до общих include файлов и библиотек в настройке проекта, согласно нашим переменным среды:

и для линковки:


Пришла очередь добавить нужные нам include-ы:
//apache log4cxx
#pragma warning(push)
#pragma warning(disable: 4231 4250)
//warning C4231: nonstandard extension used : 'extern' before template explicit instantiation c:\libs\apache\apache-log4cxx-0.10.0\src\main\include\log4cxx\rolling\timebasedrollingpolicy.h 221 p2jbTestApp
//warning C4250: 'log4cxx::rolling::TimeBasedRollingPolicy' : inherits 'log4cxx::rolling::RollingPolicyBase::log4cxx::rolling::RollingPolicyBase::setOption' via dominance
#include <log4cxx/rolling/rollingfileappender.h>
#include <log4cxx/logger.h>
#include <log4cxx/consoleappender.h>
#include <log4cxx/logmanager.h>
#include <log4cxx/patternlayout.h>
#include <log4cxx/rolling/timebasedrollingpolicy.h>
#include <log4cxx/helpers/simpledateformat.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/xml/domconfigurator.h>
#pragma warning(pop)
Теперь надобно сделать конфигурационный файл. Я сделал его таким:
<?xml version="1.0" encoding="UTF-8" ?>
<!-- debug="true" -->
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" >
<appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} [%t] %level %c{2}#%M %F:%L - %m%n"/>
</layout>
</appender>
<appender name="DailyRollingFileAppender" class="org.apache.log4j.rolling.DailyRollingFileAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} [%t] %level %c{2}#%M %F:%L - %m%n"/>
</layout>
<param name="Encoding" value="UTF-16" />
<param name="file" value="logfile.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="append" value="true"/>
</appender>
<root>
<priority value="all" />
<appender-ref ref="DailyRollingFileAppender"/>
<appender-ref ref="ConsoleAppender"/>
</root>
</log4j:configuration>
Подробнее можно прочесть в документации к log4j, т.к. форматы файлов «почти совпадают».
Ну и ниже тестовая программа:
void foo(void*)
{
log4cxx::LoggerPtr logger = log4cxx::Logger::getRootLogger();
for(int i=0;i<10;++i){
LOG4CXX_DEBUG((logger), L"debug" << L"other debug message");
LOG4CXX_TRACE((logger), L"trace");
LOG4CXX_INFO((logger), L"привет, мир!");
LOG4CXX_WARN((logger), L"WARN");
LOG4CXX_ERROR((logger), L"error");
LOG4CXX_FATAL((logger), L"FATAL");
}
}
int _tmain(int argc, _TCHAR* argv[])
{
setlocale(LC_ALL, "Russian_Russia.OCP"); //иначе русский не будет нормально работать
TCHAR selfName[MAX_PATH];
HMODULE hModule = GetModuleHandle(NULL);
GetModuleFileName(hModule, selfName, _countof(selfName));
std::wstring configFile(selfName);
configFile.append(L".logconfig");
log4cxx::xml::DOMConfigurator::configure(configFile);
for(int i=0;i<10;++i){
_beginthread(foo,0,NULL);
}
std::cin.get();
return 0;
}
Замечу «хитрость» использования:
LOG4CXX_DEBUG((logger), L"debug" << L"other debug message");
из цикла «как это работает». Дело в том, что второй аргумент макроса передается на вход в stream, и именно поэтому сюда можно писать несколько сообщений (не только текст), используя operator <<.
Заключение
Мы посмотрели сборку и базовую настройку log4cxx на простом примере.
Из плюсо�� библиотеки стоит выделить настраиваемость через конфигурационный файл, поддержку unicode «из коробки» (включая различные кодировки выходных файлов).
Из минусов надо заметить относительную сложность сборки, также поговаривают что библиотека течёт и не такая уж и быстрая.
Вне этого топика осталось: advanced конфигурирование, сравнение с другими логгерами, проверка «мифа о течах».
Приятного логирования!
