regulators: Create error log entries

Create error log entries when the following regulator operations fail:
* configuration
* presence detection
* sensor monitoring
* closing I2C devices

Use the recently created error_logging_utils namespace to create error
logs based on caught exceptions.

Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
Change-Id: I25824ecfdaa270abbce92b52bdea0602271d926d
diff --git a/phosphor-regulators/src/configuration.cpp b/phosphor-regulators/src/configuration.cpp
index 04babc7..ddf25ba 100644
--- a/phosphor-regulators/src/configuration.cpp
+++ b/phosphor-regulators/src/configuration.cpp
@@ -20,6 +20,7 @@
 #include "action_utils.hpp"
 #include "chassis.hpp"
 #include "device.hpp"
+#include "error_logging_utils.hpp"
 #include "exception_utils.hpp"
 #include "rail.hpp"
 #include "system.hpp"
@@ -72,7 +73,9 @@
         services.getJournal().logError(exception_utils::getMessages(e));
         services.getJournal().logError("Unable to configure " + deviceOrRailID);
 
-        // TODO: Create error log entry
+        // Create error log entry
+        error_logging_utils::logError(std::current_exception(),
+                                      Entry::Level::Warning, services);
     }
 }
 
diff --git a/phosphor-regulators/src/device.cpp b/phosphor-regulators/src/device.cpp
index 8ae7afb..08c5174 100644
--- a/phosphor-regulators/src/device.cpp
+++ b/phosphor-regulators/src/device.cpp
@@ -17,6 +17,7 @@
 #include "device.hpp"
 
 #include "chassis.hpp"
+#include "error_logging_utils.hpp"
 #include "exception_utils.hpp"
 #include "system.hpp"
 
@@ -63,7 +64,9 @@
         services.getJournal().logError(exception_utils::getMessages(e));
         services.getJournal().logError("Unable to close device " + id);
 
-        // TODO: Create error log entry
+        // Create error log entry
+        error_logging_utils::logError(std::current_exception(),
+                                      Entry::Level::Notice, services);
     }
 }
 
diff --git a/phosphor-regulators/src/presence_detection.cpp b/phosphor-regulators/src/presence_detection.cpp
index 3ed5350..74c241b 100644
--- a/phosphor-regulators/src/presence_detection.cpp
+++ b/phosphor-regulators/src/presence_detection.cpp
@@ -20,6 +20,7 @@
 #include "action_utils.hpp"
 #include "chassis.hpp"
 #include "device.hpp"
+#include "error_logging_utils.hpp"
 #include "exception_utils.hpp"
 #include "system.hpp"
 
@@ -54,7 +55,9 @@
             services.getJournal().logError("Unable to determine presence of " +
                                            device.getID());
 
-            // TODO: Create error log entry
+            // Create error log entry
+            error_logging_utils::logError(std::current_exception(),
+                                          Entry::Level::Warning, services);
         }
     }
 
diff --git a/phosphor-regulators/src/sensor_monitoring.cpp b/phosphor-regulators/src/sensor_monitoring.cpp
index 1ce1eee..c46ff1a 100644
--- a/phosphor-regulators/src/sensor_monitoring.cpp
+++ b/phosphor-regulators/src/sensor_monitoring.cpp
@@ -20,6 +20,7 @@
 #include "action_utils.hpp"
 #include "chassis.hpp"
 #include "device.hpp"
+#include "error_logging_utils.hpp"
 #include "exception_utils.hpp"
 #include "rail.hpp"
 #include "system.hpp"
@@ -48,7 +49,10 @@
         services.getJournal().logError("Unable to monitor sensors for rail " +
                                        rail.getID());
 
-        // TODO: Create error log entry
+        // Create error log entry
+        // TODO: Add ErrorHistory data member and specify as parameter below
+        error_logging_utils::logError(std::current_exception(),
+                                      Entry::Level::Warning, services);
     }
 }
 
diff --git a/phosphor-regulators/test/configuration_tests.cpp b/phosphor-regulators/test/configuration_tests.cpp
index 7db4ac5..47279be 100644
--- a/phosphor-regulators/test/configuration_tests.cpp
+++ b/phosphor-regulators/test/configuration_tests.cpp
@@ -20,6 +20,7 @@
 #include "i2c_interface.hpp"
 #include "i2c_write_byte_action.hpp"
 #include "mock_action.hpp"
+#include "mock_error_logging.hpp"
 #include "mock_journal.hpp"
 #include "mock_services.hpp"
 #include "mocked_i2c_interface.hpp"
@@ -43,6 +44,7 @@
 using namespace phosphor::power::regulators::pmbus_utils;
 
 using ::testing::A;
+using ::testing::Ref;
 using ::testing::Return;
 using ::testing::Throw;
 using ::testing::TypedEq;
@@ -195,8 +197,10 @@
 
     // Test where fails
     {
-        // Create mock services.  Expect logDebug() and logError() to be called.
+        // Create mock services.  Expect logDebug(), logError(), and
+        // logI2CError() to be called.
         MockServices services{};
+        MockErrorLogging& errorLogging = services.getMockErrorLogging();
         MockJournal& journal = services.getMockJournal();
         std::vector<std::string> expectedErrMessagesException{
             "I2CException: Failed to write byte: bus /dev/i2c-1, addr 0x70",
@@ -205,6 +209,10 @@
         EXPECT_CALL(journal, logDebug("Configuring vdd_reg")).Times(1);
         EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
         EXPECT_CALL(journal, logError("Unable to configure vdd_reg")).Times(1);
+        EXPECT_CALL(errorLogging,
+                    logI2CError(Entry::Level::Warning, Ref(journal),
+                                "/dev/i2c-1", 0x70, 0))
+            .Times(1);
 
         // Create I2CWriteByteAction with register 0x7C and value 0x0A
         std::unique_ptr<I2CWriteByteAction> action =
@@ -392,8 +400,10 @@
 
     // Test where fails
     {
-        // Create mock services.  Expect logDebug() and logError() to be called.
+        // Create mock services.  Expect logDebug(), logError(), and logI2CError
+        // to be called.
         MockServices services{};
+        MockErrorLogging& errorLogging = services.getMockErrorLogging();
         MockJournal& journal = services.getMockJournal();
         std::vector<std::string> expectedErrMessagesException{
             "I2CException: Failed to write byte: bus /dev/i2c-1, addr 0x70",
@@ -402,6 +412,10 @@
         EXPECT_CALL(journal, logDebug("Configuring vio2")).Times(1);
         EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
         EXPECT_CALL(journal, logError("Unable to configure vio2")).Times(1);
+        EXPECT_CALL(errorLogging,
+                    logI2CError(Entry::Level::Warning, Ref(journal),
+                                "/dev/i2c-1", 0x70, 0))
+            .Times(1);
 
         // Create I2CWriteByteAction with register 0x7C and value 0x0A
         std::unique_ptr<I2CWriteByteAction> action =
diff --git a/phosphor-regulators/test/device_tests.cpp b/phosphor-regulators/test/device_tests.cpp
index 594578f..33bdab3 100644
--- a/phosphor-regulators/test/device_tests.cpp
+++ b/phosphor-regulators/test/device_tests.cpp
@@ -20,6 +20,7 @@
 #include "i2c_interface.hpp"
 #include "id_map.hpp"
 #include "mock_action.hpp"
+#include "mock_error_logging.hpp"
 #include "mock_journal.hpp"
 #include "mock_services.hpp"
 #include "mocked_i2c_interface.hpp"
@@ -43,6 +44,7 @@
 using namespace phosphor::power::regulators::test_utils;
 
 using ::testing::A;
+using ::testing::Ref;
 using ::testing::Return;
 using ::testing::Throw;
 using ::testing::TypedEq;
@@ -273,14 +275,20 @@
             .WillOnce(Throw(
                 i2c::I2CException{"Failed to close", "/dev/i2c-1", 0x70}));
 
-        // Create mock services.  Expect logError() to be called.
+        // Create mock services.  Expect logError() and logI2CError() to be
+        // called.
         MockServices services{};
+        MockErrorLogging& errorLogging = services.getMockErrorLogging();
         MockJournal& journal = services.getMockJournal();
         std::vector<std::string> expectedErrMessagesException{
             "I2CException: Failed to close: bus /dev/i2c-1, addr 0x70"};
         EXPECT_CALL(journal, logError("Unable to close device vdd_reg"))
             .Times(1);
         EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
+        EXPECT_CALL(errorLogging,
+                    logI2CError(Entry::Level::Notice, Ref(journal),
+                                "/dev/i2c-1", 0x70, 0))
+            .Times(1);
 
         // Create Device
         Device device{
diff --git a/phosphor-regulators/test/presence_detection_tests.cpp b/phosphor-regulators/test/presence_detection_tests.cpp
index f489b7f..e89af2c 100644
--- a/phosphor-regulators/test/presence_detection_tests.cpp
+++ b/phosphor-regulators/test/presence_detection_tests.cpp
@@ -19,6 +19,7 @@
 #include "device.hpp"
 #include "i2c_interface.hpp"
 #include "mock_action.hpp"
+#include "mock_error_logging.hpp"
 #include "mock_journal.hpp"
 #include "mock_presence_service.hpp"
 #include "mock_services.hpp"
@@ -27,6 +28,8 @@
 #include "rule.hpp"
 #include "system.hpp"
 
+#include <sdbusplus/exception.hpp>
+
 #include <memory>
 #include <stdexcept>
 #include <string>
@@ -39,10 +42,40 @@
 
 using namespace phosphor::power::regulators;
 
+using ::testing::Ref;
 using ::testing::Return;
 using ::testing::Throw;
 
 /**
+ * Concrete subclass of sdbusplus::exception_t abstract base class.
+ */
+class TestSDBusError : public sdbusplus::exception_t
+{
+  public:
+    TestSDBusError(const std::string& error) : error{error}
+    {
+    }
+
+    const char* what() const noexcept override
+    {
+        return error.c_str();
+    }
+
+    const char* name() const noexcept override
+    {
+        return "";
+    }
+
+    const char* description() const noexcept override
+    {
+        return "";
+    }
+
+  private:
+    const std::string error{};
+};
+
+/**
  * Creates the parent objects that normally contain a PresenceDetection object.
  *
  * A PresenceDetection object is normally contained within a hierarchy of
@@ -239,8 +272,7 @@
                     isPresent("/xyz/openbmc_project/inventory/system/chassis/"
                               "motherboard/cpu2"))
             .Times(1)
-            .WillOnce(
-                Throw(std::runtime_error{"DBusError: Invalid object path."}));
+            .WillOnce(Throw(TestSDBusError{"DBusError: Invalid object path."}));
 
         // Define expected journal messages that should be passed to MockJournal
         MockJournal& journal = services.getMockJournal();
@@ -254,6 +286,12 @@
                     logError("Unable to determine presence of vdd_reg"))
             .Times(1);
 
+        // Expect logDBusError() to be called
+        MockErrorLogging& errorLogging = services.getMockErrorLogging();
+        EXPECT_CALL(errorLogging,
+                    logDBusError(Entry::Level::Warning, Ref(journal)))
+            .Times(1);
+
         // Execute PresenceDetection.  Should return true when an error occurs.
         EXPECT_TRUE(detection->execute(services, *system, *chassis, *device));
 
diff --git a/phosphor-regulators/test/sensor_monitoring_tests.cpp b/phosphor-regulators/test/sensor_monitoring_tests.cpp
index 4d31e4e..ebb8998 100644
--- a/phosphor-regulators/test/sensor_monitoring_tests.cpp
+++ b/phosphor-regulators/test/sensor_monitoring_tests.cpp
@@ -19,6 +19,7 @@
 #include "device.hpp"
 #include "i2c_interface.hpp"
 #include "mock_action.hpp"
+#include "mock_error_logging.hpp"
 #include "mock_journal.hpp"
 #include "mock_services.hpp"
 #include "mocked_i2c_interface.hpp"
@@ -43,6 +44,7 @@
 using namespace phosphor::power::regulators::pmbus_utils;
 
 using ::testing::A;
+using ::testing::Ref;
 using ::testing::Return;
 using ::testing::Throw;
 using ::testing::TypedEq;
@@ -128,19 +130,24 @@
 
     // Test where fails
     {
-        // Create mock services.  Expect logError() to be called.
+        // Create mock services.  Expect logError() and logI2CError() to be
+        // called.
         MockServices services{};
+        MockErrorLogging& errorLogging = services.getMockErrorLogging();
         MockJournal& journal = services.getMockJournal();
         EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
         std::vector<std::string> expectedErrMessagesException{
             "I2CException: Failed to write byte: bus /dev/i2c-1, addr 0x70",
             "ActionError: pmbus_read_sensor: { type: iout, command: 0x8C, "
             "format: linear_11 }"};
-
         EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
         EXPECT_CALL(journal,
                     logError("Unable to monitor sensors for rail vio2"))
             .Times(1);
+        EXPECT_CALL(errorLogging,
+                    logI2CError(Entry::Level::Warning, Ref(journal),
+                                "/dev/i2c-1", 0x70, 0))
+            .Times(1);
 
         // Create PMBusReadSensorAction
         pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};