Added Periodic reportingType support to Report
When report interval expires report will collect readings from
metrics and update timestamp.
Tested:
- Added new units tests covering added code
- All existing unit tests are passing
Change-Id: I7f23ca05d77efb0f18d2c0d0f138c524ffb4f6af
Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
diff --git a/src/interfaces/metric.hpp b/src/interfaces/metric.hpp
new file mode 100644
index 0000000..51fc8fa
--- /dev/null
+++ b/src/interfaces/metric.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "metric_value.hpp"
+
+#include <vector>
+
+namespace interfaces
+{
+
+class Metric
+{
+ public:
+ virtual ~Metric() = default;
+
+ virtual const std::vector<MetricValue>& getReadings() const = 0;
+};
+
+} // namespace interfaces
diff --git a/src/interfaces/types.hpp b/src/interfaces/types.hpp
index 09a75cd..0d5eeb2 100644
--- a/src/interfaces/types.hpp
+++ b/src/interfaces/types.hpp
@@ -9,3 +9,7 @@
using ReadingParameters =
std::vector<std::tuple<std::vector<sdbusplus::message::object_path>,
std::string, std::string, std::string>>;
+
+using Readings = std::tuple<
+ uint64_t,
+ std::vector<std::tuple<std::string, std::string, double, uint64_t>>>;
diff --git a/src/metric.cpp b/src/metric.cpp
new file mode 100644
index 0000000..b40da5a
--- /dev/null
+++ b/src/metric.cpp
@@ -0,0 +1 @@
+#include "metric.hpp"
diff --git a/src/metric.hpp b/src/metric.hpp
new file mode 100644
index 0000000..a676e25
--- /dev/null
+++ b/src/metric.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "interfaces/metric.hpp"
+#include "interfaces/sensor_listener.hpp"
+
+class Metric : public interfaces::Metric, public interfaces::SensorListener
+{
+ public:
+ const std::vector<MetricValue>& getReadings() const override
+ {
+ return readings;
+ }
+
+ void sensorUpdated(interfaces::Sensor&, uint64_t) override
+ {}
+
+ void sensorUpdated(interfaces::Sensor&, uint64_t, double value) override
+ {}
+
+ private:
+ std::vector<MetricValue> readings;
+};
diff --git a/src/metric_value.hpp b/src/metric_value.hpp
new file mode 100644
index 0000000..d01ac4e
--- /dev/null
+++ b/src/metric_value.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include <cstdint>
+#include <string>
+
+struct MetricValue
+{
+ std::string id;
+ std::string metadata;
+ double value;
+ uint64_t timestamp;
+};
diff --git a/src/report.cpp b/src/report.cpp
index 81e3b05..2e68d45 100644
--- a/src/report.cpp
+++ b/src/report.cpp
@@ -2,9 +2,7 @@
#include "report_manager.hpp"
-using Readings = std::tuple<
- uint64_t,
- std::vector<std::tuple<std::string, std::string, double, uint64_t>>>;
+#include <numeric>
Report::Report(boost::asio::io_context& ioc,
const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
@@ -13,9 +11,11 @@
const bool logToMetricReportsCollection,
const std::chrono::milliseconds period,
const ReadingParameters& metricParams,
- interfaces::ReportManager& reportManager) :
- name{reportName},
- path{reportDir + name}, interval{period}, objServer(objServer)
+ interfaces::ReportManager& reportManager,
+ std::vector<std::shared_ptr<interfaces::Metric>> metrics) :
+ name(reportName),
+ path(reportDir + name), interval(period), objServer(objServer),
+ metrics(std::move(metrics)), timer(ioc)
{
reportIface = objServer->add_unique_interface(
path, reportIfaceName,
@@ -34,7 +34,10 @@
return true;
});
dbusIface.register_property("Persistency", bool{false});
- dbusIface.register_property("Readings", Readings{});
+ 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",
@@ -51,4 +54,52 @@
});
});
});
+
+ if (reportingType == "Periodic")
+ {
+ scheduleTimer(interval);
+ }
+}
+
+void Report::timerProc(boost::system::error_code ec, Report& self)
+{
+ if (ec)
+ {
+ return;
+ }
+
+ self.updateReadings();
+ self.scheduleTimer(self.interval);
+}
+
+void Report::scheduleTimer(std::chrono::milliseconds timerInterval)
+{
+ timer.expires_after(timerInterval);
+ timer.async_wait(
+ [this](boost::system::error_code ec) { timerProc(ec, *this); });
+}
+
+void Report::updateReadings()
+{
+ auto numElements = std::accumulate(
+ metrics.begin(), metrics.end(), 0u, [](auto sum, const auto& metric) {
+ return sum + metric->getReadings().size();
+ });
+
+ readingsCache.resize(numElements);
+
+ auto it = readingsCache.begin();
+
+ for (const auto& metric : metrics)
+ {
+ for (const auto& reading : metric->getReadings())
+ {
+ *(it++) = std::make_tuple(reading.id, reading.metadata,
+ reading.value, reading.timestamp);
+ }
+ }
+
+ std::get<0>(readings) = std::time(0);
+ std::get<1>(readings) = readingsCache;
+ reportIface->signal_property("Readings");
}
diff --git a/src/report.hpp b/src/report.hpp
index fb40614..8cef26a 100644
--- a/src/report.hpp
+++ b/src/report.hpp
@@ -1,10 +1,12 @@
#pragma once
+#include "interfaces/metric.hpp"
#include "interfaces/report.hpp"
#include "interfaces/report_manager.hpp"
#include "interfaces/types.hpp"
#include <boost/asio/io_context.hpp>
+#include <boost/asio/steady_timer.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <chrono>
@@ -20,12 +22,13 @@
const bool logToMetricReportsCollection,
const std::chrono::milliseconds period,
const ReadingParameters& metricParams,
- interfaces::ReportManager& reportManager);
+ interfaces::ReportManager& reportManager,
+ std::vector<std::shared_ptr<interfaces::Metric>> metrics);
~Report() = default;
- Report(Report&) = delete;
+ Report(const Report&) = delete;
Report(Report&&) = delete;
- Report& operator=(Report&) = delete;
+ Report& operator=(const Report&) = delete;
Report& operator=(Report&&) = delete;
std::string getName() const override
@@ -39,12 +42,20 @@
}
private:
+ static void timerProc(boost::system::error_code, Report& self);
+ void scheduleTimer(std::chrono::milliseconds interval);
+ void updateReadings();
+
const std::string name;
const std::string path;
std::chrono::milliseconds interval;
+ Readings readings = {};
+ std::tuple_element_t<1, Readings> readingsCache = {};
std::shared_ptr<sdbusplus::asio::object_server> objServer;
std::unique_ptr<sdbusplus::asio::dbus_interface> reportIface;
std::unique_ptr<sdbusplus::asio::dbus_interface> deleteIface;
+ std::vector<std::shared_ptr<interfaces::Metric>> metrics;
+ boost::asio::steady_timer timer;
public:
static constexpr const char* reportIfaceName =
diff --git a/src/report_factory.cpp b/src/report_factory.cpp
index 9f51db5..27e4ee7 100644
--- a/src/report_factory.cpp
+++ b/src/report_factory.cpp
@@ -15,7 +15,10 @@
std::chrono::milliseconds period, const ReadingParameters& metricParams,
interfaces::ReportManager& reportManager) const
{
+ std::vector<std::shared_ptr<interfaces::Metric>> metrics;
+
return std::make_unique<Report>(
ioc, objServer, name, reportingType, emitsReadingsSignal,
- logToMetricReportsCollection, period, metricParams, reportManager);
+ logToMetricReportsCollection, period, metricParams, reportManager,
+ std::move(metrics));
}