Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/newyaroslav/log-it-cpp

LogIt++ is a flexible and versatile C++ logging library with support for various backends and stream-based output.
https://github.com/newyaroslav/log-it-cpp

cpp cpp11 log logger logger-backend logger-interface logger-middleware logging logs

Last synced: 18 days ago
JSON representation

LogIt++ is a flexible and versatile C++ logging library with support for various backends and stream-based output.

Awesome Lists containing this project

README

        

# LogIt++ Library
![LogIt++ Logo](docs/logo-640x320.png)

## Введение

**LogIt++** — это гибкая и универсальная библиотека логирования на C++, которая поддерживает различные бэкенды и потоковый вывод. Она предоставляет простой в использовании интерфейс для логирования сообщений с разными уровнями важности и позволяет настраивать форматы и назначения логов.

Библиотека сочетает простоту макросов для логирования, аналогичную **IceCream-Cpp**, и возможности настройки бэкендов и форматов логов, как в **spdlog**. LogIt++ полностью совместим с `C++11`.

## Возможности

- **Гибкое форматирование логов**:

Настраивайте формат сообщений логов с помощью паттернов. Вы можете переопределить паттерны через макросы или указать их напрямую при добавлении бэкенда логгера. Поддерживаются как стандартные флаги форматирования (`%H`, `%M`, `%S`, `%v` и другие), так и специальные, такие как `%N([...])` для указания fallback-логов без аргументов.

```
#define LOGIT_CONSOLE_PATTERN "%H:%M:%S.%e | %^%N([%!g:%#])%v%$"

try {
throw std::runtime_error("An example runtime error");
} catch (const std::exception& ex) {
LOGIT_FATAL(ex);
}

// Вывод:
> 23:59:59.128 | An example runtime error
```

- **Логирование с использованием макросов**:

Легко логируйте переменные и сообщения с помощью макросов. Просто выберите подходящий макрос и передайте переменные или аргументы.

```
float someFloat = 123.456f;
int someInt = 789;
LOGIT_INFO(someFloat, someInt);

auto now = std::chrono::system_clock::now();
LOGIT_PRINT_INFO("TimePoint example: ", now);
```

- **Поддержка нескольких бэкендов**:

Легко настройте логгеры для вывода в консоль и файлы. При необходимости добавьте отправку сообщений на сервер или в базу данных, создавая собственные бэкенды.

```
// Добавление трёх бэкендов: консольного, файлового и уникального файлового логгера
LOGIT_ADD_CONSOLE_DEFAULT();
LOGIT_ADD_FILE_LOGGER_DEFAULT();
LOGIT_ADD_UNIQUE_FILE_LOGGER_DEFAULT_SINGLE_MODE();
```

- **Асинхронное логирование**:

Улучшите производительность приложения с помощью асинхронного логирования. Все логгеры по умолчанию обрабатывают сообщения в отдельном потоке.

- **Потоковое логирование**:

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

```
LOGIT_STREAM_INFO() << "Stream-based info logging with short macro. Integer value: " << 123;
```

- **Расширяемость**:

Создавайте собственные логгеры и форматтеры для удовлетворения ваших специфических потребностей.

```
class CustomLogger : public logit::ILogger {
public:
CustomLogger() = default;

/// \brief Логирует сообщение, форматируя запись и сообщение.
/// \param record Лог-запись с деталями события.
/// \param message Отформатированное сообщение лога.
void log(const logit::LogRecord& record, const std::string& message) override {
// Реализация отправки логов...
}

~CustomLogger() override = default;
};

LOGIT_ADD_LOGGER(CustomLogger, (), logit::SimpleLogFormatter, ("%v"));
```

---

## Использование

Ниже приведен простой пример использования LogIt++ в вашем приложении:

```cpp
#define LOGIT_SHORT_NAME
#include

int main() {
// Инициализация логгера с выводом в консоль по умолчанию
LOGIT_ADD_CONSOLE_DEFAULT();

float a = 123.456f;
int b = 789;
int c = 899;
const char* someStr = "Hello, World!";

// Базовое логирование с использованием макросов
LOG_INFO("Starting the application");
LOG_DEBUG("Variable values", a, b);
LOG_WARN("This is a warning message");

// Логирование с форматированием
LOG_PRINTF_INFO("Formatted log: value of a = %.2f", a);
LOG_FORMAT_WARN("%.4d", b, c);

// Логирование ошибок и фатальных ошибок
LOG_ERROR("An error occurred", b);
LOG_FATAL("Fatal error. Terminating application.");

// Условное логирование
LOG_ERROR_IF(b < 0, "Value of b is negative");
LOG_WARN_IF(a > 100, "Value of a exceeds 100");

// Потоковое логирование с использованием коротких и длинных макросов
LOG_S_INFO() << "Logging a float: " << a << ", and an int: " << b;
LOG_S_ERROR() << "Error occurred in the system";
LOGIT_STREAM_WARN() << "Warning: potential issue detected with value: " << someStr;

// Использование LOGIT_TRACE для трассировки выполнения функций
LOGIT_TRACE0(); // Trace without arguments
LOG_PRINT_TRACE("Entering main function with variable a =", a);

// Ожидание завершения всех асинхронных операций логирования
LOGIT_WAIT();

return 0;
}
```

Для получения дополнительных примеров использования обратитесь к папке `examples` в репозитории, где можно найти подробные демонстрации различных сценариев логирования и конфигураций.

---

## Настройка форматов логов

`LogIt++` поддерживает настраиваемое форматирование сообщений с использованием паттернов, которые определяют вид каждого сообщения. Вы можете задавать паттерны через макросы или передавать их при добавлении бэкендов логгера.

### Пример формата

Пример задания пользовательского формата для консольного логгера:

```
LOGIT_ADD_LOGGER(
logit::ConsoleLogger, (),
logit::SimpleLogFormatter,
("%Y-%m-%d %H:%M:%S.%e [%l] %^%N(%g:%#)%v%$")
);
```

Или задайте паттерн с использованием макросов:

```
#define LOGIT_CONSOLE_PATTERN "%H:%M:%S.%e | %^%N([%!g:%#])%v%$"
LOGIT_ADD_CONSOLE_DEFAULT();
```

Логгер автоматически подставит в шаблон указанные данные, например:

```
23:59:59.128 | path/to/file.cpp:123 A sample log message
```

### Флаги форматирования сообщений

`LogIt++` поддерживает настраиваемое форматирование сообщений лога с использованием флагов форматирования. Вы можете задать, как должно выглядеть каждое сообщение лога, используя заполнители для различных данных, таких как временная метка, уровень лога, имя файла, имя функции и сообщение.

Ниже приведен список поддерживаемых флагов форматирования:

- *Флаги форматирования даты и времени*:

- `%Y`: Год (например, 2024)
- `%m`: Месяц (01-12)
- `%d`: День месяца (01-31)
- `%H`: Час (00-23)
- `%M`: Минута (00-59)
- `%S`: Секунда (00-59)
- `%e`: Миллисекунда (000-999)
- `%C`: Двузначный год (например, 24 для 2024 года)
- `%c`: Полная дата и время (например, Пн Окт 4 12:45:30 2024)
- `%D`: Короткая дата (например, 04/10/24)
- `%T`, `%X`: Время в формате ISO 8601 (например, 12:45:30)
- `%F`: Дата в формате ISO 8601 (например, 2024-10-04)
- `%s`, `%E`: Unix-временная метка в секундах
- `%ms`: Unix-временная метка в миллисекундах
- `%b`: Сокращенное название месяца (например, Янв)
- `%B`: Полное название месяца (например, Январь)
- `%a`: Сокращенное название дня недели (например, Пн)
- `%A`: Полное название дня недели (например, Понедельник)

- *Флаги уровня логирования*:

- `%l`: Полный уровень лога (например, INFO, ERROR)
- `%L`: Сокращенный уровень лога (например, I для INFO, E для ERROR)

- *Флаги для файла и функции*:

- `%f`, `%fn`, `%bs`: Имя исходного файла
- `%g`, `%ffn`: Полный путь к файлу
- `%#`: Номер строки
- `%!`: Имя функции

- *Флаги потоков*:

- `%t`: Идентификатор потока

- *Флаги цвета*:

- `%^`: Начало цветового форматирования
- `%$`: Конец цветового форматирования
- `%SC`: Начало удаления цветовых кодов (Strip Color)
- `%EC`: Конец удаления цветовых кодов (End Color)

- *Флаги сообщения*:

- `%v`: Содержимое сообщения лога
- `%N(...)`: Используется как замена, если нет аргументов (*например, при вызове* `LOG_TRACE0()`). В скобках указывается шаблон для вывода. Пример: `%N(%g:%#)` добавит имя файла и номер строки, если нет сообщения.

### Поддержка выравнивания и обрезки текста

`LogIt++` позволяет форматировать текст сообщения с помощью ширины (`width`), выравнивания и обрезки:

- Выравнивание:
- Левое: Используется знак `-` перед числом ширины, например: `%-10v`.
- Центрирование: Используется знак `=` перед числом ширины, например: `%=10v`.
- Правое (по умолчанию): `%10v`.

- Обрезка:
- Символ `!` после числа ширины указывает, что текст нужно обрезать, если он превышает заданную длину. Пример: `%10!v`.

**Примеры**:

- `%10v` – правое выравнивание сообщения на 10 символов.
- `%-10v` – левое выравнивание сообщения на 10 символов.
- `%10!v` – обрезка текста до 10 символов с правым выравниванием.
- `%-10!v` – левое выравнивание сообщения с обрезкой до 10 символов.

### Продвинутая обработка путей

Для флагов, связанных с файлами (%f, %g, %@), при обрезке строки обеспечивается сохранение имени файла и начала пути, а средняя часть заменяется на ..., если ширина меньше длины пути.

**Пример:**

- Вход: `/very/long/path/to/file.cpp`
- Обрезано до ширины 15: `/very...file.cpp`

---

## Укороченные макросы для логирования

`LogIt++` предоставляет укороченные версии макросов для логирования, когда определён флаг `LOGIT_SHORT_NAME`. Эти макросы позволяют лаконично логировать сообщения на разных уровнях, включая стандартное и потоковое логирование.

### Доступные макросы для уровня TRACE:

- Основное логирование:

- `LOG_T(...)`: Регистрирует сообщение уровня TRACE.
- `LOG_T0()`: Регистрирует сообщение уровня TRACE без аргументов.
- `LOG_0T()`: Псевдоним для `LOG_T0()`.
- `LOG_0_T()`: Псевдоним для `LOG_T0()`.
- `LOG_T_NOARGS()`: Псевдоним для `LOG_T0()`.
- `LOG_NOARGS_T()`: Псевдоним для `LOG_T0()`.

- Логирование с форматированием:

- `LOG_TF(fmt, ...)`: Регистрирует отформатированное сообщение уровня TRACE с использованием строк формата.
- `LOG_FT(fmt, ...)``: Псевдоним для `LOG_TF(fmt, ...)`.
- `LOG_T_PRINT(...)`: Регистрирует сообщение уровня TRACE, печатая каждый аргумент.
- `LOG_PRINT_T(...)`: Псевдоним для `LOG_T_PRINT(...)`.
- `LOG_T_PRINTF(fmt, ...)`: Регистрирует отформатированное сообщение уровня TRACE с использованием форматирования в стиле printf.
- `LOG_PRINTF_T(fmt, ...)`: Псевдоним для `LOG_T_PRINTF(fmt, ...)`.
- `LOG_TP(...)`: Псевдоним для `LOG_T_PRINT(...)`.
- `LOG_PT(...)`: Псевдоним для `LOG_T_PRINT(...)`.
- `LOG_TPF(fmt, ...)`: Псевдоним для `LOG_T_PRINTF(fmt, ...)`.
- `LOG_PFT(fmt, ...)`: Псевдоним для `LOG_T_PRINTF(fmt, ...)`.

- Альтернативные макросы уровня `TRACE`:

- `LOG_TRACE(...)`: Регистрирует сообщение уровня TRACE (то же, что и `LOG_T(...)`).
- `LOG_TRACE0()`: Регистрирует сообщение уровня TRACE без аргументов (то же, что и `LOG_T0()`).
- `LOG_0TRACE()`: Псевдоним для `LOG_TRACE0()`.
- `LOG_0_TRACE()`: Псевдоним для `LOG_TRACE0()`.
- `LOG_TRACE_NOARGS()`: Регистрирует сообщение уровня TRACE без аргументов (то же, что и `LOG_T_NOARGS()`).
- `LOG_NOARGS_TRACE()`: Псевдоним для `LOG_TRACE_NOARGS()`.
- `LOG_TRACEF(fmt, ...)`: Регистрирует отформатированное сообщение уровня TRACE (то же, что и `LOG_TF(fmt, ...)`).
- `LOG_FTRACE(fmt, ...)`: Псевдоним для `LOG_TRACEF(fmt, ...)`.
- `LOG_TRACE_PRINT(...)`: Регистрирует сообщение уровня TRACE, печатая каждый аргумент (то же, что и `LOG_T_PRINT(...)`).
- `LOG_PRINT_TRACE(...)`: Псевдоним для `LOG_TRACE_PRINT(...)`.
- `LOG_TRACE_PRINTF(fmt, ...)`: Регистрирует отформатированное сообщение уровня TRACE с использованием форматирования в стиле printf (так же, как `LOG_T_PRINTF(fmt, ...)`).
- `LOG_PRINTF_TRACE(fmt, ...)`: Псевдоним для `LOG_TRACE_PRINTF(fmt, ...)`.

Эти макросы обеспечивают гибкость и удобство при регистрации сообщений на уровне TRACE. Они позволяют выбирать между различными стилями регистрации, такими как стандартная регистрация, форматированная регистрация и печать каждого аргумента отдельно.

**Примечание**: Аналогичные макросы доступны для других уровней журнала — **INFO** (`LOG_I`, `LOG_INFO`), **DEBUG** (`LOG_D`, `LOG_DEBUG`), **WARN** (`LOG_W`, `LOG_WARN`), **ERROR** (`LOG_E`, `LOG_ERROR`) и **FATAL** (`LOG_F`, `LOG_FATAL`). Соглашения об именовании одинаковы для всех уровней, вам нужно только заменить букву уровня или слово в имени макроса.

- Пример:

```cpp
LOG_T("Trace message using short macro");
LOG_TF("%.4d", 999);
LOG_T_PRINT("Printing trace message with multiple variables: ", var1, var2);
LOG_TRACE("Trace message (alias for LOG_T)");
LOG_TRACE_PRINTF("Formatted trace: value = %d", value);
```

---

## Конфигурационные макросы

LogIt++ предоставляет несколько макросов, которые позволяют настраивать библиотеку под ваши нужды. Ниже приведены доступные конфигурационные макросы:

- **LOGIT_BASE_PATH**: Определяет базовый путь, используемый для файлов логов. Если `LOGIT_BASE_PATH` не определен или пуст (`{}`), будет использоваться полный путь из переменной `__FILE__`. Вы можете переопределить это, указав собственный базовый путь для логов.

```cpp
#define LOGIT_BASE_PATH "/path/to/your/project"
```

- **LOGIT_DEFAULT_COLOR**: Определяет цвет консоли по умолчанию. Если `LOGIT_DEFAULT_COLOR` не определен, по умолчанию используется `TextColor::LightGray`. Вы можете установить собственный цвет текста для консоли, переопределив этот макрос.

```cpp
#define LOGIT_DEFAULT_COLOR TextColor::Green
```

- **LOGIT_CURRENT_TIMESTAMP_MS**: Макрос для получения текущей временной метки в миллисекундах. По умолчанию используется `std::chrono` для получения метки времени. Вы можете переопределить этот макрос, чтобы использовать собственную функцию получения времени.

```cpp
#define LOGIT_CURRENT_TIMESTAMP_MS() my_custom_timestamp_function()
```

- **LOGIT_CONSOLE_PATTERN**: Определяет шаблон лога для вывода в консоль. Этот шаблон контролирует формат сообщений, отправляемых в консоль, включая временную метку, сообщение и цвет. Если `LOGIT_CONSOLE_PATTERN` не определен, он по умолчанию установлен на `%H:%M:%S.%e | %^%v%$`.

```cpp
#define LOGIT_CONSOLE_PATTERN "%H:%M:%S.%e | %^%v%$"
```

- **LOGIT_FILE_LOGGER_PATH**: Определяет путь к каталогу для логов. Если `LOGIT_FILE_LOGGER_PATH` не определен, по умолчанию используется *"data/logs"*. Вы можете задать этот путь для управления тем, где будут храниться логи.

```cpp
#define LOGIT_FILE_LOGGER_PATH "/custom/log/directory"
```

- **LOGIT_FILE_LOGGER_AUTO_DELETE_DAYS**: Определяет количество дней, по истечении которых старые файлы логов будут удалены. Если `LOGIT_FILE_LOGGER_AUTO_DELETE_DAYS` не определен, по умолчанию используется `30` дней. Вы можете задать это значение для управления политикой хранения логов.

```cpp
#define LOGIT_FILE_LOGGER_AUTO_DELETE_DAYS 60 // Хранить логи 60 дней
```

- **LOGIT_FILE_LOGGER_PATTERN**: Определяет шаблон лога для файловых логгеров. Этот шаблон контролирует формат сообщений, записываемых в файлы логов, включая временную метку, имя файла, номер строки, имя функции и информацию о потоке. Если `LOGIT_FILE_LOGGER_PATTERN` не определен, используется по умолчанию `[%Y-%m-%d %H:%M:%S.%e] [%ffn:%#] [%!] [thread:%t] [%l] %SC%v`.

```cpp
#define LOGIT_FILE_LOGGER_PATTERN "[%Y-%m-%d %H:%M:%S.%e] [%l] %SC%v"
```

- **LOGIT_UNIQUE_FILE_LOGGER_PATH**: Определяет путь по умолчанию для уникальных файлов логов. Если `LOGIT_UNIQUE_FILE_LOGGER_PATH` не определен, используется *"data/logs/unique_logs"*. Вы можете указать собственный путь для уникальных файлов логов.

```cpp
#define LOGIT_UNIQUE_FILE_LOGGER_PATH "/custom/unique/log/directory"
```

- **LOGIT_UNIQUE_FILE_LOGGER_PATTERN**: Определяет шаблон лога для уникальных файлов логов. Если `LOGIT_UNIQUE_FILE_LOGGER_PATTERN` не определен, по умолчанию используется `"%v"`. Вы можете настроить этот шаблон для управления форматом сообщений в уникальных файлах.

```cpp
#define LOGIT_UNIQUE_FILE_LOGGER_PATTERN "%v"
```

- **LOGIT_UNIQUE_FILE_LOGGER_HASH_LENGTH**: Определяет длину хеша, используемого в уникальных именах файлов логов. Если `LOGIT_UNIQUE_FILE_LOGGER_HASH_LENGTH` не определен, по умолчанию используется `8` символов. Это обеспечивает уникальные имена файлов для каждого лога.

```cpp
#define LOGIT_UNIQUE_FILE_LOGGER_HASH_LENGTH 12 // Set hash length to 12 characters
```

- **LOGIT_SHORT_NAME**: Включает короткие имена для макросов логирования, таких как `LOG_T`, `LOG_D`, `LOG_E` и другие, для более лаконичных записей логов.

- **LOGIT_USE_FMT_LIB**: Включает использование библиотеки fmt для форматирования строк.

---

## Пример пользовательского логгера и форматтера

Вы можете расширить возможности LogIt++ с помощью реализации собственных логгеров и форматтеров. Вот как это сделать:

### Пример пользовательского логгера

```cpp
#include
#include
#include

class FileLogger : public logit::ILogger {
public:
FileLogger(const std::string& file_name) : m_file_name(file_name) {
m_log_file.open(file_name, std::ios::out | std::ios::app);
}

~FileLogger() {
if (m_log_file.is_open()) {
m_log_file.close();
}
}

void log(const logit::LogRecord& record, const std::string& message) override {
std::lock_guard lock(m_mutex);
if (m_log_file.is_open()) {
m_log_file << message << std::endl;
}
}

void wait() override {}

private:
std::string m_file_name;
std::ofstream m_log_file;
std::mutex m_mutex;
};
```

### Пример пользовательского форматтера

```cpp
#include
#include

class JsonLogFormatter : public logit::ILogFormatter {
public:
std::string format(const logit::LogRecord& record) const override {
Json::Value log_entry;
log_entry["level"] = static_cast(record.log_level);
log_entry["timestamp_ms"] = record.timestamp_ms;
log_entry["file"] = record.file;
log_entry["line"] = record.line;
log_entry["function"] = record.function;
log_entry["message"] = record.format;

Json::StreamWriterBuilder writer;
return Json::writeString(writer, log_entry);
}
};
```

---

## Установка

LogIt++ — это библиотека, работающая только с заголовками. Чтобы интегрировать её в ваш проект, выполните следующие шаги:

1. Клонируйте репозиторий с его подмодулями:

```bash
git clone --recurse-submodules https://github.com/NewYaroslav/log-it-cpp.git
```
2. Включите заголовочные файлы LogIt++ в ваш проект:

```cpp
#include
```

3. Настройте пути к заголовочным файлам для зависимостей, таких как time-shield-cpp.

LogIt++ зависит от *time-shield-cpp*, который находится в папке `libs` как подмодуль. Убедитесь, что путь к `libs\time-shield-cpp\include` добавлен в каталоги заголовков вашего проекта. Если вы используете IDE, такие как *Visual Studio* или *CLion*, вы можете добавить этот путь в настройках проекта.

4. (Необязательно) Включите поддержку библиотеки fmt:

LogIt++ поддерживает библиотеку *fmt* для продвинутого форматирования строк, которая также включена как подмодуль. Чтобы включить *fmt* в LogIt++, определите макрос `LOGIT_USE_FMT_LIB` в вашем проекте:

```cpp
#define LOGIT_USE_FMT_LIB
```

---

## Документация

Подробную документацию для LogIt++, включая описание API и примеры использования, можно найти [здесь](https://newyaroslav.github.io/log-it-cpp/).

---

## Лицензия
Эта библиотека распространяется под лицензией MIT. Подробности смотрите в файле [LICENSE](https://github.com/NewYaroslav/log-it-cpp/blob/main/LICENSE) в репозитории.