Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions README-RU.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ try {

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

Легко логируйте переменные и сообщения с помощью макросов. Просто выберите подходящий макрос и передайте переменные или аргументы. Для printf-подобного форматирования используйте `LOGIT_FORMAT_<LEVEL>`.
Легко логируйте переменные и сообщения с помощью макросов. Выберите макрос в зависимости от стиля форматирования:

* `LOGIT_PRINTF_<LEVEL>` повторяет поведение функции `printf` и позволяет задавать формат для каждого аргумента.
* `LOGIT_FORMAT_<LEVEL>` применяет один и тот же формат ко всему списку аргументов.

```
float someFloat = 123.456f;
Expand All @@ -37,7 +40,8 @@ LOGIT_INFO(someFloat, someInt);

auto now = std::chrono::system_clock::now();
LOGIT_PRINT_INFO("TimePoint example: ", now);
LOGIT_FORMAT_INFO("%s: %d", "status", 200); // printf-подобное форматирование
LOGIT_PRINTF_INFO("%.2f %d", someFloat, someInt); // как printf
LOGIT_FORMAT_INFO("%.2f", someFloat, 654.321f); // один формат для всех аргументов
```

- **Фильтры и ограничение частоты логов**:
Expand Down Expand Up @@ -111,7 +115,8 @@ LOGIT_ADD_LOGGER(CustomLogger, (), logit::SimpleLogFormatter, ("%v"));
| --------------- | -------- |
| `LOGIT_<LEVEL>(...)` | Логирование с указанным уровнем (`TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`). |
| `LOGIT_PRINT_<LEVEL>(...)` | Логирование заранее сформированной строки или сообщения, собранного через потоки. |
| `LOGIT_FORMAT_<LEVEL>(fmt, ...)` | printf-подобное форматирование с форматной строкой и аргументами. |
| `LOGIT_PRINTF_<LEVEL>(fmt, ...)` | форматирование в стиле `printf` с плейсхолдерами для каждого аргумента. |
| `LOGIT_FORMAT_<LEVEL>(fmt, ...)` | применение одного и того же формата ко всем аргументам. |
| `LOGIT_STREAM_<LEVEL>()` | Потоковое логирование через `<<`; короткие версии `LOG_S_<LEVEL>()` доступны при определении `LOGIT_SHORT_NAME`. |
| `LOGIT_<LEVEL>_IF(condition, ...)` | Логирование только если условие истинно. |
| `LOGIT_<LEVEL>_ONCE(...)` | Логирование только при первом вызове. |
Expand Down Expand Up @@ -461,7 +466,6 @@ LogIt++ предоставляет несколько макросов, кото

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

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

---

Expand Down Expand Up @@ -548,13 +552,9 @@ git clone --recurse-submodules https://github.com/NewYaroslav/log-it-cpp.git

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

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

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

```cpp
#define LOGIT_USE_FMT_LIB
```
LogIt++ включает библиотеку *fmt* для форматирования с `{}`. Чтобы использовать макросы `LOGIT_FMT_*` и `LOGIT_SCOPE_FMT_*`, соберите библиотеку с опцией CMake `-DLOGIT_WITH_FMT=ON`.

## Системные бэкенды

Expand Down
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ try {

- **Macro-Based Logging**:

Easily log variables and messages using macros. Simply choose the appropriate macro and pass variables or arguments to it. Use `LOGIT_FORMAT_<LEVEL>` for printf-style formatting.
Easily log variables and messages using macros. Choose the macro that matches the desired formatting style:

* `LOGIT_PRINTF_<LEVEL>` mimics `printf`, where the format string controls each argument.
* `LOGIT_FORMAT_<LEVEL>` applies the same format to every argument in the list.

```
float someFloat = 123.456f;
Expand All @@ -49,7 +52,8 @@ LOGIT_INFO(someFloat, someInt);

auto now = std::chrono::system_clock::now();
LOGIT_PRINT_INFO("TimePoint example: ", now);
LOGIT_FORMAT_INFO("%s: %d", "status", 200); // printf-style
LOGIT_PRINTF_INFO("%.2f %d", someFloat, someInt); // printf-style
LOGIT_FORMAT_INFO("%.2f", someFloat, 654.321f); // same format for all args
```

- **Log Filters and Throttling**:
Expand Down Expand Up @@ -439,7 +443,6 @@ LogIt++ provides several macros that allow for customization and configuration.

- **LOGIT_SHORT_NAME**: Enables short names for logging macros, such as `LOG_T`, `LOG_D`, `LOG_E`, etc., for more concise logging statements.

- **LOGIT_USE_FMT_LIB**: Enables the use of the fmt library for string formatting.

---

Expand Down Expand Up @@ -511,7 +514,8 @@ public:
| ------------- | ----------- |
| `LOGIT_<LEVEL>(...)` | Log a message with the given level (`TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`). |
| `LOGIT_PRINT_<LEVEL>(...)` | Log a pre-formatted string or stream-built message. |
| `LOGIT_FORMAT_<LEVEL>(fmt, ...)` | printf-style formatting with a format string and arguments. |
| `LOGIT_PRINTF_<LEVEL>(fmt, ...)` | `printf`-style formatting with placeholders for each argument. |
| `LOGIT_FORMAT_<LEVEL>(fmt, ...)` | Apply the same format string to every argument. |
| `LOGIT_STREAM_<LEVEL>()` | Stream-style logging with `<<` operators; short aliases `LOG_S_<LEVEL>()` when `LOGIT_SHORT_NAME` is defined. |
| `LOGIT_<LEVEL>_IF(condition, ...)` | Log only when `condition` is true. |
| `LOGIT_<LEVEL>_ONCE(...)` | Log only the first time the macro is executed. |
Expand Down Expand Up @@ -576,13 +580,9 @@ git clone --recurse-submodules https://github.com/NewYaroslav/log-it-cpp.git
LogIt++ depends on **time-shield-cpp**, which is located in the `libs` folder as a submodule. Ensure that the path to `libs\time-shield-cpp\include` is added to your project's include directories.
If you are using an IDE like **Visual Studio** or **CLion**, you can add the include path in the project settings.

4. (Optional) Enable fmt support:

LogIt++ supports the *fmt* library for advanced string formatting, which is also included as a submodule. To enable *fmt* in LogIt++, define the macro `LOGIT_USE_FMT_LIB` in your project:
4. (Optional) Enable fmt-style macros:

```cpp
#define LOGIT_USE_FMT_LIB
```
LogIt++ includes the *fmt* library for `{}`-based formatting. To use the `LOGIT_FMT_*` and `LOGIT_SCOPE_FMT_*` macros, build the library with the CMake option `-DLOGIT_WITH_FMT=ON`.

## System Backends

Expand Down
23 changes: 5 additions & 18 deletions docs/mainpage.dox
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ try {

\subsection macro_logging Logging with Macros

Log variables and messages easily using macros. Simply select the appropriate macro and pass variables or arguments.
Log variables and messages easily using macros. Simply select the appropriate macro and pass variables or arguments. Use `LOGIT_PRINTF_<LEVEL>` for `printf`-style formatting and `LOGIT_FORMAT_<LEVEL>` to apply the same format to every argument.

\code{.cpp}
float someFloat = 123.456f;
Expand All @@ -42,6 +42,8 @@ LOGIT_INFO(someFloat, someInt);

auto now = std::chrono::system_clock::now();
LOGIT_PRINT_INFO("TimePoint example: ", now);
LOGIT_PRINTF_INFO("%.2f %d", someFloat, someInt); // printf-style
LOGIT_FORMAT_INFO("%.2f", someFloat, 654.321f); // same format for all args
\endcode

\subsection multiple_backends Support for Multiple Backends
Expand Down Expand Up @@ -449,15 +451,6 @@ Enables short names for logging macros, such as `LOG_T`, `LOG_D`, `LOG_E`, etc.,
#define LOGIT_SHORT_NAME
\endcode

- **LOGIT_USE_FMT_LIB**:

Enables the use of the fmt library for string formatting. If defined, the logging system will use fmt for advanced formatting of log messages.

\code{.cpp}
// Enable use of the fmt library for formatting.
#define LOGIT_USE_FMT_LIB
\endcode

\section custom_backend_sec Custom Logger Backend and Formatter

LogIt++ allows you to extend the logging system by creating your own loggers and formatters. This section explains how to implement a custom backend for logging and a custom log formatter.
Expand Down Expand Up @@ -574,7 +567,7 @@ LogIt++ is a header-only library, which means it can be easily included in your

\subsection step1 Step 1: Clone the Repository

First, clone the LogIt++ repository from GitHub along with its submodules. The library has dependencies on other header-only libraries, such as **time-shield-cpp** (for time utilities) and **fmt** (for string formatting, if `LOGIT_USE_FMT_LIB` is enabled).
First, clone the LogIt++ repository from GitHub along with its submodules. The library has dependencies on other header-only libraries, such as **time-shield-cpp** (for time utilities) and **fmt** (used by `LOGIT_FMT_*` macros).

To clone the repository with submodules, use the following command:

Expand Down Expand Up @@ -606,13 +599,7 @@ If you are using an IDE like **Visual Studio** or **CLion**, you can add the inc

\subsection step4 Step 4: Using fmt (Optional)

LogIt++ supports the **fmt** library for advanced string formatting, which is also included as a submodule. To enable `fmt` in LogIt++, define the macro `LOGIT_USE_FMT_LIB` in your project:

\code{cpp}
#define LOGIT_USE_FMT_LIB
\endcode

This will allow you to use `fmt`-style formatting within your log messages. The `fmt` library is also located in the `libs` folder of the repository.
LogIt++ ships with the **fmt** library for `{}`-style formatting. To use the `LOGIT_FMT_*` and `LOGIT_SCOPE_FMT_*` macros, build the library with the CMake option `-DLOGIT_WITH_FMT=ON`.

\subsection step5 Step 5: Build and Run Your Project

Expand Down
3 changes: 3 additions & 0 deletions examples/example_logit_basic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ int main() {
LOGIT_PRINT_ERROR("An error has occurred during processing with color: ", color);
LOGIT_FATAL("Fatal error! Immediate attention required!");

// printf-style formatting
LOGIT_PRINTF_INFO("%.2f %d", someFloat, someInt);

// Demonstrating formatted logging for homogeneous variables
LOGIT_FORMAT_INFO("%.2f", someFloat, 654.321f); // Two float values
LOGIT_FORMAT_INFO("%.4d", someInt, 999); // Two int values
Expand Down
71 changes: 67 additions & 4 deletions include/logit_cpp/logit/LogMacros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,16 +128,19 @@ static_assert(LOGIT_LEVEL_FATAL == static_cast<int>(logit::LogLevel::LOG_LVL_FAT
#define LOGIT_DETAIL_SCOPE_T(level, threshold_ms, phase) \
::logit::detail::ScopeTimer LOGIT_CONCAT(_logit_scope_, __COUNTER__)(level, (phase), __FILE__, __LINE__, LOGIT_FUNCTION, -1, (threshold_ms))

#define LOGIT_DETAIL_SCOPE_PRINTF(level, fmt_str, ...) \
::logit::detail::ScopeTimer LOGIT_CONCAT(_logit_scope_, __COUNTER__)(level, logit::format(fmt_str, __VA_ARGS__), __FILE__, __LINE__, LOGIT_FUNCTION, -1, 0)
#define LOGIT_DETAIL_SCOPE_PRINTF_T(level, threshold_ms, fmt_str, ...) \
::logit::detail::ScopeTimer LOGIT_CONCAT(_logit_scope_, __COUNTER__)(level, logit::format(fmt_str, __VA_ARGS__), __FILE__, __LINE__, LOGIT_FUNCTION, -1, (threshold_ms))

#ifdef LOGIT_WITH_FMT
#define LOGIT_DETAIL_SCOPE_FMT(level, fmt_str, ...) \
::logit::detail::ScopeTimer LOGIT_CONCAT(_logit_scope_, __COUNTER__)(level, fmt::format(fmt_str, __VA_ARGS__), __FILE__, __LINE__, LOGIT_FUNCTION, -1, 0)
#define LOGIT_DETAIL_SCOPE_FMT_T(level, threshold_ms, fmt_str, ...) \
::logit::detail::ScopeTimer LOGIT_CONCAT(_logit_scope_, __COUNTER__)(level, fmt::format(fmt_str, __VA_ARGS__), __FILE__, __LINE__, LOGIT_FUNCTION, -1, (threshold_ms))
#else
#define LOGIT_DETAIL_SCOPE_FMT(level, fmt_str, ...) \
::logit::detail::ScopeTimer LOGIT_CONCAT(_logit_scope_, __COUNTER__)(level, logit::format(fmt_str, __VA_ARGS__), __FILE__, __LINE__, LOGIT_FUNCTION, -1, 0)
#define LOGIT_DETAIL_SCOPE_FMT_T(level, threshold_ms, fmt_str, ...) \
::logit::detail::ScopeTimer LOGIT_CONCAT(_logit_scope_, __COUNTER__)(level, logit::format(fmt_str, __VA_ARGS__), __FILE__, __LINE__, LOGIT_FUNCTION, -1, (threshold_ms))
#define LOGIT_DETAIL_SCOPE_FMT(level, fmt_str, ...) do { } while (0)
#define LOGIT_DETAIL_SCOPE_FMT_T(level, threshold_ms, fmt_str, ...) do { } while (0)
#endif

#if LOGIT_COMPILED_LEVEL <= LOGIT_LEVEL_TRACE
Expand Down Expand Up @@ -194,6 +197,66 @@ static_assert(LOGIT_LEVEL_FATAL == static_cast<int>(logit::LogLevel::LOG_LVL_FAT
#define LOGIT_SCOPE_FATAL_T(threshold_ms, phase) do { } while (0)
#endif

#if LOGIT_COMPILED_LEVEL <= LOGIT_LEVEL_TRACE
#define LOGIT_SCOPE_PRINTF_TRACE(fmt_str, ...) \
LOGIT_DETAIL_SCOPE_PRINTF(::logit::LogLevel::LOG_LVL_TRACE, fmt_str, __VA_ARGS__)
#define LOGIT_SCOPE_PRINTF_TRACE_T(threshold_ms, fmt_str, ...) \
LOGIT_DETAIL_SCOPE_PRINTF_T(::logit::LogLevel::LOG_LVL_TRACE, threshold_ms, fmt_str, __VA_ARGS__)
#else
#define LOGIT_SCOPE_PRINTF_TRACE(fmt_str, ...) do { } while (0)
#define LOGIT_SCOPE_PRINTF_TRACE_T(threshold_ms, fmt_str, ...) do { } while (0)
#endif

#if LOGIT_COMPILED_LEVEL <= LOGIT_LEVEL_DEBUG
#define LOGIT_SCOPE_PRINTF_DEBUG(fmt_str, ...) \
LOGIT_DETAIL_SCOPE_PRINTF(::logit::LogLevel::LOG_LVL_DEBUG, fmt_str, __VA_ARGS__)
#define LOGIT_SCOPE_PRINTF_DEBUG_T(threshold_ms, fmt_str, ...) \
LOGIT_DETAIL_SCOPE_PRINTF_T(::logit::LogLevel::LOG_LVL_DEBUG, threshold_ms, fmt_str, __VA_ARGS__)
#else
#define LOGIT_SCOPE_PRINTF_DEBUG(fmt_str, ...) do { } while (0)
#define LOGIT_SCOPE_PRINTF_DEBUG_T(threshold_ms, fmt_str, ...) do { } while (0)
#endif

#if LOGIT_COMPILED_LEVEL <= LOGIT_LEVEL_INFO
#define LOGIT_SCOPE_PRINTF_INFO(fmt_str, ...) \
LOGIT_DETAIL_SCOPE_PRINTF(::logit::LogLevel::LOG_LVL_INFO, fmt_str, __VA_ARGS__)
#define LOGIT_SCOPE_PRINTF_INFO_T(threshold_ms, fmt_str, ...) \
LOGIT_DETAIL_SCOPE_PRINTF_T(::logit::LogLevel::LOG_LVL_INFO, threshold_ms, fmt_str, __VA_ARGS__)
#else
#define LOGIT_SCOPE_PRINTF_INFO(fmt_str, ...) do { } while (0)
#define LOGIT_SCOPE_PRINTF_INFO_T(threshold_ms, fmt_str, ...) do { } while (0)
#endif

#if LOGIT_COMPILED_LEVEL <= LOGIT_LEVEL_WARN
#define LOGIT_SCOPE_PRINTF_WARN(fmt_str, ...) \
LOGIT_DETAIL_SCOPE_PRINTF(::logit::LogLevel::LOG_LVL_WARN, fmt_str, __VA_ARGS__)
#define LOGIT_SCOPE_PRINTF_WARN_T(threshold_ms, fmt_str, ...) \
LOGIT_DETAIL_SCOPE_PRINTF_T(::logit::LogLevel::LOG_LVL_WARN, threshold_ms, fmt_str, __VA_ARGS__)
#else
#define LOGIT_SCOPE_PRINTF_WARN(fmt_str, ...) do { } while (0)
#define LOGIT_SCOPE_PRINTF_WARN_T(threshold_ms, fmt_str, ...) do { } while (0)
#endif

#if LOGIT_COMPILED_LEVEL <= LOGIT_LEVEL_ERROR
#define LOGIT_SCOPE_PRINTF_ERROR(fmt_str, ...) \
LOGIT_DETAIL_SCOPE_PRINTF(::logit::LogLevel::LOG_LVL_ERROR, fmt_str, __VA_ARGS__)
#define LOGIT_SCOPE_PRINTF_ERROR_T(threshold_ms, fmt_str, ...) \
LOGIT_DETAIL_SCOPE_PRINTF_T(::logit::LogLevel::LOG_LVL_ERROR, threshold_ms, fmt_str, __VA_ARGS__)
#else
#define LOGIT_SCOPE_PRINTF_ERROR(fmt_str, ...) do { } while (0)
#define LOGIT_SCOPE_PRINTF_ERROR_T(threshold_ms, fmt_str, ...) do { } while (0)
#endif

#if LOGIT_COMPILED_LEVEL <= LOGIT_LEVEL_FATAL
#define LOGIT_SCOPE_PRINTF_FATAL(fmt_str, ...) \
LOGIT_DETAIL_SCOPE_PRINTF(::logit::LogLevel::LOG_LVL_FATAL, fmt_str, __VA_ARGS__)
#define LOGIT_SCOPE_PRINTF_FATAL_T(threshold_ms, fmt_str, ...) \
LOGIT_DETAIL_SCOPE_PRINTF_T(::logit::LogLevel::LOG_LVL_FATAL, threshold_ms, fmt_str, __VA_ARGS__)
#else
#define LOGIT_SCOPE_PRINTF_FATAL(fmt_str, ...) do { } while (0)
#define LOGIT_SCOPE_PRINTF_FATAL_T(threshold_ms, fmt_str, ...) do { } while (0)
#endif

#if LOGIT_COMPILED_LEVEL <= LOGIT_LEVEL_TRACE
#define LOGIT_SCOPE_FMT_TRACE(fmt_str, ...) \
LOGIT_DETAIL_SCOPE_FMT(::logit::LogLevel::LOG_LVL_TRACE, fmt_str, __VA_ARGS__)
Expand Down
16 changes: 1 addition & 15 deletions include/logit_cpp/logit/utils/format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,17 @@
#include <vector>
#include <string>

#ifdef LOGIT_USE_FMT_LIB
#include <fmt/core.h>
#endif

namespace logit {

/// \brief Formats a string according to the specified format.
///
/// This function formats a string using either the custom implementation
/// based on `vsnprintf`) or the `fmt` library, depending on whether
/// the macro `LOGIT_USE_FMT_LIB` is defined.
/// This function uses a `vsnprintf`-based implementation.
///
/// \param fmt The format string (similar to printf format).
/// \param ... A variable number of arguments matching the format string.
/// \see https://habr.com/ru/articles/318962/
/// \return A formatted std::string.
inline std::string format(const char *fmt, ...) {
# ifdef LOGIT_USE_FMT_LIB
va_list args;
va_start(args, fmt);
std::string result = fmt::vformat(fmt, fmt::make_format_args(args));
va_end(args);
return result;
# else
va_list args;
va_start(args, fmt);
std::vector<char> buffer(1024);
Expand All @@ -52,7 +39,6 @@ namespace logit {
buffer.clear();
buffer.resize(size);
}
# endif
}

}; // namespace logit
Expand Down
4 changes: 4 additions & 0 deletions tests/compiled_level_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ int main() {
LOGIT_SCOPE_TRACE_T(0, should_not_compile<int>());
LOGIT_SCOPE_FMT_TRACE("{}", should_not_compile<int>());
LOGIT_SCOPE_FMT_TRACE_T(0, "{}", should_not_compile<int>());
LOGIT_SCOPE_PRINTF_TRACE("%d", should_not_compile<int>());
LOGIT_SCOPE_PRINTF_TRACE_T(0, "%d", should_not_compile<int>());

// DEBUG macros
LOGIT_DEBUG(should_not_compile<int>());
Expand Down Expand Up @@ -79,5 +81,7 @@ int main() {
LOGIT_SCOPE_DEBUG_T(0, should_not_compile<int>());
LOGIT_SCOPE_FMT_DEBUG("{}", should_not_compile<int>());
LOGIT_SCOPE_FMT_DEBUG_T(0, "{}", should_not_compile<int>());
LOGIT_SCOPE_PRINTF_DEBUG("%d", should_not_compile<int>());
LOGIT_SCOPE_PRINTF_DEBUG_T(0, "%d", should_not_compile<int>());
return 0;
}
23 changes: 23 additions & 0 deletions tests/printf_format_macros_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#define LOGIT_FILE_LOGGER_PATH "."
#include <LogIt.hpp>
#include <fstream>
#include <string>

int main() {
LOGIT_ADD_FILE_LOGGER_DEFAULT();
float f = 123.456f;
int i = 789;
LOGIT_PRINTF_INFO("%.2f %d", f, i);
LOGIT_FORMAT_INFO("%.1f", f, 654.321f);
LOGIT_WAIT();
std::ifstream in(LOGIT_GET_LAST_FILE_PATH(0));
std::string line;
bool found_printf = false;
bool found_format = false;
while (std::getline(in, line)) {
if (line.find("123.46 789") != std::string::npos) found_printf = true;
if (line.find("f: 123.5, 654.3") != std::string::npos) found_format = true;
}
LOGIT_SHUTDOWN();
return (found_printf && found_format) ? 0 : 1;
}
Loading