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