1 #pragma once
2 
3 #include "health_metric_config.hpp"
4 #include "health_utils.hpp"
5 
6 #include <xyz/openbmc_project/Association/Definitions/server.hpp>
7 #include <xyz/openbmc_project/Inventory/Item/Bmc/server.hpp>
8 #include <xyz/openbmc_project/Metric/Value/server.hpp>
9 
10 #include <deque>
11 #include <tuple>
12 
13 namespace phosphor::health::metric
14 {
15 
16 using phosphor::health::utils::paths_t;
17 using phosphor::health::utils::startUnit;
18 using AssociationIntf =
19     sdbusplus::xyz::openbmc_project::Association::server::Definitions;
20 using ValueIntf = sdbusplus::xyz::openbmc_project::Metric::server::Value;
21 using PathIntf =
22     sdbusplus::common::xyz::openbmc_project::metric::Value::namespace_path;
23 static constexpr auto BmcPath =
24     sdbusplus::common::xyz::openbmc_project::metric::Value::bmc;
25 using BmcIntf = sdbusplus::xyz::openbmc_project::Inventory::Item::server::Bmc;
26 using MetricIntf =
27     sdbusplus::server::object_t<ValueIntf, ThresholdIntf, AssociationIntf>;
28 
29 struct MValue
30 {
31     /** @brief Current value of metric */
32     double current;
33     /** @brief Total value of metric */
34     double total;
35 };
36 
37 class HealthMetric : public MetricIntf
38 {
39   public:
40     using MType = phosphor::health::metric::Type;
41 
42     HealthMetric() = delete;
43     HealthMetric(const HealthMetric&) = delete;
44     HealthMetric(HealthMetric&&) = delete;
45     virtual ~HealthMetric() = default;
46 
HealthMetric(sdbusplus::bus_t & bus,MType type,const config::HealthMetric & config,const paths_t & bmcPaths)47     HealthMetric(sdbusplus::bus_t& bus, MType type,
48                  const config::HealthMetric& config, const paths_t& bmcPaths) :
49         MetricIntf(bus, getPath(type, config.name, config.subType).c_str(),
50                    action::defer_emit),
51         bus(bus), type(type), config(config)
52     {
53         create(bmcPaths);
54         this->emit_object_added();
55     }
56 
57     /** @brief Update the health metric with the given value */
58     void update(MValue value);
59 
60   private:
61     /** @brief Create a new health metric object */
62     void create(const paths_t& bmcPaths);
63     /** @brief Init properties for the health metric object */
64     void initProperties();
65     /** @brief Check if specified value should be notified based on hysteresis
66      */
67     auto shouldNotify(MValue value) -> bool;
68     /** @brief Check specified threshold for the given value */
69     void checkThreshold(Type type, Bound bound, MValue value);
70     /** @brief Check all thresholds for the given value */
71     void checkThresholds(MValue value);
72     /** @brief Get the object path for the given type, name and subtype */
73     auto getPath(MType type, std::string name, SubType subType) -> std::string;
74     /** @brief D-Bus bus connection */
75     sdbusplus::bus_t& bus;
76     /** @brief Metric type */
77     MType type;
78     /** @brief Metric configuration */
79     const config::HealthMetric config;
80     /** @brief Window for metric history */
81     std::deque<double> history;
82     /** @brief Last notified value for the metric change */
83     double lastNotifiedValue = 0;
84 };
85 
86 } // namespace phosphor::health::metric
87