Skip to content

Commit 1aa94df

Browse files
harshit-agheraedtanous
authored andcommitted
sensor_utils: Add PeakReading property
Add support for PeakReading and PeakReadingTime for sensors. This enhancement allows sensor readings to include max observed value information in the Redfish API, along with timestamp. It uses PDI xyz.openbmc_project.Telemetry.Report. Property PeakReading is added if OperationType in PDI property ReadingParameters is set to Maximum. Current Limitation - The ResetMetrics action is currently not supported for sensor URIs. As a result, the ability to clear PeakReading values for GPU Power Sensors has not been implemented. Future Consideration - If ResetMetrics action support is added in the future, the corresponding functionality will also need to be implemented in the dbus-sensor application to ensure full compatibility. Schema: https://redfish.dmtf.org/schemas/v1/Sensor.v1_2_0.yaml (PeakReading) Backend implementation for reference: https://gerrit.openbmc.org/c/openbmc/dbus-sensors/+/82479 Tested: Build an image for nvl32-obmc machine with the following patches cherry picked. https://gerrit.openbmc.org/c/openbmc/openbmc/+/85490 https://gerrit.openbmc.org/c/openbmc/bmcweb/+/82449. The patch cherry-picks the following patches that are currently under review. ``` 1. device tree https://lore.kernel.org/all/[email protected]/ 2. mctpd patches CodeConstruct/mctp#85 3. u-boot changes https://lore.kernel.org/openbmc/[email protected]/T/#t 4. kernel changes as specified in the openbmc patch (for espi) 5. entity-manager changes https://gerrit.openbmc.org/c/openbmc/entity-manager/+/85455 6. platform-init changes https://gerrit.openbmc.org/c/openbmc/platform-init/+/85456 7. spi changes https://lore.kernel.org/all/[email protected]/ ``` ``` > curl -s -k -u 'root:0penBmc' https://10.137.203.137/redfish/v1/Chassis/NVIDIA_GB200_1/Sensors/power_NVIDIA_GB200_GPU_0_Power_0 { "@odata.id": "/redfish/v1/Chassis/NVIDIA_GB200_1/Sensors/power_NVIDIA_GB200_GPU_0_Power_0", "@odata.type": "#Sensor.v1_2_0.Sensor", "Id": "power_NVIDIA_GB200_GPU_0_Power_0", "Name": "NVIDIA GB200 GPU 0 Power 0", "PeakReading": 52.671, "PeakReadingTime": 0, "Reading": 27.214, "ReadingRangeMax": 5000.0, "ReadingRangeMin": 0.0, "ReadingType": "Power", "ReadingUnits": "W", "Status": { "Health": "OK", "State": "Enabled" } }% ```` Change-Id: I8c1ab6ce85f31419db4a1d931bf99722d24afbd7 Signed-off-by: Harshit Aghera <[email protected]>
1 parent 57d41fe commit 1aa94df

File tree

4 files changed

+119
-1
lines changed

4 files changed

+119
-1
lines changed

docs/Redfish.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,8 @@ Fields common to all schemas
291291
#### Sensor
292292

293293
- Implementation
294+
- PeakReading
295+
- PeakReadingTime
294296
- Reading
295297
- ReadingBasis
296298
- ReadingRangeMax

include/dbus_utility.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ using DbusVariantType = std::variant<
4949
std::vector<uint16_t>,
5050
sdbusplus::message::object_path,
5151
std::tuple<uint64_t, std::vector<std::tuple<std::string, double, uint64_t>>>,
52+
std::tuple<uint64_t, std::vector<std::tuple<std::string, std::string, double, uint64_t>>>,
5253
std::vector<sdbusplus::message::object_path>,
5354
std::vector<std::tuple<std::string, std::string>>,
5455
std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>,

redfish-core/include/utils/sensor_utils.hpp

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,47 @@ inline sensor::ReadingType toReadingType(std::string_view sensorType)
288288

289289
} // namespace sensors
290290

291+
// represents metric Id, metadata, reading value and timestamp of single
292+
// reading update in milliseconds
293+
using Reading = std::tuple<std::string, std::string, double, uint64_t>;
294+
// represents multiple independent readings
295+
using Readings = std::vector<Reading>;
296+
// represents a timestamp and multiple independent readings
297+
using Statistics = std::tuple<uint64_t, Readings>;
298+
// represents sensor's path, its metadata
299+
using SensorPaths =
300+
std::vector<std::tuple<sdbusplus::message::object_path, std::string>>;
301+
// represents reading parameters for statistics readings
302+
using ReadingParameters =
303+
std::vector<std::tuple<SensorPaths, std::string, std::string, uint64_t>>;
304+
305+
inline void updateSensorStatistics(
306+
nlohmann::json& sensorJson, const std::optional<Statistics>& statistics,
307+
const std::optional<ReadingParameters>& readingParameters)
308+
{
309+
if (statistics.has_value() && readingParameters.has_value())
310+
{
311+
Readings metrics = std::get<1>(*statistics);
312+
for (const auto& [sensorPaths, operationType, metricId, duration] :
313+
*readingParameters)
314+
{
315+
if (operationType ==
316+
"xyz.openbmc_project.Telemetry.Report.OperationType.Maximum")
317+
{
318+
if (metrics.size() == 1)
319+
{
320+
const auto& [id, metadata, value, timestamp] = metrics[0];
321+
sensorJson["PeakReading"] = value;
322+
if (timestamp != 0)
323+
{
324+
sensorJson["PeakReadingTime"] = timestamp;
325+
}
326+
}
327+
}
328+
}
329+
}
330+
}
331+
291332
/**
292333
* @brief Returns the Redfish State value for the specified inventory item.
293334
* @param inventoryItem D-Bus inventory item associated with a sensor.
@@ -519,11 +560,14 @@ inline void objectPropertiesToJson(
519560
bool available = true;
520561
std::optional<std::string> readingBasis;
521562
std::optional<std::string> implementation;
563+
std::optional<Statistics> statistics;
564+
std::optional<ReadingParameters> readingParameters;
522565

523566
const bool success = sdbusplus::unpackPropertiesNoThrow(
524567
dbus_utils::UnpackErrorPrinter(), propertiesDict, "Available",
525568
checkAvailable, "ReadingBasis", readingBasis, "Implementation",
526-
implementation);
569+
implementation, "Readings", statistics, "ReadingParameters",
570+
readingParameters);
527571
if (!success)
528572
{
529573
messages::internalError();
@@ -583,6 +627,8 @@ inline void objectPropertiesToJson(
583627
sensorJson["Implementation"] = implementationOpt;
584628
}
585629
}
630+
631+
updateSensorStatistics(sensorJson, statistics, readingParameters);
586632
}
587633
else if (sensorType == "temperature")
588634
{

test/redfish-core/include/utils/sensor_utils_test.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// SPDX-FileCopyrightText: Copyright OpenBMC Authors
33
#include "utils/sensor_utils.hpp"
44

5+
#include <optional>
56
#include <string>
7+
#include <tuple>
68

79
#include <gtest/gtest.h>
810

@@ -112,5 +114,72 @@ TEST(IsExcerptNode, False)
112114
EXPECT_FALSE(isExcerptNode(ChassisSubNode::unknownNode));
113115
}
114116

117+
TEST(UpdateSensorStatistics, ParametersValid)
118+
{
119+
nlohmann::json sensorJson;
120+
Reading reading =
121+
std::make_tuple("metricId1", "metadata1", 42.5, 1234567890);
122+
Readings metrics = {reading};
123+
Statistics statistics = std::make_tuple(1234567890, metrics);
124+
SensorPaths sensorPaths;
125+
ReadingParameters readingParams = {std::make_tuple(
126+
sensorPaths,
127+
"xyz.openbmc_project.Telemetry.Report.OperationType.Maximum",
128+
"metricId1", 60)};
129+
130+
updateSensorStatistics(sensorJson, statistics, readingParams);
131+
132+
EXPECT_EQ(sensorJson["PeakReading"], 42.5);
133+
EXPECT_EQ(sensorJson["PeakReadingTime"], 1234567890);
134+
}
135+
136+
TEST(UpdateSensorStatistics, EmptyMetrics)
137+
{
138+
nlohmann::json sensorJson;
139+
Readings metrics;
140+
Statistics statistics = std::make_tuple(1234567890, metrics);
141+
SensorPaths sensorPaths;
142+
ReadingParameters readingParams = {std::make_tuple(
143+
sensorPaths,
144+
"xyz.openbmc_project.Telemetry.Report.OperationType.Maximum",
145+
"metricId1", 60)};
146+
147+
updateSensorStatistics(sensorJson, statistics, readingParams);
148+
149+
EXPECT_FALSE(sensorJson.contains("PeakReading"));
150+
EXPECT_FALSE(sensorJson.contains("PeakReadingTime"));
151+
}
152+
153+
TEST(UpdateSensorStatistics, NonMaximumOperationType)
154+
{
155+
nlohmann::json sensorJson;
156+
Reading reading =
157+
std::make_tuple("metricId1", "metadata1", 42.5, 1234567890);
158+
Readings metrics = {reading};
159+
Statistics statistics = std::make_tuple(1234567890, metrics);
160+
SensorPaths sensorPaths;
161+
ReadingParameters readingParams = {std::make_tuple(
162+
sensorPaths,
163+
"xyz.openbmc_project.Telemetry.Report.OperationType.Minimum",
164+
"metricId1", 60)};
165+
166+
updateSensorStatistics(sensorJson, statistics, readingParams);
167+
168+
EXPECT_FALSE(sensorJson.contains("PeakReading"));
169+
EXPECT_FALSE(sensorJson.contains("PeakReadingTime"));
170+
}
171+
172+
TEST(UpdateSensorStatistics, ParamsNullopt)
173+
{
174+
nlohmann::json sensorJson;
175+
std::optional<Statistics> statistics = std::nullopt;
176+
std::optional<ReadingParameters> readingParams = std::nullopt;
177+
178+
updateSensorStatistics(sensorJson, statistics, readingParams);
179+
180+
EXPECT_FALSE(sensorJson.contains("PeakReading"));
181+
EXPECT_FALSE(sensorJson.contains("PeakReadingTime"));
182+
}
183+
115184
} // namespace
116185
} // namespace redfish::sensor_utils

0 commit comments

Comments
 (0)