@@ -34,33 +34,47 @@ SISL_LOGGING_INIT(vmod_metrics_framework)
3434
3535using namespace sisl;
3636
37+ class Group1Metrics : public MetricsGroup {
38+ public:
39+ explicit Group1Metrics (const char * inst_name)
40+ : MetricsGroup(" Group1" , inst_name, group_impl_type_t ::thread_buf_signal) {
41+ REGISTER_COUNTER (counter1, " Counter1" );
42+ REGISTER_COUNTER (counter2, " Counter2" );
43+ REGISTER_COUNTER (counter3, " Counter3" );
44+ register_me_to_farm ();
45+ }
46+ ~Group1Metrics () { deregister_me_from_farm (); }
47+ };
48+
49+ class Group2Metrics : public MetricsGroup {
50+ public:
51+ explicit Group2Metrics (const char * inst_name)
52+ : MetricsGroup(" Group2" , inst_name, group_impl_type_t ::thread_buf_signal) {
53+ REGISTER_GAUGE (gauge1, " Gauge1" );
54+ REGISTER_GAUGE (gauge2, " Gauge2" );
55+ register_me_to_farm ();
56+ }
57+ ~Group2Metrics () { deregister_me_from_farm (); }
58+ };
59+
3760void userA () {
38- auto mgroup = std::make_shared< ThreadBufferMetricsGroup >(" Group1" , " Instance1" );
39- mgroup->register_counter (" counter1" , " Counter1" );
40- mgroup->register_counter (" counter2" , " Counter2" );
41- mgroup->register_counter (" counter3" , " Counter3" );
42- MetricsFarm::getInstance ().register_metrics_group (mgroup);
43-
44- mgroup->counter_increment (0 );
45- mgroup->counter_increment (2 , 4 );
61+ Group1Metrics metrics (" Instance1" );
62+
63+ COUNTER_INCREMENT (metrics, counter1, 1 );
64+ COUNTER_INCREMENT (metrics, counter3, 4 );
4665 std::this_thread::sleep_for (std::chrono::seconds (3 ));
47- mgroup-> counter_increment ( 1 );
66+ COUNTER_INCREMENT (metrics, counter2, 1 );
4867 std::this_thread::sleep_for (std::chrono::seconds (4 ));
49- MetricsFarm::getInstance ().deregister_metrics_group (mgroup);
5068}
5169
5270void userB () {
53- auto mgroup = std::make_shared< ThreadBufferMetricsGroup >(" Group2" , " Instance1" );
54- mgroup->register_gauge (" gauge1" , " Gauge1" );
55- mgroup->register_gauge (" gauge2" , " Gauge2" );
56- MetricsFarm::getInstance ().register_metrics_group (mgroup);
71+ Group2Metrics metrics (" Instance1" );
5772
58- mgroup-> gauge_update ( 0 , 5 );
73+ GAUGE_UPDATE (metrics, gauge1 , 5 );
5974 std::this_thread::sleep_for (std::chrono::seconds (3 ));
60- mgroup-> gauge_update ( 1 , 2 );
61- mgroup-> gauge_update ( 0 , 3 );
75+ GAUGE_UPDATE (metrics, gauge2 , 2 );
76+ GAUGE_UPDATE (metrics, gauge1 , 3 );
6277 std::this_thread::sleep_for (std::chrono::seconds (4 ));
63- MetricsFarm::getInstance ().deregister_metrics_group (mgroup);
6478}
6579
6680// clang-format off
@@ -134,7 +148,7 @@ void gather() {
134148 }
135149}
136150
137- TEST (farmTest , gather) {
151+ TEST (FarmTest , gather) {
138152 std::thread th1 (userA);
139153 std::thread th2 (userB);
140154 std::thread th3 (gather);
@@ -144,6 +158,67 @@ TEST(farmTest, gather) {
144158 th3.join ();
145159}
146160
161+ // Helper class for DirectAccess tests
162+ class TestMetrics : public MetricsGroup {
163+ public:
164+ explicit TestMetrics (const char * inst_name, group_impl_type_t type = group_impl_type_t ::rcu)
165+ : MetricsGroup(" TestGroup" , inst_name, type) {
166+ REGISTER_COUNTER (test_counter, " Test counter" );
167+ REGISTER_GAUGE (test_gauge, " Test gauge" );
168+ REGISTER_HISTOGRAM (test_histogram, " Test histogram" );
169+ register_me_to_farm ();
170+ }
171+ ~TestMetrics () { deregister_me_from_farm (); }
172+ };
173+
174+ // Parameterized test fixture for DirectAccess tests
175+ class DirectAccessTest : public ::testing::TestWithParam< group_impl_type_t > {};
176+
177+ // Test direct access to counter, gauge, and histogram values
178+ TEST_P (DirectAccessTest, allMetricTypes) {
179+ group_impl_type_t impl_type = GetParam ();
180+ TestMetrics metrics (" direct_access_test" , impl_type);
181+
182+ // Test counter
183+ COUNTER_INCREMENT (metrics, test_counter, 5 );
184+ COUNTER_INCREMENT (metrics, test_counter, 10 );
185+ COUNTER_INCREMENT (metrics, test_counter, 15 );
186+ int64_t counter_value = COUNTER_VALUE (metrics, test_counter);
187+ EXPECT_EQ (counter_value, 30 );
188+
189+ // Test gauge
190+ GAUGE_UPDATE (metrics, test_gauge, 100 );
191+ EXPECT_EQ (GAUGE_VALUE (metrics, test_gauge), 100 );
192+ GAUGE_UPDATE (metrics, test_gauge, 250 );
193+ EXPECT_EQ (GAUGE_VALUE (metrics, test_gauge), 250 );
194+
195+ // Test histogram
196+ HISTOGRAM_OBSERVE (metrics, test_histogram, 10 );
197+ HISTOGRAM_OBSERVE (metrics, test_histogram, 20 );
198+ HISTOGRAM_OBSERVE (metrics, test_histogram, 30 );
199+ HISTOGRAM_OBSERVE (metrics, test_histogram, 40 );
200+ HISTOGRAM_OBSERVE (metrics, test_histogram, 50 );
201+
202+ sisl::HistogramStatistics stats = HISTOGRAM_VALUE (metrics, test_histogram);
203+ EXPECT_EQ (stats.count , 5 );
204+ EXPECT_DOUBLE_EQ (stats.average , 30.0 );
205+ EXPECT_GT (stats.p50 , 0.0 );
206+ EXPECT_GT (stats.p95 , 0.0 );
207+ EXPECT_GT (stats.p99 , 0.0 );
208+ }
209+
210+ INSTANTIATE_TEST_SUITE_P (AllImplementations, DirectAccessTest,
211+ ::testing::Values (group_impl_type_t ::rcu, group_impl_type_t ::atomic,
212+ group_impl_type_t ::thread_buf_signal),
213+ [](const ::testing::TestParamInfo< group_impl_type_t >& info) {
214+ switch (info.param ) {
215+ case group_impl_type_t ::rcu: return " RCU" ;
216+ case group_impl_type_t ::atomic: return " Atomic" ;
217+ case group_impl_type_t ::thread_buf_signal: return " ThreadLocal" ;
218+ default : return " Unknown" ;
219+ }
220+ });
221+
147222int main (int argc, char * argv[]) {
148223 ::testing::InitGoogleTest (&argc, argv);
149224 return RUN_ALL_TESTS ();
0 commit comments