ipmi: Add sdr cache reset logs

Add some limited logs on when sensor cache gets reset every 30 seconds.

Tested:
ipmi still works after updating the library
```
$ systemctl restart phosphor-ipmi-host
$ ipmitool sdr
BRICK2_P12V_IOUT | 13.08 Amps        | ok
CPU0_P1V1_IOUT   | 7.75 Amps         | ok
CPU0_P1V8_IOUT   | 6.39 Amps         | ok
CPU0_P3V3_IOUT   | 0 Amps            | ok
```

Log Example with the timeout working.

Restart the psu sensors to reset the sdr cache.
```
$ journalctl -f | grep "Sensor Cache Tree"
May 29 13:12:35 gbmc ipmid[18845]: Sensor Cache Tree reset with /xyz/openbmc_project/sensors/current/BRICK2_P12V_IOUT/chassis
...
May 29 13:12:35 gbmc ipmid[18845]: Sensor Cache Tree reset with /xyz/openbmc_project/sensors/current/CPU0_VSOC_IOUT/inventory

May 29 13:13:14 gbmc ipmid[18845]: Sensor Cache Tree reset with /xyz/openbmc_project/sensors/current/BRICK2_P12V_IOUT/chassis
...
```

Fusion-Link: http://fusion2/66e1dc13-01b8-3808-8f90-5e2af7e19f43
Google-Bug-Id: 325269540
Change-Id: Id1cfecfab5e37412f6e72cc90ca2e7fca47f4816
Signed-off-by: Willy Tu <wltu@google.com>
(cherry picked from commit 4bb47cba39c2c4041c5e1cc90e589e715b37be9a)
diff --git a/recipes-phosphor/ipmi/phosphor-ipmi-host/0007-dbus-sdr-Add-limited-log-on-sensorTree-Resets.patch b/recipes-phosphor/ipmi/phosphor-ipmi-host/0007-dbus-sdr-Add-limited-log-on-sensorTree-Resets.patch
new file mode 100644
index 0000000..75b51c4
--- /dev/null
+++ b/recipes-phosphor/ipmi/phosphor-ipmi-host/0007-dbus-sdr-Add-limited-log-on-sensorTree-Resets.patch
@@ -0,0 +1,160 @@
+From efda29daceb0dd149744a4d9a3f0f46dcd9bedd8 Mon Sep 17 00:00:00 2001
+From: Willy Tu <wltu@google.com>
+Date: Wed, 29 May 2024 17:50:09 +0000
+Subject: [PATCH] dbus-sdr: Add limited log on sensorTree Resets
+
+Tested:
+ipmi still works after updating the library
+```
+$ systemctl restart phosphor-ipmi-host
+$ ipmitool sdr
+BRICK2_P12V_IOUT | 13.08 Amps        | ok
+CPU0_P1V1_IOUT   | 7.75 Amps         | ok
+CPU0_P1V8_IOUT   | 6.39 Amps         | ok
+CPU0_P3V3_IOUT   | 0 Amps            | ok
+```
+
+Log Example with the timeout working
+```
+root@yscdn3-nfd01:~# journalctl -f | grep "Sensor Cache Tree"
+May 29 13:12:35 gbmc ipmid[18845]: Sensor Cache Tree reset with /xyz/openbmc_project/sensors/current/BRICK2_P12V_IOUT/chassis
+...
+May 29 13:12:35 gbmc ipmid[18845]: Sensor Cache Tree reset with /xyz/openbmc_project/sensors/current/CPU0_VSOC_IOUT/inventory
+
+May 29 13:13:14 gbmc ipmid[18845]: Sensor Cache Tree reset with /xyz/openbmc_project/sensors/current/BRICK2_P12V_IOUT/chassis
+...
+```
+
+Patch Tracking Bug: b/343799072
+Upstream info / review: http://go/openbmccl/71702
+Upstream-Status: Submitted
+Justification: bugfix(b/325269540). Pending upstream reviews.
+Google-Bug-Id: 325269540
+Google-Bug-Id: 343799072
+Change-Id: Ie804a3e9a9ca19e6856a0cf65ca9170c6edeca05
+Signed-off-by: Willy Tu <wltu@google.com>
+---
+ dbus-sdr/sdrutils.cpp         | 37 ++++++++++++++++++++++++++++++++---
+ dbus-sdr/sensorcommands.cpp   |  2 ++
+ include/dbus-sdr/sdrutils.hpp |  1 +
+ 3 files changed, 37 insertions(+), 3 deletions(-)
+
+diff --git a/dbus-sdr/sdrutils.cpp b/dbus-sdr/sdrutils.cpp
+index 981e1c7..b7edfa3 100644
+--- a/dbus-sdr/sdrutils.cpp
++++ b/dbus-sdr/sdrutils.cpp
+@@ -21,8 +21,9 @@
+ #include <ipmid/utils.hpp>
+ 
+ #include <algorithm>
+-#include <regex>
++#include <chrono>
+ #include <optional>
++#include <regex>
+ #include <unordered_set>
+ 
+ constexpr std::array<const char*, 7> suffixes = {
+@@ -144,6 +145,7 @@ bool isExpectedInventoryInterfacesAdded(sdbusplus::message_t& message)
+         // Only expects Item.Cable interface for now
+         if (pair.first == itemCableInterface)
+         {
++            logCacheReset(path.str);
+             return true;
+         }
+     }
+@@ -162,6 +164,34 @@ bool isInSkipTempSensorRegex(std::string_view path)
+     return std::regex_match(sensorName, skipRegex);
+ }
+ 
++void logCacheReset(std::string_view path)
++{
++    static std::chrono::time_point cacheLogTime =
++        std::chrono::system_clock::now();
++    constexpr std::chrono::seconds cacheLogTimeout(30);
++    constexpr uint8_t loggingLimit = 30;
++    static uint8_t logCount = 0;
++
++    std::chrono::time_point now = std::chrono::system_clock::now();
++    std::chrono::duration<double> elapsedSeconds = now - cacheLogTime;
++    // If the logCount is greater than the limit and we haven't timedout... then
++    // should stop logging until the timer resets.
++    if (logCount > loggingLimit && elapsedSeconds < cacheLogTimeout)
++    {
++        return;
++    }
++
++    // Reset logCount and start of cacheLogTime if we have already timedout.
++    if (elapsedSeconds >= cacheLogTimeout)
++    {
++        logCount = 0;
++        cacheLogTime = now;
++    }
++
++    logCount++;
++    std::cerr << "Sensor Cache Tree reset with " << path << std::endl;
++}
++
+ uint16_t getSensorSubtree(std::shared_ptr<SensorSubTree>& subtree)
+ {
+     static std::shared_ptr<SensorSubTree> sensorTreePtr;
+@@ -176,6 +206,7 @@ uint16_t getSensorSubtree(std::shared_ptr<SensorSubTree>& subtree)
+         msg.read(path);
+         if (isInSkipTempSensorRegex(path.str))
+             return;
++        logCacheReset(path.str);
+         sensorTreePtr.reset();
+     });
+ 
+@@ -188,6 +219,7 @@ uint16_t getSensorSubtree(std::shared_ptr<SensorSubTree>& subtree)
+         msg.read(path);
+         if (isInSkipTempSensorRegex(path.str))
+             return;
++        logCacheReset(path.str);
+         sensorTreePtr.reset();
+     });
+ 
+@@ -223,8 +255,7 @@ uint16_t getSensorSubtree(std::shared_ptr<SensorSubTree>& subtree)
+ 
+     static constexpr const int32_t depth = 2;
+ 
+-    auto lbdUpdateSensorTree = [&dbus](const char* path,
+-                                       const auto& interfaces,
++    auto lbdUpdateSensorTree = [&dbus](const char* path, const auto& interfaces,
+                                        const bool groupByObjPath = false) {
+         auto mapperCall = dbus->new_method_call(
+             "xyz.openbmc_project.ObjectMapper",
+diff --git a/dbus-sdr/sensorcommands.cpp b/dbus-sdr/sensorcommands.cpp
+index a2bebd3..f2bdd46 100644
+--- a/dbus-sdr/sensorcommands.cpp
++++ b/dbus-sdr/sensorcommands.cpp
+@@ -140,6 +140,7 @@ static sdbusplus::bus::match_t sensorAdded(
+     msg.read(path);
+     if (details::isInSkipTempSensorRegex(path.str))
+         return;
++    details::logCacheReset(path.str);
+     getSensorTree().clear();
+     getIpmiDecoratorPaths(/*ctx=*/std::nullopt).reset();
+     sdrLastAdd = std::chrono::duration_cast<std::chrono::seconds>(
+@@ -156,6 +157,7 @@ static sdbusplus::bus::match_t sensorRemoved(
+     msg.read(path);
+     if (details::isInSkipTempSensorRegex(path.str))
+         return;
++    details::logCacheReset(path.str);
+     getSensorTree().clear();
+     getIpmiDecoratorPaths(/*ctx=*/std::nullopt).reset();
+     sdrLastRemove = std::chrono::duration_cast<std::chrono::seconds>(
+diff --git a/include/dbus-sdr/sdrutils.hpp b/include/dbus-sdr/sdrutils.hpp
+index 1fa634a..d1c98ab 100644
+--- a/include/dbus-sdr/sdrutils.hpp
++++ b/include/dbus-sdr/sdrutils.hpp
+@@ -286,6 +286,7 @@ bool getSensorNumMap(std::shared_ptr<SensorNumMap>& sensorNumMap);
+ bool isExpectedInventoryInterfacesRemoved(sdbusplus::message_t& message);
+ bool isExpectedInventoryInterfacesAdded(sdbusplus::message_t& message);
+ bool isInSkipTempSensorRegex(std::string_view path);
++void logCacheReset(std::string_view path);
+ } // namespace details
+ 
+ bool getSensorSubtree(SensorSubTree& subtree);
+-- 
+2.45.1.288.g0e0cd299f1-goog
+
diff --git a/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend b/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend
index 89e8688..43b4412 100644
--- a/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend
+++ b/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend
@@ -9,4 +9,5 @@
   file://0004-Fix-ID-String-Type-Length-Code-byte-for-get-sdr-comm.patch \
   file://0005-dbus-sdr-add-event-type-for-sdr-count.patch \
   file://0006-dbus-sdr-fix-write-permission-for-external-sen.patch \
+  file://0007-dbus-sdr-Add-limited-log-on-sensorTree-Resets.patch \
 "