Monitoring System 0.1.0
System resource monitoring with pluggable collectors and alerting
Loading...
Searching...
No Matches
metric_factory.h
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
5#pragma once
6
30#include <functional>
31#include <memory>
32#include <mutex>
33#include <string>
34#include <unordered_map>
35#include <vector>
36
38
39namespace kcenon::monitoring {
40
44class metric_collector_plugin;
45
53 public:
55 virtual ~collector_interface() = default;
56
57 // Non-copyable, non-moveable
62
68 virtual bool initialize(const config_map& config) = 0;
69
74 [[nodiscard]] virtual std::string get_name() const = 0;
75
80 [[nodiscard]] virtual bool is_healthy() const = 0;
81
86 [[nodiscard]] virtual std::vector<std::string> get_metric_types() const = 0;
87};
88
93 std::unique_ptr<collector_interface> collector;
94 bool success{false};
95 std::string error_message;
96
97 explicit operator bool() const { return success; }
98};
99
103using collector_factory_fn = std::function<std::unique_ptr<collector_interface>()>;
104
119 public:
126 return instance;
127 }
128
129 ~metric_factory() = default;
130
131 // Non-copyable, non-moveable
136
143 bool register_collector(const std::string& name, collector_factory_fn factory) {
144 std::lock_guard<std::mutex> lock(mutex_);
145 if (factories_.find(name) != factories_.end()) {
146 return false;
147 }
148 factories_[name] = std::move(factory);
149 return true;
150 }
151
158 template <typename T>
159 bool register_collector(const std::string& name) {
160 return register_collector(name, []() {
161 return std::make_unique<T>();
162 });
163 }
164
170 bool unregister_collector(const std::string& name) {
171 std::lock_guard<std::mutex> lock(mutex_);
172 return factories_.erase(name) > 0;
173 }
174
180 bool is_registered(const std::string& name) const {
181 std::lock_guard<std::mutex> lock(mutex_);
182 return factories_.find(name) != factories_.end();
183 }
184
189 std::vector<std::string> get_registered_collectors() const {
190 std::lock_guard<std::mutex> lock(mutex_);
191 std::vector<std::string> names;
192 names.reserve(factories_.size());
193 for (const auto& [name, _] : factories_) {
194 names.push_back(name);
195 }
196 return names;
197 }
198
205 create_result create(const std::string& name, const config_map& config = {}) {
206 create_result result;
207
208 // Find factory
209 collector_factory_fn factory;
210 {
211 std::lock_guard<std::mutex> lock(mutex_);
212 auto it = factories_.find(name);
213 if (it == factories_.end()) {
214 result.error_message = "Unknown collector: " + name;
215 return result;
216 }
217 factory = it->second;
218 }
219
220 // Create collector
221 try {
222 result.collector = factory();
223 if (!result.collector) {
224 result.error_message = "Factory returned null for: " + name;
225 return result;
226 }
227 } catch (const std::exception& e) {
228 result.error_message = "Failed to create collector '" + name + "': " + e.what();
229 return result;
230 } catch (...) {
231 result.error_message = "Unknown error creating collector: " + name;
232 return result;
233 }
234
235 // Initialize collector
236 try {
237 if (!result.collector->initialize(config)) {
238 result.error_message = "Initialization failed for: " + name;
239 result.collector.reset();
240 return result;
241 }
242 } catch (const std::exception& e) {
243 result.error_message =
244 "Exception during initialization of '" + name + "': " + e.what();
245 result.collector.reset();
246 return result;
247 } catch (...) {
248 result.error_message = "Unknown error initializing collector: " + name;
249 result.collector.reset();
250 return result;
251 }
252
253 result.success = true;
254 return result;
255 }
256
263 std::unique_ptr<collector_interface> create_or_null(const std::string& name,
264 const config_map& config = {}) {
265 auto result = create(name, config);
266 return std::move(result.collector);
267 }
268
274 std::vector<std::unique_ptr<collector_interface>> create_multiple(
275 const std::unordered_map<std::string, config_map>& configs) {
276 std::vector<std::unique_ptr<collector_interface>> collectors;
277 collectors.reserve(configs.size());
278
279 for (const auto& [name, config] : configs) {
280 auto result = create(name, config);
281 if (result) {
282 collectors.push_back(std::move(result.collector));
283 }
284 }
285
286 return collectors;
287 }
288
292 void clear() {
293 std::lock_guard<std::mutex> lock(mutex_);
294 factories_.clear();
295 }
296
297 private:
298 metric_factory() = default;
299
300 mutable std::mutex mutex_;
301 std::unordered_map<std::string, collector_factory_fn> factories_;
302};
303
312#define REGISTER_COLLECTOR(CollectorType) \
313 namespace { \
314 static const bool CollectorType##_registered = []() { \
315 return kcenon::monitoring::metric_factory::instance() \
316 .register_collector<CollectorType>(#CollectorType); \
317 }(); \
318 }
319
320} // namespace kcenon::monitoring
Base interface for type-erased collectors.
virtual bool is_healthy() const =0
virtual std::string get_name() const =0
collector_interface(const collector_interface &)=delete
collector_interface(collector_interface &&)=delete
collector_interface & operator=(collector_interface &&)=delete
collector_interface & operator=(const collector_interface &)=delete
virtual bool initialize(const config_map &config)=0
virtual std::vector< std::string > get_metric_types() const =0
Unified factory for metric collector instantiation.
std::vector< std::string > get_registered_collectors() const
Get list of registered collector names.
bool unregister_collector(const std::string &name)
Unregister a collector.
std::vector< std::unique_ptr< collector_interface > > create_multiple(const std::unordered_map< std::string, config_map > &configs)
Create multiple collectors from configuration.
metric_factory(const metric_factory &)=delete
std::unordered_map< std::string, collector_factory_fn > factories_
std::unique_ptr< collector_interface > create_or_null(const std::string &name, const config_map &config={})
Create a collector and return raw pointer (for compatibility)
static metric_factory & instance()
Get the singleton instance.
bool is_registered(const std::string &name) const
Check if a collector is registered.
void clear()
Clear all registered collectors.
create_result create(const std::string &name, const config_map &config={})
Create a collector instance.
metric_factory & operator=(metric_factory &&)=delete
bool register_collector(const std::string &name, collector_factory_fn factory)
Register a collector factory function.
metric_factory & operator=(const metric_factory &)=delete
metric_factory(metric_factory &&)=delete
bool register_collector(const std::string &name)
Register a collector type using template.
Unified configuration parsing utility.
std::function< std::unique_ptr< collector_interface >()> collector_factory_fn
Factory function type for creating collectors.
std::unordered_map< std::string, std::string > config_map
Type alias for configuration map.
Result of collector creation.
std::unique_ptr< collector_interface > collector