xref: /openbmc/telemetry/src/metrics/collection_data.cpp (revision 583ba441654657bb4ba9d051b747144a7258c159)
1f7ea2997SKrzysztof Grobelny #include "metrics/collection_data.hpp"
2f7ea2997SKrzysztof Grobelny 
3f7ea2997SKrzysztof Grobelny #include "metrics/collection_function.hpp"
4f7ea2997SKrzysztof Grobelny 
5f7ea2997SKrzysztof Grobelny namespace metrics
6f7ea2997SKrzysztof Grobelny {
7f7ea2997SKrzysztof Grobelny 
updateLastValue(double value)8f7ea2997SKrzysztof Grobelny bool CollectionData::updateLastValue(double value)
9f7ea2997SKrzysztof Grobelny {
10f7ea2997SKrzysztof Grobelny     const bool changed = lastValue != value;
11f7ea2997SKrzysztof Grobelny     lastValue = value;
12f7ea2997SKrzysztof Grobelny     return changed;
13f7ea2997SKrzysztof Grobelny }
14f7ea2997SKrzysztof Grobelny 
15f7ea2997SKrzysztof Grobelny class DataPoint : public CollectionData
16f7ea2997SKrzysztof Grobelny {
17f7ea2997SKrzysztof Grobelny   public:
update(Milliseconds)18f7ea2997SKrzysztof Grobelny     std::optional<double> update(Milliseconds) override
19f7ea2997SKrzysztof Grobelny     {
20f7ea2997SKrzysztof Grobelny         return lastReading;
21f7ea2997SKrzysztof Grobelny     }
22f7ea2997SKrzysztof Grobelny 
update(Milliseconds,double reading)23f7ea2997SKrzysztof Grobelny     double update(Milliseconds, double reading) override
24f7ea2997SKrzysztof Grobelny     {
25f7ea2997SKrzysztof Grobelny         lastReading = reading;
26f7ea2997SKrzysztof Grobelny         return reading;
27f7ea2997SKrzysztof Grobelny     }
28f7ea2997SKrzysztof Grobelny 
29f7ea2997SKrzysztof Grobelny   private:
30f7ea2997SKrzysztof Grobelny     std::optional<double> lastReading;
31f7ea2997SKrzysztof Grobelny };
32f7ea2997SKrzysztof Grobelny 
33f7ea2997SKrzysztof Grobelny class DataInterval : public CollectionData
34f7ea2997SKrzysztof Grobelny {
35f7ea2997SKrzysztof Grobelny   public:
DataInterval(std::shared_ptr<CollectionFunction> function,CollectionDuration duration)36f7ea2997SKrzysztof Grobelny     DataInterval(std::shared_ptr<CollectionFunction> function,
37f7ea2997SKrzysztof Grobelny                  CollectionDuration duration) :
38f535cad6SPatrick Williams         function(std::move(function)), duration(duration)
39f7ea2997SKrzysztof Grobelny     {
40f7ea2997SKrzysztof Grobelny         if (duration.t.count() == 0)
41f7ea2997SKrzysztof Grobelny         {
4262c08e9bSKrzysztof Grobelny             throw errors::InvalidArgument(
4362c08e9bSKrzysztof Grobelny                 "ReadingParameters.CollectionDuration");
44f7ea2997SKrzysztof Grobelny         }
45f7ea2997SKrzysztof Grobelny     }
46f7ea2997SKrzysztof Grobelny 
update(Milliseconds timestamp)47f7ea2997SKrzysztof Grobelny     std::optional<double> update(Milliseconds timestamp) override
48f7ea2997SKrzysztof Grobelny     {
49f7ea2997SKrzysztof Grobelny         if (readings.empty())
50f7ea2997SKrzysztof Grobelny         {
51f7ea2997SKrzysztof Grobelny             return std::nullopt;
52f7ea2997SKrzysztof Grobelny         }
53f7ea2997SKrzysztof Grobelny 
54f7ea2997SKrzysztof Grobelny         cleanup(timestamp);
55f7ea2997SKrzysztof Grobelny 
56f7ea2997SKrzysztof Grobelny         return function->calculate(readings, timestamp);
57f7ea2997SKrzysztof Grobelny     }
58f7ea2997SKrzysztof Grobelny 
update(Milliseconds timestamp,double reading)59f7ea2997SKrzysztof Grobelny     double update(Milliseconds timestamp, double reading) override
60f7ea2997SKrzysztof Grobelny     {
61f7ea2997SKrzysztof Grobelny         readings.emplace_back(timestamp, reading);
62f7ea2997SKrzysztof Grobelny 
63f7ea2997SKrzysztof Grobelny         cleanup(timestamp);
64f7ea2997SKrzysztof Grobelny 
65f7ea2997SKrzysztof Grobelny         return function->calculate(readings, timestamp);
66f7ea2997SKrzysztof Grobelny     }
67f7ea2997SKrzysztof Grobelny 
68f7ea2997SKrzysztof Grobelny   private:
cleanup(Milliseconds timestamp)69f7ea2997SKrzysztof Grobelny     void cleanup(Milliseconds timestamp)
70f7ea2997SKrzysztof Grobelny     {
71f7ea2997SKrzysztof Grobelny         auto it = readings.begin();
72f7ea2997SKrzysztof Grobelny         for (auto kt = std::next(readings.rbegin()); kt != readings.rend();
73f7ea2997SKrzysztof Grobelny              ++kt)
74f7ea2997SKrzysztof Grobelny         {
75f7ea2997SKrzysztof Grobelny             const auto& [nextItemTimestamp, nextItemReading] = *std::prev(kt);
76f7ea2997SKrzysztof Grobelny             if (timestamp >= nextItemTimestamp &&
77f7ea2997SKrzysztof Grobelny                 timestamp - nextItemTimestamp > duration.t)
78f7ea2997SKrzysztof Grobelny             {
79f7ea2997SKrzysztof Grobelny                 it = kt.base();
80f7ea2997SKrzysztof Grobelny                 break;
81f7ea2997SKrzysztof Grobelny             }
82f7ea2997SKrzysztof Grobelny         }
83f7ea2997SKrzysztof Grobelny         readings.erase(readings.begin(), it);
84f7ea2997SKrzysztof Grobelny 
85f7ea2997SKrzysztof Grobelny         if (timestamp > duration.t)
86f7ea2997SKrzysztof Grobelny         {
87*583ba441SPatrick Williams             readings.front().first =
88*583ba441SPatrick Williams                 std::max(readings.front().first, timestamp - duration.t);
89f7ea2997SKrzysztof Grobelny         }
90f7ea2997SKrzysztof Grobelny     }
91f7ea2997SKrzysztof Grobelny 
92f7ea2997SKrzysztof Grobelny     std::shared_ptr<CollectionFunction> function;
93f7ea2997SKrzysztof Grobelny     std::vector<ReadingItem> readings;
94f7ea2997SKrzysztof Grobelny     CollectionDuration duration;
95f7ea2997SKrzysztof Grobelny };
96f7ea2997SKrzysztof Grobelny 
97f7ea2997SKrzysztof Grobelny class DataStartup : public CollectionData
98f7ea2997SKrzysztof Grobelny {
99f7ea2997SKrzysztof Grobelny   public:
DataStartup(std::shared_ptr<CollectionFunction> function)100f7ea2997SKrzysztof Grobelny     explicit DataStartup(std::shared_ptr<CollectionFunction> function) :
101f7ea2997SKrzysztof Grobelny         function(std::move(function))
102f7ea2997SKrzysztof Grobelny     {}
103f7ea2997SKrzysztof Grobelny 
update(Milliseconds timestamp)104f7ea2997SKrzysztof Grobelny     std::optional<double> update(Milliseconds timestamp) override
105f7ea2997SKrzysztof Grobelny     {
106f7ea2997SKrzysztof Grobelny         if (readings.empty())
107f7ea2997SKrzysztof Grobelny         {
108f7ea2997SKrzysztof Grobelny             return std::nullopt;
109f7ea2997SKrzysztof Grobelny         }
110f7ea2997SKrzysztof Grobelny 
111f7ea2997SKrzysztof Grobelny         return function->calculateForStartupInterval(readings, timestamp);
112f7ea2997SKrzysztof Grobelny     }
113f7ea2997SKrzysztof Grobelny 
update(Milliseconds timestamp,double reading)114f7ea2997SKrzysztof Grobelny     double update(Milliseconds timestamp, double reading) override
115f7ea2997SKrzysztof Grobelny     {
116f7ea2997SKrzysztof Grobelny         readings.emplace_back(timestamp, reading);
117f7ea2997SKrzysztof Grobelny         return function->calculateForStartupInterval(readings, timestamp);
118f7ea2997SKrzysztof Grobelny     }
119f7ea2997SKrzysztof Grobelny 
120f7ea2997SKrzysztof Grobelny   private:
121f7ea2997SKrzysztof Grobelny     std::shared_ptr<CollectionFunction> function;
122f7ea2997SKrzysztof Grobelny     std::vector<ReadingItem> readings;
123f7ea2997SKrzysztof Grobelny };
124f7ea2997SKrzysztof Grobelny 
makeCollectionData(size_t size,OperationType op,CollectionTimeScope timeScope,CollectionDuration duration)125*583ba441SPatrick Williams std::vector<std::unique_ptr<CollectionData>> makeCollectionData(
126*583ba441SPatrick Williams     size_t size, OperationType op, CollectionTimeScope timeScope,
127f7ea2997SKrzysztof Grobelny     CollectionDuration duration)
128f7ea2997SKrzysztof Grobelny {
129f7ea2997SKrzysztof Grobelny     using namespace std::string_literals;
130f7ea2997SKrzysztof Grobelny 
131f7ea2997SKrzysztof Grobelny     std::vector<std::unique_ptr<CollectionData>> result;
132f7ea2997SKrzysztof Grobelny 
133f7ea2997SKrzysztof Grobelny     result.reserve(size);
134f7ea2997SKrzysztof Grobelny 
135f7ea2997SKrzysztof Grobelny     switch (timeScope)
136f7ea2997SKrzysztof Grobelny     {
137f7ea2997SKrzysztof Grobelny         case CollectionTimeScope::interval:
138*583ba441SPatrick Williams             std::generate_n(
139*583ba441SPatrick Williams                 std::back_inserter(result), size,
140f7ea2997SKrzysztof Grobelny                 [cf = makeCollectionFunction(op), duration] {
1413a1c297aSPatrick Williams                     return std::make_unique<DataInterval>(cf, duration);
142f7ea2997SKrzysztof Grobelny                 });
143f7ea2997SKrzysztof Grobelny             break;
144f7ea2997SKrzysztof Grobelny         case CollectionTimeScope::point:
145f7ea2997SKrzysztof Grobelny             std::generate_n(std::back_inserter(result), size,
146f7ea2997SKrzysztof Grobelny                             [] { return std::make_unique<DataPoint>(); });
147f7ea2997SKrzysztof Grobelny             break;
148f7ea2997SKrzysztof Grobelny         case CollectionTimeScope::startup:
149f7ea2997SKrzysztof Grobelny             std::generate_n(std::back_inserter(result), size,
150f7ea2997SKrzysztof Grobelny                             [cf = makeCollectionFunction(op)] {
151f7ea2997SKrzysztof Grobelny                                 return std::make_unique<DataStartup>(cf);
152f7ea2997SKrzysztof Grobelny                             });
153f7ea2997SKrzysztof Grobelny             break;
154f7ea2997SKrzysztof Grobelny     }
155f7ea2997SKrzysztof Grobelny 
156f7ea2997SKrzysztof Grobelny     return result;
157f7ea2997SKrzysztof Grobelny }
158f7ea2997SKrzysztof Grobelny 
159f7ea2997SKrzysztof Grobelny } // namespace metrics
160