1 /** 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 17 #include "error_logging_utils.hpp" 18 19 #include "config_file_parser_error.hpp" 20 #include "exception_utils.hpp" 21 #include "i2c_interface.hpp" 22 #include "journal.hpp" 23 #include "pmbus_error.hpp" 24 #include "write_verification_error.hpp" 25 26 #include <sdbusplus/exception.hpp> 27 28 #include <vector> 29 30 using ConfigFileParserError = phosphor::power::util::ConfigFileParserError; 31 32 namespace phosphor::power::regulators::error_logging_utils 33 { 34 35 void logError(std::exception_ptr eptr, Entry::Level severity, 36 Services& services) 37 { 38 // Specify empty error history so that all error types will be logged 39 ErrorHistory history{}; 40 logError(eptr, severity, services, history); 41 } 42 43 void logError(std::exception_ptr eptr, Entry::Level severity, 44 Services& services, ErrorHistory& history) 45 { 46 // Check for null exception pointer 47 if (!eptr) 48 { 49 return; 50 } 51 52 // Get exception to log from specified exception and any nested exceptions 53 std::exception_ptr exceptionToLog = internal::getExceptionToLog(eptr); 54 55 // Log an error based on the exception 56 ErrorLogging& errorLogging = services.getErrorLogging(); 57 Journal& journal = services.getJournal(); 58 ErrorType errorType{}; 59 try 60 { 61 std::rethrow_exception(exceptionToLog); 62 } 63 catch (const ConfigFileParserError& e) 64 { 65 errorType = ErrorType::configFile; 66 if (!history.wasLogged(errorType)) 67 { 68 history.setWasLogged(errorType, true); 69 errorLogging.logConfigFileError(severity, journal); 70 } 71 } 72 catch (const PMBusError& e) 73 { 74 errorType = ErrorType::pmbus; 75 if (!history.wasLogged(errorType)) 76 { 77 history.setWasLogged(errorType, true); 78 errorLogging.logPMBusError(severity, journal, e.getInventoryPath()); 79 } 80 } 81 catch (const WriteVerificationError& e) 82 { 83 errorType = ErrorType::writeVerification; 84 if (!history.wasLogged(errorType)) 85 { 86 history.setWasLogged(errorType, true); 87 errorLogging.logWriteVerificationError(severity, journal, 88 e.getInventoryPath()); 89 } 90 } 91 catch (const i2c::I2CException& e) 92 { 93 errorType = ErrorType::i2c; 94 if (!history.wasLogged(errorType)) 95 { 96 history.setWasLogged(errorType, true); 97 errorLogging.logI2CError(severity, journal, e.bus, e.addr, 98 e.errorCode); 99 } 100 } 101 catch (const sdbusplus::exception_t& e) 102 { 103 errorType = ErrorType::dbus; 104 if (!history.wasLogged(errorType)) 105 { 106 history.setWasLogged(errorType, true); 107 errorLogging.logDBusError(severity, journal); 108 } 109 } 110 catch (const std::exception& e) 111 { 112 errorType = ErrorType::internal; 113 if (!history.wasLogged(errorType)) 114 { 115 history.setWasLogged(errorType, true); 116 errorLogging.logInternalError(severity, journal); 117 } 118 } 119 catch (...) 120 { 121 errorType = ErrorType::internal; 122 if (!history.wasLogged(errorType)) 123 { 124 history.setWasLogged(errorType, true); 125 errorLogging.logInternalError(severity, journal); 126 } 127 } 128 } 129 130 namespace internal 131 { 132 133 std::exception_ptr getExceptionToLog(std::exception_ptr eptr) 134 { 135 // Default to selecting the outermost exception 136 std::exception_ptr exceptionToLog{eptr}; 137 138 // Get vector containing this exception and any nested exceptions 139 std::vector<std::exception_ptr> exceptions = 140 exception_utils::getExceptions(eptr); 141 142 // Define temporary constants for exception priorities 143 const int lowPriority{0}, mediumPriority{1}, highPriority{2}; 144 145 // Loop through the exceptions from innermost to outermost. Find the 146 // exception with the highest priority. If there is a tie, select the 147 // outermost exception with that priority. 148 int highestPriorityFound{-1}; 149 for (std::exception_ptr curptr : exceptions) 150 { 151 int priority{-1}; 152 try 153 { 154 std::rethrow_exception(curptr); 155 } 156 catch (const ConfigFileParserError& e) 157 { 158 priority = highPriority; 159 } 160 catch (const PMBusError& e) 161 { 162 priority = highPriority; 163 } 164 catch (const WriteVerificationError& e) 165 { 166 priority = highPriority; 167 } 168 catch (const i2c::I2CException& e) 169 { 170 priority = highPriority; 171 } 172 catch (const sdbusplus::exception_t& e) 173 { 174 priority = mediumPriority; 175 } 176 catch (const std::exception& e) 177 { 178 priority = lowPriority; 179 } 180 catch (...) 181 { 182 priority = lowPriority; 183 } 184 185 if (priority >= highestPriorityFound) 186 { 187 highestPriorityFound = priority; 188 exceptionToLog = curptr; 189 } 190 } 191 192 return exceptionToLog; 193 } 194 195 } // namespace internal 196 197 } // namespace phosphor::power::regulators::error_logging_utils 198