Implement Report persistency
Now Report properties are stored in non-volatile memory. It allows
to restore Report after system restart. Persistency of a report is
controlled by Persistency property in Report interface.
Tested:
- Passed unit tests
- Verified that report is stored in /var/lib/telemetry dir
- Verified that report is restored from storage after telemetry
service start
Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com>
Change-Id: Iccfe21603eecffc4e174a4403f699b03de320db9
diff --git a/src/report.cpp b/src/report.cpp
index 2e68d45..b2ac261 100644
--- a/src/report.cpp
+++ b/src/report.cpp
@@ -1,58 +1,103 @@
#include "report.hpp"
#include "report_manager.hpp"
+#include "utils/transform.hpp"
+
+#include <phosphor-logging/log.hpp>
#include <numeric>
Report::Report(boost::asio::io_context& ioc,
const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
- const std::string& reportName, const std::string& reportingType,
- const bool emitsReadingsSignal,
- const bool logToMetricReportsCollection,
- const std::chrono::milliseconds period,
- const ReadingParameters& metricParams,
+ const std::string& reportName,
+ const std::string& reportingTypeIn,
+ const bool emitsReadingsUpdateIn,
+ const bool logToMetricReportsCollectionIn,
+ const std::chrono::milliseconds intervalIn,
+ const ReadingParameters& readingParametersIn,
interfaces::ReportManager& reportManager,
+ interfaces::JsonStorage& reportStorageIn,
std::vector<std::shared_ptr<interfaces::Metric>> metrics) :
name(reportName),
- path(reportDir + name), interval(period), objServer(objServer),
- metrics(std::move(metrics)), timer(ioc)
+ path(reportDir + name), reportingType(reportingTypeIn),
+ interval(intervalIn), emitsReadingsUpdate(emitsReadingsUpdateIn),
+ logToMetricReportsCollection(logToMetricReportsCollectionIn),
+ readingParameters(readingParametersIn), objServer(objServer),
+ metrics(std::move(metrics)), timer(ioc),
+ fileName(std::to_string(std::hash<std::string>{}(name))),
+ reportStorage(reportStorageIn)
{
+ deleteIface = objServer->add_unique_interface(
+ path, deleteIfaceName, [this, &ioc, &reportManager](auto& dbusIface) {
+ dbusIface.register_method("Delete", [this, &ioc, &reportManager] {
+ if (persistency)
+ {
+ reportStorage.remove(fileName);
+ }
+ boost::asio::post(ioc, [this, &reportManager] {
+ reportManager.removeReport(this);
+ });
+ });
+ });
+
reportIface = objServer->add_unique_interface(
- path, reportIfaceName,
- [this, &reportingType, &emitsReadingsSignal,
- &logToMetricReportsCollection, &metricParams](auto& dbusIface) {
- dbusIface.register_property(
+ path, reportIfaceName, [this](auto& dbusIface) {
+ dbusIface.register_property_rw(
"Interval", static_cast<uint64_t>(interval.count()),
- [this](const uint64_t newVal, uint64_t& actualVal) {
+ sdbusplus::vtable::property_::emits_change,
+ [this](uint64_t newVal, auto&) {
std::chrono::milliseconds newValT(newVal);
if (newValT < ReportManager::minInterval)
{
return false;
}
- actualVal = newVal;
interval = newValT;
return true;
+ },
+ [this](const auto&) {
+ return static_cast<uint64_t>(interval.count());
});
- dbusIface.register_property("Persistency", bool{false});
+ persistency = storeConfiguration();
+ dbusIface.register_property_rw(
+ "Persistency", persistency,
+ sdbusplus::vtable::property_::emits_change,
+ [this](bool newVal, const auto&) {
+ if (newVal == persistency)
+ {
+ return true;
+ }
+ if (newVal)
+ {
+ persistency = storeConfiguration();
+ }
+ else
+ {
+ reportStorage.remove(fileName);
+ persistency = false;
+ }
+ return true;
+ },
+ [this](const auto&) { return persistency; });
dbusIface.register_property_r(
"Readings", readings,
sdbusplus::vtable::property_::emits_change,
[this](const auto&) { return readings; });
- dbusIface.register_property("ReportingType", reportingType);
- dbusIface.register_property("ReadingParameters", metricParams);
- dbusIface.register_property("EmitsReadingsUpdate",
- emitsReadingsSignal);
- dbusIface.register_property("LogToMetricReportsCollection",
- logToMetricReportsCollection);
- });
-
- deleteIface = objServer->add_unique_interface(
- path, deleteIfaceName, [this, &ioc, &reportManager](auto& dbusIface) {
- dbusIface.register_method("Delete", [this, &ioc, &reportManager] {
- boost::asio::post(ioc, [this, &reportManager] {
- reportManager.removeReport(this);
- });
- });
+ dbusIface.register_property_r(
+ "ReportingType", reportingType,
+ sdbusplus::vtable::property_::const_,
+ [this](const auto&) { return reportingType; });
+ dbusIface.register_property_r(
+ "ReadingParameters", readingParameters,
+ sdbusplus::vtable::property_::const_,
+ [this](const auto&) { return readingParameters; });
+ dbusIface.register_property_r(
+ "EmitsReadingsUpdate", emitsReadingsUpdate,
+ sdbusplus::vtable::property_::const_,
+ [this](const auto&) { return emitsReadingsUpdate; });
+ dbusIface.register_property_r(
+ "LogToMetricReportsCollection", logToMetricReportsCollection,
+ sdbusplus::vtable::property_::const_,
+ [this](const auto&) { return logToMetricReportsCollection; });
});
if (reportingType == "Periodic")
@@ -101,5 +146,34 @@
std::get<0>(readings) = std::time(0);
std::get<1>(readings) = readingsCache;
+
reportIface->signal_property("Readings");
}
+
+bool Report::storeConfiguration() const
+{
+ try
+ {
+ nlohmann::json data;
+
+ data["Version"] = reportVersion;
+ data["Name"] = name;
+ data["ReportingType"] = reportingType;
+ data["EmitsReadingsUpdate"] = emitsReadingsUpdate;
+ data["LogToMetricReportsCollection"] = logToMetricReportsCollection;
+ data["Interval"] = interval.count();
+ data["ReadingParameters"] = utils::transform(
+ metrics, [](const auto& metric) { return metric->to_json(); });
+
+ reportStorage.store(fileName, data);
+ }
+ catch (const std::exception& e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Failed to store a report in storage",
+ phosphor::logging::entry("msg=", e.what()));
+ return false;
+ }
+
+ return true;
+}