Plog — простая и кроссплатформенная библиотека для логирования на C++

Предлагаю вашему вниманию ещё одну библиотеку для логирования на C++.

Особенности:
— Очень маленькая (менее 1000 строк кода)
— Легко использовать
— Только хедеры
— Без сторонних зависимостей
— Кроссплатформенная: Windows, Linux, Mac OS X, Android (gcc, clang, msvc)
— Потоко- и типобезопасная
— Форматирование: TXT, CSV, FuncMessage
— Аппендеры: RollingFile, Console, Android
— Автоматически захватывает указатель на ’this’ (работает только на msvc)
— Ленивое вычисление
— Знает про юникод и широкие строки, файлы пишет в UTF8
— Не требует C++11
— Расширяемая

Пример:

#include <plog/Log.h> // Step1: include the header.

int main()
{
    plog::init(plog::debug, "Hello.txt"); // Step2: initialize the logger.

    // Step3: write log messages using a special macro. 
    // There are several log macros, use the macro you liked the most.

    LOGD << "Hello log!"; // short macro
    LOG_DEBUG << "Hello log!"; // long macro
    LOG(plog::debug) << "Hello log!"; // function-style macro

    return 0;
}

Результат:

2015-05-18 23:12:43.921 DEBUG [21428] [main@13] Hello log!
2015-05-18 23:12:43.968 DEBUG [21428] [main@14] Hello log!
2015-05-18 23:12:43.968 DEBUG [21428] [main@15] Hello log!

Исходный код и документация на английском: github.com/SergiusTheBest/plog

LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Кстати, предпоследний пункт —

— Не требует C++11
лично для меня это минус.
В идеальном варианте можно сделать (поддержку/не поддержку С++11) на этапе компиляции.

Реальность такова, что не все проекты перешли на С++11. Ограничивать совместимость библиотеки со старыми проектами глупо.

Я же говорю — опционально сделайте.

От чего пришлось отказаться из С++11:
-шаблонный параметр по-умолчанию для функции;
-mutex;
-auto.
Оно того не стоит, причём код станет сложнее, так как надо поддерживать 2 варианта (до С++11 и после).

А, ну и что в итоге получили — самый велосипедистый велосипед или самый баянистый баян?

Получил самый удобный лог. Занете лог удобнее — поделитесь :)

Вечером обязательно попробую, надеюсь c VS-2012 (не помню какая там версия С++ компилера) он нормально работает.

Супер. Если работали с другими логами — можете сравнить.

Чем отличается от Boost.Log?

Практически всё то же самое, что и для google glog: dou.ua/...orums/topic/13720/#706885
+ ленивые вычисления и простота в использовании

Теперь для комплекта надо написать message bus. Можно сразу с намёком на rpc.

* только хедеры: проще интеграция в проект
* CSV формат лога
* автоматически пишет указатель this в лог
* дружит с широкими строками и null указателями
* пишет файл в UTF8
* поддерживает стандартный лог Android
* гибкость: хочешь писать лог в несколько файлов (например default.log, db.log, auth.log) — пожалуйста, хочешь перенаправить лог из DLL в основной EXE файл — нет проблем
* простой и красивый код
* расширяемость

util::Singleton не потокобезопасный
trollface.jpeg

Разрешите не согласиться: util::Singleton реализует синглтон с предопределённым временем жизни, с разных потоков вызвается только метод getInstance().

Ваша библиотека действительно не потокобезопасна. Из того что я заметил, проблемные места — это функция init(), так как там используется локальная static переменная и функция Logger::addAppender(), так как там добавляние в вектор m_appenders тоже не защищено. Это то что бросается в глаза.

Инициализация и не должна делаться с разных потоков. Это как конструктор объекта.

Инициализация может выполняться где угодно до использования, если не оговорены ограничения. Так как в описании библиотеки стоит thread-safe и в примерах есть множественные вызовы plog::init, значит их можно вызывать и из разных потоков в том числе.
Я не пытаюсь к Вам придраться, но к написанию библиотек применяются очень высокие требования и стандарты. Нельзя назвать библиотеку thread-safe когда в ней есть широко известные проблемы.

Дельное замечание, добавлю в документацию. Спасибо.

Да это я так, потрындеть. «Видишь синглтон — скажи, что он не потокобезопасен». С++ 03 гарантирует это :) А за компактный логер на гитхабе — спасибо.

Из конструктивной критики:
* я думаю, можно его сделать более масштабируемым с точки зрения многопоточности. Гляну и набросаю пул-реквест на досуге.
* со временем жизни могут быть проблемы, но это фундаментальная особенность синглтонов в С++ pastebin.com/3cPqmVrx А дальше — отличное поле для дебатов по поводу увеличения травмобезопасности в подобных ситуациях.

В вашем примере ничего страшного не произойдёт — просто сообщение из деструктора не запишется. Такой же пример можно написать абсолютно для любого лога: в С++ всегда есть возможность выстрелить себе в ногу :)

А если там вместо MyConfigSingleton будет какой-нибудь ThreadPoolSingleton, который останавливает потоки в деструкторе — то появится трудноуловимый race-condition, т.к. деструкторы логгера, синглтона и аппендеров не содержат блокировок.

Ну это уже надуманный пример. Человек перенесёт инициализацию лога чуть раньше (либо остановит потоки раньше) и решит проблему.

Такой же пример можно написать абсолютно для любого лога
Ну, если логгер не будет удаляться никогда — то как минимум проблемы несвоевременного удаления не будет. Появятся другие :)


Не сочтите за занудство, просто дискуссии о многопоточности в Си с крестами — это ж самый смак! Очень рекомендую драму в двух частях на эту тему: Part I, Part II. Не помню, что я пытался сделать на thread-safe синглтонах, но помню, что с подачи этих двух товарищей, в конце-концов переделал попроще.

Относительно лога это больше не многопоточность, а время жизни глобальных объектов.

Подписаться на комментарии