Inherits from Task
The Logger
class provides a centralized logging facility for the task framework. It extends
the base Task
class to integrate with the signal-slot system, handling log messages from
various components and formatting them for output. The Logger supports different message levels (log,
warning, error) and can be connected to multiple tasks for comprehensive application-wide logging.
class Logger : public Task {
public:
// Constructor with optional prefix
explicit Logger(const std::string &prefix = ">>");
virtual ~Logger() = default;
// Logging methods
void log(const ArgumentPack &args);
void warn(const ArgumentPack &args);
void error(const ArgumentPack &args);
// Static helper to create logging signals for a task
static void createSignalsFor(Task *task);
// Connect to all signals of a task
void connectAllSignalsTo(Task *task);
void connectAllSignalsTo(const std::vector<Task *> &tasks);
private:
std::string m_prefix;
};
Method | Description | Format | Use Case |
---|---|---|---|
log() |
Regular informational messages | Standard console output | General information, status updates |
warn() |
Warning messages | Yellow colored text | Potential issues, non-critical problems |
error() |
Error messages | Red colored text | Critical errors, failure conditions |
// Create a logger with a custom prefix
auto logger = std::make_shared<Logger>("MyApp");
// Log different types of messages
ArgumentPack infoArgs;
infoArgs.add<std::string>("Application started successfully");
logger->log(infoArgs);
ArgumentPack warnArgs;
warnArgs.add<std::string>("Configuration file not found, using defaults");
logger->warn(warnArgs);
ArgumentPack errorArgs;
errorArgs.add<std::string>("Failed to connect to database: Connection refused");
logger->error(errorArgs);
// Output:
// MyApp Application started successfully
// MyApp WARNING: Configuration file not found, using defaults
// MyApp ERROR: Failed to connect to database: Connection refused
// Create a logger
auto logger = std::make_shared<Logger>("System");
// Create various components
auto algorithm = std::make_shared<MyAlgorithm>();
auto counter = std::make_shared<Counter>(0, 0, 100);
auto threadPool = std::make_shared<ThreadPool>();
// Connect logger to all components
logger->connectAllSignalsTo(algorithm.get());
logger->connectAllSignalsTo(counter.get());
logger->connectAllSignalsTo(threadPool.get());
// Add tasks to thread pool
threadPool->createAndAdd<MyTask>("Task1", 100);
threadPool->createAndAdd<MyTask>("Task2", 200);
// Execute thread pool - all logging goes through the logger
threadPool->exec();
// Output example:
// System Thread pool executing 2 tasks
// System Task1 started
// System Task2 started
// System Task1 completed successfully
// System Task2 completed successfully
// System Thread pool execution finished in 201ms
// Create specialized loggers for different subsystems
auto systemLogger = std::make_shared<Logger>("SYSTEM");
auto networkLogger = std::make_shared<Logger>("NETWORK");
auto dataLogger = std::make_shared<Logger>("DATA");
// Create components
auto networkComponent = std::make_shared<NetworkHandler>();
auto dataProcessor = std::make_shared<DataProcessor>();
auto systemMonitor = std::make_shared<SystemMonitor>();
// Connect specialized loggers to appropriate components
networkLogger->connectAllSignalsTo(networkComponent.get());
dataLogger->connectAllSignalsTo(dataProcessor.get());
systemLogger->connectAllSignalsTo(systemMonitor.get());
// Example output:
// NETWORK Connection established with server at 192.168.1.100
// DATA Processing 1024 records from dataset
// SYSTEM CPU usage: 45%, Memory: 512MB
// NETWORK WARNING: High latency detected (150ms)
// DATA ERROR: Invalid record format at position 512
The Logger class is designed to integrate with all components in the task framework. Here are some common integration patterns:
// Create logger and algorithm
auto logger = std::make_shared<Logger>("Processor");
auto algorithm = std::make_shared<DataProcessor>();
// Connect logger to algorithm
logger->connectAllSignalsTo(algorithm.get());
// Execute algorithm with logging
algorithm->exec();
// Typical log output:
// Processor Starting data processing...
// Processor Processing file data.csv
// Processor 25% complete
// Processor 50% complete
// Processor 75% complete
// Processor 100% complete
// Processor Data processing completed successfully
// Create logger and thread pool
auto logger = std::make_shared<Logger>("ThreadPool");
auto pool = std::make_shared<ThreadPool>();
// Connect logger to the thread pool
logger->connectAllSignalsTo(pool.get());
// Add tasks to the pool
for (int i = 0; i < 5; i++) {
auto task = pool->createAndAdd<MyTask>("Task" + std::to_string(i), i * 100);
// Connect logger to each task as well
logger->connectAllSignalsTo(task);
}
// Execute all tasks
pool->exec();
// Output includes both pool and task logs:
// ThreadPool Starting execution of 5 tasks
// ThreadPool Task0 started
// ThreadPool Task1 started
// ThreadPool Task2 started
// ThreadPool Task0 completed
// ThreadPool Task3 started
// ThreadPool Task1 completed
// ThreadPool Task4 started
// ThreadPool Task2 completed
// ThreadPool Task3 completed
// ThreadPool Task4 completed
// ThreadPool All tasks completed in 450ms
The Logger class provides several configuration options:
// Different prefix options
auto logger1 = std::make_shared<Logger>(">>"); // Default
auto logger2 = std::make_shared<Logger>("MyApp");
auto logger3 = std::make_shared<Logger>("[Server]");
auto logger4 = std::make_shared<Logger>("GUI::");
// Output examples:
// >> Application message
// MyApp Application message
// [Server] Application message
// GUI:: Application message
The Logger provides a static helper method to create standard logging signals for Task objects:
// Creating a custom task with logging capabilities
class MyCustomTask : public Task {
public:
MyCustomTask() {
// Create standard logging signals
Logger::createSignalsFor(this);
// Now the task has log, warn, and error signals
}
void doSomething() {
// Use logging signals
emitString("log", "Operation started");
try {
// Work...
emitString("log", "Operation completed");
} catch (const std::exception& e) {
emitString("error", std::string("Operation failed: ") + e.what());
}
}
};
The createSignalsFor()
method creates the following signals for the task:
log
- For regular informational messageswarn
- For warning messageserror
- For error messagesThe Logger formats messages differently based on their type:
// Regular log messages
void Logger::log(const ArgumentPack &args) {
if (!args.empty()) {
try {
std::cout << m_prefix << " " << args.get<std::string>(0)
<< std::endl;
} catch (const std::bad_cast &) {
std::cout << m_prefix << " [invalid format]" << std::endl;
}
}
}
// Warning messages (yellow text)
void Logger::warn(const ArgumentPack &args) {
if (!args.empty()) {
try {
std::cerr << "\033[33m" << m_prefix
<< " WARNING: " << args.get<std::string>(0) << "\033[0m"
<< std::endl;
} catch (const std::bad_cast &) {
std::cerr << "\033[33m" << m_prefix
<< " WARNING: [invalid format]\033[0m" << std::endl;
}
}
}
// Error messages (red text)
void Logger::error(const ArgumentPack &args) {
if (!args.empty()) {
try {
std::cerr << "\033[31m" << m_prefix
<< " ERROR: " << args.get<std::string>(0) << "\033[0m"
<< std::endl;
} catch (const std::bad_cast &) {
std::cerr << "\033[31m" << m_prefix
<< " ERROR: [invalid format]\033[0m" << std::endl;
}
}
}
The Logger class is designed to be thread-safe for concurrent access:
This allows safe logging from multiple threads in parallel applications:
// Create a shared logger
auto logger = std::make_shared<Logger>("ThreadSafe");
// Create a thread pool with multiple worker threads
auto pool = std::make_shared<ThreadPool>();
// Add tasks that will log concurrently
for (int i = 0; i < 10; i++) {
auto task = pool->createAndAdd<LoggingTask>(i);
// Connect logger to each task
logger->connectAllSignalsTo(task);
}
// Execute all tasks in parallel
pool->exec();
// All log messages will be properly formatted and synchronized,
// even though they're coming from multiple threads simultaneously