﷽
→ Последний выпуск
→ Список изменений
→ Образцы
Обзор Зачем еще одна библиотека Особенности с первого взгляда Начиная Скачать Быстрый старт Установить (необязательно) Установка аргументов приложения Конфигурация Уровень Настроить Использование файла конфигурации Использование класса el::Configurations Использование встроенных конфигураций Конфигурации по умолчанию Глобальные конфигурации Спецификаторы формата журнала Спецификаторы формата даты/времени Спецификаторы пользовательского формата Флаги регистрации Аргументы приложения Макросы конфигурации Чтение конфигураций Ведение журнала Базовый Условное ведение журнала Периодическая регистрация printf Как ведение журнала Сетевое журналирование Подробное ведение журнала Базовый Условное и случайное Подробный уровень Проверьте, включено ли подробное ведение журнала ВМодуль Регистрация новых регистраторов Отменить регистрацию регистраторов Заполнение существующих идентификаторов регистраторов Совместное использование репозитория журналов Дополнительные возможности Отслеживание производительности Условное отслеживание производительности Используйте данные отслеживания производительности Ротация файла журнала Обработка сбоев Установка пользовательских обработчиков сбоев Трассировка стека Многопоточность ПРОВЕРИТЬ Макросы Ошибка регистрации() Использование системного журнала STL-ведение журнала Поддерживаемые шаблоны Журналирование Qt Повышение регистрации Журналирование wxWidgets Расширение библиотеки Регистрация вашего собственного класса Ведение журнала стороннего класса Ручная очистка и смена файлов журналов Записать обратный вызов диспетчеризации Обратный вызов регистрации регистратора Асинхронное ведение журнала Вспомогательные классы Вклад Отправка патчей Сообщить об ошибке Совместимость Построить матрицу Лицензия Отказ от ответственности
Easylogging++ — это эффективная библиотека журналирования с одним заголовком для приложений C++. Это чрезвычайно мощный, легко расширяемый и настраиваемый продукт в соответствии с требованиями пользователя. Он предоставляет возможность писать свои собственные приемники (с помощью функции, называемой LogDispatchCallback
). Эта библиотека в настоящее время используется сотнями проектов с открытым исходным кодом на github и других сайтах управления контролем исходного кода с открытым исходным кодом.
Это руководство предназначено для Easylogging++ v9.97.1. Информацию о других версиях см. в соответствующем выпуске на github.
Вас также может заинтересовать сервер регистрации остатков.
Перейти к началу
Если вы работаете над небольшой утилитой или большим проектом на C++, эта библиотека может пригодиться. Он основан на одном заголовке и требует только ссылки на один исходный файл. (Изначально это был только заголовок, но в выпуске № 445 он был изменен на использование исходного файла. Вы все еще можете использовать только заголовок в версии 9.89).
Эта библиотека была разработана с учетом различных соображений (т. е. портативности, производительности, удобства использования, функций и простоты настройки).
Зачем еще одна библиотека? Что ж, ответ довольно прост, используйте его в том виде, в котором вы его написали, чтобы вы могли исправлять проблемы (если таковые имеются) по ходу дела или поднимать их на github. Вдобавок к этому, я лично не видел ни одной библиотеки журналирования на основе одного заголовка с таким дизайном, который можно было бы настроить на ходу, расширить под свои нужды и получить высокую производительность. Я видел другие библиотеки журналирования с одним заголовком для C++, но либо они используют внешние библиотеки, например, boost или Qt, для поддержки определенных функций, таких как многопоточность, регулярное выражение или дата и т. д. В этой библиотеке есть все встроенное, чтобы предотвратить использование внешних библиотек, Не то чтобы мне не нравились эти библиотеки, на самом деле я их люблю, но поскольку не все проекты используют эти библиотеки, я не мог рисковать и зависеть от них.
Перейти к началу
Easylogging++ обладает множеством функций, которые потребуются как обычному, так и продвинутому разработчику при написании программного обеспечения;
Перейти к началу
Загрузите последнюю версию из последней версии
Информацию о других выпусках можно найти на странице выпусков. Если ваше приложение не поддерживает C++11, рассмотрите возможность использования версии 8.91. Это стабильная версия для C++98 и C++03, в которой отсутствуют некоторые функции.
Перейти к началу
Чтобы начать работу с Easylogging++, вы можете выполнить три простых шага:
easylogging++.h
и easylogging++.cc
)# include " easylogging++.h "
INITIALIZE_EASYLOGGINGPP
int main ( int argc, char * argv[]) {
LOG (INFO) << " My first info log using default logger " ;
return 0 ;
}
Теперь скомпилируйте, используя
g++ main.cc easylogging++.cc -o prog -std=c++11
Это просто! Обратите внимание, что INITIALIZE_EASYLOGGINGPP
следует использовать один и только один раз, иначе вы получите ошибки компиляции. Это определение нескольких extern
переменных. Это означает, что его можно определить только один раз для каждого приложения. Лучшее место для размещения этого оператора инициализации — файл, где определена функция int main(int, char**)
, сразу после последнего оператора include.
Если вы хотите установить этот заголовок для всей системы, вы можете сделать это через:
mkdir build
cd build
cmake -Dtest=ON ../
make
make test
make install
Следующие параметры поддерживаются Easylogging++ cmake, и вы можете включить эти параметры, используя -D<option>=ON
lib_utc_datetime
— определяет ELPP_UTC_DATETIME
build_static_lib
— собирает статическую библиотеку для Easylogging++. С учетом вышесказанного вам все равно понадобится файл easylogging++.cc
для компиляции. Только для заголовка, проверьте версию 9.89 и ниже.
Альтернативно вы можете загрузить и установить easyloggingpp с помощью менеджера зависимостей vcpkg:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install easyloggingpp
Порт easyloggingpp в vcpkg постоянно обновляется членами команды Microsoft и участниками сообщества. Если версия устарела, создайте проблему или запрос на извлечение в репозитории vcpkg.
Перейти к началу
Всегда рекомендуется передавать аргументы приложения в Easylogging++. Некоторые функции Easylogging++ требуют установки аргументов приложения, например, подробное журналирование для установки подробного уровня или vmodules (объясняется позже). Для этого вы можете использовать вспомогательный макрос или вспомогательный класс;
int main ( int argc, char * argv[]) {
START_EASYLOGGINGPP (argc, argv);
...
}
Перейти к началу
Чтобы начать настройку библиотеки журналов, вы должны понимать уровни серьезности. Easylogging++ намеренно не использует иерархическое журналирование, чтобы полностью контролировать, что включено, а что нет. При этом все еще существует возможность использовать иерархическое ведение журнала с помощью LoggingFlag::HierarchicalLogging
. Easylogging++ имеет следующие уровни (упорядочены по иерархическим уровням):
Уровень | Описание |
---|---|
Глобальный | Общий уровень, представляющий все уровни. Полезно при настройке глобальной конфигурации для всех уровней. |
След | Информация, которая может быть полезна для обратного отслеживания определенных событий — в основном полезна, чем журналы отладки. |
Отлаживать | Информационные события, наиболее полезные разработчикам для отладки приложений. Применимо только в том случае, если NDEBUG не определен (для не-VC++) или определен _DEBUG (для VC++). |
Фатальный | Очень серьезная ошибка, которая предположительно приведет к аварийному завершению работы приложения. |
Ошибка | Информация об ошибке, но приложение продолжит работу. |
Предупреждение | Информация, отображающая ошибки в приложении, но приложение продолжит работать. |
Информация | В основном полезно для представления текущего прогресса приложения. |
Многословный | Информация, которая может быть очень полезной и зависит от уровня подробного ведения журнала. Подробное ведение журнала неприменимо к иерархическому ведению журнала. |
Неизвестный | Применимо только к иерархическому ведению журнала и используется для полного отключения ведения журнала. |
Перейти к началу
Easylogging++ легко настроить. Есть три возможных способа сделать это:
Конфигурация может выполняться с помощью файла, который загружается во время выполнения классом Configurations
. Этот файл имеет следующий формат;
* LEVEL:
CONFIGURATION NAME = "VALUE" ## Comment
ANOTHER CONFIG NAME = "VALUE"
Название уровня начинается со звезды (*) и заканчивается двоеточием (:). Настоятельно рекомендуется начинать файл конфигурации с Global
уровня, чтобы любая конфигурация, не указанная в файле, автоматически использовала конфигурацию с Global
. Например, если вы установили Filename
в Global
и хотите, чтобы все уровни использовали одно и то же имя файла, не задавайте его явно для каждого уровня, библиотека будет автоматически использовать значение конфигурации из Global
. В следующей таблице приведены конфигурации, поддерживаемые файлом конфигурации.
Имя конфигурации | Тип | Описание |
---|---|---|
Enabled | логическое значение | Определяет, включен ли соответствующий уровень для регистратора. Вы можете отключить все журналы, используя el::Level::Global |
To_File | логическое значение | Записывать или нет соответствующий журнал в файл журнала |
To_Standard_Output | логическое значение | Записывать ли журналы в стандартный вывод, например, в терминал или командную строку. |
Format | персонаж* | Определяет формат/шаблон ведения журнала для соответствующего уровня и средства ведения журнала. |
Filename | персонаж* | Определяет файл журнала (полный путь) для записи журналов для соответствующего уровня и средства ведения журнала. |
Subsecond_Precision | uint | Указывает точность до секунды (ранее называвшуюся «шириной в миллисекундах»). Ширина может находиться в диапазоне (1–6). |
Performance_Tracking | логическое значение | Определяет, включено ли отслеживание производительности. Это не зависит от логгера или уровня. При отслеживании производительности всегда используется регистратор производительности, если не указано иное. |
Max_Log_File_Size | size_t | Если размер файла журнала соответствующего уровня >= указанного размера, файл журнала будет усечен. |
Log_Flush_Threshold | size_t | Указывает количество записей журнала, которые будут храниться до тех пор, пока мы не очистим ожидающие данные журнала. |
Пожалуйста, не используйте двойные кавычки в комментариях, это может привести к неожиданному поведению.
Пример файла конфигурации
* GLOBAL:
FORMAT = "%datetime %msg"
FILENAME = "/tmp/logs/my.log"
ENABLED = true
TO_FILE = true
TO_STANDARD_OUTPUT = true
SUBSECOND_PRECISION = 6
PERFORMANCE_TRACKING = true
MAX_LOG_FILE_SIZE = 2097152 ## 2MB - Comment starts with two hashes (##)
LOG_FLUSH_THRESHOLD = 100 ## Flush after every 100 logs
* DEBUG:
FORMAT = "%datetime{%d/%M} %func %msg"
Содержимое файла конфигурации в приведенном выше примере простое. Мы начинаем с GLOBAL
уровня, чтобы переопределить все уровни. Любой явно определенный последующий уровень будет переопределять конфигурацию из GLOBAL
. Например, все уровни, кроме DEBUG
имеют одинаковый формат, т. е. дату и время и сообщение журнала. Для уровня DEBUG
у нас есть только дата (с днем и месяцем), исходная функция и сообщение журнала. Остальные конфигурации для DEBUG
используются из GLOBAL
. Кроме того, обратите внимание на {%d/%M}
в формате DEBUG
выше: если вы не укажете формат даты, используется формат по умолчанию. Значения даты/времени по умолчанию: %d/%M/%Y %h:%m:%s,%g
Дополнительную информацию об этих спецификаторах формата см. в разделе «Спецификатор формата даты/времени» ниже.
# include " easylogging++.h "
INITIALIZE_EASYLOGGINGPP
int main ( int argc, const char ** argv) {
// Load configuration from file
el::Configurations conf ( " /path/to/my-conf.conf " );
// Reconfigure single logger
el::Loggers::reconfigureLogger ( " default " , conf);
// Actually reconfigure all loggers instead
el::Loggers::reconfigureAllLoggers (conf);
// Now all the loggers will use configuration from file
}
Ваш файл конфигурации можно преобразовать в объект
el::Configurations
(с помощью конструктора), который можно использовать там, где это необходимо (как в примере выше).
Перейти к началу
Вы можете устанавливать конфигурации или сбрасывать конфигурации;
# include " easylogging++.h "
INITIALIZE_EASYLOGGINGPP
int main ( int argc, const char ** argv) {
el::Configurations defaultConf;
defaultConf. setToDefault ();
// Values are always std::string
defaultConf. set (el::Level::Info,
el::ConfigurationType::Format, " %datetime %level %msg " );
// default logger uses default configurations
el::Loggers::reconfigureLogger ( " default " , defaultConf);
LOG (INFO) << " Log using default file " ;
// To set GLOBAL configurations you may use
defaultConf. setGlobally (
el::ConfigurationType::Format, " %date %msg " );
el::Loggers::reconfigureLogger ( " default " , defaultConf);
return 0 ;
}
Конфигурацию достаточно настроить один раз. Если вас устраивает конфигурация по умолчанию, вы также можете использовать ее.
Перейти к началу
Встроенная конфигурация означает, что вы можете устанавливать конфигурации в std::string
, но обязательно добавляйте все символы новой строки и т. д. Это не рекомендуется, потому что это всегда беспорядочно.
el::Configurations c;
c.setToDefault();
c.parseFromText( " *GLOBAL: n FORMAT = %level %msg " );
Приведенный выше код устанавливает только объект Configurations, вам все равно необходимо перенастроить регистраторы, используя эти конфигурации.
Перейти к началу
Если вы хотите иметь конфигурацию для существующих и будущих регистраторов, вы можете использовать el::Loggers::setDefaultConfigurations(el::Configurations& configurations, bool configureExistingLoggers = false)
. Это полезно, когда вы работаете в довольно больших масштабах или используете стороннюю библиотеку, которая уже использует Easylogging++. Любой вновь созданный регистратор будет использовать конфигурации по умолчанию. Если вы хотите также настроить существующие средства ведения журнала, вы можете установить для второго аргумента значение true
(по умолчанию оно равно false
).
Перейти к началу
Level::Global
не имеет ничего общего с глобальными конфигурациями, это концепция, в которой вы можете регистрировать конфигурации для всех/или некоторых регистраторов и даже регистрировать новые регистраторы, используя файл конфигурации. Синтаксис файла конфигурации:
-- LOGGER ID ## Case sensitive
## Everything else is same as configuration file
-- ANOTHER LOGGER ID
## Configuration for this logger
Идентификатор регистратора начинается с двух тире. После того, как вы написали свой глобальный файл конфигурации, вы можете настроить все свои регистраторы (и зарегистрировать новые), используя одну функцию;
int main ( void ) {
// Registers new and configures it or
// configures existing logger - everything in global.conf
el::Loggers::configureFromGlobal ( " global.conf " );
// .. Your prog
return 0 ;
}
Обратите внимание: невозможно зарегистрировать новый регистратор, используя глобальную конфигурацию, без определения его конфигурации. Вы должны определить хотя бы одну конфигурацию. Другие способы регистрации регистраторов обсуждаются в разделе «Ведение журналов» ниже.
Перейти к началу
Вы можете настроить формат ведения журнала, используя следующие спецификаторы:
Спецификатор | Заменено на |
---|---|
%logger | Идентификатор регистратора |
%thread | Идентификатор потока — использует std::thread, если доступен, в противном случае GetCurrentThreadId() в Windows. |
%thread_name | Используйте Helpers::setThreadName , чтобы установить имя текущего потока (откуда вы запускаете setThreadName ). См. образец имен потоков. |
%level | Уровень серьезности (информация, отладка, ошибка, предупреждение, фатальный, подробный, трассировка) |
%levshort | Уровень серьезности (короткая версия, т. е. I для информации и соответственно D, E, W, F, V, T) |
%vlevel | Уровень детализации (применимо к подробному журналированию) |
%datetime | Дата и/или время. Шаблон можно настраивать. См. раздел «Спецификаторы формата даты/времени» ниже. |
%user | Пользователь, в данный момент запускающий приложение |
%host | Приложение имени компьютера запущено |
%file * | Имя исходного файла (полный путь). Эта функция зависит от наличия макроса __FILE__ компилятора. |
%fbase * | Имя исходного файла (только базовое имя) |
%line * | Номер исходной строки. Эта функция зависит от наличия макроса __LINE__ компиляции. |
%func * | Функция регистрации |
%loc * | Имя исходного файла и номер строки журнала (через двоеточие) |
%msg | Фактическое сообщение журнала |
% | Escape-символ (например, %%level запишет %level) |
__LINE__
, __FILE__
и т. д. Перейти к началу
Вы можете настроить формат даты/времени, используя следующие спецификаторы.
Спецификатор | Заменено на |
---|---|
%d | День месяца (дополненный нулями) |
%a | День недели - короткий (пн, вт, ср, чт, пт, сб, вс) |
%A | День недели – длинный (понедельник, вторник, среда, четверг, пятница, суббота, воскресенье) |
%M | Месяц (дополненный нулями) |
%b | Месяц - короткий (январь, февраль, март, апрель, май, июнь, июль, август, сентябрь, октябрь, ноябрь, декабрь) |
%B | Месяц - Длинный (январь, февраль, март, апрель, май, июнь, июль, август, сентябрь, октябрь, ноябрь, декабрь) |
%y | Год — две цифры (13, 14 и т. д.). |
%Y | Год — четырехзначный (2013, 2014 и т. д.). |
%h | Час (12-часовой формат) |
%H | Час (24-часовой формат) |
%m | Минута (дополненная нулями) |
%s | Второй (дополненный нулями) |
%g | Субсекундная часть (точность настраивается ConfigurationType::Sub SecondPrecision) |
%F | Обозначение AM/PM |
% | Побег персонаж |
Обратите внимание, что длина даты/времени ограничена максимум 30
символами.
Перейти к началу
Вы также можете указать свои собственные спецификаторы формата. Для этого вы можете использовать el::Helpers::installCustomFormatSpecifier
. Прекрасным примером является %ip_addr
для приложения TCP-сервера;
const char * getIp ( const el::LogMessage*) {
return " 192.168.1.1 " ;
}
int main ( void ) {
el::Helpers::installCustomFormatSpecifier ( el::CustomFormatSpecifier ( " %ip_addr " , getIp));
el::Loggers::reconfigureAllLoggers (el::ConfigurationType::Format, " %datetime %level %ip_addr : %msg " );
LOG (INFO) << " This is request from client " ;
return 0 ;
}
Перейти к началу
В некоторых частях журнала вы можете установить флаги журналирования; вот поддерживаемые флаги:
Флаг | Описание |
---|---|
NewLineForContainer (1) | Убедитесь, что у нас есть новая строка для каждой записи журнала контейнера. |
AllowVerboseIfModuleNotSpecified (2) | Проверяет, что если используется -vmodule и не указан модуль, то через этот модуль разрешено подробное ведение журнала. Скажем, параметр был -vmodule=main*=3, и подробный журнал записывается из файла с именем Something.cpp, тогда, если этот флаг включен, журнал будет записан, в противном случае он будет запрещен. Примечание: наличие этого противоречит цели -vmodule. |
LogDetailedCrashReason (4) | При обработке сбоев по умолчанию также будет регистрироваться подробная причина сбоя (по умолчанию отключено) (проблема № 90). |
DisableApplicationAbortOnFatalLog (8) | Позволяет отключить прерывание приложения при входе в систему на уровне FATAL. Обратите внимание, что это не относится к обработчикам сбоев по умолчанию, поскольку приложение должно быть прервано после обработки сигнала сбоя. (Не добавлено по умолчанию) (выпуск № 119) |
ImmediateFlush (16) | Сбрасывает журнал при каждой записи журнала (зависит от производительности). По умолчанию отключено. |
StrictLogFileSizeCheck (32) | Обеспечивает проверку размера файла журнала для каждого журнала. |
ColoredTerminalOutput (64) | Вывод терминала будет красочным, если он поддерживается терминалом. |
MultiLoggerSupport (128) | Включает поддержку использования нескольких средств ведения журнала для регистрации одного сообщения. (Например, CLOG(INFO, "default", "network") << This will be logged using default and network loggers; ) |
DisablePerformanceTrackingCheckpointComparison (256) | Отключает сравнение контрольных точек |
DisableVModules (512) | Отключает использование vmodules |
DisableVModulesExtensions (1024) | Отключает расширение vmodules. Это означает, что если у вас есть vmodule -vmodule=main*=4, он будет охватывать все, начиная с main, где, как если бы у вас это не было определено, вы будете защищены для любого файла, начинающегося с main и заканчивающегося одним из следующих расширений; .h .c .cpp .cc .cxx .-inl-.h .hxx .hpp. Обратите внимание, что следующий vmodule неверен -vmodule=main.=4, поскольку этот макрос не определен, поскольку он будет проверять main..c, обратите внимание на двойные точки. Если вы хотите, чтобы это было действительно, посмотрите на флаг регистрации выше: AllowVerboseIfModuleNotSpecified '?' и '' поддерживаются подстановочные знаки |
HierarchicalLogging (2048) | Включает иерархическое ведение журнала. Это неприменимо к подробному журналированию. |
CreateLoggerAutomatically (4096) | Создает журнал автоматически, когда он недоступен. |
AutoSpacing (8192) | Автоматически добавляет пробелы. Например, LOG(INFO) << "DODGE" << "THIS!"; выведет «УВЕРНИТЕ ЭТО!» |
FixedTimeFormat (16384) | Применимо только для отслеживания производительности — это позволяет избежать времени на форматирование. Например, 1001 ms будет записано как есть, а не в формате 1.01 sec |
IgnoreSigInt (32768) | При сбое приложения игнорировать сигнал прерывания |
Вы можете установить/снять эти флаги, используя статические el::Loggers::addFlag
и el::Loggers::removeFlag
. Вы можете проверить, доступен ли определенный флаг, используя el::Loggers::hasFlag
, все эти функции принимают строго типизированное перечисление el::LoggingFlag
Вы можете установить эти флаги, используя аргумент командной строки
--logging-flags
. Вам необходимо включить эту функцию, определив макросELPP_LOGGING_FLAGS_FROM_ARG
(вам необходимо обязательно использоватьSTART_EASYLOGGINGPP(argc, argv)
для настройки аргументов).
Вы также можете установить флаги по умолчанию (начальные) с помощью
ELPP_DEFAULT_LOGGING_FLAGS
и установить числовое значение для начальных флагов.
Перейти к началу
В следующей таблице объясняются все аргументы командной строки, которые вы можете использовать для определения определенного поведения; Вам нужно будет инициализировать аргументы приложения, используя START_EASYLOGGINGPP(argc, argv)
в вашей функции main(int, char**)
.
Аргумент | Описание |
---|---|
-v | Активирует максимальную многословность |
--v=2 | Активирует уровень детализации до уровня 2 (допустимый диапазон: 0–9). |
--verbose | Активирует максимальную многословность |
-vmodule=MODULE_NAME | Активирует подробность для файлов, начиная с основного до уровня 1, остальные файлы зависят от флага журналирования AllowVerboseIfModuleNotSpecified . См. раздел «Флаги журналирования» выше. Два модуля можно разделить запятой. Обратите внимание: vmodules идут последними в порядке приоритета проверки аргументов для подробного журналирования, например, если в аргументах приложения перед vmodules указано -v, vmodules будут игнорироваться. |
--logging-flags=3 | Устанавливает флаг регистрации. В примере ie, 3 , он устанавливает флаг ведения журнала NewLineForContainer и AllowVerboseIfModuleNotSpecified . Дополнительную информацию и значения см. в разделе «Флаги журналирования» выше. См. раздел макросов, чтобы отключить эту функцию. |
--default-log-file=FILE | Устанавливает файл журнала по умолчанию для существующих и будущих средств ведения журнала. Возможно, вы захотите определить ELPP_NO_DEFAULT_LOG_FILE , чтобы предотвратить создание пустого файла журнала по умолчанию во время предварительной обработки. См. раздел макросов, чтобы отключить эту функцию. |
Перейти к началу
Некоторые параметры журналирования могут быть установлены с помощью макросов, это продуманное решение, например, если у нас определен ELPP_THREAD_SAFE
, все потокобезопасные функции включены, в противном случае отключены (убедившись, что с этим связаны излишки потокобезопасности). Чтобы облегчить запоминание и предотвратить возможные конфликты, все макросы начинаются с ELPP_
ПРИМЕЧАНИЕ. Все макросы можно определить одним из следующих способов:
Определите макросы, используя опцию компилятора -D
, например, в случае g++
вы будете использовать g++ source.cpp ... -DELPP_SYSLOG -DELPP_THREAD_SAFE ...
( рекомендуемый способ )
Определите макросы внутри "easylogging++.h"
(определение макросов в других файлах не будет работать)
Имя макроса | Описание |
---|---|
ELPP_DEBUG_ASSERT_FAILURE | Прерывает приложение при первом сбое утверждения. Это утверждение связано с неверным вводом, например неверным файлом конфигурации и т. д. |
ELPP_UNICODE | Включает поддержку Unicode при входе в систему. Требуется START_EASYLOGGINGPP |
ELPP_THREAD_SAFE | Включает потокобезопасность — убедитесь, что для Linux установлена связь -lpthread. |
ELPP_FORCE_USE_STD_THREAD | Принудительно использовать стандартную библиотеку C++ для потоковой обработки (полезно только при использовании ELPP_THREAD_SAFE . |
ELPP_FEATURE_CRASH_LOG | Применимо только к GCC. Включает трассировку стека при сбое приложения |
ELPP_DISABLE_DEFAULT_CRASH_HANDLING | Отключает обработку сбоев по умолчанию. Вы можете использовать el::Helpers::setCrashHandler для использования собственного обработчика. |
ELPP_DISABLE_LOGS | Отключает все журналы - (предварительная обработка) |
ELPP_DISABLE_DEBUG_LOGS | Отключает журналы отладки — (предварительная обработка) |
ELPP_DISABLE_INFO_LOGS | Отключает информационные журналы - (предварительная обработка) |
ELPP_DISABLE_WARNING_LOGS | Отключает журналы предупреждений - (предварительная обработка) |
ELPP_DISABLE_ERROR_LOGS | Отключает журналы ошибок - (предварительная обработка) |
ELPP_DISABLE_FATAL_LOGS | Отключает фатальные журналы - (предварительная обработка) |
ELPP_DISABLE_VERBOSE_LOGS | Отключает подробные журналы - (предварительная обработка) |
ELPP_DISABLE_TRACE_LOGS | Отключает журналы трассировки — (предварительная обработка) |
ELPP_FORCE_ENV_VAR_FROM_BASH | Если переменная среды не найдена, принудительно используйте альтернативную команду bash, чтобы найти значение, например whoami для имени пользователя. (НЕ ИСПОЛЬЗУЙТЕ ЭТОТ МАКРОС С LD_PRELOAD ДЛЯ БИБЛИОТЕК, КОТОРЫЕ УЖЕ ИСПОЛЬЗУЮТ Easylogging++, ИЛИ ВЫ ПОЛУЧИТЕ ПЕРЕПОЛНЕНИЕ СТЕКА ДЛЯ ПРОЦЕССОВ ( popen ) (подробности см. в выпуске № 87)) |
ELPP_DEFAULT_LOG_FILE | Полное имя файла, в котором вы хотите создать исходные файлы. Вам необходимо вставить значение этого макроса в кавычки, например, -DELPP_DEFAULT_LOG_FILE='"logs/el.gtest.log"' Обратите внимание, что двойные кавычки внутри одинарных кавычек, двойные кавычки - это значения для const char* , а одинарные кавычки указывают значение макрос |
ELPP_NO_LOG_TO_FILE | Изначально отключить запись в файл |
ELPP_NO_DEFAULT_LOG_FILE | Если вы не хотите инициализировать библиотеку с помощью файла журнала по умолчанию, определите этот макрос. Это приведет к входу на нулевое устройство для Unix и Windows. На других платформах вы можете получить сообщение об ошибке, и вам нужно будет использовать ELPP_DEFAULT_LOG_FILE . (пиар для нулевых устройств других платформ приветствуется) |
ELPP_FRESH_LOG_FILE | Никогда не добавляет файл журнала при его создании (используйте с осторожностью, так как это может привести к неожиданным результатам для некоторых пользователей). |
ELPP_DEBUG_ERRORS | Если вы хотите обнаружить внутренние ошибки, возникающие в Easylogging++, которые могут быть вызваны конфигурацией или чем-то еще, вы можете включить их, определив этот макрос. Вы получите свои ошибки в стандартном выводе, то есть в терминале или командной строке. |
ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS | Принудительно отключает спецификаторы пользовательского формата |
ELPP_DISABLE_LOGGING_FLAGS_FROM_ARG | Принудительно отключает возможность устанавливать флаги журналирования с использованием аргументов командной строки. |
ELPP_DISABLE_LOG_FILE_FROM_ARG | Принудительно отключает возможность установки файла журнала по умолчанию из аргументов командной строки. |
ELPP_WINSOCK2 | В системе Windows принудительно использовать winsock2.h вместо winsock.h , когда определен WIN32_LEAN_AND_MEAN |
ELPP_CUSTOM_COUT (расширенный) | Возвращает значение, например, #define ELPP_CUSTOM_COUT qDebug() или #define ELPP_CUSTOM_COUT std::cerr . При этом будет использоваться значение для стандартного вывода (вместо использования std::cout |
ELPP_CUSTOM_COUT_LINE (дополнительно) | Используется с ELPP_CUSTOM_COUT для определения способа записи строки журнала с пользовательским cout. например, #define ELPP_CUSTOM_COUT_LINE(msg) QString::fromStdString(msg).trimmed() |
ELPP_NO_CHECK_MACROS | Не определять макросы CHECK |
ELPP_NO_DEBUG_MACROS | Не определяйте макросы DEBUG |
ELPP_UTC_DATETIME | Использует время UTC вместо местного времени (по сути, использует gmtime вместо localtime и семейных функций) |
ELPP_NO_GLOBAL_LOCK | Не закрывайте все хранилище при отправке. Это следует использовать с осторожностью. См. выпуск № 580. |
Перейти к началу
Если вы хотите прочитать конфигурации определенного регистратора, вы можете сделать это, используя функцию typedConfigurations()
в классе Logger.
el::Logger* l = el::Loggers::getLogger( " default " );
bool enabled = l-> typedConfigurations ()->enabled(el::Level::Info);
// Or to read log format/pattern
std::string format =
l-> typedConfigurations ()->logFormat(el::Level::Info).format();
Перейти к началу
Вход в easylogging++ осуществляется с помощью набора макросов. Это сделано для того, чтобы облегчить пользователю задачу и не дать ему узнать ненужные подробности того, как все делается.
Вам предоставляются два основных макроса, которые вы можете использовать для записи журналов:
LOG(LEVEL)
CLOG(LEVEL, logger ID)
LOG
использует регистратор «по умолчанию», а в CLOG (Custom LOG) вы указываете идентификатор регистратора. Информацию об УРОВНЯХ см. в разделе «Конфигурации — Уровни» выше. Различные регистраторы могут иметь разные конфигурации в зависимости от ваших потребностей. Вы также можете написать собственный макрос для доступа к пользовательскому регистратору. У вас также есть различные макросы для подробного ведения журнала, которые описаны в разделе ниже. Вот очень простой пример использования этих макросов после инициализации easylogging++.
LOG (INFO) << "This is info log";
CLOG (ERROR, " performance " ) << "This is info log using performance logger";
Существует другой способ использования того же макроса, например, LOG
(и связанных макросов). Это значит, что вы определяете макросы ELPP_DEFAULT_LOGGER
и ELPP_DEFAULT_PERFORMANCE_LOGGER
с уже зарегистрированным идентификатором регистратора, и теперь, когда вы используете макрос LOG
, он автоматически будет использовать указанный регистратор вместо регистратора default
. Обратите внимание, что это должно быть определено в исходном файле, а не в заголовочном файле. Это сделано для того, чтобы при включении заголовка мы случайно не использовали недействительный регистратор.
Быстрый пример здесь
# ifndef ELPP_DEFAULT_LOGGER
# define ELPP_DEFAULT_LOGGER " update_manager "
# endif
# ifndef ELPP_DEFAULT_PERFORMANCE_LOGGER
# define ELPP_DEFAULT_PERFORMANCE_LOGGER ELPP_DEFAULT_LOGGER
# endif
# include " easylogging++.h "
UpdateManager::UpdateManager {
_TRACE; // Logs using LOG(TRACE) provided logger is already registered - i.e, update_manager
LOG (INFO) << " This will log using update_manager logger as well " ;
}
# include " easylogging++.h "
UpdateManager::UpdateManager {
_TRACE; // Logs using LOG(TRACE) using default logger because no `ELPP_DEFAULT_LOGGER` is defined unless you have it in makefile
}
Вы также можете писать журналы, напрямую используя класс
Logger
. Эта функция доступна в компиляторах, поддерживающих шаблоны с переменным числом вариантов. Вы можете узнать больше, просмотревsamples/STL/logger-log-functions.cpp
.
Перейти к началу
Easylogging++ обеспечивает определенные аспекты ведения журнала, одним из которых является условное ведение журнала, т. е. журнал будет записываться только в том случае, если выполняется определенное условие. Это очень удобно в некоторых ситуациях. Вспомогательные макросы заканчиваются на _IF;
LOG_IF(condition, LEVEL)
CLOG_IF(condition, LEVEL, logger ID)
LOG_IF (condition, INFO) << "Logged if condition is true";
LOG_IF ( false , WARNING) << "Never logged";
CLOG_IF ( true , INFO, " performance " ) << "Always logged (performance logger)"
Те же макросы доступны для подробного журналирования с помощью V
в начале, т. е. VLOG_IF
и CVLOG_IF
. дополнительную информацию см. в разделе подробного журналирования ниже. У вас могут быть настолько сложные условия, насколько вы хотите, в зависимости от ваших потребностей.
Перейти к началу
Периодическое ведение журнала — еще один полезный аспект ведения журнала с помощью Easylogging++. Это означает, что журнал будет записан, если он будет выполнен определенное время или часть определенного времени, например, каждое 10-е, 100-е или 2-е попадание. Вспомогательные макросы заканчиваются на _EVERY_N
;
LOG_EVERY_N(n, LEVEL)
CLOG_EVERY_N(n, LEVEL, logger ID)
Есть и другие способы регистрации, основанные на количестве посещений. Эти полезные макросы
LOG_AFTER_N(n, LEVEL)
; Регистрируется только тогда, когда мы достигли количества попаданий n
LOG_N_TIMES(n, LEVEL)
; Журналы n раз for ( int i = 1 ; i <= 10 ; ++i) {
LOG_EVERY_N ( 2 , INFO) << " Logged every second iter " ;
}
// 5 logs written; 2, 4, 6, 7, 10
for ( int i = 1 ; i <= 10 ; ++i) {
LOG_AFTER_N ( 2 , INFO) << " Log after 2 hits; " << i;
}
// 8 logs written; 3, 4, 5, 6, 7, 8, 9, 10
for ( int i = 1 ; i <= 100 ; ++i) {
LOG_N_TIMES ( 3 , INFO) << " Log only 3 times; " << i;
}
// 3 logs writter; 1, 2, 3
Те же версии макросов доступны только для режима
DEBUG
. Эти макросы начинаются сD
(для отладки), за которой следует то же имя. например,DLOG
для регистрации только в режиме отладки (т. е. когда_DEBUG
определен илиNDEBUG
не определен)
Перейти к началу
printf
Как ведение журнала Для компиляторов, поддерживающих шаблоны с переменным числом вариантов C++11, доступна возможность ведения журнала, например «printf». Это делается с помощью класса Logger
. Эта функция является потокобезопасной и типобезопасной (поскольку мы не используем никаких макросов, таких как LOG(INFO)
и т. д.).
Это делается в два этапа:
el::Loggers::getLogger(<logger_id>);
Единственное отличие от printf
заключается в том, что для ведения журнала с использованием этих функций требуется %v
для каждого аргумента (это сделано для обеспечения безопасности типов); вместо спецификаторов пользовательского формата. Вы можете избежать этого с помощью %%v
Ниже приведены различные сигнатуры функций:
info(const char*, const T&, const Args&...)
warn(const char*, const T&, const Args&...)
error(const char*, const T&, const Args&...)
debug(const char*, const T&, const Args&...)
fatal(const char*, const T&, const Args&...)
trace(const char*, const T&, const Args&...)
verbose(int vlevel, const char*, const T&, const Args&...)
// Use default logger
el::Logger* defaultLogger = el::Loggers::getLogger( " default " );
// STL logging (`ELPP_STL_LOGGING` should be defined)
std::vector< int > i;
i.push_back( 1 );
defaultLogger-> warn ( " My first ultimate log message %v %v %v " , 123 , 222 , i);
// Escaping
defaultLogger-> info ( " My first ultimate log message %% %%v %v %v " , 123 , 222 );
Спецификаторы формата
%file
,%func
%line
и%loc
не будут работать сprintf
как и ведение журнала.
Перейти к началу
Вы можете отправлять свои сообщения в сеть. Но вам придется реализовать свой собственный способ, используя API диспетчера журналов. Для этой цели мы написали полностью рабочий образец. См. образец отправки в сеть.
Перейти к началу
Подробное ведение журнала полезно в любом программном обеспечении для записи большего количества информации, чем обычно. Очень полезно для устранения неполадок. Ниже приведены подробные журналы конкретных макросов;
VLOG(verbose-level)
CVLOG(verbose-level, logger ID)
Перейти к началу
Подробное ведение журнала также имеет аспекты условного и случайного ведения журнала, т. е.
VLOG_IF(condition, verbose-level)
CVLOG_IF(condition, verbose-level, loggerID)
VLOG_EVERY_N(n, verbose-level)
CVLOG_EVERY_N(n, verbose-level, loggerID)
VLOG_AFTER_N(n, verbose-level)
CVLOG_AFTER_N(n, verbose-level, loggerID)
VLOG_N_TIMES(n, verbose-level)
CVLOG_N_TIMES(n, verbose-level, loggerID)
Перейти к началу
Уровень детализации — это уровень детализации, который может иметь диапазон от 1 до 9. Подробный уровень не будет активен, если вы не установите для него аргументы приложения. Пожалуйста, прочитайте раздел «Аргументы приложения», чтобы узнать больше о подробном журналировании.
Чтобы изменить уровень детализации на лету, используйте функцию Loggers::setVerboseLevel(base::type::VerboseLevel)
, также известную как Loggers::setVerboseLevel(int)
. (Вы можете проверить текущий уровень подробностей с помощью Loggers::verboseLevel()
Перейти к началу
Вы можете использовать макрос VLOG_IS_ON(verbose-level)
, чтобы проверить, включено ли определенное ведение журнала для исходного файла для указанного подробного уровня. Возвращает логическое значение, которое вы можете встроить в условие if.
if (VLOG_IS_ON( 2 )) {
// Verbosity level 2 is on for this file
}
Перейти к началу
VModule — это функция подробного журналирования (как указано в таблице выше), где вы можете указать подробную информацию по модулям/исходному файлу. Ниже приведены несколько примеров с пояснениями; Любой из приведенных ниже vmodule начинается с -vmodule=
и флаг LoggingFlag::DisableVModulesExtensions
не установлен. Vmodule можно полностью отключить, добавив флаг LoggingFlag::DisableVModules
Пример с флагом LoggingFlag::AllowVerboseIfModuleNotSpecified
;
main=3,parser*=4
:
main{.h, .c, .cpp, .cc, .cxx, -inl.h, .hxx, .hpp}
parser{.h, .c, .cpp, .cc, .cxx, -inl.h, .hxx, .hpp}