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
80 changes: 41 additions & 39 deletions README-RU.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,51 +88,53 @@ LOGIT_ADD_LOGGER(CustomLogger, (), logit::SimpleLogFormatter, ("%v"));

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

Ниже приведен простой пример использования LogIt++ в вашем приложении:
Ниже приведен простой пример использования LogIt++ в вашем приложении. Размер очереди и поведение при переполнении настраиваются с помощью `LOGIT_SET_MAX_QUEUE` и `LOGIT_SET_QUEUE_POLICY` (используйте `LOGIT_QUEUE_DROP` или `LOGIT_QUEUE_BLOCK`):

```cpp
#define LOGIT_SHORT_NAME
#include <LogIt.hpp>

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;
// Инициализация логгера с выводом в консоль по умолчанию
LOGIT_ADD_CONSOLE_DEFAULT();
LOGIT_SET_MAX_QUEUE(64);
LOGIT_SET_QUEUE_POLICY(LOGIT_QUEUE_DROP);

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;
}
```

Expand Down
82 changes: 42 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,51 +93,53 @@ LOGIT_ADD_LOGGER(CustomLogger, (), logit::SimpleLogFormatter, ("%v"));

## Usage

Here’s a simple example demonstrating how to use LogIt++ in your application:
Here’s a simple example demonstrating how to use LogIt++ in your application. The task queue size and overflow behavior are configurable via `LOGIT_SET_MAX_QUEUE` and `LOGIT_SET_QUEUE_POLICY` (use `LOGIT_QUEUE_DROP` or `LOGIT_QUEUE_BLOCK`):

```cpp
#define LOGIT_SHORT_NAME
#include <LogIt.hpp>

int main() {
// Initialize the logger with default console output
LOGIT_ADD_CONSOLE_DEFAULT();

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

// Basic logging using macros
LOG_INFO("Starting the application");
LOG_DEBUG("Variable values", a, b);
LOG_WARN("This is a warning message");

// Formatted logging
LOG_PRINTF_INFO("Formatted log: value of a = %.2f", a);
LOG_FORMAT_WARN("%.4d", b, c);

// Error and fatal logs
LOG_ERROR("An error occurred", b);
LOG_FATAL("Fatal error. Terminating application.");

// Conditional logging
LOG_ERROR_IF(b < 0, "Value of b is negative");
LOG_WARN_IF(a > 100, "Value of a exceeds 100");

// Stream-based logging with short and long names
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;

// Using LOGIT_TRACE for tracing function execution
LOGIT_TRACE0(); // Trace without arguments
LOG_PRINT_TRACE("Entering main function with variable a =", a);

// Wait for all asynchronous logs to be processed
LOGIT_WAIT();

return 0;
// Initialize the logger with default console output
LOGIT_ADD_CONSOLE_DEFAULT();
LOGIT_SET_MAX_QUEUE(64);
LOGIT_SET_QUEUE_POLICY(LOGIT_QUEUE_DROP);

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

// Basic logging using macros
LOG_INFO("Starting the application");
LOG_DEBUG("Variable values", a, b);
LOG_WARN("This is a warning message");

// Formatted logging
LOG_PRINTF_INFO("Formatted log: value of a = %.2f", a);
LOG_FORMAT_WARN("%.4d", b, c);

// Error and fatal logs
LOG_ERROR("An error occurred", b);
LOG_FATAL("Fatal error. Terminating application.");

// Conditional logging
LOG_ERROR_IF(b < 0, "Value of b is negative");
LOG_WARN_IF(a > 100, "Value of a exceeds 100");

// Stream-based logging with short and long names
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;

// Using LOGIT_TRACE for tracing function execution
LOGIT_TRACE0(); // Trace without arguments
LOG_PRINT_TRACE("Entering main function with variable a =", a);

// Wait for all asynchronous logs to be processed
LOGIT_WAIT();

return 0;
}
```

Expand Down Expand Up @@ -495,4 +497,4 @@ Detailed documentation for LogIt++, including API reference and usage examples,
---

## License
This library is licensed under the MIT License. See the [LICENSE](https://github.com/NewYaroslav/log-it-cpp/blob/main/LICENSE) file in the repository for more details.
This library is licensed under the MIT License. See the [LICENSE](https://github.com/NewYaroslav/log-it-cpp/blob/main/LICENSE) file in the repository for more details.
7 changes: 7 additions & 0 deletions docs/groups.dox
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ if (LOGIT_IS_LOGGER_ENABLED(1)) {
LOGIT_INFO("Logger 1 is enabled");
}
\endcode

\par Task Executor Configuration
Use `LOGIT_QUEUE_DROP` or `LOGIT_QUEUE_BLOCK` with `LOGIT_SET_QUEUE_POLICY`.
\code
LOGIT_SET_MAX_QUEUE(64); // Limit queue size
LOGIT_SET_QUEUE_POLICY(LOGIT_QUEUE_DROP); // Drop tasks when full
\endcode
*/

/*!
Expand Down
2 changes: 2 additions & 0 deletions examples/example_logit_basic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ int main() {
LOGIT_ADD_CONSOLE_DEFAULT();
LOGIT_ADD_FILE_LOGGER_DEFAULT();
LOGIT_ADD_UNIQUE_FILE_LOGGER_DEFAULT_SINGLE_MODE();
LOGIT_SET_MAX_QUEUE(64);
LOGIT_SET_QUEUE_POLICY(LOGIT_QUEUE_DROP);

logit::test_log_depth_3();

Expand Down
22 changes: 22 additions & 0 deletions include/logit_cpp/logit/LogMacros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,28 @@

/// \}

/// \name Task Executor Configuration
/// Macros for configuring the TaskExecutor.
/// \{

/// \brief Sets the maximum number of queued tasks.
/// \param size Maximum queue size (0 for unlimited).
#define LOGIT_SET_MAX_QUEUE(size) \
logit::detail::TaskExecutor::get_instance().set_max_queue_size(size)

/// \brief Queue policy for dropping tasks when the queue is full.
#define LOGIT_QUEUE_DROP logit::detail::QueuePolicy::Drop

/// \brief Queue policy for blocking when the queue is full.
#define LOGIT_QUEUE_BLOCK logit::detail::QueuePolicy::Block

/// \brief Sets the behavior when the queue is full.
/// \param mode LOGIT_QUEUE_DROP or LOGIT_QUEUE_BLOCK.
#define LOGIT_SET_QUEUE_POLICY(mode) \
logit::detail::TaskExecutor::get_instance().set_queue_policy(mode)

/// \}

/// \brief Macro for waiting for all asynchronous loggers to finish processing.
#define LOGIT_WAIT() logit::Logger::get_instance().wait()

Expand Down
36 changes: 34 additions & 2 deletions include/logit_cpp/logit/detail/TaskExecutor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@

namespace logit { namespace detail {

/// \brief Queue overflow handling policy.
enum class QueuePolicy { Drop, Block };

#if defined(__EMSCRIPTEN__)

/// \class TaskExecutor
Expand All @@ -33,6 +36,9 @@ namespace logit { namespace detail {
void wait() {}
void shutdown() {}

void set_max_queue_size(std::size_t) {}
void set_queue_policy(QueuePolicy) {}

private:
TaskExecutor() = default;
~TaskExecutor() = default;
Expand Down Expand Up @@ -63,6 +69,15 @@ namespace logit { namespace detail {
void add_task(std::function<void()> task) {
std::unique_lock<std::mutex> lock(m_queue_mutex);
if (m_stop_flag) return;
if (m_max_queue_size > 0 && m_tasks_queue.size() >= m_max_queue_size) {
if (m_overflow_policy == QueuePolicy::Drop) {
return;
}
m_queue_condition.wait(lock, [this]() {
return m_tasks_queue.size() < m_max_queue_size || m_stop_flag;
});
if (m_stop_flag) return;
}
m_tasks_queue.push(std::move(task));
lock.unlock();
m_queue_condition.notify_one();
Expand All @@ -86,18 +101,34 @@ namespace logit { namespace detail {
std::unique_lock<std::mutex> lock(m_queue_mutex);
m_stop_flag = true;
lock.unlock();
m_queue_condition.notify_one();
m_queue_condition.notify_all();
if (m_worker_thread.joinable()) {
m_worker_thread.join();
}
}

/// \brief Sets the maximum size of the task queue.
/// \param size Maximum number of tasks in the queue (0 for unlimited).
void set_max_queue_size(std::size_t size) {
std::lock_guard<std::mutex> lock(m_queue_mutex);
m_max_queue_size = size;
}

/// \brief Sets the behavior when the queue is full.
/// \param policy QueuePolicy::Drop to discard tasks or QueuePolicy::Block to wait.
void set_queue_policy(QueuePolicy policy) {
std::lock_guard<std::mutex> lock(m_queue_mutex);
m_overflow_policy = policy;
}

private:
std::queue<std::function<void()>> m_tasks_queue; ///< Queue holding tasks to be executed.
mutable std::mutex m_queue_mutex; ///< Mutex to protect access to the task queue.
std::condition_variable m_queue_condition; ///< Condition variable to signal task availability.
std::thread m_worker_thread; ///< Worker thread for executing tasks.
bool m_stop_flag; ///< Flag indicating if the worker thread should stop.
std::size_t m_max_queue_size; ///< Maximum number of tasks in the queue (0 for unlimited).
QueuePolicy m_overflow_policy; ///< Policy for handling queue overflow.

/// \brief The worker thread function that processes tasks from the queue.
void worker_function() {
Expand All @@ -113,12 +144,13 @@ namespace logit { namespace detail {
task = std::move(m_tasks_queue.front());
m_tasks_queue.pop();
lock.unlock();
m_queue_condition.notify_one();
task();
}
}

/// \brief Private constructor to enforce the singleton pattern.
TaskExecutor() : m_stop_flag(false) {
TaskExecutor() : m_stop_flag(false), m_max_queue_size(0), m_overflow_policy(QueuePolicy::Block) {
m_worker_thread = std::thread(&TaskExecutor::worker_function, this);
}

Expand Down
Loading