11#include <gtest/gtest.h>
33 return kcenon::common::make_error<monitoring_data>(
34 static_cast<int>(monitoring_error_code::monitoring_disabled),
35 "Monitoring is disabled for this component"
47 data.
add_tag(
"component_type",
"test");
48 data.
add_tag(
"version",
"1.0.0");
49 data.
add_tag(
"status",
"running");
51 return kcenon::common::ok(std::move(data));
97 data.
add_tag(
"host",
"localhost");
98 data.
add_tag(
"region",
"us-east");
102 ASSERT_TRUE(
cpu.has_value());
103 EXPECT_DOUBLE_EQ(
cpu.value(), 75.5);
106 ASSERT_TRUE(
memory.has_value());
107 EXPECT_DOUBLE_EQ(
memory.value(), 1024.0);
109 auto missing = data.
get_metric(
"nonexistent");
110 EXPECT_FALSE(missing.has_value());
114 ASSERT_TRUE(
host.has_value());
115 EXPECT_EQ(
host.value(),
"localhost");
117 auto region = data.
get_tag(
"region");
118 ASSERT_TRUE(region.has_value());
119 EXPECT_EQ(region.value(),
"us-east");
124 EXPECT_FALSE(data.
empty());
136 data1.
add_tag(
"tag1",
"value1");
140 data2.
add_tag(
"tag2",
"value2");
149 ASSERT_TRUE(metric2.has_value());
150 EXPECT_DOUBLE_EQ(metric2.value(), 20.0);
155 data3.
add_tag(
"tag3",
"value3");
157 data1.
merge(data3,
"prefix");
159 auto prefixed_metric = data1.
get_metric(
"prefix.metric3");
160 ASSERT_TRUE(prefixed_metric.has_value());
161 EXPECT_DOUBLE_EQ(prefixed_metric.value(), 30.0);
163 auto prefixed_tag = data1.
get_tag(
"prefix.tag3");
164 ASSERT_TRUE(prefixed_tag.has_value());
165 EXPECT_EQ(prefixed_tag.value(),
"value3");
175 EXPECT_TRUE(data.
empty());
183 EXPECT_FALSE(data.
empty());
190 EXPECT_TRUE(data.
empty());
213 ASSERT_TRUE(result.is_ok());
215 auto data = result.value();
216 EXPECT_EQ(data.get_component_name(),
"test_comp_1");
219 auto op_count = data.get_metric(
"operation_count");
220 ASSERT_TRUE(op_count.has_value());
221 EXPECT_DOUBLE_EQ(op_count.value(), 2.0);
223 auto cpu = data.get_metric(
"cpu_usage");
224 ASSERT_TRUE(
cpu.has_value());
225 EXPECT_DOUBLE_EQ(
cpu.value(), 45.5);
227 auto memory = data.get_metric(
"memory_usage");
228 ASSERT_TRUE(
memory.has_value());
229 EXPECT_DOUBLE_EQ(
memory.value(), 2048.0);
232 auto type = data.get_tag(
"component_type");
233 ASSERT_TRUE(type.has_value());
234 EXPECT_EQ(type.value(),
"test");
236 auto version = data.get_tag(
"version");
237 ASSERT_TRUE(version.has_value());
238 EXPECT_EQ(version.value(),
"1.0.0");
251 EXPECT_TRUE(result.is_ok());
255 EXPECT_TRUE(disable_result.is_ok());
260 EXPECT_TRUE(result.is_err());
261 EXPECT_EQ(
static_cast<monitoring_error_code>(result.error().code), monitoring_error_code::monitoring_disabled);
265 EXPECT_TRUE(enable_result.is_ok());
270 EXPECT_TRUE(result.is_ok());
288 EXPECT_TRUE(reset_result.is_ok());
301 auto comp1 = std::make_shared<test_monitorable_component>(
"comp1");
302 auto comp2 = std::make_shared<test_monitorable_component>(
"comp2");
303 auto comp3 = std::make_shared<test_monitorable_component>(
"comp3");
306 comp1->set_cpu_usage(25.0);
307 comp1->set_memory_usage(1000.0);
308 comp1->perform_operation();
310 comp2->set_cpu_usage(50.0);
311 comp2->set_memory_usage(2000.0);
312 comp2->perform_operation();
313 comp2->perform_operation();
315 comp3->set_cpu_usage(75.0);
316 comp3->set_memory_usage(3000.0);
317 comp3->perform_operation();
318 comp3->perform_operation();
319 comp3->perform_operation();
326 EXPECT_EQ(aggregator.
size(), 3);
330 EXPECT_EQ(ids.size(), 3);
331 EXPECT_TRUE(std::find(ids.begin(), ids.end(),
"comp1") != ids.end());
332 EXPECT_TRUE(std::find(ids.begin(), ids.end(),
"comp2") != ids.end());
333 EXPECT_TRUE(std::find(ids.begin(), ids.end(),
"comp3") != ids.end());
337 ASSERT_NE(retrieved,
nullptr);
338 EXPECT_EQ(retrieved->get_monitoring_id(),
"comp2");
348 auto comp1 = std::make_shared<test_monitorable_component>(
"comp1");
349 comp1->set_cpu_usage(30.0);
350 comp1->set_memory_usage(1500.0);
352 auto comp2 = std::make_shared<test_monitorable_component>(
"comp2");
353 comp2->set_cpu_usage(60.0);
354 comp2->set_memory_usage(2500.0);
361 ASSERT_TRUE(result.is_ok());
363 auto aggregated = result.value();
364 EXPECT_EQ(aggregated.get_component_name(),
"test_aggregator");
367 auto comp1_cpu = aggregated.get_metric(
"comp1.cpu_usage");
368 ASSERT_TRUE(comp1_cpu.has_value());
369 EXPECT_DOUBLE_EQ(comp1_cpu.value(), 30.0);
371 auto comp2_cpu = aggregated.get_metric(
"comp2.cpu_usage");
372 ASSERT_TRUE(comp2_cpu.has_value());
373 EXPECT_DOUBLE_EQ(comp2_cpu.value(), 60.0);
376 auto component_count = aggregated.get_metric(
"aggregator.component_count");
377 ASSERT_TRUE(component_count.has_value());
378 EXPECT_DOUBLE_EQ(component_count.value(), 2.0);
387 auto comp1 = std::make_shared<test_monitorable_component>(
"comp1");
388 auto comp2 = std::make_shared<test_monitorable_component>(
"comp2");
390 comp1->set_cpu_usage(40.0);
391 comp2->set_cpu_usage(80.0);
394 comp2->set_monitoring_enabled(
false);
401 ASSERT_TRUE(result.is_ok());
403 auto aggregated = result.value();
406 auto comp1_cpu = aggregated.get_metric(
"comp1.cpu_usage");
407 ASSERT_TRUE(comp1_cpu.has_value());
410 auto comp2_cpu = aggregated.get_metric(
"comp2.cpu_usage");
411 EXPECT_FALSE(comp2_cpu.has_value());
414 auto comp2_error = aggregated.get_tag(
"comp2.error");
415 EXPECT_FALSE(comp2_error.has_value());
424 auto comp1 = std::make_shared<test_monitorable_component>(
"comp1");
425 auto comp2 = std::make_shared<test_monitorable_component>(
"comp2");
426 auto comp3 = std::make_shared<test_monitorable_component>(
"comp3");
432 EXPECT_EQ(aggregator.
size(), 3);
436 EXPECT_TRUE(removed);
437 EXPECT_EQ(aggregator.
size(), 2);
441 EXPECT_FALSE(removed);
442 EXPECT_EQ(aggregator.
size(), 2);
446 EXPECT_TRUE(std::find(ids.begin(), ids.end(),
"comp1") != ids.end());
447 EXPECT_FALSE(std::find(ids.begin(), ids.end(),
"comp2") != ids.end());
448 EXPECT_TRUE(std::find(ids.begin(), ids.end(),
"comp3") != ids.end());
452 EXPECT_EQ(aggregator.
size(), 0);
459 auto start_time = std::chrono::system_clock::now();
464 auto end_time = std::chrono::system_clock::now();
467 EXPECT_GE(timestamp, start_time);
468 EXPECT_LE(timestamp, end_time);
477 const int thread_count = 10;
478 const int operations_per_thread = 1000;
479 std::vector<std::thread> threads;
482 for (
int i = 0; i < thread_count; ++i) {
483 threads.emplace_back([&component]() {
484 for (
int j = 0; j < operations_per_thread; ++j) {
490 EXPECT_TRUE(result.is_ok());
497 for (
auto& t : threads) {
506 ASSERT_TRUE(result.is_ok());
508 auto op_count = result.value().get_metric(
"operation_count");
509 ASSERT_TRUE(op_count.has_value());
510 EXPECT_DOUBLE_EQ(op_count.value(),
511 static_cast<double>(thread_count * operations_per_thread));
Base class providing default monitorable implementation.
common::VoidResult reset_monitoring() override
Reset monitoring data.
bool is_monitoring_enabled() const override
Check if monitoring is enabled.
std::string get_monitoring_id() const override
Get monitoring identifier.
common::VoidResult set_monitoring_enabled(bool enable) override
Enable or disable monitoring.
Utility class to aggregate metrics from multiple monitorable components.
std::size_t size() const
Get the number of registered components.
common::Result< monitoring_data > collect_all() const
Collect data from all components.
std::vector< std::string > get_component_ids() const
Get all component IDs.
bool remove_component(const std::string &id)
Remove a component by ID.
std::shared_ptr< monitorable_interface > get_component(const std::string &id) const
Get a specific component by ID.
void clear()
Clear all components.
void add_component(std::shared_ptr< monitorable_interface > component)
Add a component to monitor.
void set_memory_usage(double usage)
void set_cpu_usage(double usage)
std::atomic< double > cpu_usage_
test_monitorable_component(const std::string &id)
kcenon::common::Result< monitoring_data > get_monitoring_data() const override
Get current monitoring data from the component.
std::atomic< double > memory_usage_
int get_operation_count() const
std::atomic< int > operation_count_
Interface for components that expose monitoring metrics.
monitoring_error_code
Comprehensive error codes for monitoring system operations.
@ memory
Memory/DRAM power domain (RAPL)
@ cpu
CPU power domain (RAPL)
Container for monitoring metrics from a component.
void merge(const monitoring_data &other, const std::string &prefix="")
Merge another monitoring_data into this one.
std::size_t metric_count() const
Get the number of metrics.
bool empty() const
Check if data is empty.
std::chrono::system_clock::time_point get_timestamp() const
Get the timestamp.
std::optional< std::string > get_tag(const std::string &key) const
Get a tag value.
std::size_t tag_count() const
Get the number of tags.
void clear()
Clear all metrics and tags.
std::optional< double > get_metric(const std::string &key) const
Get a metric value.
const std::string & get_component_name() const
Get the component name.
void add_metric(const std::string &key, double value)
Add a numeric metric.
void add_tag(const std::string &key, const std::string &value)
Add a tag (string metadata)
TEST_F(MonitorableInterfaceTest, MonitoringDataBasicOperations)