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