xref: /openbmc/telemetry/src/report_factory.cpp (revision 62c08e9b)
12f9f9b87SWludzik, Jozef #include "report_factory.hpp"
22f9f9b87SWludzik, Jozef 
36ccfcbf5SKrzysztof Grobelny #include "metric.hpp"
42f9f9b87SWludzik, Jozef #include "report.hpp"
5e2362796SWludzik, Jozef #include "sensor.hpp"
68069771cSKrzysztof Grobelny #include "utils/clock.hpp"
7e8fc5751SKrzysztof Grobelny #include "utils/conversion.hpp"
81477fe6aSWludzik, Jozef #include "utils/dbus_mapper.hpp"
9e2362796SWludzik, Jozef #include "utils/transform.hpp"
102f9f9b87SWludzik, Jozef 
112f9f9b87SWludzik, Jozef ReportFactory::ReportFactory(
12e2362796SWludzik, Jozef     std::shared_ptr<sdbusplus::asio::connection> bus,
131477fe6aSWludzik, Jozef     const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
141477fe6aSWludzik, Jozef     SensorCache& sensorCache) :
15e2362796SWludzik, Jozef     bus(std::move(bus)),
161477fe6aSWludzik, Jozef     objServer(objServer), sensorCache(sensorCache)
172f9f9b87SWludzik, Jozef {}
182f9f9b87SWludzik, Jozef 
192f9f9b87SWludzik, Jozef std::unique_ptr<interfaces::Report> ReportFactory::make(
20b8cc78ddSKrzysztof Grobelny     const std::string& id, const std::string& name,
21b8cc78ddSKrzysztof Grobelny     const ReportingType reportingType,
2251497a0cSKrzysztof Grobelny     const std::vector<ReportAction>& reportActions, Milliseconds period,
2351497a0cSKrzysztof Grobelny     uint64_t appendLimit, const ReportUpdates reportUpdates,
243eb56865SSzymon Dompke     interfaces::ReportManager& reportManager,
25d2238194SKrzysztof Grobelny     interfaces::JsonStorage& reportStorage,
26493e62ebSKrzysztof Grobelny     std::vector<LabeledMetricParameters> labeledMetricParams, bool enabled,
27493e62ebSKrzysztof Grobelny     Readings readings) const
282f9f9b87SWludzik, Jozef {
29f7ea2997SKrzysztof Grobelny     auto metrics = utils::transform(
30d2238194SKrzysztof Grobelny         labeledMetricParams,
31d2238194SKrzysztof Grobelny         [this](const LabeledMetricParameters& param)
32d2238194SKrzysztof Grobelny             -> std::shared_ptr<interfaces::Metric> {
33dcc4e193SKrzysztof Grobelny             namespace ts = utils::tstring;
34dcc4e193SKrzysztof Grobelny 
35d2238194SKrzysztof Grobelny             return std::make_shared<Metric>(
36dcc4e193SKrzysztof Grobelny                 getSensors(param.at_label<ts::SensorPath>()),
37dcc4e193SKrzysztof Grobelny                 param.at_label<ts::OperationType>(), param.at_label<ts::Id>(),
38dcc4e193SKrzysztof Grobelny                 param.at_label<ts::CollectionTimeScope>(),
398069771cSKrzysztof Grobelny                 param.at_label<ts::CollectionDuration>(),
408069771cSKrzysztof Grobelny                 std::make_unique<Clock>());
41d2238194SKrzysztof Grobelny         });
42c8e3a64aSKrzysztof Grobelny 
43493e62ebSKrzysztof Grobelny     return std::make_unique<Report>(
44493e62ebSKrzysztof Grobelny         bus->get_io_context(), objServer, id, name, reportingType,
45493e62ebSKrzysztof Grobelny         reportActions, period, appendLimit, reportUpdates, reportManager,
46493e62ebSKrzysztof Grobelny         reportStorage, std::move(metrics), *this, enabled,
47493e62ebSKrzysztof Grobelny         std::make_unique<Clock>(), std::move(readings));
48fdb06a14SSzymon Dompke }
49fdb06a14SSzymon Dompke 
50fdb06a14SSzymon Dompke void ReportFactory::updateMetrics(
51fdb06a14SSzymon Dompke     std::vector<std::shared_ptr<interfaces::Metric>>& metrics, bool enabled,
5232305f14SSzymon Dompke     const std::vector<LabeledMetricParameters>& labeledMetricParams) const
53fdb06a14SSzymon Dompke {
54fdb06a14SSzymon Dompke     std::vector<std::shared_ptr<interfaces::Metric>> oldMetrics = metrics;
55fdb06a14SSzymon Dompke     std::vector<std::shared_ptr<interfaces::Metric>> newMetrics;
56fdb06a14SSzymon Dompke 
57fdb06a14SSzymon Dompke     for (const auto& labeledMetricParam : labeledMetricParams)
58fdb06a14SSzymon Dompke     {
59fdb06a14SSzymon Dompke         auto existing = std::find_if(oldMetrics.begin(), oldMetrics.end(),
60fdb06a14SSzymon Dompke                                      [labeledMetricParam](auto metric) {
61fdb06a14SSzymon Dompke                                          return labeledMetricParam ==
62fdb06a14SSzymon Dompke                                                 metric->dumpConfiguration();
63fdb06a14SSzymon Dompke                                      });
64fdb06a14SSzymon Dompke 
65fdb06a14SSzymon Dompke         if (existing != oldMetrics.end())
66fdb06a14SSzymon Dompke         {
67fdb06a14SSzymon Dompke             newMetrics.emplace_back(*existing);
68fdb06a14SSzymon Dompke             oldMetrics.erase(existing);
69fdb06a14SSzymon Dompke             continue;
70fdb06a14SSzymon Dompke         }
71fdb06a14SSzymon Dompke 
72fdb06a14SSzymon Dompke         namespace ts = utils::tstring;
73fdb06a14SSzymon Dompke         newMetrics.emplace_back(std::make_shared<Metric>(
74fdb06a14SSzymon Dompke             getSensors(labeledMetricParam.at_label<ts::SensorPath>()),
75fdb06a14SSzymon Dompke             labeledMetricParam.at_label<ts::OperationType>(),
76fdb06a14SSzymon Dompke             labeledMetricParam.at_label<ts::Id>(),
77fdb06a14SSzymon Dompke             labeledMetricParam.at_label<ts::CollectionTimeScope>(),
78fdb06a14SSzymon Dompke             labeledMetricParam.at_label<ts::CollectionDuration>(),
79fdb06a14SSzymon Dompke             std::make_unique<Clock>()));
80fdb06a14SSzymon Dompke 
81fdb06a14SSzymon Dompke         if (enabled)
82fdb06a14SSzymon Dompke         {
83fdb06a14SSzymon Dompke             newMetrics.back()->initialize();
84fdb06a14SSzymon Dompke         }
85fdb06a14SSzymon Dompke     }
86fdb06a14SSzymon Dompke 
87fdb06a14SSzymon Dompke     if (enabled)
88fdb06a14SSzymon Dompke     {
89fdb06a14SSzymon Dompke         for (auto& metric : oldMetrics)
90fdb06a14SSzymon Dompke         {
91fdb06a14SSzymon Dompke             metric->deinitialize();
92fdb06a14SSzymon Dompke         }
93fdb06a14SSzymon Dompke     }
94fdb06a14SSzymon Dompke 
95fdb06a14SSzymon Dompke     metrics = std::move(newMetrics);
962f9f9b87SWludzik, Jozef }
976ccfcbf5SKrzysztof Grobelny 
98dcc4e193SKrzysztof Grobelny Sensors ReportFactory::getSensors(
9994f71c51SSzymon Dompke     const std::vector<LabeledSensorInfo>& sensorPaths) const
1006ccfcbf5SKrzysztof Grobelny {
101d2238194SKrzysztof Grobelny     using namespace utils::tstring;
102d2238194SKrzysztof Grobelny 
103b8cc78ddSKrzysztof Grobelny     return utils::transform(
104b8cc78ddSKrzysztof Grobelny         sensorPaths,
10594f71c51SSzymon Dompke         [this](const LabeledSensorInfo& sensorPath)
106dcc4e193SKrzysztof Grobelny             -> std::shared_ptr<interfaces::Sensor> {
107dcc4e193SKrzysztof Grobelny             return sensorCache.makeSensor<Sensor>(
108b8cc78ddSKrzysztof Grobelny                 sensorPath.at_label<Service>(), sensorPath.at_label<Path>(),
109b8cc78ddSKrzysztof Grobelny                 sensorPath.at_label<Metadata>(), bus->get_io_context(), bus);
110dcc4e193SKrzysztof Grobelny         });
1116ccfcbf5SKrzysztof Grobelny }
1126ccfcbf5SKrzysztof Grobelny 
113d2238194SKrzysztof Grobelny std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
114d2238194SKrzysztof Grobelny     boost::asio::yield_context& yield,
115d2238194SKrzysztof Grobelny     const ReadingParameters& metricParams) const
1166ccfcbf5SKrzysztof Grobelny {
117fdb06a14SSzymon Dompke     if (metricParams.empty())
118fdb06a14SSzymon Dompke     {
119fdb06a14SSzymon Dompke         return {};
120fdb06a14SSzymon Dompke     }
121*62c08e9bSKrzysztof Grobelny 
1221477fe6aSWludzik, Jozef     auto tree = utils::getSubTreeSensors(yield, bus);
123fdb06a14SSzymon Dompke     return getMetricParamsFromSensorTree(metricParams, tree);
124fdb06a14SSzymon Dompke }
125d2238194SKrzysztof Grobelny 
126fdb06a14SSzymon Dompke std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
127fdb06a14SSzymon Dompke     const ReadingParameters& metricParams) const
128fdb06a14SSzymon Dompke {
129fdb06a14SSzymon Dompke     if (metricParams.empty())
130fdb06a14SSzymon Dompke     {
131fdb06a14SSzymon Dompke         return {};
132fdb06a14SSzymon Dompke     }
133*62c08e9bSKrzysztof Grobelny 
134fdb06a14SSzymon Dompke     auto tree = utils::getSubTreeSensors(bus);
135fdb06a14SSzymon Dompke     return getMetricParamsFromSensorTree(metricParams, tree);
136fdb06a14SSzymon Dompke }
137fdb06a14SSzymon Dompke 
138fdb06a14SSzymon Dompke std::vector<LabeledMetricParameters>
139fdb06a14SSzymon Dompke     ReportFactory::getMetricParamsFromSensorTree(
140fdb06a14SSzymon Dompke         const ReadingParameters& metricParams,
141fdb06a14SSzymon Dompke         const std::vector<utils::SensorTree>& tree) const
142fdb06a14SSzymon Dompke {
143*62c08e9bSKrzysztof Grobelny     try
144*62c08e9bSKrzysztof Grobelny     {
145d2238194SKrzysztof Grobelny         return utils::transform(metricParams, [&tree](const auto& item) {
146b8cc78ddSKrzysztof Grobelny             auto [sensorPaths, operationType, id, collectionTimeScope,
147b8cc78ddSKrzysztof Grobelny                   collectionDuration] = item;
148d2238194SKrzysztof Grobelny 
14994f71c51SSzymon Dompke             std::vector<LabeledSensorInfo> sensorParameters;
150dcc4e193SKrzysztof Grobelny 
151b8cc78ddSKrzysztof Grobelny             for (const auto& [sensorPath, metadata] : sensorPaths)
152dcc4e193SKrzysztof Grobelny             {
153*62c08e9bSKrzysztof Grobelny                 auto it = std::find_if(tree.begin(), tree.end(),
154*62c08e9bSKrzysztof Grobelny                                        [path = sensorPath](const auto& v) {
155*62c08e9bSKrzysztof Grobelny                                            return v.first == path;
156*62c08e9bSKrzysztof Grobelny                                        });
157d2238194SKrzysztof Grobelny 
158e8fc5751SKrzysztof Grobelny                 if (it != tree.end() && it->second.size() == 1)
159d2238194SKrzysztof Grobelny                 {
160e8fc5751SKrzysztof Grobelny                     const auto& [service, ifaces] = it->second.front();
161*62c08e9bSKrzysztof Grobelny                     sensorParameters.emplace_back(service, sensorPath,
162*62c08e9bSKrzysztof Grobelny                                                   metadata);
163dcc4e193SKrzysztof Grobelny                 }
164d2238194SKrzysztof Grobelny             }
165d2238194SKrzysztof Grobelny 
166dcc4e193SKrzysztof Grobelny             if (sensorParameters.size() != sensorPaths.size())
167dcc4e193SKrzysztof Grobelny             {
168*62c08e9bSKrzysztof Grobelny                 throw errors::InvalidArgument("ReadingParameters",
169*62c08e9bSKrzysztof Grobelny                                               "Service not found.");
170dcc4e193SKrzysztof Grobelny             }
171dcc4e193SKrzysztof Grobelny 
172b8cc78ddSKrzysztof Grobelny             if (operationType.empty())
173b8cc78ddSKrzysztof Grobelny             {
174b8cc78ddSKrzysztof Grobelny                 operationType = utils::enumToString(OperationType::avg);
175b8cc78ddSKrzysztof Grobelny             }
17660fee077SKrzysztof Grobelny             else if (operationType == "SINGLE")
17760fee077SKrzysztof Grobelny             {
17860fee077SKrzysztof Grobelny                 operationType = utils::enumToString(OperationType::avg);
17960fee077SKrzysztof Grobelny                 collectionTimeScope =
18060fee077SKrzysztof Grobelny                     utils::enumToString(CollectionTimeScope::point);
18160fee077SKrzysztof Grobelny             }
182b8cc78ddSKrzysztof Grobelny 
183b8cc78ddSKrzysztof Grobelny             if (collectionTimeScope.empty())
184b8cc78ddSKrzysztof Grobelny             {
185b8cc78ddSKrzysztof Grobelny                 collectionTimeScope =
186b8cc78ddSKrzysztof Grobelny                     utils::enumToString(CollectionTimeScope::point);
187b8cc78ddSKrzysztof Grobelny             }
188b8cc78ddSKrzysztof Grobelny 
189dcc4e193SKrzysztof Grobelny             return LabeledMetricParameters(
190*62c08e9bSKrzysztof Grobelny                 std::move(sensorParameters),
191*62c08e9bSKrzysztof Grobelny                 utils::toOperationType(operationType), id,
192*62c08e9bSKrzysztof Grobelny                 utils::toCollectionTimeScope(collectionTimeScope),
193dcc4e193SKrzysztof Grobelny                 CollectionDuration(Milliseconds(collectionDuration)));
194d2238194SKrzysztof Grobelny         });
1956ccfcbf5SKrzysztof Grobelny     }
196*62c08e9bSKrzysztof Grobelny     catch (const errors::InvalidArgument& e)
197*62c08e9bSKrzysztof Grobelny     {
198*62c08e9bSKrzysztof Grobelny         if (e.propertyName == "ReadingParameters")
199*62c08e9bSKrzysztof Grobelny         {
200*62c08e9bSKrzysztof Grobelny             throw;
201*62c08e9bSKrzysztof Grobelny         }
202*62c08e9bSKrzysztof Grobelny 
203*62c08e9bSKrzysztof Grobelny         using namespace std::literals::string_literals;
204*62c08e9bSKrzysztof Grobelny         throw errors::InvalidArgument("ReadingParameters."s + e.propertyName);
205*62c08e9bSKrzysztof Grobelny     }
206*62c08e9bSKrzysztof Grobelny }
207