Monitoring System 0.1.0
System resource monitoring with pluggable collectors and alerting
Loading...
Searching...
No Matches
monitor_factory_pattern_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
16#include <kcenon/common/interfaces/logger_interface.h>
17#include <kcenon/common/interfaces/monitoring_interface.h>
18#include <iostream>
19#include <memory>
20#include <unordered_map>
21#include <mutex>
22#include <vector>
23
24using namespace kcenon::monitoring;
25using namespace common::interfaces;
26
30class monitor_factory : public IMonitorProvider {
31private:
32 static std::shared_ptr<monitor_factory> instance_;
33 static std::mutex instance_mutex_;
34
35 std::shared_ptr<IMonitor> default_monitor_;
36 std::unordered_map<std::string, std::shared_ptr<IMonitor>> named_monitors_;
37 std::shared_ptr<ILogger> shared_logger_;
38 mutable std::mutex factory_mutex_;
39
40 monitor_factory() = default;
41
42public:
43 static std::shared_ptr<monitor_factory> instance() {
44 std::lock_guard<std::mutex> lock(instance_mutex_);
45 if (!instance_) {
46 instance_ = std::shared_ptr<monitor_factory>(new monitor_factory());
47 }
48 return instance_;
49 }
50
51 void set_shared_logger(std::shared_ptr<ILogger> logger) {
52 std::lock_guard<std::mutex> lock(factory_mutex_);
53 shared_logger_ = logger;
54
55 // Note: Logger injection not available in performance_monitor yet
56 // Future enhancement: Add ILogger support to performance_monitor
57 }
58
59 // IMonitorProvider implementation
60 std::shared_ptr<IMonitor> get_monitor() override {
61 std::lock_guard<std::mutex> lock(factory_mutex_);
62
63 if (!default_monitor_) {
64 default_monitor_ = std::make_shared<performance_monitor>();
65 }
66
67 return default_monitor_;
68 }
69
70 std::shared_ptr<IMonitor> create_monitor(const std::string& name) override {
71 std::lock_guard<std::mutex> lock(factory_mutex_);
72
73 auto it = named_monitors_.find(name);
74 if (it != named_monitors_.end()) {
75 return it->second;
76 }
77
78 auto monitor = std::make_shared<performance_monitor>();
79 named_monitors_[name] = monitor;
80 return monitor;
81 }
82
83 std::vector<std::string> list_monitors() const {
84 std::lock_guard<std::mutex> lock(factory_mutex_);
85 std::vector<std::string> names;
86 names.reserve(named_monitors_.size());
87
88 for (const auto& [name, _] : named_monitors_) {
89 names.push_back(name);
90 }
91
92 return names;
93 }
94
95 size_t monitor_count() const {
96 std::lock_guard<std::mutex> lock(factory_mutex_);
97 return named_monitors_.size() + (default_monitor_ ? 1 : 0);
98 }
99
100 void reset() {
101 std::lock_guard<std::mutex> lock(factory_mutex_);
102 default_monitor_.reset();
103 named_monitors_.clear();
104 }
105};
106
107std::shared_ptr<monitor_factory> monitor_factory::instance_ = nullptr;
109
113class example_logger : public ILogger {
114private:
115 std::string prefix_;
116 std::atomic<size_t> count_{0};
117 log_level min_level_ = log_level::trace;
118
119public:
120 explicit example_logger(const std::string& prefix = "LOG")
121 : prefix_(prefix) {}
122
123 common::VoidResult log(log_level level, const std::string& message) override {
124 std::cout << "[" << prefix_ << "] [" << to_string(level) << "] "
125 << message << std::endl;
126 count_++;
127 return common::ok();
128 }
129
130 common::VoidResult log(log_level level, const std::string& message,
131 const std::string&, int, const std::string&) override {
132 return log(level, message);
133 }
134
135 common::VoidResult log(const log_entry& entry) override {
136 return log(entry.level, entry.message);
137 }
138
139 bool is_enabled(log_level level) const override {
140 return static_cast<int>(level) >= static_cast<int>(min_level_);
141 }
142
143 common::VoidResult set_level(log_level level) override {
144 min_level_ = level;
145 return common::ok();
146 }
147
148 log_level get_level() const override {
149 return min_level_;
150 }
151
152 common::VoidResult flush() override {
153 std::cout << std::flush;
154 return common::ok();
155 }
156
157 size_t count() const { return count_.load(); }
158};
159
164 std::cout << "\n=== Example 1: Basic Factory Pattern ===" << std::endl;
165
166 auto factory = monitor_factory::instance();
167
168 std::cout << "Getting default monitor from factory..." << std::endl;
169 auto monitor = factory->get_monitor();
170
171 if (monitor) {
172 std::cout << "✓ Obtained monitor instance" << std::endl;
173
174 monitor->record_metric("test_metric", 42.0);
175
176 auto metrics = monitor->get_metrics();
177 if (metrics) {
178 std::cout << "✓ Monitor has " << metrics.value().metrics.size()
179 << " metrics" << std::endl;
180 }
181 }
182}
183
188 std::cout << "\n=== Example 2: Named Monitors ===" << std::endl;
189
190 auto factory = monitor_factory::instance();
191
192 // Create named monitors
193 auto web_monitor = factory->create_monitor("web_server");
194 auto db_monitor = factory->create_monitor("database");
195 auto cache_monitor = factory->create_monitor("cache");
196
197 std::cout << "Created 3 named monitors" << std::endl;
198
199 // Use monitors
200 web_monitor->record_metric("requests", 1000.0);
201 db_monitor->record_metric("queries", 500.0);
202 cache_monitor->record_metric("hits", 750.0);
203
204 // List all monitors
205 auto names = factory->list_monitors();
206 std::cout << "\nRegistered monitors (" << names.size() << "):" << std::endl;
207 for (const auto& name : names) {
208 std::cout << " - " << name << std::endl;
209 }
210}
211
216 std::cout << "\n=== Example 3: Factory with Shared Logger ===" << std::endl;
217
218 auto factory = monitor_factory::instance();
219 auto logger = std::make_shared<example_logger>("FACTORY");
220
221 // Set shared logger for all monitors
222 factory->set_shared_logger(logger);
223
224 std::cout << "Shared logger configured for factory" << std::endl;
225
226 // All new monitors will automatically use the shared logger
227 auto monitor1 = factory->create_monitor("service_a");
228 auto monitor2 = factory->create_monitor("service_b");
229
230 std::cout << "\nRecording metrics with shared logger..." << std::endl;
231 monitor1->record_metric("metric_a", 10.0);
232 monitor2->record_metric("metric_b", 20.0);
233
234 std::cout << "\nShared logger received " << logger->count()
235 << " messages from all monitors" << std::endl;
236}
237
242 std::cout << "\n=== Example 4: Monitor Reuse ===" << std::endl;
243
244 auto factory = monitor_factory::instance();
245
246 // Create monitor with specific name
247 auto monitor1 = factory->create_monitor("shared_monitor");
248 monitor1->record_metric("counter", 1.0);
249
250 // Get same monitor by name (reuse)
251 auto monitor2 = factory->create_monitor("shared_monitor");
252
253 // They are the same instance
254 std::cout << "Monitor instances "
255 << (monitor1 == monitor2 ? "identical ✓" : "different ✗")
256 << std::endl;
257
258 monitor2->record_metric("counter", 2.0);
259
260 // Check metrics
261 auto metrics = monitor1->get_metrics();
262 if (metrics) {
263 std::cout << "Shared monitor has " << metrics.value().metrics.size()
264 << " metrics (accumulated from both uses)" << std::endl;
265 }
266}
267
272 std::cout << "\n=== Example 5: IMonitorProvider Interface ===" << std::endl;
273
274 // Use factory through IMonitorProvider interface
275 std::shared_ptr<IMonitorProvider> provider = monitor_factory::instance();
276
277 std::cout << "Using factory via IMonitorProvider interface" << std::endl;
278
279 auto monitor = provider->get_monitor();
280 if (monitor) {
281 std::cout << "✓ Retrieved monitor through provider interface" << std::endl;
282
283 monitor->record_metric("provider_test", 99.0);
284
285 auto health = monitor->check_health();
286 if (health) {
287 std::cout << "✓ Monitor health: "
288 << to_string(health.value().status) << std::endl;
289 }
290 }
291
292 auto named = provider->create_monitor("provider_created");
293 if (named) {
294 std::cout << "✓ Created named monitor through provider" << std::endl;
295 }
296}
297
301class aggregating_monitor : public IMonitor {
302private:
303 std::vector<std::shared_ptr<IMonitor>> monitors_;
304 std::mutex mutex_;
305
306public:
307 void add_monitor(std::shared_ptr<IMonitor> monitor) {
308 std::lock_guard<std::mutex> lock(mutex_);
309 monitors_.push_back(monitor);
310 }
311
312 common::VoidResult record_metric(const std::string& name, double value) override {
313 std::lock_guard<std::mutex> lock(mutex_);
314 for (auto& monitor : monitors_) {
315 monitor->record_metric(name, value);
316 }
317 return common::ok();
318 }
319
320 common::VoidResult record_metric(
321 const std::string& name,
322 double value,
323 const std::unordered_map<std::string, std::string>& tags) override
324 {
325 std::lock_guard<std::mutex> lock(mutex_);
326 for (auto& monitor : monitors_) {
327 monitor->record_metric(name, value, tags);
328 }
329 return common::ok();
330 }
331
332 common::Result<metrics_snapshot> get_metrics() override {
333 std::lock_guard<std::mutex> lock(mutex_);
334
335 metrics_snapshot combined;
336 combined.source_id = "aggregating_monitor";
337 combined.capture_time = std::chrono::system_clock::now();
338
339 for (auto& monitor : monitors_) {
340 auto result = monitor->get_metrics();
341 if (result) {
342 for (const auto& metric : result.value().metrics) {
343 combined.metrics.push_back(metric);
344 }
345 }
346 }
347
348 return common::ok(std::move(combined));
349 }
350
351 common::Result<health_check_result> check_health() override {
352 health_check_result result;
353 result.timestamp = std::chrono::system_clock::now();
354 result.status = health_status::healthy;
355 result.message = "Aggregating monitor";
356
357 return common::ok(std::move(result));
358 }
359
360 common::VoidResult reset() override {
361 std::lock_guard<std::mutex> lock(mutex_);
362 for (auto& monitor : monitors_) {
363 monitor->reset();
364 }
365 return common::ok();
366 }
367
368 size_t monitor_count() const {
369 std::lock_guard<std::mutex> lock(mutex_);
370 return monitors_.size();
371 }
372};
373
375 std::cout << "\n=== Example 6: Aggregating Monitor Pattern ===" << std::endl;
376
377 auto factory = monitor_factory::instance();
378 auto aggregator = std::make_shared<aggregating_monitor>();
379
380 // Create multiple monitors and add to aggregator
381 auto mon1 = factory->create_monitor("service_1");
382 auto mon2 = factory->create_monitor("service_2");
383 auto mon3 = factory->create_monitor("service_3");
384
385 aggregator->add_monitor(mon1);
386 aggregator->add_monitor(mon2);
387 aggregator->add_monitor(mon3);
388
389 std::cout << "Aggregator managing " << aggregator->monitor_count()
390 << " monitors" << std::endl;
391
392 // Record to aggregator - broadcasts to all
393 aggregator->record_metric("broadcast_metric", 100.0);
394
395 std::cout << "\nMetric broadcasted to all monitors" << std::endl;
396
397 // Get combined metrics
398 auto metrics = aggregator->get_metrics();
399 if (metrics) {
400 std::cout << "Combined metrics count: "
401 << metrics.value().metrics.size() << std::endl;
402 }
403}
404
409 std::cout << "\n=== Example 7: Factory Lifecycle Management ===" << std::endl;
410
411 auto factory = monitor_factory::instance();
412
413 std::cout << "Initial monitor count: " << factory->monitor_count() << std::endl;
414
415 // Create some monitors
416 factory->create_monitor("temp_1");
417 factory->create_monitor("temp_2");
418
419 std::cout << "After creation: " << factory->monitor_count() << std::endl;
420
421 // Reset factory
422 factory->reset();
423
424 std::cout << "After reset: " << factory->monitor_count() << std::endl;
425 std::cout << "✓ Factory lifecycle managed successfully" << std::endl;
426}
427
428int main() {
429 std::cout << "========================================================" << std::endl;
430 std::cout << "Monitor Factory Pattern Examples (Phase 4)" << std::endl;
431 std::cout << "Advanced DI Patterns for Monitoring System" << std::endl;
432 std::cout << "========================================================" << std::endl;
433
434 try {
442
443 std::cout << "\n========================================================" << std::endl;
444 std::cout << "All factory pattern examples completed!" << std::endl;
445 std::cout << "Key Patterns Demonstrated:" << std::endl;
446 std::cout << " ✓ Singleton factory pattern" << std::endl;
447 std::cout << " ✓ Named monitor management" << std::endl;
448 std::cout << " ✓ Shared logger injection" << std::endl;
449 std::cout << " ✓ Monitor reuse and lifecycle" << std::endl;
450 std::cout << " ✓ IMonitorProvider interface" << std::endl;
451 std::cout << " ✓ Aggregating monitor pattern" << std::endl;
452 std::cout << "========================================================" << std::endl;
453
454 } catch (const std::exception& e) {
455 std::cerr << "Error: " << e.what() << std::endl;
456 return 1;
457 }
458
459 return 0;
460}
Example 6: Aggregating monitor pattern.
common::VoidResult record_metric(const std::string &name, double value) override
void add_monitor(std::shared_ptr< IMonitor > monitor)
common::Result< metrics_snapshot > get_metrics() override
common::VoidResult record_metric(const std::string &name, double value, const std::unordered_map< std::string, std::string > &tags) override
common::Result< health_check_result > check_health() override
std::vector< std::shared_ptr< IMonitor > > monitors_
common::VoidResult reset() override
Simple logger for examples.
log_level get_level() const override
common::VoidResult log(log_level level, const std::string &message, const std::string &, int, const std::string &) override
bool is_enabled(log_level level) const override
common::VoidResult set_level(log_level level) override
example_logger(const std::string &prefix="LOG")
common::VoidResult flush() override
common::VoidResult log(log_level level, const std::string &message) override
common::VoidResult log(const log_entry &entry) override
Monitor factory implementing singleton pattern with DI.
std::unordered_map< std::string, std::shared_ptr< IMonitor > > named_monitors_
std::shared_ptr< IMonitor > create_monitor(const std::string &name) override
static std::shared_ptr< monitor_factory > instance_
monitor_factory()=default
void set_shared_logger(std::shared_ptr< ILogger > logger)
std::vector< std::string > list_monitors() const
std::shared_ptr< ILogger > shared_logger_
std::shared_ptr< IMonitor > default_monitor_
std::shared_ptr< IMonitor > get_monitor() override
static std::shared_ptr< monitor_factory > instance()
void example_2_named_monitors()
Example 2: Named monitors via factory.
void example_5_provider_interface()
Example 5: Provider interface usage.
void example_6_aggregating_pattern()
void example_4_monitor_reuse()
Example 4: Monitor reuse via factory.
void example_3_factory_with_logger()
Example 3: Factory with shared logger.
void example_1_basic_factory()
Example 1: Basic factory pattern.
void example_7_factory_lifecycle()
Example 7: Factory cleanup and reset.
auto to_string(plugin_load_error error) -> std::string
Convert plugin_load_error to string.
Performance monitoring and profiling implementation.
Result pattern type definitions for monitoring system.
Result of a health check operation.
std::chrono::system_clock::time_point timestamp
Basic metric structure for interface compatibility.
std::variant< double, int64_t, std::string > value
Complete snapshot of metrics at a point in time.
std::chrono::system_clock::time_point capture_time
std::vector< metric_value > metrics