1. Overview
The asyncLogger.hpp header defines the AsyncLogger class, a singleton component that performs non-blocking, asynchronous logging to a persistent file. The design ensures that security-critical workflows (e.g., phishing scanning) can emit diagnostic events without blocking the caller, even under I/O pressure or partial filesystem failures.
Functionally, AsyncLogger provides:
- Asynchronous log event ingestion that never blocks the calling thread
- A background worker thread that drains an in-memory queue to a log file
- Safe shutdown semantics via stop flags and thread joining
- Timestamped log entries in a human-readable format
- Best-effort directory creation and I/O failure tolerance
2. Licensing and Linking Exception
This file header indicates the project is distributed under the GNU General Public License (GPL), with an additional exception permitting linking with the OpenSSL library under the terms described in the file. Implementations and redistributions must comply with the GPL for non-OpenSSL code and respect the stated exception conditions.
3. Dependencies and Includes
#include <fstream>
#include <string>
#include <mutex>
#include <queue>
#include <thread>
#include <chrono>
#include <condition_variable>
#include <filesystem>
#include <iostream>
#include <atomic>
- <fstream> – file output stream for appending log entries
- <string> – message and path storage
- <mutex> – synchronization for queue access
- <queue> – in-memory FIFO buffer for pending log messages
- <thread> – background worker thread execution
- <chrono> – time retrieval for timestamps
- <condition_variable> – wake/sleep coordination between producers and consumer
- <filesystem> – directory creation and path handling
- <iostream> – included for general diagnostics (not required for the core logic)
- <atomic> – stop flag management without races
4. Class Declaration and Scope
class AsyncLogger
The class is implemented as a process-wide singleton accessible via AsyncLogger::instance(). The constructor is private to enforce a single shared logger and ensure a single background worker thread.
5. Singleton Access
static AsyncLogger& instance();
Returns the singleton instance. Initialization occurs on first use via a function-local static object, which is thread-safe in modern C++ toolchains.
6. Public Interface
6.1 Asynchronous Logging
void log_block(const std::string& msg);
Enqueues a timestamped log line into an in-memory queue and returns immediately. The caller is never blocked on filesystem operations. If shutdown has started, the method returns without enqueueing.
Operational behavior:
- Checks a stop flag and drops messages once shutdown is requested
- Pushes
timestamp() + " " + msginto the FIFO queue - Signals the worker thread via a condition variable
6.2 Flush Trigger
void flush();
Triggers a wake-up of the worker thread to encourage an immediate drain of the queue. This method is intended primarily for tests or controlled shutdown flows.
6.3 Safe Stop
void stop();
Requests a graceful shutdown of the background worker thread. The method sets an atomic stop flag, notifies the worker, and joins the thread if it is joinable. Repeated calls are safe (idempotent).
7. Internal Architecture
7.1 Worker Thread
The constructor starts a dedicated worker thread that:
- Waits on a condition variable until new messages arrive or shutdown is requested
- Swaps the shared queue into a local queue to minimize lock contention
- Appends all queued lines to the log file and flushes the output stream
- Ignores I/O exceptions to avoid destabilizing the application
7.2 Log Destination
/var/log/BastionGuard/phishing_scanner.log
The logger targets a system log directory under /var/log. On initialization, it attempts to create /var/log/BastionGuard using std::filesystem::create_directories.
7.3 Timestamp Formatting
static std::string timestamp();
Produces a human-readable timestamp string in the format: [YYYY-MM-DD HH:MM:SS]. The implementation uses the local time zone (localtime_r) and std::strftime for formatting.
8. Internal State
std::thread worker_;
std::queue<std::string> queue_;
std::mutex mtx_;
std::condition_variable cv_;
std::string log_path_;
std::atomic<bool> stop_{false};
- worker_ – background consumer thread responsible for file writes
- queue_ – shared FIFO buffer of pending log messages
- mtx_ – mutex protecting shared state (
queue_) - cv_ – condition variable for producer/consumer coordination
- log_path_ – log file destination path
- stop_ – atomic stop flag controlling shutdown behavior
9. Reliability and Security Considerations
- Filesystem permissions: writing to
/var/logtypically requires elevated permissions; deployments should ensure correct ownership/permissions or provide a fallback path - Best-effort semantics: I/O errors are intentionally ignored to prevent logging failures from impacting security enforcement or UI responsiveness
- Log integrity: if logs are security-relevant, consider additional measures such as log rotation, tamper-evident storage, and restricted access controls
- Backpressure: the queue is unbounded; in high-volume scenarios, consider a bounded queue and drop/compact policies to avoid memory growth
- Timestamp policy: timestamps use local time; if cross-system correlation is required, consider emitting UTC timestamps or including timezone offsets
- Shutdown ordering: callers should ensure
stop()is invoked during controlled shutdown to minimize log loss; the destructor also callsstop()as a safety net