Logger System 0.1.3
High-performance C++20 thread-safe logging system with asynchronous capabilities
Loading...
Searching...
No Matches
structured_logging_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
25
26#include <iostream>
27#include <thread>
28#include <chrono>
29
30using namespace kcenon::logger;
31
36 std::cout << "\n=== Basic Structured Logging ===\n" << std::endl;
37
38 auto logger_instance = std::make_shared<logger>(false); // Synchronous mode
39 logger_instance->add_writer(std::make_unique<console_writer>());
40 logger_instance->start();
41
42 // Basic structured log with various field types using canonical API
43 logger_instance->log_structured(log_level::info)
44 .message("User login successful")
45 .field("user_id", 12345)
46 .field("username", "john_doe")
47 .field("ip_address", "192.168.1.100")
48 .field("login_time_ms", 42.5)
49 .field("mfa_enabled", true)
50 .emit();
51
52 // Error with structured details
53 logger_instance->log_structured(log_level::error)
54 .message("Database connection failed")
55 .field("host", "db.example.com")
56 .field("port", 5432)
57 .field("retry_count", 3)
58 .field("timeout_ms", 30000)
59 .emit();
60
61 // Debug with technical details
62 logger_instance->log_structured(log_level::debug)
63 .message("Cache lookup performed")
64 .field("cache_key", "user:12345:profile")
65 .field("hit", false)
66 .field("latency_us", 150)
67 .emit();
68
69 logger_instance->stop();
70}
71
76 std::cout << "\n=== Context Propagation Example ===\n" << std::endl;
77
78 auto logger_instance = std::make_shared<logger>(false);
79 logger_instance->add_writer(std::make_unique<console_writer>());
80 logger_instance->start();
81
82 // Set distributed tracing context using unified context API
83 logger_instance->context()
84 .set("trace_id", std::string("0af7651916cd43dd8448eb211c80319c"), context_category::trace)
85 .set("span_id", std::string("b7ad6b7169203331"), context_category::trace)
86 .set("correlation_id", std::string("req-abc-123"), context_category::trace);
87
88 // All subsequent logs will include trace context
89 logger_instance->log_structured(log_level::info)
90 .message("Processing API request")
91 .field("endpoint", "/api/v1/users")
92 .field("method", "GET")
93 .emit();
94
95 logger_instance->log_structured(log_level::info)
96 .message("Database query executed")
97 .field("query_type", "SELECT")
98 .field("rows_returned", 42)
99 .emit();
100
101 // Clear all trace context IDs when request is complete
102 logger_instance->context().clear(context_category::trace);
103
104 logger_instance->stop();
105}
106
111 std::cout << "\n=== Context Scope Example ===\n" << std::endl;
112
113 auto logger_instance = std::make_shared<logger>(false);
114 logger_instance->add_writer(std::make_unique<console_writer>());
115 logger_instance->start();
116
117 // Outer scope: request-level context
118 {
119 log_context_scope request_scope({
120 {"request_id", std::string("req-12345")},
121 {"user_id", static_cast<int64_t>(1001)},
122 {"tenant", std::string("acme-corp")}
123 });
124
125 logger_instance->log_structured(log_level::info)
126 .message("Request processing started")
127 .emit();
128
129 // Inner scope: operation-specific context
130 {
131 log_context_scope db_scope({
132 {"operation", std::string("user_lookup")},
133 {"database", std::string("users_db")}
134 });
135
136 logger_instance->log_structured(log_level::debug)
137 .message("Executing database query")
138 .field("query_time_ms", 15.3)
139 .emit();
140 }
141 // db_scope ended - "operation" and "database" removed
142
143 logger_instance->log_structured(log_level::info)
144 .message("Request processing completed")
145 .field("total_time_ms", 45.7)
146 .emit();
147 }
148 // request_scope ended - all context cleared
149
150 logger_instance->stop();
151}
152
157 std::cout << "\n=== Scoped Context (Single Field) ===\n" << std::endl;
158
159 auto logger_instance = std::make_shared<logger>(false);
160 logger_instance->add_writer(std::make_unique<console_writer>());
161 logger_instance->start();
162
163 // Using scoped_context for single fields
164 {
165 scoped_context order_ctx("order_id", static_cast<int64_t>(98765));
166
167 logger_instance->log_structured(log_level::info)
168 .message("Processing order")
169 .field("status", "pending")
170 .emit();
171
172 {
173 scoped_context item_ctx("item_id", static_cast<int64_t>(42));
174
175 logger_instance->log_structured(log_level::debug)
176 .message("Validating item")
177 .field("quantity", 3)
178 .emit();
179 }
180
181 logger_instance->log_structured(log_level::info)
182 .message("Order completed")
183 .field("status", "completed")
184 .emit();
185 }
186
187 logger_instance->stop();
188}
189
194 std::cout << "\n=== JSON Formatter Example ===\n" << std::endl;
195
196 // Create a log entry with structured fields
197 log_entry entry(log_level::info, "User profile updated");
198 entry.fields = log_fields{
199 {"user_id", static_cast<int64_t>(12345)},
200 {"fields_changed", static_cast<int64_t>(3)},
201 {"notification_sent", true}
202 };
203
204 // Format with JSON formatter
205 json_formatter formatter;
206 std::string output = formatter.format(entry);
207
208 std::cout << "JSON formatted output:\n" << output << std::endl;
209}
210
215 std::cout << "\n=== Logfmt Formatter Example ===\n" << std::endl;
216
217 // Create a log entry with structured fields
218 log_entry entry(log_level::info, "HTTP request completed");
219 entry.fields = log_fields{
220 {"method", std::string("POST")},
221 {"path", std::string("/api/orders")},
222 {"status_code", static_cast<int64_t>(201)},
223 {"duration_ms", 125.5}
224 };
225
226 // Format with logfmt formatter
227 logfmt_formatter formatter;
228 std::string output = formatter.format(entry);
229
230 std::cout << "Logfmt formatted output:\n" << output << std::endl;
231}
232
237 std::cout << "\n=== Template Formatter Example ===\n" << std::endl;
238
239 // Create a log entry with structured fields
240 log_entry entry(log_level::info, "Session created");
241 entry.fields = log_fields{
242 {"user_id", static_cast<int64_t>(12345)},
243 {"session_id", std::string("sess-abc-123")}
244 };
245
246 // Format with custom template
247 template_formatter formatter("[{timestamp_local}] [{level:8}] {message} | user={user_id}");
248 std::string output = formatter.format(entry);
249
250 std::cout << "Template formatted output:\n" << output << std::endl;
251
252 // Try different templates
253 formatter.set_template("{level}: {message} (session={session_id})");
254 std::string output2 = formatter.format(entry);
255 std::cout << "Alternative template:\n" << output2 << std::endl;
256}
257
262 std::cout << "\n=== Multithreaded Context Example ===\n" << std::endl;
263
264 auto logger_instance = std::make_shared<logger>(true); // Async mode for MT
265 logger_instance->add_writer(std::make_unique<console_writer>());
266 logger_instance->start();
267
268 auto worker = [&](int thread_id) {
269 // Each thread has its own context (thread-local storage)
270 log_context_scope scope({
271 {"thread_id", static_cast<int64_t>(thread_id)},
272 {"worker", std::string("processor-" + std::to_string(thread_id))}
273 });
274
275 for (int i = 0; i < 3; ++i) {
276 logger_instance->log_structured(log_level::info)
277 .message("Processing item")
278 .field("item_number", i)
279 .emit();
280
281 std::this_thread::sleep_for(std::chrono::milliseconds(10));
282 }
283 };
284
285 std::thread t1(worker, 1);
286 std::thread t2(worker, 2);
287
288 t1.join();
289 t2.join();
290
291 logger_instance->stop();
292}
293
298 std::cout << "\n=== Logger Context Example ===\n" << std::endl;
299
300 auto logger_instance = std::make_shared<logger>(false);
301 logger_instance->add_writer(std::make_unique<console_writer>());
302 logger_instance->start();
303
304 // Set logger-level context (applies to all logs)
305 logger_instance->context()
306 .set("service", std::string("order-service"))
307 .set("version", std::string("1.2.3"))
308 .set("environment", std::string("production"));
309
310 // All logs will include service, version, and environment
311 logger_instance->log_structured(log_level::info)
312 .message("Service started")
313 .emit();
314
315 logger_instance->log_structured(log_level::info)
316 .message("Processing request")
317 .field("request_id", "req-001")
318 .emit();
319
320 // Check if context exists
321 if (!logger_instance->context().empty()) {
322 auto ctx = logger_instance->context().to_fields();
323 std::cout << "Current context has " << ctx.size() << " fields" << std::endl;
324 }
325
326 // Remove specific context
327 logger_instance->context().remove("environment");
328
329 // Clear all context
330 logger_instance->context().clear();
331
332 logger_instance->stop();
333}
334
335int main() {
336 try {
346
347 std::cout << "\n=== All structured logging examples completed! ===" << std::endl;
348
349 } catch (const std::exception& e) {
350 std::cerr << "Error: " << e.what() << std::endl;
351 return 1;
352 }
353
354 return 0;
355}
JSON formatter for structured logging.
std::string format(const log_entry &entry) const override
Format a log entry into a string.
RAII guard for structured logging context.
Formatter that outputs logfmt-structured log messages.
std::string format(const log_entry &entry) const override
Format a log entry to logfmt string.
Convenience class for setting a single context field with RAII.
Customizable formatter using template strings with placeholders.
std::string format(const log_entry &entry) const override
Format a log entry using the template.
void set_template(const std::string &template_pattern)
Set a new template pattern.
Console writer for logging to stdout/stderr.
JSON formatter for structured logging kcenon.
RAII-based context scope management for structured logging kcenon.
Logfmt formatter for structured logging kcenon.
High-performance, thread-safe logging system with asynchronous capabilities.
std::unordered_map< std::string, log_value > log_fields
Type alias for structured fields map.
Definition log_entry.h:75
Represents a single log entry with all associated metadata.
Definition log_entry.h:155
std::optional< log_fields > fields
Optional structured fields for key-value logging.
Definition log_entry.h:213
Fluent builder for structured log entries kcenon.
void context_propagation_example()
Demonstrates context propagation for distributed tracing.
void context_scope_example()
Demonstrates RAII-based context scopes.
void scoped_context_single_field()
Demonstrates single-field scoped context.
void basic_structured_logging()
Demonstrates basic structured logging with key-value fields.
void multithreaded_context_example()
Demonstrates thread-safe context in multi-threaded environment.
void logger_context_example()
Demonstrates logger-level context fields.
void template_formatter_example()
Demonstrates template-based custom formatter.
void logfmt_formatter_example()
Demonstrates Logfmt formatter for key=value output.
void json_formatter_example()
Demonstrates JSON formatter for structured output.
Template-based customizable formatter for structured logging kcenon.