1 #pragma once 2 3 #include "utility.hpp" 4 5 #include <nlohmann/json.hpp> 6 #include <xyz/openbmc_project/Logging/Entry/server.hpp> 7 8 #include <filesystem> 9 #include <string> 10 #include <tuple> 11 12 namespace phosphor::fan::monitor 13 { 14 15 /** 16 * @class FFDCFile 17 * 18 * This class holds a file that is used for event log FFDC 19 * which needs a file descriptor as input. The file is 20 * deleted upon destruction. 21 */ 22 class FFDCFile 23 { 24 public: 25 FFDCFile() = delete; 26 FFDCFile(const FFDCFile&) = delete; 27 FFDCFile& operator=(const FFDCFile&) = delete; 28 FFDCFile(FFDCFile&&) = delete; 29 FFDCFile& operator=(FFDCFile&&) = delete; 30 31 /** 32 * @brief Constructor 33 * 34 * Opens the file and saves the descriptor 35 * 36 * @param[in] name - The filename 37 */ 38 explicit FFDCFile(const std::filesystem::path& name); 39 40 /** 41 * @brief Destructor - Deletes the file 42 */ 43 ~FFDCFile() 44 { 45 std::filesystem::remove(_name); 46 } 47 48 /** 49 * @brief Returns the file descriptor 50 * 51 * @return int - The descriptor 52 */ 53 int fd() 54 { 55 return _fd(); 56 } 57 58 private: 59 /** 60 * @brief The file descriptor holder 61 */ 62 util::FileDescriptor _fd; 63 64 /** 65 * @brief The filename 66 */ 67 const std::filesystem::path _name; 68 }; 69 70 /** 71 * @class FanError 72 * 73 * This class represents a fan error. It has a commit() interface 74 * that will create the event log with certain FFDC. 75 */ 76 class FanError 77 { 78 public: 79 FanError() = delete; 80 ~FanError() = default; 81 FanError(const FanError&) = delete; 82 FanError& operator=(const FanError&) = delete; 83 FanError(FanError&&) = delete; 84 FanError& operator=(FanError&&) = delete; 85 86 /** 87 * @brief Constructor 88 * 89 * @param[in] error - The error name, like 90 * xyz.openbmc_project.Fan.Error.Fault 91 * @param[in] fan - The failing fan's inventory path 92 * @param[in] sensor - The failing sensor's inventory path. Can be empty 93 * if the error is for the FRU and not the sensor. 94 * @param[in] severity - The severity of the error 95 */ 96 FanError(const std::string& error, const std::string& fan, 97 const std::string& sensor, 98 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level 99 severity) : 100 _errorName(error), 101 _fanName(fan), _sensorName(sensor), 102 _severity( 103 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage( 104 severity)) 105 {} 106 107 /** 108 * @brief Constructor 109 * 110 * This version doesn't take a fan or sensor name. 111 * 112 * @param[in] error - The error name, like 113 * xyz.openbmc_project.Fan.Error.Fault 114 * @param[in] severity - The severity of the error 115 */ 116 FanError(const std::string& error, 117 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level 118 severity) : 119 _errorName(error), 120 _severity( 121 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage( 122 severity)) 123 {} 124 125 /** 126 * @brief Commits the error by calling the D-Bus method to create 127 * the event log. 128 * 129 * The FFDC is passed in here so that if an error is committed 130 * more than once it can have up to date FFDC. 131 * 132 * @param[in] jsonFFDC - Free form JSON data that should be sent in as 133 * FFDC. 134 * @param[in] isPowerOffError - If this is committed at the time of the 135 * power off. 136 */ 137 void commit(const nlohmann::json& jsonFFDC, bool isPowerOffError = false); 138 139 private: 140 /** 141 * @brief returns a JSON structure containing the previous N journal 142 * entries. 143 * 144 * @param[in] numLines - Number of lines of journal to retrieve 145 */ 146 nlohmann::json getJournalEntries(int numLines) const; 147 148 /** 149 * Gets the realtime (wallclock) timestamp for the current journal entry. 150 * 151 * @param journal current journal entry 152 * @return timestamp as a date/time string 153 */ 154 std::string getTimeStamp(sd_journal* journal) const; 155 156 /** 157 * Gets the value of the specified field for the current journal entry. 158 * 159 * Returns an empty string if the current journal entry does not have the 160 * specified field. 161 * 162 * @param journal current journal entry 163 * @param field journal field name 164 * @return field value 165 */ 166 std::string getFieldValue(sd_journal* journal, 167 const std::string& field) const; 168 169 /** 170 * @brief Returns an FFDCFile holding the Logger contents 171 * 172 * @return std::unique_ptr<FFDCFile> - The file object 173 */ 174 std::unique_ptr<FFDCFile> makeLogFFDCFile(); 175 176 /** 177 * @brief Returns an FFDCFile holding the contents of the JSON FFDC 178 * 179 * @param[in] ffdcData - The JSON data to write to a file 180 * 181 * @return std::unique_ptr<FFDCFile> - The file object 182 */ 183 std::unique_ptr<FFDCFile> makeJsonFFDCFile(const nlohmann::json& ffdcData); 184 185 /** 186 * @brief Create and returns the AdditionalData property to use for the 187 * event log. 188 * 189 * @param[in] isPowerOffError - If this is committed at the time of the 190 * power off. 191 * @return map<string, string> - The AdditionalData contents 192 */ 193 std::map<std::string, std::string> getAdditionalData(bool isPowerOffError); 194 195 /** 196 * @brief The error name (The event log's 'Message' property) 197 */ 198 const std::string _errorName; 199 200 /** 201 * @brief The inventory name of the failing fan 202 */ 203 const std::string _fanName; 204 205 /** 206 * @brief The inventory name of the failing sensor, if there is one. 207 */ 208 const std::string _sensorName; 209 210 /** 211 * @brief The severity of the event log. This is the string 212 * representation of the Entry::Level property. 213 */ 214 const std::string _severity; 215 }; 216 217 } // namespace phosphor::fan::monitor 218