xref: /openbmc/telemetry/src/report_factory.cpp (revision f535cad6)
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 
ReportFactory(std::shared_ptr<sdbusplus::asio::connection> bus,const std::shared_ptr<sdbusplus::asio::object_server> & objServer,SensorCache & sensorCache)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) :
15*f535cad6SPatrick Williams     bus(std::move(bus)), objServer(objServer), sensorCache(sensorCache)
162f9f9b87SWludzik, Jozef {}
172f9f9b87SWludzik, Jozef 
make(const std::string & id,const std::string & name,const ReportingType reportingType,const std::vector<ReportAction> & reportActions,Milliseconds period,uint64_t appendLimit,const ReportUpdates reportUpdates,interfaces::ReportManager & reportManager,interfaces::JsonStorage & reportStorage,std::vector<LabeledMetricParameters> labeledMetricParams,bool enabled,Readings readings) const182f9f9b87SWludzik, Jozef std::unique_ptr<interfaces::Report> ReportFactory::make(
19b8cc78ddSKrzysztof Grobelny     const std::string& id, const std::string& name,
20b8cc78ddSKrzysztof Grobelny     const ReportingType reportingType,
2151497a0cSKrzysztof Grobelny     const std::vector<ReportAction>& reportActions, Milliseconds period,
2251497a0cSKrzysztof Grobelny     uint64_t appendLimit, const ReportUpdates reportUpdates,
233eb56865SSzymon Dompke     interfaces::ReportManager& reportManager,
24d2238194SKrzysztof Grobelny     interfaces::JsonStorage& reportStorage,
25493e62ebSKrzysztof Grobelny     std::vector<LabeledMetricParameters> labeledMetricParams, bool enabled,
26493e62ebSKrzysztof Grobelny     Readings readings) const
272f9f9b87SWludzik, Jozef {
28c7935fa1SPatrick Williams     auto metrics = utils::transform(labeledMetricParams,
29d2238194SKrzysztof Grobelny                                     [this](const LabeledMetricParameters& param)
30d2238194SKrzysztof Grobelny                                         -> std::shared_ptr<interfaces::Metric> {
31dcc4e193SKrzysztof Grobelny         namespace ts = utils::tstring;
32dcc4e193SKrzysztof Grobelny 
33d2238194SKrzysztof Grobelny         return std::make_shared<Metric>(
34dcc4e193SKrzysztof Grobelny             getSensors(param.at_label<ts::SensorPath>()),
35cff70c14SKrzysztof Grobelny             param.at_label<ts::OperationType>(),
36dcc4e193SKrzysztof Grobelny             param.at_label<ts::CollectionTimeScope>(),
378069771cSKrzysztof Grobelny             param.at_label<ts::CollectionDuration>(),
388069771cSKrzysztof Grobelny             std::make_unique<Clock>());
39d2238194SKrzysztof Grobelny     });
40c8e3a64aSKrzysztof Grobelny 
41493e62ebSKrzysztof Grobelny     return std::make_unique<Report>(
42493e62ebSKrzysztof Grobelny         bus->get_io_context(), objServer, id, name, reportingType,
43493e62ebSKrzysztof Grobelny         reportActions, period, appendLimit, reportUpdates, reportManager,
44493e62ebSKrzysztof Grobelny         reportStorage, std::move(metrics), *this, enabled,
45493e62ebSKrzysztof Grobelny         std::make_unique<Clock>(), std::move(readings));
46fdb06a14SSzymon Dompke }
47fdb06a14SSzymon Dompke 
updateMetrics(std::vector<std::shared_ptr<interfaces::Metric>> & metrics,bool enabled,const std::vector<LabeledMetricParameters> & labeledMetricParams) const48fdb06a14SSzymon Dompke void ReportFactory::updateMetrics(
49fdb06a14SSzymon Dompke     std::vector<std::shared_ptr<interfaces::Metric>>& metrics, bool enabled,
5032305f14SSzymon Dompke     const std::vector<LabeledMetricParameters>& labeledMetricParams) const
51fdb06a14SSzymon Dompke {
52fdb06a14SSzymon Dompke     std::vector<std::shared_ptr<interfaces::Metric>> oldMetrics = metrics;
53fdb06a14SSzymon Dompke     std::vector<std::shared_ptr<interfaces::Metric>> newMetrics;
54fdb06a14SSzymon Dompke 
55fdb06a14SSzymon Dompke     for (const auto& labeledMetricParam : labeledMetricParams)
56fdb06a14SSzymon Dompke     {
57fdb06a14SSzymon Dompke         auto existing = std::find_if(oldMetrics.begin(), oldMetrics.end(),
58fdb06a14SSzymon Dompke                                      [labeledMetricParam](auto metric) {
593a1c297aSPatrick Williams             return labeledMetricParam == metric->dumpConfiguration();
60fdb06a14SSzymon Dompke         });
61fdb06a14SSzymon Dompke 
62fdb06a14SSzymon Dompke         if (existing != oldMetrics.end())
63fdb06a14SSzymon Dompke         {
64fdb06a14SSzymon Dompke             newMetrics.emplace_back(*existing);
65fdb06a14SSzymon Dompke             oldMetrics.erase(existing);
66fdb06a14SSzymon Dompke             continue;
67fdb06a14SSzymon Dompke         }
68fdb06a14SSzymon Dompke 
69fdb06a14SSzymon Dompke         namespace ts = utils::tstring;
70fdb06a14SSzymon Dompke         newMetrics.emplace_back(std::make_shared<Metric>(
71fdb06a14SSzymon Dompke             getSensors(labeledMetricParam.at_label<ts::SensorPath>()),
72fdb06a14SSzymon Dompke             labeledMetricParam.at_label<ts::OperationType>(),
73fdb06a14SSzymon Dompke             labeledMetricParam.at_label<ts::CollectionTimeScope>(),
74fdb06a14SSzymon Dompke             labeledMetricParam.at_label<ts::CollectionDuration>(),
75fdb06a14SSzymon Dompke             std::make_unique<Clock>()));
76fdb06a14SSzymon Dompke 
77fdb06a14SSzymon Dompke         if (enabled)
78fdb06a14SSzymon Dompke         {
79fdb06a14SSzymon Dompke             newMetrics.back()->initialize();
80fdb06a14SSzymon Dompke         }
81fdb06a14SSzymon Dompke     }
82fdb06a14SSzymon Dompke 
83fdb06a14SSzymon Dompke     if (enabled)
84fdb06a14SSzymon Dompke     {
85fdb06a14SSzymon Dompke         for (auto& metric : oldMetrics)
86fdb06a14SSzymon Dompke         {
87fdb06a14SSzymon Dompke             metric->deinitialize();
88fdb06a14SSzymon Dompke         }
89fdb06a14SSzymon Dompke     }
90fdb06a14SSzymon Dompke 
91fdb06a14SSzymon Dompke     metrics = std::move(newMetrics);
922f9f9b87SWludzik, Jozef }
936ccfcbf5SKrzysztof Grobelny 
getSensors(const std::vector<LabeledSensorInfo> & sensorPaths) const94dcc4e193SKrzysztof Grobelny Sensors ReportFactory::getSensors(
9594f71c51SSzymon Dompke     const std::vector<LabeledSensorInfo>& sensorPaths) const
966ccfcbf5SKrzysztof Grobelny {
97d2238194SKrzysztof Grobelny     using namespace utils::tstring;
98d2238194SKrzysztof Grobelny 
99c7935fa1SPatrick Williams     return utils::transform(sensorPaths,
10094f71c51SSzymon Dompke                             [this](const LabeledSensorInfo& sensorPath)
101dcc4e193SKrzysztof Grobelny                                 -> std::shared_ptr<interfaces::Sensor> {
102dcc4e193SKrzysztof Grobelny         return sensorCache.makeSensor<Sensor>(
103b8cc78ddSKrzysztof Grobelny             sensorPath.at_label<Service>(), sensorPath.at_label<Path>(),
104b8cc78ddSKrzysztof Grobelny             sensorPath.at_label<Metadata>(), bus->get_io_context(), bus);
105dcc4e193SKrzysztof Grobelny     });
1066ccfcbf5SKrzysztof Grobelny }
1076ccfcbf5SKrzysztof Grobelny 
convertMetricParams(boost::asio::yield_context & yield,const ReadingParameters & metricParams) const108d2238194SKrzysztof Grobelny std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
109d2238194SKrzysztof Grobelny     boost::asio::yield_context& yield,
110d2238194SKrzysztof Grobelny     const ReadingParameters& metricParams) const
1116ccfcbf5SKrzysztof Grobelny {
112fdb06a14SSzymon Dompke     if (metricParams.empty())
113fdb06a14SSzymon Dompke     {
114fdb06a14SSzymon Dompke         return {};
115fdb06a14SSzymon Dompke     }
11662c08e9bSKrzysztof Grobelny 
1171477fe6aSWludzik, Jozef     auto tree = utils::getSubTreeSensors(yield, bus);
118fdb06a14SSzymon Dompke     return getMetricParamsFromSensorTree(metricParams, tree);
119fdb06a14SSzymon Dompke }
120d2238194SKrzysztof Grobelny 
convertMetricParams(const ReadingParameters & metricParams) const121fdb06a14SSzymon Dompke std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
122fdb06a14SSzymon Dompke     const ReadingParameters& metricParams) const
123fdb06a14SSzymon Dompke {
124fdb06a14SSzymon Dompke     if (metricParams.empty())
125fdb06a14SSzymon Dompke     {
126fdb06a14SSzymon Dompke         return {};
127fdb06a14SSzymon Dompke     }
12862c08e9bSKrzysztof Grobelny 
129fdb06a14SSzymon Dompke     auto tree = utils::getSubTreeSensors(bus);
130fdb06a14SSzymon Dompke     return getMetricParamsFromSensorTree(metricParams, tree);
131fdb06a14SSzymon Dompke }
132fdb06a14SSzymon Dompke 
133fdb06a14SSzymon Dompke std::vector<LabeledMetricParameters>
getMetricParamsFromSensorTree(const ReadingParameters & metricParams,const std::vector<utils::SensorTree> & tree) const134fdb06a14SSzymon Dompke     ReportFactory::getMetricParamsFromSensorTree(
135fdb06a14SSzymon Dompke         const ReadingParameters& metricParams,
136fdb06a14SSzymon Dompke         const std::vector<utils::SensorTree>& tree) const
137fdb06a14SSzymon Dompke {
13862c08e9bSKrzysztof Grobelny     try
13962c08e9bSKrzysztof Grobelny     {
140d2238194SKrzysztof Grobelny         return utils::transform(metricParams, [&tree](const auto& item) {
141cff70c14SKrzysztof Grobelny             auto [sensorPaths, operationType, collectionTimeScope,
142b8cc78ddSKrzysztof Grobelny                   collectionDuration] = item;
143d2238194SKrzysztof Grobelny 
14494f71c51SSzymon Dompke             std::vector<LabeledSensorInfo> sensorParameters;
145dcc4e193SKrzysztof Grobelny 
146b8cc78ddSKrzysztof Grobelny             for (const auto& [sensorPath, metadata] : sensorPaths)
147dcc4e193SKrzysztof Grobelny             {
14862c08e9bSKrzysztof Grobelny                 auto it = std::find_if(tree.begin(), tree.end(),
14962c08e9bSKrzysztof Grobelny                                        [path = sensorPath](const auto& v) {
15062c08e9bSKrzysztof Grobelny                     return v.first == path;
15162c08e9bSKrzysztof Grobelny                 });
152d2238194SKrzysztof Grobelny 
153e8fc5751SKrzysztof Grobelny                 if (it != tree.end() && it->second.size() == 1)
154d2238194SKrzysztof Grobelny                 {
155e8fc5751SKrzysztof Grobelny                     const auto& [service, ifaces] = it->second.front();
15662c08e9bSKrzysztof Grobelny                     sensorParameters.emplace_back(service, sensorPath,
15762c08e9bSKrzysztof Grobelny                                                   metadata);
158dcc4e193SKrzysztof Grobelny                 }
159d2238194SKrzysztof Grobelny             }
160d2238194SKrzysztof Grobelny 
161dcc4e193SKrzysztof Grobelny             if (sensorParameters.size() != sensorPaths.size())
162dcc4e193SKrzysztof Grobelny             {
16362c08e9bSKrzysztof Grobelny                 throw errors::InvalidArgument("ReadingParameters",
16462c08e9bSKrzysztof Grobelny                                               "Service not found.");
165dcc4e193SKrzysztof Grobelny             }
166dcc4e193SKrzysztof Grobelny 
167b8cc78ddSKrzysztof Grobelny             if (operationType.empty())
168b8cc78ddSKrzysztof Grobelny             {
169b8cc78ddSKrzysztof Grobelny                 operationType = utils::enumToString(OperationType::avg);
170b8cc78ddSKrzysztof Grobelny             }
17160fee077SKrzysztof Grobelny             else if (operationType == "SINGLE")
17260fee077SKrzysztof Grobelny             {
17360fee077SKrzysztof Grobelny                 operationType = utils::enumToString(OperationType::avg);
17460fee077SKrzysztof Grobelny                 collectionTimeScope =
17560fee077SKrzysztof Grobelny                     utils::enumToString(CollectionTimeScope::point);
17660fee077SKrzysztof Grobelny             }
177b8cc78ddSKrzysztof Grobelny 
178b8cc78ddSKrzysztof Grobelny             if (collectionTimeScope.empty())
179b8cc78ddSKrzysztof Grobelny             {
180b8cc78ddSKrzysztof Grobelny                 collectionTimeScope =
181b8cc78ddSKrzysztof Grobelny                     utils::enumToString(CollectionTimeScope::point);
182b8cc78ddSKrzysztof Grobelny             }
183b8cc78ddSKrzysztof Grobelny 
184dcc4e193SKrzysztof Grobelny             return LabeledMetricParameters(
18562c08e9bSKrzysztof Grobelny                 std::move(sensorParameters),
186cff70c14SKrzysztof Grobelny                 utils::toOperationType(operationType),
18762c08e9bSKrzysztof Grobelny                 utils::toCollectionTimeScope(collectionTimeScope),
188dcc4e193SKrzysztof Grobelny                 CollectionDuration(Milliseconds(collectionDuration)));
189d2238194SKrzysztof Grobelny         });
1906ccfcbf5SKrzysztof Grobelny     }
19162c08e9bSKrzysztof Grobelny     catch (const errors::InvalidArgument& e)
19262c08e9bSKrzysztof Grobelny     {
19362c08e9bSKrzysztof Grobelny         if (e.propertyName == "ReadingParameters")
19462c08e9bSKrzysztof Grobelny         {
19562c08e9bSKrzysztof Grobelny             throw;
19662c08e9bSKrzysztof Grobelny         }
19762c08e9bSKrzysztof Grobelny 
19862c08e9bSKrzysztof Grobelny         using namespace std::literals::string_literals;
19962c08e9bSKrzysztof Grobelny         throw errors::InvalidArgument("ReadingParameters."s + e.propertyName);
20062c08e9bSKrzysztof Grobelny     }
20162c08e9bSKrzysztof Grobelny }
202