blob: 77189c1de83667c4cb2d7f14b2a6b4c8fe269369 [file] [log] [blame]
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +02001#include "report.hpp"
2
3#include "report_manager.hpp"
Wludzik, Jozefe2362792020-10-27 17:23:55 +01004#include "utils/transform.hpp"
5
6#include <phosphor-logging/log.hpp>
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +02007#include <sdbusplus/vtable.hpp>
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +02008
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +02009#include <numeric>
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020010
11Report::Report(boost::asio::io_context& ioc,
12 const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
Wludzik, Jozefe2362792020-10-27 17:23:55 +010013 const std::string& reportName,
14 const std::string& reportingTypeIn,
15 const bool emitsReadingsUpdateIn,
16 const bool logToMetricReportsCollectionIn,
17 const std::chrono::milliseconds intervalIn,
18 const ReadingParameters& readingParametersIn,
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020019 interfaces::ReportManager& reportManager,
Wludzik, Jozefe2362792020-10-27 17:23:55 +010020 interfaces::JsonStorage& reportStorageIn,
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020021 std::vector<std::shared_ptr<interfaces::Metric>> metrics) :
22 name(reportName),
Wludzik, Jozefe2362792020-10-27 17:23:55 +010023 path(reportDir + name), reportingType(reportingTypeIn),
24 interval(intervalIn), emitsReadingsUpdate(emitsReadingsUpdateIn),
25 logToMetricReportsCollection(logToMetricReportsCollectionIn),
26 readingParameters(readingParametersIn), objServer(objServer),
27 metrics(std::move(metrics)), timer(ioc),
28 fileName(std::to_string(std::hash<std::string>{}(name))),
29 reportStorage(reportStorageIn)
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020030{
Wludzik, Jozefe2362792020-10-27 17:23:55 +010031 deleteIface = objServer->add_unique_interface(
32 path, deleteIfaceName, [this, &ioc, &reportManager](auto& dbusIface) {
33 dbusIface.register_method("Delete", [this, &ioc, &reportManager] {
34 if (persistency)
35 {
36 reportStorage.remove(fileName);
37 }
38 boost::asio::post(ioc, [this, &reportManager] {
39 reportManager.removeReport(this);
40 });
41 });
42 });
43
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020044 reportIface = objServer->add_unique_interface(
Wludzik, Jozefe2362792020-10-27 17:23:55 +010045 path, reportIfaceName, [this](auto& dbusIface) {
46 dbusIface.register_property_rw(
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020047 "Interval", static_cast<uint64_t>(interval.count()),
Wludzik, Jozefe2362792020-10-27 17:23:55 +010048 sdbusplus::vtable::property_::emits_change,
49 [this](uint64_t newVal, auto&) {
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020050 std::chrono::milliseconds newValT(newVal);
51 if (newValT < ReportManager::minInterval)
52 {
53 return false;
54 }
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020055 interval = newValT;
56 return true;
Wludzik, Jozefe2362792020-10-27 17:23:55 +010057 },
58 [this](const auto&) {
59 return static_cast<uint64_t>(interval.count());
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020060 });
Wludzik, Jozefe2362792020-10-27 17:23:55 +010061 persistency = storeConfiguration();
62 dbusIface.register_property_rw(
63 "Persistency", persistency,
64 sdbusplus::vtable::property_::emits_change,
65 [this](bool newVal, const auto&) {
66 if (newVal == persistency)
67 {
68 return true;
69 }
70 if (newVal)
71 {
72 persistency = storeConfiguration();
73 }
74 else
75 {
76 reportStorage.remove(fileName);
77 persistency = false;
78 }
79 return true;
80 },
81 [this](const auto&) { return persistency; });
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +020082
83 auto readingsFlag = sdbusplus::vtable::property_::none;
84 if (emitsReadingsUpdate)
85 {
86 readingsFlag = sdbusplus::vtable::property_::emits_change;
87 }
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020088 dbusIface.register_property_r(
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +020089 "Readings", readings, readingsFlag,
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020090 [this](const auto&) { return readings; });
Wludzik, Jozefe2362792020-10-27 17:23:55 +010091 dbusIface.register_property_r(
92 "ReportingType", reportingType,
93 sdbusplus::vtable::property_::const_,
94 [this](const auto&) { return reportingType; });
95 dbusIface.register_property_r(
96 "ReadingParameters", readingParameters,
97 sdbusplus::vtable::property_::const_,
98 [this](const auto&) { return readingParameters; });
99 dbusIface.register_property_r(
100 "EmitsReadingsUpdate", emitsReadingsUpdate,
101 sdbusplus::vtable::property_::const_,
102 [this](const auto&) { return emitsReadingsUpdate; });
103 dbusIface.register_property_r(
104 "LogToMetricReportsCollection", logToMetricReportsCollection,
105 sdbusplus::vtable::property_::const_,
106 [this](const auto&) { return logToMetricReportsCollection; });
Krzysztof Grobelnyf32f6fe2020-10-30 13:51:58 +0100107 dbusIface.register_method("Update", [this] {
108 if (reportingType == "OnRequest")
109 {
110 updateReadings();
111 }
112 });
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +0200113 });
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200114
115 if (reportingType == "Periodic")
116 {
117 scheduleTimer(interval);
118 }
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000119
120 for (auto& metric : this->metrics)
121 {
122 metric->initialize();
123 }
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200124}
125
126void Report::timerProc(boost::system::error_code ec, Report& self)
127{
128 if (ec)
129 {
130 return;
131 }
132
133 self.updateReadings();
134 self.scheduleTimer(self.interval);
135}
136
137void Report::scheduleTimer(std::chrono::milliseconds timerInterval)
138{
139 timer.expires_after(timerInterval);
140 timer.async_wait(
141 [this](boost::system::error_code ec) { timerProc(ec, *this); });
142}
143
144void Report::updateReadings()
145{
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000146 std::tuple_element_t<1, Readings> readingsCache(metrics.size());
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200147
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000148 std::transform(std::begin(metrics), std::end(metrics),
149 std::begin(readingsCache), [](const auto& metric) {
150 const auto& reading = metric->getReading();
151 return std::make_tuple(reading.id, reading.metadata,
152 reading.value, reading.timestamp);
153 });
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200154
155 std::get<0>(readings) = std::time(0);
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100156 std::get<1>(readings) = std::move(readingsCache);
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100157
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200158 reportIface->signal_property("Readings");
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +0200159}
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100160
161bool Report::storeConfiguration() const
162{
163 try
164 {
165 nlohmann::json data;
166
167 data["Version"] = reportVersion;
168 data["Name"] = name;
169 data["ReportingType"] = reportingType;
170 data["EmitsReadingsUpdate"] = emitsReadingsUpdate;
171 data["LogToMetricReportsCollection"] = logToMetricReportsCollection;
172 data["Interval"] = interval.count();
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000173 data["ReadingParameters"] =
174 utils::transform(metrics, [](const auto& metric) {
175 return metric->dumpConfiguration();
176 });
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100177
178 reportStorage.store(fileName, data);
179 }
180 catch (const std::exception& e)
181 {
182 phosphor::logging::log<phosphor::logging::level::ERR>(
183 "Failed to store a report in storage",
Wludzik, Jozef982c5b52021-01-02 12:05:21 +0100184 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100185 return false;
186 }
187
188 return true;
189}