Logger System 0.1.3
High-performance C++20 thread-safe logging system with asynchronous capabilities
Loading...
Searching...
No Matches
monitoring_integration_example.cpp
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2021-2025, šŸ€ā˜€šŸŒ•šŸŒ„ 🌊
3// See the LICENSE file in the project root for full license information.
4
15#include <kcenon/common/interfaces/logger_interface.h>
16#include <kcenon/common/interfaces/monitoring_interface.h>
17#include <iostream>
18#include <memory>
19#include <vector>
20#include <thread>
21#include <chrono>
22#include <iomanip>
23#include <mutex>
24#include <unordered_map>
25
26using namespace kcenon::logger;
27namespace ci = kcenon::common::interfaces;
28
32class aggregating_monitor : public ci::IMonitor,
33 public ci::IMonitorProvider,
34 public std::enable_shared_from_this<aggregating_monitor> {
35private:
36 std::vector<std::shared_ptr<ci::IMonitorable>> monitored_components_;
37 std::unordered_map<std::string, double> aggregated_metrics_;
38 mutable std::mutex mutex_;
39
40public:
41 void register_component(std::shared_ptr<ci::IMonitorable> component) {
42 std::lock_guard<std::mutex> lock(mutex_);
43 monitored_components_.push_back(component);
44 std::cout << "[AggregatingMonitor] Registered component: "
45 << component->get_component_name() << std::endl;
46 }
47
49 const std::string& name,
50 double value) override
51 {
52 std::lock_guard<std::mutex> lock(mutex_);
53 aggregated_metrics_[name] = value;
54 return kcenon::common::ok();
55 }
56
58 const std::string& name,
59 double value,
60 const std::unordered_map<std::string, std::string>& tags) override
61 {
62 std::string tagged_name = name;
63 for (const auto& [k, v] : tags) {
64 tagged_name += "." + k + ":" + v;
65 }
66 return record_metric(tagged_name, value);
67 }
68
70 std::lock_guard<std::mutex> lock(mutex_);
71
72 ci::metrics_snapshot snapshot;
73 snapshot.source_id = "aggregating_monitor";
74 snapshot.capture_time = std::chrono::system_clock::now();
75
76 // Add own metrics
77 for (const auto& [name, value] : aggregated_metrics_) {
78 snapshot.add_metric(name, value);
79 }
80
81 // Collect metrics from all registered components
82 for (const auto& component : monitored_components_) {
83 auto comp_data = component->get_monitoring_data();
84 if (kcenon::common::is_ok(comp_data)) {
85 const auto& component_metrics = kcenon::common::get_value(comp_data);
86 for (const auto& metric : component_metrics.metrics) {
87 snapshot.metrics.push_back(metric);
88 }
89 } else {
90 snapshot.add_metric("component_error_" + component->get_component_name(), 1.0);
91 }
92 }
93
94 return kcenon::common::Result<ci::metrics_snapshot>::ok(std::move(snapshot));
95 }
96
98 std::lock_guard<std::mutex> lock(mutex_);
99
100 ci::health_check_result result;
101 result.timestamp = std::chrono::system_clock::now();
102 result.status = ci::health_status::healthy;
103 result.message = "Aggregating monitor operational";
104
105 // Check health of all components
106 for (const auto& component : monitored_components_) {
107 auto comp_health = component->health_check();
108 const auto component_name = component->get_component_name();
109
110 if (kcenon::common::is_ok(comp_health)) {
111 const auto& component_result = kcenon::common::get_value(comp_health);
112 result.metadata["component_status:" + component_name] = ci::to_string(component_result.status);
113
114 if (component_result.status == ci::health_status::unhealthy) {
115 result.status = ci::health_status::unhealthy;
116 result.message = "One or more components unhealthy";
117 } else if (component_result.status == ci::health_status::degraded &&
118 result.status == ci::health_status::healthy) {
119 result.status = ci::health_status::degraded;
120 result.message = "One or more components degraded";
121 }
122 } else {
123 const auto& error = kcenon::common::get_error(comp_health);
124 result.metadata["component_status:" + component_name] = "error:" + error.message;
125 if (result.status == ci::health_status::healthy) {
126 result.status = ci::health_status::degraded;
127 result.message = "Component health check failed";
128 }
129 }
130 }
131
133 }
134
136 std::lock_guard<std::mutex> lock(mutex_);
137 aggregated_metrics_.clear();
138 return kcenon::common::ok();
139 }
140
141 // IMonitorProvider implementation
142 std::shared_ptr<ci::IMonitor> get_monitor() override {
143 return shared_from_this();
144 }
145
146 std::shared_ptr<ci::IMonitor> create_monitor(const std::string& name) override {
147 // For this example, return self
148 return shared_from_this();
149 }
150
151 size_t get_component_count() const {
152 std::lock_guard<std::mutex> lock(mutex_);
153 return monitored_components_.size();
154 }
155};
156
160void print_metrics_snapshot(const ci::metrics_snapshot& snapshot) {
161 std::cout << "\n--- Metrics Snapshot ---" << std::endl;
162 std::cout << "Source: " << snapshot.source_id << std::endl;
163 std::cout << "Captured at: "
164 << std::chrono::system_clock::to_time_t(snapshot.capture_time)
165 << std::endl;
166 std::cout << "Metrics:" << std::endl;
167
168 for (const auto& metric : snapshot.metrics) {
169 std::cout << " " << std::setw(30) << std::left << metric.name
170 << ": " << metric.value << std::endl;
171 }
172}
173
177void print_health_result(const ci::health_check_result& health) {
178 std::cout << "\n--- Health Check ---" << std::endl;
179 std::cout << "Status: " << ci::to_string(health.status) << std::endl;
180 std::cout << "Message: " << health.message << std::endl;
181
182 if (!health.metadata.empty()) {
183 std::cout << "Component Status:" << std::endl;
184 for (const auto& [key, value] : health.metadata) {
185 if (key.rfind("component_status:", 0) == 0) {
186 std::cout << " - " << key.substr(std::string("component_status:").size())
187 << ": " << value << std::endl;
188 }
189 }
190 }
191
192 std::cout << "Check duration: "
193 << health.check_duration.count() << "ms" << std::endl;
194}
195
200 std::cout << "\n=== Example 1: Basic Monitor Integration ===" << std::endl;
201
202 auto monitor = std::make_shared<aggregating_monitor>();
203
204 auto logger_result = logger_builder()
205 .with_async(false)
206 .with_monitoring(monitor)
207 .build();
208
209 if (!logger_result) {
210 std::cerr << "Failed to create logger" << std::endl;
211 return;
212 }
213
214 auto logger_instance = std::shared_ptr<logger>(std::move(logger_result.value()));
215
216 // Register logger as monitored component
217 // TODO: Implement IMonitorable interface on logger class (Phase 2.2)
218 // Currently logger doesn't inherit from IMonitorable
219 // monitor->register_component(std::static_pointer_cast<ci::IMonitorable>(logger_instance));
220 std::cout << "[Note: logger IMonitorable integration pending Phase 2.2]" << std::endl;
221
222 // Perform logging operations
223 for (int i = 0; i < 5; ++i) {
224 logger_instance->log(ci::log_level::info,
225 "Log message " + std::to_string(i + 1));
226 }
227
228 // Get aggregated metrics
229 auto metrics = monitor->get_metrics();
230 if (kcenon::common::is_ok(metrics)) {
232 }
233
234 // Check aggregated health
235 auto health = monitor->check_health();
236 if (kcenon::common::is_ok(health)) {
238 }
239}
240
245 std::cout << "\n=== Example 2: Multiple Loggers, Single Monitor ===" << std::endl;
246
247 auto monitor = std::make_shared<aggregating_monitor>();
248
249 // Create multiple logger instances
250 auto logger1_result = logger_builder()
251 .with_async(false)
252 .with_monitoring(monitor)
253 .build();
254
255 auto logger2_result = logger_builder()
256 .with_async(false)
257 .with_monitoring(monitor)
258 .build();
259
260 if (!logger1_result || !logger2_result) {
261 std::cerr << "Failed to create loggers" << std::endl;
262 return;
263 }
264
265 auto logger1 = std::shared_ptr<logger>(std::move(logger1_result.value()));
266 auto logger2 = std::shared_ptr<logger>(std::move(logger2_result.value()));
267
268 // Register both loggers
269 // TODO: Implement IMonitorable interface on logger class (Phase 2.2)
270 // monitor->register_component(std::static_pointer_cast<ci::IMonitorable>(logger1));
271 // monitor->register_component(std::static_pointer_cast<ci::IMonitorable>(logger2));
272 std::cout << "[Note: logger IMonitorable integration pending Phase 2.2]" << std::endl;
273
274 // Both loggers use the same monitor
275 logger1->log(ci::log_level::info, std::string("Message from logger 1"));
276 logger2->log(ci::log_level::warning, std::string("Message from logger 2"));
277 logger1->log(ci::log_level::error, std::string("Error from logger 1"));
278
279 std::cout << "\nMonitor tracks " << monitor->get_component_count()
280 << " components" << std::endl;
281
282 // Get combined metrics
283 auto metrics = monitor->get_metrics();
284 if (kcenon::common::is_ok(metrics)) {
285 std::cout << "Combined metrics from all loggers:" << std::endl;
287 }
288}
289
294 std::cout << "\n=== Example 3: IMonitorable Interface ===" << std::endl;
295
296 auto monitor = std::make_shared<aggregating_monitor>();
297
298 auto logger_result = logger_builder()
299 .with_async(false)
300 .with_monitoring(monitor)
301 .build();
302
303 if (!logger_result) return;
304
305 auto logger_instance = std::shared_ptr<logger>(std::move(logger_result.value()));
306
307 // Cast to IMonitorable to demonstrate interface usage
308 if (auto monitorable = std::dynamic_pointer_cast<ci::IMonitorable>(logger_instance)) {
309 std::cout << "Logger component name: "
310 << monitorable->get_component_name() << std::endl;
311
312 // Perform operations
313 logger_instance->log(ci::log_level::info, std::string("Test message 1"));
314 logger_instance->log(ci::log_level::info, std::string("Test message 2"));
315
316 // Get monitoring data directly from logger
317 auto data = monitorable->get_monitoring_data();
318 if (kcenon::common::is_ok(data)) {
319 std::cout << "\nDirect monitoring data from logger:" << std::endl;
321 }
322
323 // Health check directly from logger
324 auto health = monitorable->health_check();
325 if (kcenon::common::is_ok(health)) {
326 std::cout << "\nDirect health check from logger:" << std::endl;
328 }
329 }
330}
331
336 std::cout << "\n=== Example 4: Monitoring System Integration Simulation ===" << std::endl;
337 std::cout << "Note: This demonstrates how logger_system and monitoring_system" << std::endl;
338 std::cout << " interact via interfaces without circular dependencies" << std::endl;
339
340 // Simulate monitoring_system providing a monitor
341 std::shared_ptr<ci::IMonitor> monitor = std::make_shared<aggregating_monitor>();
342
343 // Logger receives monitor through DI
344 auto logger_result = logger_builder()
345 .with_async(true) // Async mode for realistic scenario
346 .with_monitoring(monitor)
347 .build();
348
349 if (!logger_result) return;
350
351 auto logger_instance = std::shared_ptr<logger>(std::move(logger_result.value()));
352
353 std::cout << "\nPhase 1: Logger operates and reports to monitor" << std::endl;
354
355 // Simulate application activity
356 for (int i = 0; i < 10; ++i) {
357 logger_instance->log(ci::log_level::info,
358 "Application event " + std::to_string(i + 1));
359 std::this_thread::sleep_for(std::chrono::milliseconds(100));
360 }
361
362 // Give async logger time to flush
363 std::this_thread::sleep_for(std::chrono::milliseconds(500));
364
365 std::cout << "\nPhase 2: Monitoring system queries metrics" << std::endl;
366
367 // Monitoring system can query the monitor
368 auto metrics = monitor->get_metrics();
369 if (kcenon::common::is_ok(metrics)) {
370 std::cout << "Monitoring system received metrics:" << std::endl;
372 }
373
374 // Monitoring system can check logger health through IMonitorable
375 if (auto monitorable = std::dynamic_pointer_cast<ci::IMonitorable>(logger_instance)) {
376 auto health = monitorable->health_check();
377 if (kcenon::common::is_ok(health)) {
378 std::cout << "\nLogger health status:" << std::endl;
380 }
381 }
382
383 std::cout << "\nāœ“ Integration successful without circular dependencies" << std::endl;
384}
385
386int main() {
387 std::cout << "============================================================" << std::endl;
388 std::cout << "Logger-Monitor Integration Examples (Phase 4)" << std::endl;
389 std::cout << "Demonstrating loose coupling via common_system interfaces" << std::endl;
390 std::cout << "============================================================" << std::endl;
391
392 try {
397
398 std::cout << "\n============================================================" << std::endl;
399 std::cout << "All integration examples completed successfully!" << std::endl;
400 std::cout << "============================================================" << std::endl;
401
402 } catch (const std::exception& e) {
403 std::cerr << "Error: " << e.what() << std::endl;
404 return 1;
405 }
406
407 return 0;
408}
Aggregating monitor that collects metrics from multiple sources.
kcenon::common::VoidResult reset() override
std::shared_ptr< ci::IMonitor > create_monitor(const std::string &name) override
kcenon::common::Result< ci::health_check_result > check_health() override
kcenon::common::VoidResult record_metric(const std::string &name, double value) override
std::vector< std::shared_ptr< ci::IMonitorable > > monitored_components_
std::shared_ptr< ci::IMonitor > get_monitor() override
kcenon::common::VoidResult record_metric(const std::string &name, double value, const std::unordered_map< std::string, std::string > &tags) override
void register_component(std::shared_ptr< ci::IMonitorable > component)
std::unordered_map< std::string, double > aggregated_metrics_
kcenon::common::Result< ci::metrics_snapshot > get_metrics() override
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_async(bool async=true)
result< std::unique_ptr< logger > > build()
Builder pattern implementation for flexible logger configuration kcenon.
void example_3_imonitorable_interface()
Example 3: Demonstrating IMonitorable interface.
void example_2_multiple_loggers()
Example 2: Multiple loggers with single monitor.
void example_1_basic_integration()
Example 1: Basic monitor integration with logger.
void print_health_result(const ci::health_check_result &health)
Print health check result.
void print_metrics_snapshot(const ci::metrics_snapshot &snapshot)
Print metrics snapshot in formatted way.
void example_4_monitoring_system_simulation()
Example 4: Simulating monitoring_system integration.
bool is_ok(const Result< T > &result)
VoidResult ok()
T & get_value(Result< T > &result)
error_info & get_error(Result< T > &result)
@ size
Rotate based on file size only.