regulators: Complete SensorMonitoring class

Complete the SensorMonitoring class.  This class implements the
"sensor_monitoring" object in the JSON config file.

Add calls to the startRail() and endRail() methods of the Sensors
service.

Add ErrorHistory data member so that errors are only logged once per
boot since sensor monitoring occurs repeatedly once per second.

Add error count data member to limit the number of error messages
written to the journal since monitoring occurs repeatedly.

Update all affected test cases.

Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
Change-Id: I0bd20d03ccea9e15cd0f97529f6ccdad2fa015c8
diff --git a/phosphor-regulators/src/sensor_monitoring.cpp b/phosphor-regulators/src/sensor_monitoring.cpp
index c46ff1a..b5e31ef 100644
--- a/phosphor-regulators/src/sensor_monitoring.cpp
+++ b/phosphor-regulators/src/sensor_monitoring.cpp
@@ -23,6 +23,7 @@
 #include "error_logging_utils.hpp"
 #include "exception_utils.hpp"
 #include "rail.hpp"
+#include "sensors.hpp"
 #include "system.hpp"
 
 #include <exception>
@@ -31,8 +32,15 @@
 {
 
 void SensorMonitoring::execute(Services& services, System& system,
-                               Chassis& /*chassis*/, Device& device, Rail& rail)
+                               Chassis& chassis, Device& device, Rail& rail)
 {
+    // Notify sensors service that monitoring is starting for this rail
+    Sensors& sensors = services.getSensors();
+    sensors.startRail(rail.getID(), device.getFRU(),
+                      chassis.getInventoryPath());
+
+    // Read all sensors defined for this rail
+    bool errorOccurred{false};
     try
     {
         // Create ActionEnvironment
@@ -44,16 +52,25 @@
     }
     catch (const std::exception& e)
     {
-        // Log error messages in journal
-        services.getJournal().logError(exception_utils::getMessages(e));
-        services.getJournal().logError("Unable to monitor sensors for rail " +
-                                       rail.getID());
+        // Set flag to notify sensors service that an error occurred
+        errorOccurred = true;
 
-        // Create error log entry
-        // TODO: Add ErrorHistory data member and specify as parameter below
+        // Log error messages in journal for the first 3 errors
+        if (++errorCount <= 3)
+        {
+            services.getJournal().logError(exception_utils::getMessages(e));
+            services.getJournal().logError(
+                "Unable to monitor sensors for rail " + rail.getID());
+        }
+
+        // Create error log entry if this type hasn't already been logged
         error_logging_utils::logError(std::current_exception(),
-                                      Entry::Level::Warning, services);
+                                      Entry::Level::Warning, services,
+                                      errorHistory);
     }
+
+    // Notify sensors service that monitoring has ended for this rail
+    sensors.endRail(errorOccurred);
 }
 
 } // namespace phosphor::power::regulators
diff --git a/phosphor-regulators/src/sensor_monitoring.hpp b/phosphor-regulators/src/sensor_monitoring.hpp
index 211c534..0254fb2 100644
--- a/phosphor-regulators/src/sensor_monitoring.hpp
+++ b/phosphor-regulators/src/sensor_monitoring.hpp
@@ -16,6 +16,7 @@
 #pragma once
 
 #include "action.hpp"
+#include "error_history.hpp"
 #include "services.hpp"
 
 #include <memory>
@@ -67,6 +68,20 @@
     }
 
     /**
+     * Clears all error history.
+     *
+     * All data on previously logged errors will be deleted.  If errors occur
+     * again in the future they will be logged again.
+     *
+     * This method is normally called when the system is being powered on.
+     */
+    void clearErrorHistory()
+    {
+        errorHistory.clear();
+        errorCount = 0;
+    }
+
+    /**
      * Executes the actions to read the sensors for a rail.
      *
      * @param services system services like error logging and the journal
@@ -93,6 +108,19 @@
      * Actions that read the sensors for a rail.
      */
     std::vector<std::unique_ptr<Action>> actions{};
+
+    /**
+     * History of which error types have been logged.
+     *
+     * Since sensor monitoring runs repeatedly based on a timer, each error type
+     * is only logged once.
+     */
+    ErrorHistory errorHistory{};
+
+    /**
+     * Number of errors that have occurred.
+     */
+    unsigned int errorCount{0};
 };
 
 } // namespace phosphor::power::regulators