Logger System 0.1.3
High-performance C++20 thread-safe logging system with asynchronous capabilities
Loading...
Searching...
No Matches
writer_builder_example.cpp
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
19#include <kcenon/logger/builders/writer_builder.h>
23
24#ifdef LOGGER_WITH_ENCRYPTION
25#include <kcenon/logger/security/secure_key.h>
27#endif
28
29#include <iostream>
30#include <memory>
31
32using namespace kcenon::logger;
33namespace common = kcenon::common;
34using log_level = common::interfaces::log_level;
35
40public:
41 explicit level_filter(log_level min_level) : min_level_(min_level) {}
42
43 bool should_log(const log_entry& entry) const override {
44 return entry.level >= min_level_;
45 }
46
47 std::string get_name() const override {
48 return "level_filter";
49 }
50
51private:
52 log_level min_level_;
53};
54
61 std::cout << "\n=== Example 1: Basic File Writer ===\n";
62
63 auto writer = writer_builder()
64 .file("basic.log")
65 .build();
66
67 std::cout << "Created basic file writer: " << writer->get_name() << "\n";
68}
69
78 std::cout << "\n=== Example 2: Async + Buffered File Writer ===\n";
79
80 auto writer = writer_builder()
81 .file("app.log")
82 .buffered(500) // Buffer up to 500 entries
83 .async(20000) // Large queue for high throughput
84 .build();
85
86 std::cout << "Created async+buffered writer: " << writer->get_name() << "\n";
87 std::cout << " - Buffering reduces I/O operations\n";
88 std::cout << " - Async processing enables high throughput\n";
89
90 // Note: async_writer needs to be started
91 if (auto* async_w = dynamic_cast<async_writer*>(writer.get())) {
92 async_w->start();
93 std::cout << " - Async writer started\n";
94 async_w->stop();
95 }
96}
97
104 std::cout << "\n=== Example 3: Filtered Console Writer ===\n";
105
106 auto filter = std::make_unique<level_filter>(log_level::warning);
107
108 auto writer = writer_builder()
109 .console()
110 .filtered(std::move(filter))
111 .build();
112
113 std::cout << "Created filtered console writer: " << writer->get_name() << "\n";
114 std::cout << " - Only logs WARNING and above\n";
115}
116
117#ifdef LOGGER_WITH_ENCRYPTION
124void example_encrypted_logging() {
125 std::cout << "\n=== Example 4: Encrypted Logging ===\n";
126
127 using namespace kcenon::logger::security;
128
129 auto key_result = secure_key_storage::generate_key(32);
130 if (key_result.is_err()) {
131 std::cout << "Failed to generate encryption key: "
132 << key_result.error().message << "\n";
133 return;
134 }
135
136 auto writer = writer_builder()
137 .file("secure.log.enc")
138 .encrypted(std::move(key_result.value()))
139 .buffered(100)
140 .async()
141 .build();
142
143 std::cout << "Created encrypted writer: " << writer->get_name() << "\n";
144 std::cout << " - 32-byte AES encryption\n";
145 std::cout << " - Buffered for efficiency\n";
146 std::cout << " - Async for performance\n";
147
148 if (auto* async_w = dynamic_cast<async_writer*>(writer.get())) {
149 async_w->start();
150 async_w->stop();
151 }
152}
153#endif
154
163 std::cout << "\n=== Example 5: Production Multi-Writer Setup ===\n";
164
165 logger log;
166
167 // Main log: async file with buffering
168 auto main_writer = writer_builder()
169 .file("app.log")
170 .buffered(500)
171 .async(20000)
172 .build();
173
174 std::cout << "Main writer: " << main_writer->get_name() << "\n";
175
176 // Start async writer before adding to logger
177 if (auto* async_main = dynamic_cast<async_writer*>(main_writer.get())) {
178 async_main->start();
179 }
180
181 log.add_writer("main", std::move(main_writer));
182
183 // Error log: separate file for errors only
184 auto error_filter = std::make_unique<level_filter>(log_level::error);
185
186 auto error_writer = writer_builder()
187 .file("errors.log")
188 .filtered(std::move(error_filter))
189 .async()
190 .build();
191
192 std::cout << "Error writer: " << error_writer->get_name() << "\n";
193
194 if (auto* async_error = dynamic_cast<async_writer*>(error_writer.get())) {
195 async_error->start();
196 }
197
198 log.add_writer("errors", std::move(error_writer));
199
200 // Log some messages
201 std::cout << "\nLogging messages:\n";
202 log.log(log_level::info, std::string("Application started"));
203 log.log(log_level::warning, std::string("Low disk space"));
204 log.log(log_level::error, std::string("Failed to connect to database"));
205
206 std::cout << " - INFO: Goes to app.log\n";
207 std::cout << " - WARNING: Goes to app.log\n";
208 std::cout << " - ERROR: Goes to both app.log and errors.log\n";
209
210 log.flush();
211}
212
219 std::cout << "\n=== Example 6: Builder vs Manual Composition ===\n";
220
221 std::cout << "\nManual composition (verbose):\n";
222 std::cout << " auto writer = std::make_unique<async_writer>(\n";
223 std::cout << " std::make_unique<buffered_writer>(\n";
224 std::cout << " std::make_unique<file_writer>(\"app.log\"),\n";
225 std::cout << " 500\n";
226 std::cout << " ),\n";
227 std::cout << " 20000\n";
228 std::cout << " );\n";
229
230 std::cout << "\nBuilder pattern (readable):\n";
231 std::cout << " auto writer = writer_builder()\n";
232 std::cout << " .file(\"app.log\")\n";
233 std::cout << " .buffered(500)\n";
234 std::cout << " .async(20000)\n";
235 std::cout << " .build();\n";
236
237 auto writer = writer_builder()
238 .file("app.log")
239 .buffered(500)
240 .async(20000)
241 .build();
242
243 std::cout << "\nResult: " << writer->get_name() << "\n";
244 std::cout << "Benefits:\n";
245 std::cout << " ✓ More readable and self-documenting\n";
246 std::cout << " ✓ Less error-prone (no manual nesting)\n";
247 std::cout << " ✓ Easy to add/remove decorators\n";
248 std::cout << " ✓ Type-safe at compile time\n";
249
250 if (auto* async_w = dynamic_cast<async_writer*>(writer.get())) {
251 async_w->start();
252 async_w->stop();
253 }
254}
255
256int main() {
257 std::cout << "Writer Builder Examples\n";
258 std::cout << "=======================\n";
259 std::cout << "\nThese examples demonstrate how to use writer_builder\n";
260 std::cout << "to compose log writers using the Decorator pattern.\n";
261
262 try {
266
267#ifdef LOGGER_WITH_ENCRYPTION
268 example_encrypted_logging();
269#else
270 std::cout << "\n=== Example 4: Encrypted Logging ===\n";
271 std::cout << "Skipped (LOGGER_WITH_ENCRYPTION not defined)\n";
272#endif
273
276
277 std::cout << "\n=== All Examples Completed Successfully ===\n";
278 } catch (const std::exception& e) {
279 std::cerr << "\nError: " << e.what() << "\n";
280 return 1;
281 }
282
283 return 0;
284}
Asynchronous wrapper for log writers.
Asynchronous wrapper for log writers.
Filter logs by minimum level.
Definition log_filter.h:72
common::VoidResult add_writer(log_writer_ptr writer)
Definition logger.cpp:265
common::VoidResult log(common::interfaces::log_level level, const std::string &message) override
Log a message with specified level (ILogger interface)
Definition logger.cpp:378
common::VoidResult flush() override
Flush any buffered log messages (ILogger interface)
Definition logger.cpp:574
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.
Interface for log filters used by filtered_logger.
High-performance, thread-safe logging system with asynchronous capabilities.
common::interfaces::log_level log_level
RAII wrapper for encryption keys with secure memory management.
Represents a single log entry with all associated metadata.
Definition log_entry.h:155
log_level level
Severity level of the log message.
Definition log_entry.h:162
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.
void example_production_setup()
Example 5: Production Setup with Multiple Writers.