xref: /openbmc/telemetry/src/report_factory.cpp (revision 5ade2b1d0ccb71a3de23396dea77c375bedc0362)
1 #include "report_factory.hpp"
2 
3 #include "metric.hpp"
4 #include "report.hpp"
5 #include "sensor.hpp"
6 #include "utils/transform.hpp"
7 
8 ReportFactory::ReportFactory(
9     std::shared_ptr<sdbusplus::asio::connection> bus,
10     const std::shared_ptr<sdbusplus::asio::object_server>& objServer) :
11     bus(std::move(bus)),
12     objServer(objServer)
13 {}
14 
15 std::unique_ptr<interfaces::Report> ReportFactory::make(
16     std::optional<std::reference_wrapper<boost::asio::yield_context>> yield,
17     const std::string& name, const std::string& reportingType,
18     bool emitsReadingsSignal, bool logToMetricReportsCollection,
19     std::chrono::milliseconds period, const ReadingParameters& metricParams,
20     interfaces::ReportManager& reportManager,
21     interfaces::JsonStorage& reportStorage) const
22 {
23     std::optional<std::vector<ReportFactory::SensorTree>> sensorTree;
24 
25     std::vector<std::shared_ptr<interfaces::Metric>> metrics;
26     metrics.reserve(metricParams.size());
27 
28     for (const auto& [sensorPaths, op, id, metadata] : metricParams)
29     {
30         if (!sensorTree && yield && sensorPaths.size() > 0)
31         {
32             sensorTree = getSensorTree(*yield);
33         }
34 
35         std::vector<std::shared_ptr<interfaces::Sensor>> sensors =
36             getSensors(sensorTree, sensorPaths);
37 
38         metrics.emplace_back(
39             std::make_shared<Metric>(std::move(sensors), op, id, metadata));
40     }
41 
42     return std::make_unique<Report>(
43         bus->get_io_context(), objServer, name, reportingType,
44         emitsReadingsSignal, logToMetricReportsCollection, period, metricParams,
45         reportManager, reportStorage, std::move(metrics));
46 }
47 
48 std::vector<std::shared_ptr<interfaces::Sensor>> ReportFactory::getSensors(
49     const std::optional<std::vector<ReportFactory::SensorTree>>& tree,
50     const std::vector<sdbusplus::message::object_path>& sensorPaths) const
51 {
52     if (tree)
53     {
54         std::vector<std::shared_ptr<interfaces::Sensor>> sensors;
55 
56         for (const auto& [sensor, ifacesMap] : *tree)
57         {
58             auto it = std::find(sensorPaths.begin(), sensorPaths.end(), sensor);
59             if (it != sensorPaths.end())
60             {
61                 for (const auto& [service, ifaces] : ifacesMap)
62                 {
63                     sensors.emplace_back(sensorCache.makeSensor<Sensor>(
64                         service, sensor, bus->get_io_context(), bus));
65                 }
66             }
67         }
68 
69         return sensors;
70     }
71     else
72     {
73         return utils::transform(
74             sensorPaths,
75             [this](const std::string& sensor)
76                 -> std::shared_ptr<interfaces::Sensor> {
77                 std::string::size_type pos = sensor.find_first_of(":");
78                 auto service = sensor.substr(0, pos);
79                 auto path = sensor.substr(pos + 1);
80                 return sensorCache.makeSensor<Sensor>(
81                     service, path, bus->get_io_context(), bus);
82             });
83     }
84 }
85 
86 std::vector<ReportFactory::SensorTree>
87     ReportFactory::getSensorTree(boost::asio::yield_context& yield) const
88 {
89     std::array<const char*, 1> interfaces = {
90         "xyz.openbmc_project.Sensor.Value"};
91     boost::system::error_code ec;
92 
93     auto result = bus->yield_method_call<std::vector<SensorTree>>(
94         yield, ec, "xyz.openbmc_project.ObjectMapper",
95         "/xyz/openbmc_project/object_mapper",
96         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
97         "/xyz/openbmc_project/sensors", 2, interfaces);
98     if (ec)
99     {
100         throw std::runtime_error("failed");
101     }
102     return result;
103 }
104