Line data Source code
1 : /*
2 : * If not stated otherwise in this file or this component's LICENSE file the
3 : * following copyright and licenses apply:
4 : *
5 : * Copyright 2026 Sky UK
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : #ifndef FIREBOLT_RIALTO_SERVER_METRICS_ACCUMULATOR_H_
21 : #define FIREBOLT_RIALTO_SERVER_METRICS_ACCUMULATOR_H_
22 :
23 : #include <cmath>
24 : #include <cstdint>
25 : #include <limits>
26 :
27 : namespace firebolt::rialto::server
28 : {
29 : struct MetricsStatistics
30 : {
31 : double min{0.0};
32 : double max{0.0};
33 : double mean{0.0};
34 : double stddev{0.0};
35 : std::uint64_t count{0};
36 : };
37 :
38 : /**
39 : * @brief Numerically stable running statistics using Welford's online algorithm.
40 : * Computes min, max, mean, and standard deviation in O(1) memory.
41 : */
42 : class MetricsAccumulator
43 : {
44 : public:
45 42 : MetricsAccumulator() = default;
46 : ~MetricsAccumulator() = default;
47 :
48 38 : void addSample(double value)
49 : {
50 38 : ++m_count;
51 38 : if (value < m_min)
52 : {
53 29 : m_min = value;
54 : }
55 38 : if (value > m_max)
56 : {
57 38 : m_max = value;
58 : }
59 :
60 : // Welford's online algorithm
61 38 : const double kDelta{value - m_mean};
62 38 : m_mean += kDelta / static_cast<double>(m_count);
63 38 : const double kDelta2{value - m_mean};
64 38 : m_m2 += kDelta * kDelta2;
65 : }
66 :
67 64 : void reset()
68 : {
69 64 : m_count = 0;
70 64 : m_min = std::numeric_limits<double>::max();
71 64 : m_max = std::numeric_limits<double>::lowest();
72 64 : m_mean = 0.0;
73 64 : m_m2 = 0.0;
74 : }
75 :
76 37 : MetricsStatistics getStats() const
77 : {
78 37 : MetricsStatistics stats;
79 37 : stats.count = m_count;
80 37 : if (m_count == 0)
81 : {
82 8 : return stats;
83 : }
84 29 : stats.min = m_min;
85 29 : stats.max = m_max;
86 29 : stats.mean = m_mean;
87 29 : stats.stddev = (m_count > 1) ? std::sqrt(m_m2 / static_cast<double>(m_count - 1)) : 0.0;
88 29 : return stats;
89 : }
90 :
91 8 : std::uint64_t getCount() const { return m_count; }
92 :
93 : private:
94 : std::uint64_t m_count{0};
95 : double m_min{std::numeric_limits<double>::max()};
96 : double m_max{std::numeric_limits<double>::lowest()};
97 : double m_mean{0.0};
98 : double m_m2{0.0};
99 : };
100 : } // namespace firebolt::rialto::server
101 :
102 : #endif // FIREBOLT_RIALTO_SERVER_METRICS_ACCUMULATOR_H_
|