А еще важная информация, я ищу работу C++ разработчика, пожалуйста напишите мне (контакт), если можете помочь, я студент в Москве)
![](https://habrastorage.org/getpro/habr/upload_files/963/737/4f4/9637374f46086fccdafe08148dbfed15.png)
Logger Library
Этот проект представляет собой простую и гибкую библиотеку для логирования на C++. Библиотека поддерживает разные уровни логирования, форматирование сообщений и возможность записи логов в разные потоки.
Основные возможности
Поддержка различных уровней логирования:
DEBUG
,INFO
,WARN
,ERROR
.Настраиваемое форматирование логов.
Возможность логирования в несколько потоков с защитой от гонок данных.
Логирование в разные выходные потоки (
std::cout
, файлы и т.д.).Возможность использования глобального логгера.
Установка
Склонируйте репозиторий:
git clone <https://github.com/Fallet666/logger.git>
Перейдите в директорию проекта и соберите его с использованием CMake:
cd logger mkdir build cd build cmake .. make
Основные концепции
Logger: основной класс для логирования. Создавайте экземпляр этого класса для логирования в определенный поток.
Глобальный логгер: Singleton-экземпляр
Logger
, который можно использовать по умолчанию во всем проекте.
Функции логирования
В проекте доступны несколько функций для записи логов с разными уровнями важности. Эти функции позволяют гибко управлять выводом сообщений в зависимости от их критичности. Логи делятся на четыре уровня:
DEBUG
— Для отладочной информации.INFO
— Для общих информационных сообщений.WARN
— Для предупреждений.ERROR
— Для ошибок, требующих внимания.
Базовые функции
LOG_MESSAGE(Logger& logger, LogLevel level, const std::string& message)
Записывает сообщение с заданным уровнем. Эта функция является универсальной и может использоваться для логирования сообщений любого уровня.
Пример использования:
Logger::Logger log("Logger");
LOG_MESSAGE(log, Logger::DEBUG, "I'm MESSAGE");
Упрощенные функции для каждого уровня
Эти функции предназначены для упрощения вызова логирования на определённом уровне:
logDebug(Logger& logger, const std::string& message)
Логирует сообщение с уровнем DEBUG
.
Пример использования:
logDebug(log, "This is a debug message");
logInfo(Logger& logger, const std::string& message)
Логирует сообщение с уровнем INFO
.
Пример использования:
logInfo(log, "This is an info message");
logWarn(Logger& logger, const std::string& message)
Логирует сообщение с уровнем WARN
.
Пример использования:
logWarn(log, "This is a warning message");
logError(Logger& logger, const std::string& message)
Логирует сообщение с уровнем ERROR
.
Пример использования:
logError(log, "This is an error message");
Глобальные функции логирования
Проект также предоставляет глобальные функции логирования, которые используют глобальный логгер (globalLogger). Эти функции позволяют записывать сообщения без необходимости создания и управления собственными экземплярами логгера.
Аналогично базовым функциям существуют следующие глобальные функции логирования:
logMessageGlobal(LogLevel level, const std::string& message)
logDebugGlobal(const std::string& message)
logInfoGlobal(const std::string& message)
logWarnGlobal(const std::string& message)
logErrorGlobal(const std::string& message)
Уровень логирования
Можно установить уровень логирования через Cmake
, тогда будут отображаться логи не ниже заданного уровня. Например, если вы установите уровень Warn
, то будут отображаться логи уровня Warn
и Error
.
Пример использования:
set(DEFAULT_LOG_LEVEL DEBUG)
add_compile_definitions(GLOBAL_LOG_LEVEL=${DEFAULT_LOG_LEVEL})
Примечание
Каждая из функций логирования автоматически добавляет информацию о файле и строке, откуда был вызван лог, используя макросы FILE и LINE. Это позволяет легче отслеживать источник логов в коде.
Форматирование логов
Форматирование по умолчанию:
Строка форматирования: "%L: %T [%N]: %M\n"
Пример вывода:
DEBUG: 12:34:56 [MyLogger]: This is a debug message
Расширенное форматирование
Логи можно кастомизировать с помощью строки форматирования. По умолчанию строка форматирования может содержать следующие компоненты:
%L — Уровень логирования (DEBUG, INFO, WARN, ERROR).
%T — Время записи лога в формате HH:MM:SS.
%N — Имя логгера.
%M — Сообщение лога.
%t — Идентификатор потока, который записал лог.
%S — Имя файла, из которого был вызван лог.
%# — Номер строки в файле, откуда был вызван лог.
Эти спецификаторы можно комбинировать и располагать в любом порядке, чтобы настроить формат логов под нужды проекта.
Строка форматирования задается следующим образом:
Logger::Logger log("custom formating");
log.setFormatString("%L: %T [%N]: %M (%S: %#)\n");
Использование цветов в логах
В проекте предусмотрена возможность цветного вывода логов в консоль, чтобы легко различать сообщения разных уровней. Цвета автоматически применяются, если выходной поток логгера настроен на std::cout
.
Цветовая схема
DEBUG
— Белый (\033[37m).INFO
— Зеленый (\033[32m).WARN
— Желтый (\033[33m).ERROR
— Красный (\033[31m).
Цвета можно увидеть в терминале при выводе логов, что значительно упрощает идентификацию важности сообщений.
Отключение цвета
Цвета автоматически отключаются, если вы используете другой поток вывода (например, запись логов в файл).
Логирование в многопоточных приложениях
В проекте предусмотрена поддержка многопоточного логирования. Это значит, что несколько потоков могут одновременно записывать логи без риска порчи данных или возникновения гонок.
Синхронизация потоков
Для обеспечения потокобезопасности в классе Logger используется мьютекс (std::mutex
). Каждый раз, когда вызывается функция логирования или происходит изменение полей логгера, поток блокируется до завершения операции. Это предотвращает одновременный доступ к общим ресурсам (например, к выходному потоку или настройкам логгера), что гарантирует корректность и целостность данных в логах.
Пример многопоточного логирования:
Logger::Logger log("MultiThreadLogger");
std::vector<std::thread> threads;
for (int i = 0; i < 10; ++i) {
threads.emplace_back([&log, i] {
logInfo(log, "Message from thread " + std::to_string(i));
});
}
for (auto &t : threads) {
t.join();
}
В этом примере создается 10 потоков, каждый из которых записывает лог-сообщение с информацией о своем номере. Благодаря использованию мьютекса, все сообщения будут записаны корректно и без смешивания.
Особенности многопоточного логирования
Потокобезопасность: Использование мьютекса внутри логгера гарантирует, что одновременно будет выполняться только одна операция — либо запись сообщения, либо изменение полей логгера (например, смена выходного потока или формата лога).
Производительность: Несмотря на блокировку, логгер спроектирован так, чтобы минимизировать влияние на производительность. Однако при большом количестве логов или высокой нагрузке на систему возможны задержки.
Вывод в разные потоки: Логгер позволяет использовать различные выходные потоки для разных экземпляров, что может быть полезно для разделения логов по категориям или источникам.
Логирование в разные выходные потоки
Проект предоставляет гибкую возможность настройки выходного потока для логгера. Это означает, что вы можете направлять логи в любой поток, поддерживающий интерфейс std::ostream
, будь то стандартный вывод (std::cout
), файлы, строковые потоки (std::ostringstream
) или даже пользовательские потоки.
Установка выходного потока
При создании экземпляра логгера вы можете указать, куда будут записываться логи. По умолчанию, логи направляются в std::cout
, но это поведение можно изменить:
std::ofstream file("log.txt");
Logger::Logger log("FileLogger", file);
В этом примере логи будут записываться в файл log.txt.
Смена выходного потока
Вы также можете изменить выходной поток логгера в процессе работы программы с помощью метода setOutStream
:
Logger::Logger log("Logger");
log.setOutStream(std::cerr);
Пример использования различных потоков вывода:
std::ofstream file("output.log");
std::ostringstream oss;
Logger::Logger logToFile("FileLogger", file);
Logger::Logger logToStringStream("StringStreamLogger", oss);
Logger::Logger logToConsole("ConsoleLogger");
logInfo(logToFile, "This log goes to a file");
logWarn(logToStringStream, "This log goes to a string stream");
logError(logToConsole, "This log goes to the console");
file.close();
Если у вас есть предложения по улучшению или вы обнаружили ошибки, не стесняйтесь создавать issue
в репозитории проекта. Я всегда рад помощи со стороны сообщества и буду благодарен за ваш вклад в развитие проекта.