blob: 08a3a2cefa00e00880d4c518cb91bb93b264cfdc [file] [log] [blame]
Matt Spinler403d1f52021-02-01 15:35:25 -06001/**
2 * Copyright © 2021 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "threshold_alarm_logger.hpp"
17
Matt Spinler50bf8162021-02-01 16:24:01 -060018#include "sdbusplus.hpp"
19
20#include <fmt/format.h>
21
22#include <phosphor-logging/log.hpp>
23#include <xyz/openbmc_project/Logging/Entry/server.hpp>
24
Matt Spinler403d1f52021-02-01 15:35:25 -060025namespace sensor::monitor
26{
27
Matt Spinler50bf8162021-02-01 16:24:01 -060028using namespace sdbusplus::xyz::openbmc_project::Logging::server;
29using namespace phosphor::logging;
30using namespace phosphor::fan::util;
31
Matt Spinler403d1f52021-02-01 15:35:25 -060032const std::string warningInterface =
33 "xyz.openbmc_project.Sensor.Threshold.Warning";
34const std::string criticalInterface =
35 "xyz.openbmc_project.Sensor.Threshold.Critical";
36const std::string perfLossInterface =
37 "xyz.openbmc_project.Sensor.Threshold.PerformanceLoss";
38
Matt Spinler50bf8162021-02-01 16:24:01 -060039using ErrorData = std::tuple<ErrorName, Entry::Level>;
40
41/**
42 * Map of threshold interfaces and alarm properties and values to error data.
43 */
44const std::map<InterfaceName, std::map<PropertyName, std::map<bool, ErrorData>>>
45 thresholdData{
46
47 {warningInterface,
48 {{"WarningAlarmHigh",
49 {{true, ErrorData{"WarningHigh", Entry::Level::Warning}},
50 {false,
51 ErrorData{"WarningHighClear", Entry::Level::Informational}}}},
52 {"WarningAlarmLow",
53 {{true, ErrorData{"WarningLow", Entry::Level::Warning}},
54 {false,
55 ErrorData{"WarningLowClear", Entry::Level::Informational}}}}}},
56
57 {criticalInterface,
58 {{"CriticalAlarmHigh",
59 {{true, ErrorData{"CriticalHigh", Entry::Level::Critical}},
60 {false,
61 ErrorData{"CriticalHighClear", Entry::Level::Informational}}}},
62 {"CriticalAlarmLow",
63 {{true, ErrorData{"CriticalLow", Entry::Level::Critical}},
64 {false,
65 ErrorData{"CriticalLowClear", Entry::Level::Informational}}}}}},
66
67 {perfLossInterface,
68 {{"PerfLossAlarmHigh",
69 {{true, ErrorData{"PerfLossHigh", Entry::Level::Warning}},
70 {false,
71 ErrorData{"PerfLossHighClear", Entry::Level::Informational}}}},
72 {"PerfLossAlarmLow",
73 {{true, ErrorData{"PerfLossLow", Entry::Level::Warning}},
74 {false,
75 ErrorData{"PerfLossLowClear", Entry::Level::Informational}}}}}}};
76
Matt Spinler403d1f52021-02-01 15:35:25 -060077ThresholdAlarmLogger::ThresholdAlarmLogger(sdbusplus::bus::bus& bus,
78 sdeventplus::Event& event) :
79 bus(bus),
80 event(event),
81 warningMatch(bus,
82 "type='signal',member='PropertiesChanged',"
83 "path_namespace='/xyz/openbmc_project/sensors',"
84 "arg0='" +
85 warningInterface + "'",
86 std::bind(&ThresholdAlarmLogger::propertiesChanged, this,
87 std::placeholders::_1)),
88 criticalMatch(bus,
89 "type='signal',member='PropertiesChanged',"
90 "path_namespace='/xyz/openbmc_project/sensors',"
91 "arg0='" +
92 criticalInterface + "'",
93 std::bind(&ThresholdAlarmLogger::propertiesChanged, this,
94 std::placeholders::_1)),
95 perfLossMatch(bus,
96 "type='signal',member='PropertiesChanged',"
97 "path_namespace='/xyz/openbmc_project/sensors',"
98 "arg0='" +
99 perfLossInterface + "'",
100 std::bind(&ThresholdAlarmLogger::propertiesChanged, this,
101 std::placeholders::_1))
Matt Spinler50bf8162021-02-01 16:24:01 -0600102{
103 // check for any currently asserted threshold alarms
104 std::for_each(
105 thresholdData.begin(), thresholdData.end(),
106 [this](const auto& thresholdInterface) {
107 const auto& interface = thresholdInterface.first;
108 auto objects =
109 SDBusPlus::getSubTreeRaw(this->bus, "/", interface, 0);
110 std::for_each(objects.begin(), objects.end(),
111 [interface, this](const auto& object) {
112 const auto& path = object.first;
113 const auto& service =
114 object.second.begin()->first;
115 checkThresholds(interface, path, service);
116 });
117 });
118}
Matt Spinler403d1f52021-02-01 15:35:25 -0600119
120void ThresholdAlarmLogger::propertiesChanged(sdbusplus::message::message& msg)
121{
Matt Spinlerf5d3be42021-02-01 16:38:01 -0600122 std::map<std::string, std::variant<bool>> properties;
123 std::string sensorPath = msg.get_path();
124 std::string interface;
125
126 msg.read(interface, properties);
127
128 auto alarmProperties = thresholdData.find(interface);
129 if (alarmProperties == thresholdData.end())
130 {
131 return;
132 }
133
134 for (const auto& [propertyName, propertyValue] : properties)
135 {
136 if (alarmProperties->second.find(propertyName) !=
137 alarmProperties->second.end())
138 {
139 // If this is the first time we've seen this alarm, then
140 // assume it was off before so it doesn't create an event
141 // log for a value of false.
142
143 InterfaceKey key{sensorPath, interface};
144 if (alarms.find(key) == alarms.end())
145 {
146 alarms[key][propertyName] = false;
147 }
148
149 // Check if the value changed from what was there before.
150 auto alarmValue = std::get<bool>(propertyValue);
151 if (alarmValue != alarms[key][propertyName])
152 {
153 alarms[key][propertyName] = alarmValue;
154 createEventLog(sensorPath, interface, propertyName, alarmValue);
155 }
156 }
157 }
Matt Spinler403d1f52021-02-01 15:35:25 -0600158}
159
Matt Spinler50bf8162021-02-01 16:24:01 -0600160void ThresholdAlarmLogger::checkThresholds(const std::string& interface,
161 const std::string& sensorPath,
162 const std::string& service)
163{
164 auto properties = thresholdData.find(interface);
165 if (properties == thresholdData.end())
166 {
167 return;
168 }
169
170 for (const auto& [property, unused] : properties->second)
171 {
172 try
173 {
174 auto alarmValue = SDBusPlus::getProperty<bool>(
175 bus, service, sensorPath, interface, property);
176 alarms[InterfaceKey(sensorPath, interface)][property] = alarmValue;
177
178 // This is just for checking alarms on startup,
179 // so only look for active alarms.
180 if (alarmValue)
181 {
182 createEventLog(sensorPath, interface, property, alarmValue);
183 }
184 }
185 catch (const DBusError& e)
186 {
187 log<level::ERR>(
188 fmt::format("Failed reading sensor threshold properties: {}",
189 e.what())
190 .c_str());
191 continue;
192 }
193 }
194}
195
196void ThresholdAlarmLogger::createEventLog(const std::string& sensorPath,
197 const std::string& interface,
198 const std::string& alarmProperty,
199 bool alarmValue)
200{
201 // TODO
202}
203
Matt Spinler403d1f52021-02-01 15:35:25 -0600204} // namespace sensor::monitor