blob: af19a9127e729cdeea237d9e62500746ee71c248 [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,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000017 const Milliseconds intervalIn,
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020018 interfaces::ReportManager& reportManager,
Wludzik, Jozefe2362792020-10-27 17:23:55 +010019 interfaces::JsonStorage& reportStorageIn,
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020020 std::vector<std::shared_ptr<interfaces::Metric>> metricsIn,
21 const bool enabledIn) :
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020022 name(reportName),
Wludzik, Jozefe2362792020-10-27 17:23:55 +010023 path(reportDir + name), reportingType(reportingTypeIn),
24 interval(intervalIn), emitsReadingsUpdate(emitsReadingsUpdateIn),
25 logToMetricReportsCollection(logToMetricReportsCollectionIn),
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000026 objServer(objServer), metrics(std::move(metricsIn)), timer(ioc),
Wludzik, Jozefe2362792020-10-27 17:23:55 +010027 fileName(std::to_string(std::hash<std::string>{}(name))),
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020028 reportStorage(reportStorageIn), enabled(enabledIn)
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +020029{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000030 readingParameters =
31 toReadingParameters(utils::transform(metrics, [](const auto& metric) {
32 return metric->dumpConfiguration();
33 }));
34
35 readingParametersPastVersion =
36 utils::transform(readingParameters, [](const auto& item) {
37 return ReadingParametersPastVersion::value_type(
38 std::get<0>(item).front(), std::get<1>(item), std::get<2>(item),
39 std::get<3>(item));
40 });
41
Wludzik, Jozefe2362792020-10-27 17:23:55 +010042 deleteIface = objServer->add_unique_interface(
43 path, deleteIfaceName, [this, &ioc, &reportManager](auto& dbusIface) {
44 dbusIface.register_method("Delete", [this, &ioc, &reportManager] {
45 if (persistency)
46 {
47 reportStorage.remove(fileName);
48 }
49 boost::asio::post(ioc, [this, &reportManager] {
50 reportManager.removeReport(this);
51 });
52 });
53 });
54
Krzysztof Grobelny85db8bd2021-05-28 12:13:23 +000055 persistency = storeConfiguration();
56 reportIface = makeReportInterface();
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020057
58 if (reportingType == "Periodic")
59 {
60 scheduleTimer(interval);
61 }
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000062
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020063 if (enabled)
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000064 {
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020065 for (auto& metric : this->metrics)
66 {
67 metric->initialize();
68 }
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000069 }
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020070}
71
Krzysztof Grobelny85db8bd2021-05-28 12:13:23 +000072std::unique_ptr<sdbusplus::asio::dbus_interface> Report::makeReportInterface()
73{
74 auto dbusIface = objServer->add_unique_interface(path, reportIfaceName);
75 dbusIface->register_property_rw(
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020076 "Enabled", enabled, sdbusplus::vtable::property_::emits_change,
77 [this](bool newVal, const auto&) {
78 if (newVal != enabled)
79 {
80 if (true == newVal && "Periodic" == reportingType)
81 {
82 scheduleTimer(interval);
83 }
84 if (newVal)
85 {
86 for (auto& metric : metrics)
87 {
88 metric->initialize();
89 }
90 }
91 else
92 {
93 for (auto& metric : metrics)
94 {
95 metric->deinitialize();
96 }
97 }
98
99 enabled = newVal;
100 persistency = storeConfiguration();
101 }
102 return true;
103 },
104 [this](const auto&) { return enabled; });
105 dbusIface->register_property_rw(
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000106 "Interval", interval.count(),
Krzysztof Grobelny85db8bd2021-05-28 12:13:23 +0000107 sdbusplus::vtable::property_::emits_change,
108 [this](uint64_t newVal, auto&) {
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200109 if (Milliseconds newValT{newVal};
110 newValT >= ReportManager::minInterval)
Krzysztof Grobelny85db8bd2021-05-28 12:13:23 +0000111 {
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200112 if (newValT != interval)
113 {
114 interval = newValT;
115 persistency = storeConfiguration();
116 }
117 return true;
Krzysztof Grobelny85db8bd2021-05-28 12:13:23 +0000118 }
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200119 return false;
Krzysztof Grobelny85db8bd2021-05-28 12:13:23 +0000120 },
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000121 [this](const auto&) { return interval.count(); });
Krzysztof Grobelny85db8bd2021-05-28 12:13:23 +0000122 dbusIface->register_property_rw(
123 "Persistency", persistency, sdbusplus::vtable::property_::emits_change,
124 [this](bool newVal, const auto&) {
125 if (newVal == persistency)
126 {
127 return true;
128 }
129 if (newVal)
130 {
131 persistency = storeConfiguration();
132 }
133 else
134 {
135 reportStorage.remove(fileName);
136 persistency = false;
137 }
138 return true;
139 },
140 [this](const auto&) { return persistency; });
141
142 auto readingsFlag = sdbusplus::vtable::property_::none;
143 if (emitsReadingsUpdate)
144 {
145 readingsFlag = sdbusplus::vtable::property_::emits_change;
146 }
147 dbusIface->register_property_r("Readings", readings, readingsFlag,
148 [this](const auto&) { return readings; });
149 dbusIface->register_property_r(
150 "ReportingType", reportingType, sdbusplus::vtable::property_::const_,
151 [this](const auto&) { return reportingType; });
152 dbusIface->register_property_r(
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000153 "ReadingParameters", readingParametersPastVersion,
154 sdbusplus::vtable::property_::const_,
155 [this](const auto&) { return readingParametersPastVersion; });
156 dbusIface->register_property_r(
157 "ReadingParametersFutureVersion", readingParameters,
Krzysztof Grobelny85db8bd2021-05-28 12:13:23 +0000158 sdbusplus::vtable::property_::const_,
159 [this](const auto&) { return readingParameters; });
160 dbusIface->register_property_r(
161 "EmitsReadingsUpdate", emitsReadingsUpdate,
162 sdbusplus::vtable::property_::const_,
163 [this](const auto&) { return emitsReadingsUpdate; });
164 dbusIface->register_property_r(
165 "LogToMetricReportsCollection", logToMetricReportsCollection,
166 sdbusplus::vtable::property_::const_,
167 [this](const auto&) { return logToMetricReportsCollection; });
168 dbusIface->register_method("Update", [this] {
169 if (reportingType == "OnRequest")
170 {
171 updateReadings();
172 }
173 });
174 constexpr bool skipPropertiesChangedSignal = true;
175 dbusIface->initialize(skipPropertiesChangedSignal);
176 return dbusIface;
177}
178
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200179void Report::timerProc(boost::system::error_code ec, Report& self)
180{
181 if (ec)
182 {
183 return;
184 }
185
186 self.updateReadings();
187 self.scheduleTimer(self.interval);
188}
189
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000190void Report::scheduleTimer(Milliseconds timerInterval)
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200191{
192 timer.expires_after(timerInterval);
193 timer.async_wait(
194 [this](boost::system::error_code ec) { timerProc(ec, *this); });
195}
196
197void Report::updateReadings()
198{
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200199 if (!enabled)
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000200 {
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200201 return;
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000202 }
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200203
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000204 using ReadingsTimestamp = std::tuple_element_t<0, Readings>;
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200205 using ReadingsValue = std::tuple_element_t<1, Readings>;
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000206
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200207 std::get<ReadingsValue>(cachedReadings).clear();
208 for (const auto& metric : metrics)
209 {
210 for (const auto& [id, meta, val, timestamp] : metric->getReadings())
211 {
212 std::get<ReadingsValue>(cachedReadings)
213 .emplace_back(id, meta, val, timestamp);
214 }
215 }
216 std::get<ReadingsTimestamp>(cachedReadings) = std::time(0);
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000217 std::swap(readings, cachedReadings);
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100218
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200219 reportIface->signal_property("Readings");
Wludzik, Jozefcb88cfd2020-09-28 16:38:57 +0200220}
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100221
222bool Report::storeConfiguration() const
223{
224 try
225 {
226 nlohmann::json data;
227
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200228 data["Enabled"] = enabled;
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100229 data["Version"] = reportVersion;
230 data["Name"] = name;
231 data["ReportingType"] = reportingType;
232 data["EmitsReadingsUpdate"] = emitsReadingsUpdate;
233 data["LogToMetricReportsCollection"] = logToMetricReportsCollection;
234 data["Interval"] = interval.count();
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000235 data["ReadingParameters"] =
236 utils::transform(metrics, [](const auto& metric) {
237 return metric->dumpConfiguration();
238 });
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100239
240 reportStorage.store(fileName, data);
241 }
242 catch (const std::exception& e)
243 {
244 phosphor::logging::log<phosphor::logging::level::ERR>(
245 "Failed to store a report in storage",
Wludzik, Jozef982c5b52021-01-02 12:05:21 +0100246 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100247 return false;
248 }
249
250 return true;
251}