Logger System 0.1.3
High-performance C++20 thread-safe logging system with asynchronous capabilities
Loading...
Searching...
No Matches
di_pattern_example.cpp File Reference

Dependency Injection pattern example for logger_system Phase 4. More...

#include <kcenon/logger/core/logger_builder.h>
#include <kcenon/common/interfaces/logger_interface.h>
#include <kcenon/common/interfaces/monitoring_interface.h>
#include <iostream>
#include <memory>
#include <thread>
#include <chrono>
#include <mutex>
#include <unordered_map>
#include <sstream>
Include dependency graph for di_pattern_example.cpp:

Go to the source code of this file.

Classes

class  example_monitor
 Example monitor implementation demonstrating IMonitor interface. More...
 

Functions

void example_1_basic_di_pattern ()
 Example demonstrating DI pattern with logger and monitor.
 
void example_2_optional_monitor ()
 Example demonstrating monitor-less operation.
 
void example_3_runtime_monitor_injection ()
 Example demonstrating runtime monitor injection.
 
void example_4_monitor_swapping ()
 Example demonstrating monitor swapping.
 
void use_logger_via_interface (std::shared_ptr< ci::ILogger > logger)
 Example demonstrating ILogger interface usage.
 
void example_5_interface_based_usage ()
 
int main ()
 

Detailed Description

Dependency Injection pattern example for logger_system Phase 4.

Definition in file di_pattern_example.cpp.

Function Documentation

◆ example_1_basic_di_pattern()

void example_1_basic_di_pattern ( )

Example demonstrating DI pattern with logger and monitor.

Examples
di_pattern_example.cpp.

Definition at line 185 of file di_pattern_example.cpp.

185 {
186 std::cout << "\n=== Example 1: Basic Dependency Injection ===" << std::endl;
187
188 // Step 1: Create monitor instance (can be any IMonitor implementation)
189 auto monitor = std::make_shared<example_monitor>();
190
191 // Step 2: Inject monitor into logger via builder pattern
192 auto logger_result = logger_builder()
193 .with_async(false)
194 .with_monitoring(monitor) // DI: Inject monitor interface
195 .with_min_level(ci::log_level::debug)
196 .build();
197
198 if (!logger_result) {
199 std::cerr << "Failed to create logger: "
200 << logger_result.error_message() << std::endl;
201 return;
202 }
203
204 auto logger_instance = std::shared_ptr<logger>(std::move(logger_result.value()));
205
206 // Step 3: Use logger - metrics are automatically recorded to monitor
207 logger_instance->log(ci::log_level::info, "Application started");
208 logger_instance->log(ci::log_level::debug, "Debug message");
209 logger_instance->log(ci::log_level::warning, "Warning message");
210
211 // Step 4: Verify metrics were recorded
212 std::cout << "\nMonitor collected " << monitor->get_metric_count()
213 << " metrics" << std::endl;
214
215 // Step 5: Get health status from logger (IMonitorable interface)
216 // TODO: Implement health_check() in logger class (Phase 2.2)
217 // auto health = logger_instance->health_check();
218 // if (kcenon::common::is_ok(health)) {
219 // std::cout << "Logger health: "
220 // << ci::to_string(kcenon::common::get_value(health).status) << std::endl;
221 // }
222 std::cout << "Logger health: [health_check() not yet implemented]" << std::endl;
223}
Builder pattern for logger construction with validation.
logger_builder & with_monitoring(std::shared_ptr< common::interfaces::IMonitor > monitor)
Set monitoring interface (Phase 2.2.4)
logger_builder & with_min_level(log_level level)
logger_builder & with_async(bool async=true)
result< std::unique_ptr< logger > > build()

References kcenon::logger::logger_builder::build(), kcenon::logger::logger_builder::with_async(), kcenon::logger::logger_builder::with_min_level(), and kcenon::logger::logger_builder::with_monitoring().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ example_2_optional_monitor()

void example_2_optional_monitor ( )

Example demonstrating monitor-less operation.

Examples
di_pattern_example.cpp.

Definition at line 228 of file di_pattern_example.cpp.

228 {
229 std::cout << "\n=== Example 2: Optional Monitor (No Monitor) ===" << std::endl;
230
231 // Build logger without monitor - demonstrates optional dependency
232 auto logger_result = logger_builder()
233 .with_async(false)
234 .with_min_level(ci::log_level::info)
235 .build();
236
237 if (!logger_result) {
238 std::cerr << "Failed to create logger" << std::endl;
239 return;
240 }
241
242 auto logger_instance = std::shared_ptr<logger>(std::move(logger_result.value()));
243
244 // Logger works fine without monitor
245 logger_instance->log(ci::log_level::info, "Operating without monitor");
246 logger_instance->log(ci::log_level::warning, "Warning without monitoring");
247
248 std::cout << "Logger operates successfully without monitor (DI optional)" << std::endl;
249}

References kcenon::logger::logger_builder::build(), kcenon::logger::logger_builder::with_async(), and kcenon::logger::logger_builder::with_min_level().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ example_3_runtime_monitor_injection()

void example_3_runtime_monitor_injection ( )

Example demonstrating runtime monitor injection.

Examples
di_pattern_example.cpp.

Definition at line 254 of file di_pattern_example.cpp.

254 {
255 std::cout << "\n=== Example 3: Runtime Monitor Injection ===" << std::endl;
256
257 // Create logger without monitor initially
258 auto logger_result = logger_builder()
259 .with_async(false)
260 .build();
261
262 if (!logger_result) {
263 std::cerr << "Failed to create logger" << std::endl;
264 return;
265 }
266
267 auto logger_instance = std::shared_ptr<logger>(std::move(logger_result.value()));
268
269 std::cout << "Phase 1: Operating without monitor" << std::endl;
270 logger_instance->log(ci::log_level::info, "Message 1 - no monitoring");
271
272 // Inject monitor at runtime
273 // TODO: Implement set_monitor() in logger class (Phase 2.2)
274 auto monitor = std::make_unique<example_monitor>();
275 auto* monitor_ref = monitor.get();
276 // logger_instance->set_monitor(std::move(monitor));
277
278 std::cout << "\nPhase 2: Monitor injected at runtime [set_monitor() not yet implemented]" << std::endl;
279 logger_instance->log(ci::log_level::info, "Message 2 - with monitoring");
280 logger_instance->log(ci::log_level::info, "Message 3 - with monitoring");
281
282 std::cout << "\nMonitor recorded " << monitor_ref->get_metric_count()
283 << " metrics (only from Phase 2)" << std::endl;
284}

References kcenon::logger::logger_builder::build(), and kcenon::logger::logger_builder::with_async().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ example_4_monitor_swapping()

void example_4_monitor_swapping ( )

Example demonstrating monitor swapping.

Examples
di_pattern_example.cpp.

Definition at line 289 of file di_pattern_example.cpp.

289 {
290 std::cout << "\n=== Example 4: Monitor Swapping ===" << std::endl;
291
292 auto logger_result = logger_builder()
293 .with_async(false)
294 .build();
295
296 if (!logger_result) return;
297 auto logger_instance = std::shared_ptr<logger>(std::move(logger_result.value()));
298
299 // TODO: Implement set_monitor() in logger class (Phase 2.2)
300 auto monitor1 = std::make_unique<example_monitor>();
301 auto* monitor1_ref = monitor1.get();
302 // logger_instance->set_monitor(std::move(monitor1));
303
304 std::cout << "Using Monitor 1 [set_monitor() not yet implemented]" << std::endl;
305 logger_instance->log(ci::log_level::info, "Message to Monitor 1");
306 logger_instance->log(ci::log_level::info, "Another message to Monitor 1");
307
308 size_t monitor1_metrics = monitor1_ref->get_metric_count();
309
310 // Swap monitors at runtime
311 auto monitor2 = std::make_unique<example_monitor>();
312 auto* monitor2_ref = monitor2.get();
313 // logger_instance->set_monitor(std::move(monitor2));
314
315 std::cout << "\nSwapped to Monitor 2 [set_monitor() not yet implemented]" << std::endl;
316 logger_instance->log(ci::log_level::info, "Message to Monitor 2");
317
318 size_t monitor2_metrics = monitor2_ref->get_metric_count();
319
320 std::cout << "\nMonitor 1 metrics before swap: " << monitor1_metrics << std::endl;
321 std::cout << "Monitor 2 metrics after swap: " << monitor2_metrics << std::endl;
322}

References kcenon::logger::logger_builder::build(), and kcenon::logger::logger_builder::with_async().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ example_5_interface_based_usage()

void example_5_interface_based_usage ( )
Examples
di_pattern_example.cpp.

Definition at line 344 of file di_pattern_example.cpp.

344 {
345 std::cout << "\n=== Example 5: Interface-Based Usage ===" << std::endl;
346
347 auto monitor = std::make_shared<example_monitor>();
348 auto logger_result = logger_builder()
349 .with_async(false)
350 .with_monitoring(monitor)
351 .build();
352
353 if (!logger_result) return;
354
355 // Use logger through ILogger interface pointer
356 auto logger_instance = std::shared_ptr<logger>(std::move(logger_result.value()));
357 auto logger_adapter = std::make_shared<logger_interface_adapter>(logger_instance);
358 std::shared_ptr<ci::ILogger> logger_interface = logger_adapter;
359
360 use_logger_via_interface(logger_interface);
361
362 std::cout << "Successfully used logger through interface abstraction" << std::endl;
363}
void use_logger_via_interface(std::shared_ptr< ci::ILogger > logger)
Example demonstrating ILogger interface usage.

References kcenon::logger::logger_builder::build(), use_logger_via_interface(), kcenon::logger::logger_builder::with_async(), and kcenon::logger::logger_builder::with_monitoring().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( )

Definition at line 365 of file di_pattern_example.cpp.

365 {
366 std::cout << "==================================================" << std::endl;
367 std::cout << "Logger System - Dependency Injection Pattern Demo" << std::endl;
368 std::cout << "Phase 4: DI Pattern Implementation Examples" << std::endl;
369 std::cout << "==================================================" << std::endl;
370
371 try {
377
378 std::cout << "\n==================================================" << std::endl;
379 std::cout << "All DI pattern examples completed successfully!" << std::endl;
380 std::cout << "==================================================" << std::endl;
381
382 } catch (const std::exception& e) {
383 std::cerr << "Error: " << e.what() << std::endl;
384 return 1;
385 }
386
387 return 0;
388}
void example_2_optional_monitor()
Example demonstrating monitor-less operation.
void example_4_monitor_swapping()
Example demonstrating monitor swapping.
void example_5_interface_based_usage()
void example_1_basic_di_pattern()
Example demonstrating DI pattern with logger and monitor.
void example_3_runtime_monitor_injection()
Example demonstrating runtime monitor injection.

References example_1_basic_di_pattern(), example_2_optional_monitor(), example_3_runtime_monitor_injection(), example_4_monitor_swapping(), and example_5_interface_based_usage().

Here is the call graph for this function:

◆ use_logger_via_interface()

void use_logger_via_interface ( std::shared_ptr< ci::ILogger > logger)

Example demonstrating ILogger interface usage.

Examples
di_pattern_example.cpp.

Definition at line 327 of file di_pattern_example.cpp.

327 {
328 // This function only depends on ILogger interface
329 // Can work with any logger implementation
330
331 // Use std::string explicitly to avoid ambiguity between log overloads
332 logger->log(ci::log_level::info, std::string("Used via interface - loose coupling!"));
333
334 // Check if logger supports monitoring (IMonitorable)
335 if (auto monitorable = std::dynamic_pointer_cast<ci::IMonitorable>(logger)) {
336 auto data = monitorable->get_monitoring_data();
337 if (kcenon::common::is_ok(data)) {
338 std::cout << "Logger provides monitoring data from "
339 << kcenon::common::get_value(data).source_id << std::endl;
340 }
341 }
342}
bool is_ok(const Result< T > &result)
T & get_value(Result< T > &result)

References kcenon::common::get_value(), and kcenon::common::is_ok().

Referenced by example_5_interface_based_usage().

Here is the call graph for this function:
Here is the caller graph for this function: