This example shows how to use the writer_builder class to compose log writers using the Decorator pattern. The builder provides a fluent API that makes it easy to chain multiple decorators together.
Part of EPIC #391 - Decorator pattern refactoring.
#include <kcenon/logger/builders/writer_builder.h>
#ifdef LOGGER_WITH_ENCRYPTION
#include <kcenon/logger/security/secure_key.h>
#endif
#include <iostream>
#include <memory>
using log_level = common::interfaces::log_level;
public:
}
return "level_filter";
}
private:
};
std::cout << "\n=== Example 1: Basic File Writer ===\n";
auto writer = writer_builder()
.file("basic.log")
.build();
std::cout << "Created basic file writer: " << writer->get_name() << "\n";
}
std::cout << "\n=== Example 2: Async + Buffered File Writer ===\n";
auto writer = writer_builder()
.file("app.log")
.buffered(500)
.async(20000)
.build();
std::cout << "Created async+buffered writer: " << writer->get_name() << "\n";
std::cout << " - Buffering reduces I/O operations\n";
std::cout << " - Async processing enables high throughput\n";
if (
auto* async_w =
dynamic_cast<async_writer*
>(writer.get())) {
async_w->start();
std::cout << " - Async writer started\n";
async_w->stop();
}
}
std::cout << "\n=== Example 3: Filtered Console Writer ===\n";
auto filter = std::make_unique<level_filter>(log_level::warning);
auto writer = writer_builder()
.console()
.filtered(std::move(filter))
.build();
std::cout << "Created filtered console writer: " << writer->get_name() << "\n";
std::cout << " - Only logs WARNING and above\n";
}
#ifdef LOGGER_WITH_ENCRYPTION
void example_encrypted_logging() {
std::cout << "\n=== Example 4: Encrypted Logging ===\n";
auto key_result = secure_key_storage::generate_key(32);
if (key_result.is_err()) {
std::cout << "Failed to generate encryption key: "
<< key_result.error().message << "\n";
return;
}
auto writer = writer_builder()
.file("secure.log.enc")
.encrypted(std::move(key_result.value()))
.buffered(100)
.async()
.build();
std::cout << "Created encrypted writer: " << writer->get_name() << "\n";
std::cout << " - 32-byte AES encryption\n";
std::cout << " - Buffered for efficiency\n";
std::cout << " - Async for performance\n";
if (
auto* async_w =
dynamic_cast<async_writer*
>(writer.get())) {
async_w->start();
async_w->stop();
}
}
#endif
std::cout << "\n=== Example 5: Production Multi-Writer Setup ===\n";
auto main_writer = writer_builder()
.file("app.log")
.buffered(500)
.async(20000)
.build();
std::cout << "Main writer: " << main_writer->get_name() << "\n";
if (
auto* async_main =
dynamic_cast<async_writer*
>(main_writer.get())) {
async_main->start();
}
auto error_filter = std::make_unique<level_filter>(log_level::error);
auto error_writer = writer_builder()
.file("errors.log")
.filtered(std::move(error_filter))
.async()
.build();
std::cout << "Error writer: " << error_writer->get_name() << "\n";
if (
auto* async_error =
dynamic_cast<async_writer*
>(error_writer.get())) {
async_error->start();
}
log.
add_writer(
"errors", std::move(error_writer));
std::cout << "\nLogging messages:\n";
log.
log(log_level::info, std::string(
"Application started"));
log.
log(log_level::warning, std::string(
"Low disk space"));
log.
log(log_level::error, std::string(
"Failed to connect to database"));
std::cout << " - INFO: Goes to app.log\n";
std::cout << " - WARNING: Goes to app.log\n";
std::cout << " - ERROR: Goes to both app.log and errors.log\n";
}
std::cout << "\n=== Example 6: Builder vs Manual Composition ===\n";
std::cout << "\nManual composition (verbose):\n";
std::cout << " auto writer = std::make_unique<async_writer>(\n";
std::cout << " std::make_unique<buffered_writer>(\n";
std::cout << " std::make_unique<file_writer>(\"app.log\"),\n";
std::cout << " 500\n";
std::cout << " ),\n";
std::cout << " 20000\n";
std::cout << " );\n";
std::cout << "\nBuilder pattern (readable):\n";
std::cout << " auto writer = writer_builder()\n";
std::cout << " .file(\"app.log\")\n";
std::cout << " .buffered(500)\n";
std::cout << " .async(20000)\n";
std::cout << " .build();\n";
auto writer = writer_builder()
.file("app.log")
.buffered(500)
.async(20000)
.build();
std::cout << "\nResult: " << writer->get_name() << "\n";
std::cout << "Benefits:\n";
std::cout << " ✓ More readable and self-documenting\n";
std::cout << " ✓ Less error-prone (no manual nesting)\n";
std::cout << " ✓ Easy to add/remove decorators\n";
std::cout << " ✓ Type-safe at compile time\n";
if (
auto* async_w =
dynamic_cast<async_writer*
>(writer.get())) {
async_w->start();
async_w->stop();
}
}
std::cout << "Writer Builder Examples\n";
std::cout << "=======================\n";
std::cout << "\nThese examples demonstrate how to use writer_builder\n";
std::cout << "to compose log writers using the Decorator pattern.\n";
try {
#ifdef LOGGER_WITH_ENCRYPTION
example_encrypted_logging();
#else
std::cout << "\n=== Example 4: Encrypted Logging ===\n";
std::cout << "Skipped (LOGGER_WITH_ENCRYPTION not defined)\n";
#endif
std::cout << "\n=== All Examples Completed Successfully ===\n";
} catch (const std::exception& e) {
std::cerr << "\nError: " << e.what() << "\n";
return 1;
}
return 0;
}
Asynchronous wrapper for log writers.
Asynchronous wrapper for log writers.
Interface for log filters.
common::VoidResult add_writer(log_writer_ptr writer)
common::VoidResult log(common::interfaces::log_level level, const std::string &message) override
Log a message with specified level (ILogger interface)
common::VoidResult flush() override
Flush any buffered log messages (ILogger interface)
Custom filter that only allows specific log levels.
bool should_log(const log_entry &entry) const override
Check if a log entry should be processed.
level_filter(log_level min_level)
std::string get_name() const override
Get the name of this filter.
void example_production_setup()
Interface for log filters used by filtered_logger.
High-performance, thread-safe logging system with asynchronous capabilities.
RAII wrapper for encryption keys with secure memory management.
Represents a single log entry with all associated metadata.
log_level level
Severity level of the log message.
void example_async_buffered_file()
Example 2: Async + Buffered File Writer.
void example_basic_file_writer()
Example 1: Basic file writer.
void example_builder_vs_manual()
Example 6: Comparing Builder vs Manual Composition.
void example_filtered_console()
Example 3: Console Writer with Filtering.