Monitoring System 0.1.0
System resource monitoring with pluggable collectors and alerting
Loading...
Searching...
No Matches
test_timer_metrics.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
5#include <gtest/gtest.h>
7#include <thread>
8#include <cmath>
9
10using namespace kcenon::monitoring;
11
15class TimerMetricsTest : public ::testing::Test {
16protected:
17 void SetUp() override {}
18 void TearDown() override {}
19};
20
21TEST_F(TimerMetricsTest, EmptyTimerReturnsZero) {
23
24 EXPECT_EQ(timer.count(), 0);
25 EXPECT_DOUBLE_EQ(timer.mean(), 0.0);
26 EXPECT_DOUBLE_EQ(timer.min(), 0.0);
27 EXPECT_DOUBLE_EQ(timer.max(), 0.0);
28 EXPECT_DOUBLE_EQ(timer.median(), 0.0);
29 EXPECT_DOUBLE_EQ(timer.p99(), 0.0);
30}
31
32TEST_F(TimerMetricsTest, SingleSample) {
34 timer.record(100.0);
35
36 EXPECT_EQ(timer.count(), 1);
37 EXPECT_DOUBLE_EQ(timer.mean(), 100.0);
38 EXPECT_DOUBLE_EQ(timer.min(), 100.0);
39 EXPECT_DOUBLE_EQ(timer.max(), 100.0);
40 EXPECT_DOUBLE_EQ(timer.median(), 100.0);
41}
42
43TEST_F(TimerMetricsTest, MultipleSamples) {
45 for (int i = 1; i <= 100; ++i) {
46 timer.record(static_cast<double>(i));
47 }
48
49 EXPECT_EQ(timer.count(), 100);
50 EXPECT_DOUBLE_EQ(timer.mean(), 50.5);
51 EXPECT_DOUBLE_EQ(timer.min(), 1.0);
52 EXPECT_DOUBLE_EQ(timer.max(), 100.0);
53}
54
55TEST_F(TimerMetricsTest, MedianCalculation) {
57 // Add values 1-100
58 for (int i = 1; i <= 100; ++i) {
59 timer.record(static_cast<double>(i));
60 }
61
62 // Median of 1-100 should be around 50.5
63 double median = timer.median();
64 EXPECT_NEAR(median, 50.5, 1.0);
65}
66
67TEST_F(TimerMetricsTest, PercentileCalculations) {
69 // Add values 1-1000
70 for (int i = 1; i <= 1000; ++i) {
71 timer.record(static_cast<double>(i));
72 }
73
74 // p50 should be around 500
75 EXPECT_NEAR(timer.median(), 500.5, 5.0);
76
77 // p90 should be around 900
78 EXPECT_NEAR(timer.p90(), 900.0, 10.0);
79
80 // p95 should be around 950
81 EXPECT_NEAR(timer.p95(), 950.0, 10.0);
82
83 // p99 should be around 990
84 EXPECT_NEAR(timer.p99(), 990.0, 10.0);
85}
86
87TEST_F(TimerMetricsTest, BoundaryPercentiles) {
89 timer.record(10.0);
90 timer.record(20.0);
91 timer.record(30.0);
92
93 // Percentile at 0 should return min
94 EXPECT_DOUBLE_EQ(timer.get_percentile(0), 10.0);
95
96 // Percentile at 100 should return max
97 EXPECT_DOUBLE_EQ(timer.get_percentile(100), 30.0);
98}
99
100TEST_F(TimerMetricsTest, StandardDeviation) {
102 // Add known values for predictable stddev
103 timer.record(2.0);
104 timer.record(4.0);
105 timer.record(4.0);
106 timer.record(4.0);
107 timer.record(5.0);
108 timer.record(5.0);
109 timer.record(7.0);
110 timer.record(9.0);
111
112 // Mean = 5.0, variance = 4.0, stddev = 2.0
113 EXPECT_NEAR(timer.mean(), 5.0, 0.01);
114 EXPECT_NEAR(timer.stddev(), 2.0, 0.01);
115}
116
119 timer.record(100.0);
120 timer.record(200.0);
121
122 EXPECT_EQ(timer.count(), 2);
123
124 timer.reset();
125
126 EXPECT_EQ(timer.count(), 0);
127 EXPECT_DOUBLE_EQ(timer.mean(), 0.0);
128 EXPECT_DOUBLE_EQ(timer.min(), 0.0);
129 EXPECT_DOUBLE_EQ(timer.max(), 0.0);
130}
131
134 for (int i = 1; i <= 100; ++i) {
135 timer.record(static_cast<double>(i));
136 }
137
138 auto snap = timer.get_snapshot();
139
140 EXPECT_EQ(snap.count, 100);
141 EXPECT_DOUBLE_EQ(snap.mean, 50.5);
142 EXPECT_DOUBLE_EQ(snap.min, 1.0);
143 EXPECT_DOUBLE_EQ(snap.max, 100.0);
144 EXPECT_NEAR(snap.p50, 50.5, 1.0);
145 EXPECT_NEAR(snap.p99, 99.0, 1.0);
146}
147
148TEST_F(TimerMetricsTest, CustomReservoirSize) {
149 timer_data timer(100); // Small reservoir
150
151 // Add more samples than reservoir size
152 for (int i = 0; i < 1000; ++i) {
153 timer.record(static_cast<double>(i));
154 }
155
156 EXPECT_EQ(timer.count(), 1000);
157 EXPECT_LE(timer.samples.size(), 100); // Should not exceed reservoir size
158}
159
160TEST_F(TimerMetricsTest, ChronoDurationRecording) {
162
163 auto duration = std::chrono::milliseconds(150);
164 timer.record(duration);
165
166 EXPECT_EQ(timer.count(), 1);
167 EXPECT_NEAR(timer.mean(), 150.0, 0.01);
168}
169
170TEST_F(TimerMetricsTest, TimerScopeRecording) {
172
173 {
174 timer_scope scope(timer);
175 std::this_thread::sleep_for(std::chrono::milliseconds(10));
176 }
177
178 EXPECT_EQ(timer.count(), 1);
179 EXPECT_GE(timer.mean(), 10.0); // At least 10ms
180}
181
182TEST_F(TimerMetricsTest, P999Percentile) {
184 // Add 1000 samples
185 for (int i = 1; i <= 1000; ++i) {
186 timer.record(static_cast<double>(i));
187 }
188
189 // p999 should be close to 999
190 EXPECT_NEAR(timer.p999(), 999.0, 2.0);
191}
192
193// Test histogram_data improvements
194class HistogramMetricsTest : public ::testing::Test {
195protected:
196 void SetUp() override {}
197 void TearDown() override {}
198};
199
200TEST_F(HistogramMetricsTest, StandardBuckets) {
201 histogram_data hist;
203
204 EXPECT_EQ(hist.buckets.size(), 15);
205 EXPECT_DOUBLE_EQ(hist.buckets[0].upper_bound, 0.005);
206}
207
209 histogram_data hist;
211
212 hist.add_sample(0.1);
213 hist.add_sample(0.5);
214 hist.add_sample(1.0);
215
216 EXPECT_EQ(hist.total_count, 3);
217 EXPECT_DOUBLE_EQ(hist.sum, 1.6);
218 EXPECT_NEAR(hist.mean(), 0.533, 0.01);
219}
220
221// Test summary_data improvements
222class SummaryMetricsTest : public ::testing::Test {
223protected:
224 void SetUp() override {}
225 void TearDown() override {}
226};
227
228TEST_F(SummaryMetricsTest, BasicStatistics) {
230
231 summary.add_sample(10.0);
232 summary.add_sample(20.0);
233 summary.add_sample(30.0);
234
235 EXPECT_EQ(summary.count, 3);
236 EXPECT_DOUBLE_EQ(summary.sum, 60.0);
237 EXPECT_DOUBLE_EQ(summary.mean(), 20.0);
238 EXPECT_DOUBLE_EQ(summary.min_value, 10.0);
239 EXPECT_DOUBLE_EQ(summary.max_value, 30.0);
240}
241
244 summary.add_sample(100.0);
245
246 summary.reset();
247
248 EXPECT_EQ(summary.count, 0);
249 EXPECT_DOUBLE_EQ(summary.sum, 0.0);
250 EXPECT_DOUBLE_EQ(summary.mean(), 0.0);
251}
Test suite for timer_data with percentile calculations.
void SetUp() override
void TearDown() override
RAII timer scope for automatic duration recording with timer_data.
Common metric type definitions for efficient storage.
@ timer
StatsD-specific timer metric.
@ summary
Pre-calculated quantiles and count/sum.
Histogram data with buckets.
double mean() const noexcept
Get mean value.
void init_standard_buckets()
Initialize standard buckets.
std::vector< histogram_bucket > buckets
void add_sample(double value)
Add value to histogram.
Summary statistics for metrics.
void add_sample(double value)
Add sample to summary.
Timer data with percentile calculations.
double median() const
Get median (p50)
void record(double duration_ms)
Record a duration sample (in milliseconds)
TEST_F(TimerMetricsTest, EmptyTimerReturnsZero)