/** * Copyright © 2021 IBM Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "error_logging_utils.hpp" #include "config_file_parser_error.hpp" #include "exception_utils.hpp" #include "i2c_interface.hpp" #include "journal.hpp" #include "pmbus_error.hpp" #include "write_verification_error.hpp" #include #include namespace phosphor::power::regulators::error_logging_utils { void logError(std::exception_ptr eptr, Entry::Level severity, Services& services) { // Specify empty error history so that all error types will be logged ErrorHistory history{}; logError(eptr, severity, services, history); } void logError(std::exception_ptr eptr, Entry::Level severity, Services& services, ErrorHistory& history) { // Check for null exception pointer if (!eptr) { return; } // Get exception to log from specified exception and any nested exceptions std::exception_ptr exceptionToLog = internal::getExceptionToLog(eptr); // Log an error based on the exception ErrorLogging& errorLogging = services.getErrorLogging(); Journal& journal = services.getJournal(); ErrorType errorType{}; try { std::rethrow_exception(exceptionToLog); } catch (const ConfigFileParserError& e) { errorType = ErrorType::configFile; if (!history.wasLogged(errorType)) { history.setWasLogged(errorType, true); errorLogging.logConfigFileError(severity, journal); } } catch (const PMBusError& e) { errorType = ErrorType::pmbus; if (!history.wasLogged(errorType)) { history.setWasLogged(errorType, true); errorLogging.logPMBusError(severity, journal, e.getInventoryPath()); } } catch (const WriteVerificationError& e) { errorType = ErrorType::writeVerification; if (!history.wasLogged(errorType)) { history.setWasLogged(errorType, true); errorLogging.logWriteVerificationError(severity, journal, e.getInventoryPath()); } } catch (const i2c::I2CException& e) { errorType = ErrorType::i2c; if (!history.wasLogged(errorType)) { history.setWasLogged(errorType, true); errorLogging.logI2CError(severity, journal, e.bus, e.addr, e.errorCode); } } catch (const sdbusplus::exception_t& e) { errorType = ErrorType::dbus; if (!history.wasLogged(errorType)) { history.setWasLogged(errorType, true); errorLogging.logDBusError(severity, journal); } } catch (const std::exception& e) { errorType = ErrorType::internal; if (!history.wasLogged(errorType)) { history.setWasLogged(errorType, true); errorLogging.logInternalError(severity, journal); } } catch (...) { errorType = ErrorType::internal; if (!history.wasLogged(errorType)) { history.setWasLogged(errorType, true); errorLogging.logInternalError(severity, journal); } } } namespace internal { std::exception_ptr getExceptionToLog(std::exception_ptr eptr) { // Default to selecting the outermost exception std::exception_ptr exceptionToLog{eptr}; // Get vector containing this exception and any nested exceptions std::vector exceptions = exception_utils::getExceptions(eptr); // Define temporary constants for exception priorities const int lowPriority{0}, mediumPriority{1}, highPriority{2}; // Loop through the exceptions from innermost to outermost. Find the // exception with the highest priority. If there is a tie, select the // outermost exception with that priority. int highestPriorityFound{-1}; for (std::exception_ptr curptr : exceptions) { int priority{-1}; try { std::rethrow_exception(curptr); } catch (const ConfigFileParserError& e) { priority = highPriority; } catch (const PMBusError& e) { priority = highPriority; } catch (const WriteVerificationError& e) { priority = highPriority; } catch (const i2c::I2CException& e) { priority = highPriority; } catch (const sdbusplus::exception_t& e) { priority = mediumPriority; } catch (const std::exception& e) { priority = lowPriority; } catch (...) { priority = lowPriority; } if (priority >= highestPriorityFound) { highestPriorityFound = priority; exceptionToLog = curptr; } } return exceptionToLog; } } // namespace internal } // namespace phosphor::power::regulators::error_logging_utils