platform-mc: Add structured logging for threshold events

Create structured threshold log events up creation
and alert triggers. These will also clear previously
raised logs.

Tested:
Bump the fan speed to low and let the CPU heat up.
Ensure we emit logs on Upper Critical and Upper Hard Shutdown.
```
root@sled325945102-oob:~# busctl introspect -l xyz.openbmc_project.Logging /xyz/openbmc_project/logging/entry/19 xyz.openbmc_project.Logging.Entry | grep "AdditionalData\|Message\|Resolved"
.AdditionalData property  a{ss}  8 "READING_VALUE" "90.125" "SENSOR_NAME" "/xyz/openbmc_project/sensors/temperature/Sentinel_Dome_Slot_1_MB_CPU_TEMP_C" "THRESHOLD_VALUE" "90.0" "UNITS" "xyz.openbmc_project.Sensor.Value.Unit.DegreesC" <snip>
.Message property  s "xyz.openbmc_project.Sensor.Threshold.ReadingAboveUpperCriticalThreshold" emits-change writable
.Resolved property  b false emits-change writable

root@sled325945102-oob:~# busctl introspect -l xyz.openbmc_project.Logging /xyz/openbmc_project/logging/entry/21 xyz.openbmc_project.Logging.Entry | grep "AdditionalData\|Message\|Resolved"
.AdditionalData property  a{ss} 8 "READING_VALUE" "95.125" "SENSOR_NAME" "/xyz/openbmc_project/sensors/temperature/Sentinel_Dome_Slot_1_MB_CPU_TEMP_C" "THRESHOLD_VALUE" "95.0" "UNITS" "xyz.openbmc_project.Sensor.Value.Unit.DegreesC" <snip>
.Message property  s "xyz.openbmc_project.Sensor.Threshold.ReadingAboveUpperHardShutdownThreshold" emits-change writable
.Resolved property  b         false emits-change writable
```
Bump the fan speed back to high and let the CPU cool down.
Ensure we emit the SensorReadingNormalRange and that the
existing logs are marked as resolved.
```
root@sled325945102-oob:~# busctl introspect -l xyz.openbmc_project.Logging /xyz/openbmc_project/logging/entry/22 xyz.openbmc_project.Logging.Entry | grep "AdditionalData\|Message\|Resolved"
.AdditionalData property  a{ss} 7 "READING_VALUE" "85.75" "SENSOR_NAME" "/xyz/openbmc_project/sensors/temperature/Sentinel_Dome_Slot_1_MB_CPU_TEMP_C" "UNITS" "xyz.openbmc_project.Sensor.Value.Unit.DegreesC" <snip>
.Message property  s  "xyz.openbmc_project.Sensor.Threshold.SensorReadingNormalRange" change writable
.Resolved property  b false change writable

root@sled325945102-oob:~# busctl introspect -l xyz.openbmc_project.Logging /xyz/openbmc_project/logging/entry/19 xyz.openbmc_project.Logging.Entry | grep "AdditionalData\|Message\|Resolved"
.AdditionalData property  a{ss} 8 "READING_VALUE" "90.125" "SENSOR_NAME" "/xyz/openbmc_project/sensors/temperature/Sentinel_Dome_Slot_1_MB_CPU_TEMP_C" "THRESHOLD_VALUE" "90.0" "UNITS" "xyz.openbmc_project.Sensor.Value.Unit.DegreesC" <snip>
.Message property  s  "xyz.openbmc_project.Sensor.Threshold.ReadingAboveUpperCriticalThreshold" emits-change writable
.Resolved property  b true emits-change writable

root@sled325945102-oob:~# busctl introspect -l xyz.openbmc_project.Logging /xyz/openbmc_project/logging/entry/21 xyz.openbmc_project.Logging.Entry | grep "AdditionalData\|Message\|Resolved"
.AdditionalData property  a{ss}     8 "READING_VALUE" "95.125" "SENSOR_NAME" "/xyz/openbmc_project/sensors/temperature/Sentinel_Dome_Slot_1_MB_CPU_TEMP_C" "THRESHOLD_VALUE" "95.0" "UNITS" "xyz.openbmc_project.Sensor.Value.Unit.DegreesC" <snip>
.Message property  s "xyz.openbmc_project.Sensor.Threshold.ReadingAboveUpperHardShutdownThreshold" emits-change writable
.Resolved property  b true emits-change writable
```

Change-Id: I72623f7f929a4d7b17f87d102d34747ff6cab3ae
Signed-off-by: Amithash Prasad <amithash@meta.com>
diff --git a/platform-mc/numeric_sensor.hpp b/platform-mc/numeric_sensor.hpp
index b09bcd4..3d115b7 100644
--- a/platform-mc/numeric_sensor.hpp
+++ b/platform-mc/numeric_sensor.hpp
@@ -294,6 +294,12 @@
         return false;
     }
 
+    /* @brief Returns true if at least one threshold alarm is set
+     *
+     * @return true if at least one threshold alarm is set
+     */
+    bool hasThresholdAlarm();
+
     /* @brief raises the alarm on the warning threshold
      *
      * @param[in] direction - The threshold direction (HIGH/LOW)
@@ -381,6 +387,31 @@
 
   private:
     /**
+     * @brief resolve and clear a log entry
+     *
+     * @param[inout] log - dbus path to log entry. The log will be resolve
+     *               and the optional reset.
+     */
+    void clearThresholdLog(std::optional<sdbusplus::message::object_path>& log);
+
+    /** @brief create a log entry that all sensor alarms have cleared and is now
+     *  operating in the normal operating range.
+     *
+     *  @param[in] value - The current sensor value in normal range.
+     */
+    void createNormalRangeLog(double value);
+
+    /**
+     *  @brief Create a threshold log for the given level/direction tuple.
+     *
+     *  @param[in] level - The level of the threshold.
+     *  @param[in] direction - The direction of the threshold.
+     *  @param[in] value - The current sensor value.
+     */
+    void createThresholdLog(pldm::utils::Level level,
+                            pldm::utils::Direction direction, double value);
+
+    /**
      * @brief Check sensor reading if any threshold has been crossed and update
      * Threshold interfaces accordingly
      */
@@ -431,6 +462,12 @@
     /** @brief A power-of-10 multiplier for baseUnit */
     int8_t baseUnitModifier;
     bool useMetricInterface = false;
+
+    /** @brief An internal mapping of thresholds and its associated log
+     * entry. */
+    std::map<std::tuple<pldm::utils::Level, pldm::utils::Direction>,
+             std::optional<sdbusplus::message::object_path>>
+        assertedLog;
 };
 } // namespace platform_mc
 } // namespace pldm