Add optional sensor reading logging instrumentation
Noteworthy sensor readings,
such as the first reading,
a new minimum or maximum value,
or ending a good or bad streak of readings,
will now have some useful logging output.
This feature defaults to disabled, to enable it,
set "enableInstrumentation" constant to "true".
Tested:
It runs, and produces useful output, when enabled.
When disabled, it does nothing.
Signed-off-by: Josh Lehan <krellan@google.com>
Change-Id: I4c1b5105ad6dbb92ae6a23f2b99e2a8b68b56dca
diff --git a/include/sensor.hpp b/include/sensor.hpp
index 6fd7e43..0ef87d5 100644
--- a/include/sensor.hpp
+++ b/include/sensor.hpp
@@ -12,6 +12,10 @@
constexpr size_t sensorFailedPollTimeMs = 5000;
+// Enable useful logging with sensor instrumentation
+// This is intentionally not DEBUG, avoid clash with usage in .cpp files
+constexpr bool enableInstrumentation = false;
+
constexpr const char* sensorValueInterface = "xyz.openbmc_project.Sensor.Value";
constexpr const char* availableInterfaceName =
"xyz.openbmc_project.State.Decorator.Availability";
@@ -19,6 +23,17 @@
"xyz.openbmc_project.State.Decorator.OperationalStatus";
constexpr const size_t errorThreshold = 5;
+struct SensorInstrumentation
+{
+ // These are for instrumentation for debugging
+ int numCollectsGood = 0;
+ int numCollectsMiss = 0;
+ int numStreakGreats = 0;
+ int numStreakMisses = 0;
+ double minCollected = 0.0;
+ double maxCollected = 0.0;
+};
+
struct Sensor
{
Sensor(const std::string& name,
@@ -32,7 +47,10 @@
maxValue(max), minValue(min), thresholds(std::move(thresholdData)),
hysteresisTrigger((max - min) * 0.01),
hysteresisPublish((max - min) * 0.0001), dbusConnection(conn),
- readState(readState), errCount(0)
+ readState(readState), errCount(0),
+ instrumentation(enableInstrumentation
+ ? std::make_unique<SensorInstrumentation>()
+ : nullptr)
{}
virtual ~Sensor() = default;
virtual void checkThresholds(void) = 0;
@@ -57,6 +75,93 @@
std::shared_ptr<sdbusplus::asio::connection> dbusConnection;
PowerState readState;
size_t errCount;
+ std::unique_ptr<SensorInstrumentation> instrumentation;
+
+ void updateInstrumentation(double readValue)
+ {
+ // Do nothing if this feature is not enabled
+ if constexpr (!enableInstrumentation)
+ {
+ return;
+ }
+ if (!instrumentation)
+ {
+ return;
+ }
+
+ // Save some typing
+ auto& inst = *instrumentation;
+
+ // Show constants if first reading (even if unsuccessful)
+ if ((inst.numCollectsGood == 0) && (inst.numCollectsMiss == 0))
+ {
+ std::cerr << "Sensor " << name << ": Configuration min=" << minValue
+ << ", max=" << maxValue << ", type=" << objectType
+ << ", path=" << configurationPath << "\n";
+ }
+
+ // Sensors can use "nan" to indicate unavailable reading
+ if (!std::isfinite(readValue))
+ {
+ // Only show this if beginning a new streak
+ if (inst.numStreakMisses == 0)
+ {
+ std::cerr << "Sensor " << name
+ << ": Missing reading, Reading counts good="
+ << inst.numCollectsGood
+ << ", miss=" << inst.numCollectsMiss
+ << ", Prior good streak=" << inst.numStreakGreats
+ << "\n";
+ }
+
+ inst.numStreakGreats = 0;
+ ++(inst.numCollectsMiss);
+ ++(inst.numStreakMisses);
+
+ return;
+ }
+
+ // Only show this if beginning a new streak and not the first time
+ if ((inst.numStreakGreats == 0) && (inst.numCollectsGood != 0))
+ {
+ std::cerr << "Sensor " << name
+ << ": Recovered reading, Reading counts good="
+ << inst.numCollectsGood
+ << ", miss=" << inst.numCollectsMiss
+ << ", Prior miss streak=" << inst.numStreakMisses << "\n";
+ }
+
+ // Initialize min/max if the first successful reading
+ if (inst.numCollectsGood == 0)
+ {
+ std::cerr << "Sensor " << name << ": First reading=" << readValue
+ << "\n";
+
+ inst.minCollected = readValue;
+ inst.maxCollected = readValue;
+ }
+
+ inst.numStreakMisses = 0;
+ ++(inst.numCollectsGood);
+ ++(inst.numStreakGreats);
+
+ // Only provide subsequent output if new min/max established
+ if (readValue < inst.minCollected)
+ {
+ std::cerr << "Sensor " << name << ": Lowest reading=" << readValue
+ << "\n";
+
+ inst.minCollected = readValue;
+ }
+
+ if (readValue > inst.maxCollected)
+ {
+ std::cerr << "Sensor " << name << ": Highest reading=" << readValue
+ << "\n";
+
+ inst.maxCollected = readValue;
+ }
+ }
int setSensorValue(const double& newValue, double& oldValue)
{
@@ -286,6 +391,7 @@
}
updateValueProperty(newValue);
+ updateInstrumentation(newValue);
// Always check thresholds after changing the value,
// as the test against hysteresisTrigger now takes place in