xref: /openbmc/telemetry/src/report_factory.cpp (revision 583ba441654657bb4ba9d051b747144a7258c159)
1 #include "report_factory.hpp"
2 
3 #include "metric.hpp"
4 #include "report.hpp"
5 #include "sensor.hpp"
6 #include "utils/clock.hpp"
7 #include "utils/conversion.hpp"
8 #include "utils/dbus_mapper.hpp"
9 #include "utils/transform.hpp"
10 
ReportFactory(std::shared_ptr<sdbusplus::asio::connection> bus,const std::shared_ptr<sdbusplus::asio::object_server> & objServer,SensorCache & sensorCache)11 ReportFactory::ReportFactory(
12     std::shared_ptr<sdbusplus::asio::connection> bus,
13     const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
14     SensorCache& sensorCache) :
15     bus(std::move(bus)), objServer(objServer), sensorCache(sensorCache)
16 {}
17 
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) const18 std::unique_ptr<interfaces::Report> ReportFactory::make(
19     const std::string& id, const std::string& name,
20     const ReportingType reportingType,
21     const std::vector<ReportAction>& reportActions, Milliseconds period,
22     uint64_t appendLimit, const ReportUpdates reportUpdates,
23     interfaces::ReportManager& reportManager,
24     interfaces::JsonStorage& reportStorage,
25     std::vector<LabeledMetricParameters> labeledMetricParams, bool enabled,
26     Readings readings) const
27 {
28     auto metrics = utils::transform(
29         labeledMetricParams,
30         [this](const LabeledMetricParameters& param)
31             -> std::shared_ptr<interfaces::Metric> {
32             namespace ts = utils::tstring;
33 
34             return std::make_shared<Metric>(
35                 getSensors(param.at_label<ts::SensorPath>()),
36                 param.at_label<ts::OperationType>(),
37                 param.at_label<ts::CollectionTimeScope>(),
38                 param.at_label<ts::CollectionDuration>(),
39                 std::make_unique<Clock>());
40         });
41 
42     return std::make_unique<Report>(
43         bus->get_io_context(), objServer, id, name, reportingType,
44         reportActions, period, appendLimit, reportUpdates, reportManager,
45         reportStorage, std::move(metrics), *this, enabled,
46         std::make_unique<Clock>(), std::move(readings));
47 }
48 
updateMetrics(std::vector<std::shared_ptr<interfaces::Metric>> & metrics,bool enabled,const std::vector<LabeledMetricParameters> & labeledMetricParams) const49 void ReportFactory::updateMetrics(
50     std::vector<std::shared_ptr<interfaces::Metric>>& metrics, bool enabled,
51     const std::vector<LabeledMetricParameters>& labeledMetricParams) const
52 {
53     std::vector<std::shared_ptr<interfaces::Metric>> oldMetrics = metrics;
54     std::vector<std::shared_ptr<interfaces::Metric>> newMetrics;
55 
56     for (const auto& labeledMetricParam : labeledMetricParams)
57     {
58         auto existing = std::find_if(oldMetrics.begin(), oldMetrics.end(),
59                                      [labeledMetricParam](auto metric) {
60                                          return labeledMetricParam ==
61                                                 metric->dumpConfiguration();
62                                      });
63 
64         if (existing != oldMetrics.end())
65         {
66             newMetrics.emplace_back(*existing);
67             oldMetrics.erase(existing);
68             continue;
69         }
70 
71         namespace ts = utils::tstring;
72         newMetrics.emplace_back(std::make_shared<Metric>(
73             getSensors(labeledMetricParam.at_label<ts::SensorPath>()),
74             labeledMetricParam.at_label<ts::OperationType>(),
75             labeledMetricParam.at_label<ts::CollectionTimeScope>(),
76             labeledMetricParam.at_label<ts::CollectionDuration>(),
77             std::make_unique<Clock>()));
78 
79         if (enabled)
80         {
81             newMetrics.back()->initialize();
82         }
83     }
84 
85     if (enabled)
86     {
87         for (auto& metric : oldMetrics)
88         {
89             metric->deinitialize();
90         }
91     }
92 
93     metrics = std::move(newMetrics);
94 }
95 
getSensors(const std::vector<LabeledSensorInfo> & sensorPaths) const96 Sensors ReportFactory::getSensors(
97     const std::vector<LabeledSensorInfo>& sensorPaths) const
98 {
99     using namespace utils::tstring;
100 
101     return utils::transform(
102         sensorPaths,
103         [this](const LabeledSensorInfo& sensorPath)
104             -> std::shared_ptr<interfaces::Sensor> {
105             return sensorCache.makeSensor<Sensor>(
106                 sensorPath.at_label<Service>(), sensorPath.at_label<Path>(),
107                 sensorPath.at_label<Metadata>(), bus->get_io_context(), bus);
108         });
109 }
110 
convertMetricParams(boost::asio::yield_context & yield,const ReadingParameters & metricParams) const111 std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
112     boost::asio::yield_context& yield,
113     const ReadingParameters& metricParams) const
114 {
115     if (metricParams.empty())
116     {
117         return {};
118     }
119 
120     auto tree = utils::getSubTreeSensors(yield, bus);
121     return getMetricParamsFromSensorTree(metricParams, tree);
122 }
123 
convertMetricParams(const ReadingParameters & metricParams) const124 std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
125     const ReadingParameters& metricParams) const
126 {
127     if (metricParams.empty())
128     {
129         return {};
130     }
131 
132     auto tree = utils::getSubTreeSensors(bus);
133     return getMetricParamsFromSensorTree(metricParams, tree);
134 }
135 
136 std::vector<LabeledMetricParameters>
getMetricParamsFromSensorTree(const ReadingParameters & metricParams,const std::vector<utils::SensorTree> & tree) const137     ReportFactory::getMetricParamsFromSensorTree(
138         const ReadingParameters& metricParams,
139         const std::vector<utils::SensorTree>& tree) const
140 {
141     try
142     {
143         return utils::transform(metricParams, [&tree](const auto& item) {
144             auto [sensorPaths, operationType, collectionTimeScope,
145                   collectionDuration] = item;
146 
147             std::vector<LabeledSensorInfo> sensorParameters;
148 
149             for (const auto& [sensorPath, metadata] : sensorPaths)
150             {
151                 auto it = std::find_if(tree.begin(), tree.end(),
152                                        [path = sensorPath](const auto& v) {
153                                            return v.first == path;
154                                        });
155 
156                 if (it != tree.end() && it->second.size() == 1)
157                 {
158                     const auto& [service, ifaces] = it->second.front();
159                     sensorParameters.emplace_back(service, sensorPath,
160                                                   metadata);
161                 }
162             }
163 
164             if (sensorParameters.size() != sensorPaths.size())
165             {
166                 throw errors::InvalidArgument("ReadingParameters",
167                                               "Service not found.");
168             }
169 
170             if (operationType.empty())
171             {
172                 operationType = utils::enumToString(OperationType::avg);
173             }
174             else if (operationType == "SINGLE")
175             {
176                 operationType = utils::enumToString(OperationType::avg);
177                 collectionTimeScope =
178                     utils::enumToString(CollectionTimeScope::point);
179             }
180 
181             if (collectionTimeScope.empty())
182             {
183                 collectionTimeScope =
184                     utils::enumToString(CollectionTimeScope::point);
185             }
186 
187             return LabeledMetricParameters(
188                 std::move(sensorParameters),
189                 utils::toOperationType(operationType),
190                 utils::toCollectionTimeScope(collectionTimeScope),
191                 CollectionDuration(Milliseconds(collectionDuration)));
192         });
193     }
194     catch (const errors::InvalidArgument& e)
195     {
196         if (e.propertyName == "ReadingParameters")
197         {
198             throw;
199         }
200 
201         using namespace std::literals::string_literals;
202         throw errors::InvalidArgument("ReadingParameters."s + e.propertyName);
203     }
204 }
205