xref: /openbmc/telemetry/src/report.cpp (revision c8e3a64a1d01cfafa589477ac65952df353e141d)
1 #include "report.hpp"
2 
3 #include "report_manager.hpp"
4 
5 #include <numeric>
6 
7 Report::Report(boost::asio::io_context& ioc,
8                const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
9                const std::string& reportName, const std::string& reportingType,
10                const bool emitsReadingsSignal,
11                const bool logToMetricReportsCollection,
12                const std::chrono::milliseconds period,
13                const ReadingParameters& metricParams,
14                interfaces::ReportManager& reportManager,
15                std::vector<std::shared_ptr<interfaces::Metric>> metrics) :
16     name(reportName),
17     path(reportDir + name), interval(period), objServer(objServer),
18     metrics(std::move(metrics)), timer(ioc)
19 {
20     reportIface = objServer->add_unique_interface(
21         path, reportIfaceName,
22         [this, &reportingType, &emitsReadingsSignal,
23          &logToMetricReportsCollection, &metricParams](auto& dbusIface) {
24             dbusIface.register_property(
25                 "Interval", static_cast<uint64_t>(interval.count()),
26                 [this](const uint64_t newVal, uint64_t& actualVal) {
27                     std::chrono::milliseconds newValT(newVal);
28                     if (newValT < ReportManager::minInterval)
29                     {
30                         return false;
31                     }
32                     actualVal = newVal;
33                     interval = newValT;
34                     return true;
35                 });
36             dbusIface.register_property("Persistency", bool{false});
37             dbusIface.register_property_r(
38                 "Readings", readings,
39                 sdbusplus::vtable::property_::emits_change,
40                 [this](const auto&) { return readings; });
41             dbusIface.register_property("ReportingType", reportingType);
42             dbusIface.register_property("ReadingParameters", metricParams);
43             dbusIface.register_property("EmitsReadingsUpdate",
44                                         emitsReadingsSignal);
45             dbusIface.register_property("LogToMetricReportsCollection",
46                                         logToMetricReportsCollection);
47         });
48 
49     deleteIface = objServer->add_unique_interface(
50         path, deleteIfaceName, [this, &ioc, &reportManager](auto& dbusIface) {
51             dbusIface.register_method("Delete", [this, &ioc, &reportManager] {
52                 boost::asio::post(ioc, [this, &reportManager] {
53                     reportManager.removeReport(this);
54                 });
55             });
56         });
57 
58     if (reportingType == "Periodic")
59     {
60         scheduleTimer(interval);
61     }
62 }
63 
64 void Report::timerProc(boost::system::error_code ec, Report& self)
65 {
66     if (ec)
67     {
68         return;
69     }
70 
71     self.updateReadings();
72     self.scheduleTimer(self.interval);
73 }
74 
75 void Report::scheduleTimer(std::chrono::milliseconds timerInterval)
76 {
77     timer.expires_after(timerInterval);
78     timer.async_wait(
79         [this](boost::system::error_code ec) { timerProc(ec, *this); });
80 }
81 
82 void Report::updateReadings()
83 {
84     auto numElements = std::accumulate(
85         metrics.begin(), metrics.end(), 0u, [](auto sum, const auto& metric) {
86             return sum + metric->getReadings().size();
87         });
88 
89     readingsCache.resize(numElements);
90 
91     auto it = readingsCache.begin();
92 
93     for (const auto& metric : metrics)
94     {
95         for (const auto& reading : metric->getReadings())
96         {
97             *(it++) = std::make_tuple(reading.id, reading.metadata,
98                                       reading.value, reading.timestamp);
99         }
100     }
101 
102     std::get<0>(readings) = std::time(0);
103     std::get<1>(readings) = readingsCache;
104     reportIface->signal_property("Readings");
105 }
106