1 #pragma once 2 3 #include "config.h" 4 5 #include "common_utility.hpp" 6 #include "constants.hpp" 7 #include "exceptions.hpp" 8 #include "json_utility.hpp" 9 #include "logger.hpp" 10 #include "types.hpp" 11 12 #include <systemd/sd-bus.h> 13 14 #include <filesystem> 15 #include <iostream> 16 #include <optional> 17 #include <string> 18 #include <unordered_map> 19 20 namespace vpd 21 { 22 namespace EventLogger 23 { 24 const std::unordered_map<types::SeverityType, std::string> severityMap = { 25 {types::SeverityType::Notice, 26 "xyz.openbmc_project.Logging.Entry.Level.Notice"}, 27 {types::SeverityType::Informational, 28 "xyz.openbmc_project.Logging.Entry.Level.Informational"}, 29 {types::SeverityType::Debug, 30 "xyz.openbmc_project.Logging.Entry.Level.Debug"}, 31 {types::SeverityType::Warning, 32 "xyz.openbmc_project.Logging.Entry.Level.Warning"}, 33 {types::SeverityType::Critical, 34 "xyz.openbmc_project.Logging.Entry.Level.Critical"}, 35 {types::SeverityType::Emergency, 36 "xyz.openbmc_project.Logging.Entry.Level.Emergency"}, 37 {types::SeverityType::Alert, 38 "xyz.openbmc_project.Logging.Entry.Level.Alert"}, 39 {types::SeverityType::Error, 40 "xyz.openbmc_project.Logging.Entry.Level.Error"}}; 41 42 const std::unordered_map<types::ErrorType, std::string> errorMsgMap = { 43 {types::ErrorType::DefaultValue, "com.ibm.VPD.Error.DefaultValue"}, 44 {types::ErrorType::UndefinedError, "com.ibm.VPD.Error.UndefinedError"}, 45 {types::ErrorType::InvalidVpdMessage, "com.ibm.VPD.Error.InvalidVPD"}, 46 {types::ErrorType::VpdMismatch, "com.ibm.VPD.Error.Mismatch"}, 47 {types::ErrorType::InvalidEeprom, "com.ibm.VPD.Error.InvalidEepromPath"}, 48 {types::ErrorType::EccCheckFailed, "com.ibm.VPD.Error.EccCheckFailed"}, 49 {types::ErrorType::JsonFailure, "com.ibm.VPD.Error.InvalidJson"}, 50 {types::ErrorType::DbusFailure, "com.ibm.VPD.Error.DbusFailure"}, 51 {types::ErrorType::InvalidSystem, "com.ibm.VPD.Error.UnknownSystemType"}, 52 {types::ErrorType::EssentialFru, "com.ibm.VPD.Error.RequiredFRUMissing"}, 53 {types::ErrorType::GpioError, "com.ibm.VPD.Error.GPIOError"}, 54 {types::ErrorType::InternalFailure, 55 "xyz.openbmc_project.Common.Error.InternalFailure"}, 56 {types::ErrorType::FruMissing, "com.ibm.VPD.Error.RequiredFRUMissing"}, 57 {types::ErrorType::SystemTypeMismatch, 58 "com.ibm.VPD.Error.SystemTypeMismatch"}, 59 {types::ErrorType::UnknownSystemSettings, 60 "com.ibm.VPD.Error.UnknownSystemSettings"}, 61 {types::ErrorType::FirmwareError, "com.ibm.VPD.Error.FirmwareError"}, 62 {types::ErrorType::VpdParseError, "com.ibm.VPD.Error.VPDParseError"}}; 63 64 const std::unordered_map<types::CalloutPriority, std::string> priorityMap = { 65 {types::CalloutPriority::High, "H"}, 66 {types::CalloutPriority::Medium, "M"}, 67 {types::CalloutPriority::MediumGroupA, "A"}, 68 {types::CalloutPriority::MediumGroupB, "B"}, 69 {types::CalloutPriority::MediumGroupC, "C"}, 70 {types::CalloutPriority::Low, "L"}}; 71 72 /** 73 * @brief API to get error info based on the exception. 74 * 75 * @param[in] i_exception - Exception object. 76 * 77 * @return - Valid ExceptionDataMap on success, otherwise map having 78 * default value. 79 */ 80 inline types::ExceptionDataMap getExceptionData( 81 const std::exception& i_exception) 82 { 83 types::ExceptionDataMap l_errorInfo{ 84 {"ErrorType", types::ErrorType::UndefinedError}, 85 {"ErrorMsg", i_exception.what()}}; 86 87 try 88 { 89 if (typeid(i_exception) == typeid(DataException)) 90 { 91 const DataException& l_ex = 92 dynamic_cast<const DataException&>(i_exception); 93 l_errorInfo["ErrorType"] = l_ex.getErrorType(); 94 l_errorInfo["ErrorMsg"] = 95 std::string("Data Exception. Reason: ") + i_exception.what(); 96 } 97 else if (typeid(i_exception) == typeid(EccException)) 98 { 99 const EccException& l_ex = 100 dynamic_cast<const EccException&>(i_exception); 101 l_errorInfo["ErrorType"] = l_ex.getErrorType(); 102 l_errorInfo["ErrorMsg"] = 103 std::string("Ecc Exception. Reason: ") + i_exception.what(); 104 } 105 else if (typeid(i_exception) == typeid(JsonException)) 106 { 107 const JsonException& l_ex = 108 dynamic_cast<const JsonException&>(i_exception); 109 l_errorInfo["ErrorType"] = l_ex.getErrorType(); 110 l_errorInfo["ErrorMsg"] = 111 std::string("Json Exception. Reason: ") + i_exception.what(); 112 } 113 else if (typeid(i_exception) == typeid(GpioException)) 114 { 115 const GpioException& l_ex = 116 dynamic_cast<const GpioException&>(i_exception); 117 l_errorInfo["ErrorType"] = l_ex.getErrorType(); 118 l_errorInfo["ErrorMsg"] = 119 std::string("Gpio Exception. Reason: ") + i_exception.what(); 120 } 121 else if (typeid(i_exception) == typeid(DbusException)) 122 { 123 const DbusException& l_ex = 124 dynamic_cast<const DbusException&>(i_exception); 125 l_errorInfo["ErrorType"] = l_ex.getErrorType(); 126 l_errorInfo["ErrorMsg"] = 127 std::string("Dbus Exception. Reason: ") + i_exception.what(); 128 } 129 else if (typeid(i_exception) == typeid(FirmwareException)) 130 { 131 const FirmwareException& l_ex = 132 dynamic_cast<const FirmwareException&>(i_exception); 133 l_errorInfo["ErrorType"] = l_ex.getErrorType(); 134 l_errorInfo["ErrorMsg"] = 135 std::string("Firmware Exception. Reason: ") + 136 i_exception.what(); 137 } 138 else if (typeid(i_exception) == typeid(EepromException)) 139 { 140 const EepromException& l_ex = 141 dynamic_cast<const EepromException&>(i_exception); 142 l_errorInfo["ErrorType"] = l_ex.getErrorType(); 143 l_errorInfo["ErrorMsg"] = 144 std::string("Eeprom Exception. Reason: ") + i_exception.what(); 145 } 146 else if (typeid(i_exception) == typeid(std::runtime_error)) 147 { 148 // Since it is a standard exception no casting is required and error 149 // type is hardcoded. 150 l_errorInfo["ErrorType"] = types::ErrorType::FirmwareError; 151 l_errorInfo["ErrorMsg"] = 152 std::string("Standard runtime exception. Reason: ") + 153 i_exception.what(); 154 } 155 } 156 catch (const std::exception& l_ex) 157 { 158 logging::logMessage( 159 "Failed to get error info, reason: " + std::string(l_ex.what())); 160 } 161 return l_errorInfo; 162 } 163 164 /** 165 * @brief API to get Error type. 166 * 167 * @param[in] i_exception - Exception object. 168 * 169 * @return Error type set for the exception. 170 * types::ErrorType::InternalFailure otherwise. 171 */ 172 inline types::ErrorType getErrorType(const std::exception& i_exception) 173 { 174 const auto& l_exceptionDataMap = getExceptionData(i_exception); 175 176 auto l_itrToErrType = l_exceptionDataMap.find("ErrorType"); 177 if (l_itrToErrType == l_exceptionDataMap.end()) 178 { 179 return types::ErrorType::UndefinedError; 180 } 181 182 auto l_ptrToErrType = 183 std::get_if<types::ErrorType>(&l_itrToErrType->second); 184 if (!l_ptrToErrType) 185 { 186 return types::ErrorType::UndefinedError; 187 } 188 189 return *l_ptrToErrType; 190 } 191 192 /** 193 * @brief API to get Error msg. 194 * 195 * @param[in] i_exception - Exception object. 196 * 197 * @return Error msg set for the specific exception. Default error msg 198 * otherwise. 199 */ 200 inline std::string getErrorMsg(const std::exception& i_exception) 201 { 202 const auto& l_exceptionDataMap = getExceptionData(i_exception); 203 204 auto l_itrToErrMsg = l_exceptionDataMap.find("ErrorMsg"); 205 if (l_itrToErrMsg == l_exceptionDataMap.end()) 206 { 207 return i_exception.what(); 208 } 209 210 auto l_ptrToErrMsg = std::get_if<std::string>(&l_itrToErrMsg->second); 211 if (!l_ptrToErrMsg) 212 { 213 return i_exception.what(); 214 } 215 216 return *l_ptrToErrMsg; 217 } 218 219 /** 220 * @brief API to get string representation of a Error type enum. 221 * 222 * @param[in] i_exception - Exception object. 223 * 224 * @return Error msg set for the specific error type. Default error msg 225 * otherwise. 226 */ 227 inline std::string getErrorTypeString( 228 const types::ErrorType& i_errorType) noexcept 229 { 230 const auto l_entry = errorMsgMap.find(i_errorType); 231 return (l_entry != errorMsgMap.end() 232 ? l_entry->second 233 : errorMsgMap.at(types::ErrorType::UndefinedError)); 234 } 235 236 /** 237 * @brief An API to create a PEL with inventory path callout. 238 * 239 * This API calls an async method to create PEL, and also handles inventory 240 * path callout. 241 * 242 * Note: If inventory path callout info is not provided, it will create a 243 * PEL without any callout. Currently only one callout is handled in this 244 * API. 245 * 246 * @todo: Symbolic FRU and procedure callout needs to be handled in this 247 * API. 248 * 249 * @param[in] i_errorType - Enum to map with event message name. 250 * @param[in] i_severity - Severity of the event. 251 * @param[in] i_callouts - Callout information, list of tuple having 252 * inventory path and priority as input [optional]. 253 * @param[in] i_fileName - File name. 254 * @param[in] i_funcName - Function name. 255 * @param[in] i_internalRc - Internal return code. 256 * @param[in] i_description - Error description. 257 * @param[in] i_userData1 - Additional user data [optional]. 258 * @param[in] i_userData2 - Additional user data [optional]. 259 * @param[in] i_symFru - Symblolic FRU callout data [optional]. 260 * @param[in] i_procedure - Procedure callout data [optional]. 261 * 262 * @throw exception in case of error. 263 */ 264 inline void createAsyncPelWithInventoryCallout( 265 const types::ErrorType& i_errorType, const types::SeverityType& i_severity, 266 const std::vector<types::InventoryCalloutData>& i_callouts, 267 const std::string& i_fileName, const std::string& i_funcName, 268 const uint8_t i_internalRc, const std::string& i_description, 269 const std::optional<std::string> i_userData1, 270 const std::optional<std::string> i_userData2, 271 const std::optional<std::string> i_symFru, 272 const std::optional<std::string> i_procedure) 273 { 274 (void)i_symFru; 275 (void)i_procedure; 276 277 try 278 { 279 if (i_callouts.empty()) 280 { 281 logging::logMessage("Callout information is missing to create PEL"); 282 // TODO: Revisit this instead of simpley returning. 283 return; 284 } 285 286 if (errorMsgMap.find(i_errorType) == errorMsgMap.end()) 287 { 288 throw std::runtime_error( 289 "Error type not found in the error message map to create PEL"); 290 // TODO: Need to handle, instead of throwing exception. Create 291 // default message in message_registry.json. 292 } 293 294 const std::string& l_message = errorMsgMap.at(i_errorType); 295 296 const std::string& l_severity = 297 (severityMap.find(i_severity) != severityMap.end() 298 ? severityMap.at(i_severity) 299 : severityMap.at(types::SeverityType::Informational)); 300 301 std::string l_description = 302 (!i_description.empty() ? i_description : "VPD generic error"); 303 304 std::string l_userData1 = (i_userData1) ? (*i_userData1) : ""; 305 306 std::string l_userData2 = (i_userData2) ? (*i_userData2) : ""; 307 308 const types::InventoryCalloutData& l_invCallout = i_callouts[0]; 309 // TODO: Need to handle multiple inventory path callout's, when multiple 310 // callout's is supported by "Logging" service. 311 312 const types::CalloutPriority& l_priorityEnum = get<1>(l_invCallout); 313 314 const std::string& l_priority = 315 (priorityMap.find(l_priorityEnum) != priorityMap.end() 316 ? priorityMap.at(l_priorityEnum) 317 : priorityMap.at(types::CalloutPriority::Low)); 318 319 sd_bus* l_sdBus = nullptr; 320 sd_bus_default(&l_sdBus); 321 322 const uint8_t l_additionalDataCount = 8; 323 auto l_rc = sd_bus_call_method_async( 324 l_sdBus, NULL, constants::eventLoggingServiceName, 325 constants::eventLoggingObjectPath, constants::eventLoggingInterface, 326 "Create", NULL, NULL, "ssa{ss}", l_message.c_str(), 327 l_severity.c_str(), l_additionalDataCount, "FileName", 328 i_fileName.c_str(), "FunctionName", i_funcName.c_str(), 329 "InternalRc", std::to_string(i_internalRc).c_str(), "DESCRIPTION", 330 l_description.c_str(), "UserData1", l_userData1.c_str(), 331 "UserData2", l_userData2.c_str(), "CALLOUT_INVENTORY_PATH", 332 get<0>(l_invCallout).c_str(), "CALLOUT_PRIORITY", 333 l_priority.c_str()); 334 335 if (l_rc < 0) 336 { 337 logging::logMessage( 338 "Error calling sd_bus_call_method_async, Message = " + 339 std::string(strerror(-l_rc))); 340 } 341 } 342 catch (const std::exception& l_ex) 343 { 344 logging::logMessage( 345 "Create PEL failed with error: " + std::string(l_ex.what())); 346 } 347 } 348 349 /** 350 * @brief An API to create a PEL with device path callout. 351 * 352 * @param[in] i_errorType - Enum to map with event message name. 353 * @param[in] i_severity - Severity of the event. 354 * @param[in] i_callouts - Callout information, list of tuple having device 355 * path and error number as input. 356 * @param[in] i_fileName - File name. 357 * @param[in] i_funcName - Function name. 358 * @param[in] i_internalRc - Internal return code. 359 * @param[in] i_userData1 - Additional user data [optional]. 360 * @param[in] i_userData2 - Additional user data [optional]. 361 */ 362 inline void createAsyncPelWithI2cDeviceCallout( 363 const types::ErrorType i_errorType, const types::SeverityType i_severity, 364 const std::vector<types::DeviceCalloutData>& i_callouts, 365 const std::string& i_fileName, const std::string& i_funcName, 366 const uint8_t i_internalRc, 367 const std::optional<std::pair<std::string, std::string>> i_userData1, 368 const std::optional<std::pair<std::string, std::string>> i_userData2); 369 370 /** 371 * @brief An API to create a PEL with I2c bus callout. 372 * 373 * @param[in] i_errorType - Enum to map with event message name. 374 * @param[in] i_severity - Severity of the event. 375 * @param[in] i_callouts - Callout information, list of tuple having i2c 376 * bus, i2c address and error number as input. 377 * @param[in] i_fileName - File name. 378 * @param[in] i_funcName - Function name. 379 * @param[in] i_internalRc - Internal return code. 380 * @param[in] i_userData1 - Additional user data [optional]. 381 * @param[in] i_userData2 - Additional user data [optional]. 382 */ 383 inline void createAsyncPelWithI2cBusCallout( 384 const types::ErrorType i_errorType, const types::SeverityType i_severity, 385 const std::vector<types::I2cBusCalloutData>& i_callouts, 386 const std::string& i_fileName, const std::string& i_funcName, 387 const uint8_t i_internalRc, 388 const std::optional<std::pair<std::string, std::string>> i_userData1, 389 const std::optional<std::pair<std::string, std::string>> i_userData2); 390 391 /** 392 * @brief An API to create a PEL. 393 * 394 * @param[in] i_errorType - Enum to map with event message name. 395 * @param[in] i_severity - Severity of the event. 396 * @param[in] i_fileName - File name. 397 * @param[in] i_funcName - Function name. 398 * @param[in] i_internalRc - Internal return code. 399 * @param[in] i_description - Error description. 400 * @param[in] i_userData1 - Additional user data [optional]. 401 * @param[in] i_userData2 - Additional user data [optional]. 402 * @param[in] i_symFru - Symblolic FRU callout data [optional]. 403 * @param[in] i_procedure - Procedure callout data [optional]. 404 * 405 * @todo: Symbolic FRU and procedure callout needs to be handled in this 406 * API. 407 */ 408 inline void createAsyncPel( 409 const types::ErrorType& i_errorType, const types::SeverityType& i_severity, 410 const std::string& i_fileName, const std::string& i_funcName, 411 const uint8_t i_internalRc, const std::string& i_description, 412 const std::optional<std::string> i_userData1, 413 const std::optional<std::string> i_userData2, 414 const std::optional<std::string> i_symFru, 415 const std::optional<std::string> i_procedure) 416 { 417 (void)i_symFru; 418 (void)i_procedure; 419 try 420 { 421 if (errorMsgMap.find(i_errorType) == errorMsgMap.end()) 422 { 423 throw std::runtime_error("Unsupported error type received"); 424 // TODO: Need to handle, instead of throwing an exception. 425 } 426 427 const std::string& l_message = errorMsgMap.at(i_errorType); 428 429 const std::string& l_severity = 430 (severityMap.find(i_severity) != severityMap.end() 431 ? severityMap.at(i_severity) 432 : severityMap.at(types::SeverityType::Informational)); 433 434 const std::string l_description = 435 ((!i_description.empty() ? i_description : "VPD generic error")); 436 437 const std::string l_userData1 = ((i_userData1) ? (*i_userData1) : ""); 438 439 const std::string l_userData2 = ((i_userData2) ? (*i_userData2) : ""); 440 441 sd_bus* l_sdBus = nullptr; 442 sd_bus_default(&l_sdBus); 443 444 // VALUE_6 represents the additional data pair count passing to create 445 // PEL. If there any change in additional data, we need to pass the 446 // correct number. 447 auto l_rc = sd_bus_call_method_async( 448 l_sdBus, NULL, constants::eventLoggingServiceName, 449 constants::eventLoggingObjectPath, constants::eventLoggingInterface, 450 "Create", NULL, NULL, "ssa{ss}", l_message.c_str(), 451 l_severity.c_str(), constants::VALUE_6, "FileName", 452 i_fileName.c_str(), "FunctionName", i_funcName.c_str(), 453 "InternalRc", std::to_string(i_internalRc).c_str(), "DESCRIPTION", 454 l_description.c_str(), "UserData1", l_userData1.c_str(), 455 "UserData2", l_userData2.c_str()); 456 457 if (l_rc < 0) 458 { 459 logging::logMessage( 460 "Error calling sd_bus_call_method_async, Message = " + 461 std::string(strerror(-l_rc))); 462 } 463 } 464 catch (const sdbusplus::exception::SdBusError& l_ex) 465 { 466 logging::logMessage("Async PEL creation failed with an error: " + 467 std::string(l_ex.what())); 468 } 469 } 470 471 /** 472 * @brief An API to create PEL. 473 * 474 * This API makes synchronous call to phosphor-logging Create method. 475 * 476 * @param[in] i_errorType - Enum to map with event message name. 477 * @param[in] i_severity - Severity of the event. 478 * @param[in] i_fileName - File name. 479 * @param[in] i_funcName - Function name. 480 * @param[in] i_internalRc - Internal return code. 481 * @param[in] i_description - Error description. 482 * @param[in] i_userData1 - Additional user data [optional]. 483 * @param[in] i_userData2 - Additional user data [optional]. 484 * @param[in] i_symFru - Symblolic FRU callout data [optional].s 485 * @param[in] i_procedure - Procedure callout data [optional]. 486 * 487 * @todo: Symbolic FRU and procedure callout needs to be handled in this 488 * API. 489 */ 490 inline void createSyncPel( 491 const types::ErrorType& i_errorType, const types::SeverityType& i_severity, 492 const std::string& i_fileName, const std::string& i_funcName, 493 const uint8_t i_internalRc, const std::string& i_description, 494 const std::optional<std::string> i_userData1, 495 const std::optional<std::string> i_userData2, 496 const std::optional<std::string> i_symFru, 497 const std::optional<std::string> i_procedure) 498 { 499 (void)i_symFru; 500 (void)i_procedure; 501 try 502 { 503 if (errorMsgMap.find(i_errorType) == errorMsgMap.end()) 504 { 505 throw std::runtime_error("Unsupported error type received"); 506 // TODO: Need to handle, instead of throwing an exception. 507 } 508 509 const std::string& l_message = errorMsgMap.at(i_errorType); 510 511 const std::string& l_severity = 512 (severityMap.find(i_severity) != severityMap.end() 513 ? severityMap.at(i_severity) 514 : severityMap.at(types::SeverityType::Informational)); 515 516 const std::string l_description = 517 ((!i_description.empty() ? i_description : "VPD generic error")); 518 519 const std::string l_userData1 = ((i_userData1) ? (*i_userData1) : ""); 520 521 const std::string l_userData2 = ((i_userData2) ? (*i_userData2) : ""); 522 523 std::map<std::string, std::string> l_additionalData{ 524 {"FileName", i_fileName}, 525 {"FunctionName", i_funcName}, 526 {"DESCRIPTION", l_description}, 527 {"InteranlRc", std::to_string(i_internalRc)}, 528 {"UserData1", l_userData1.c_str()}, 529 {"UserData2", l_userData2.c_str()}}; 530 531 auto l_bus = sdbusplus::bus::new_default(); 532 auto l_method = 533 l_bus.new_method_call(constants::eventLoggingServiceName, 534 constants::eventLoggingObjectPath, 535 constants::eventLoggingInterface, "Create"); 536 l_method.append(l_message, l_severity, l_additionalData); 537 l_bus.call(l_method); 538 } 539 catch (const sdbusplus::exception::SdBusError& l_ex) 540 { 541 logging::logMessage("Sync PEL creation failed with an error: " + 542 std::string(l_ex.what())); 543 } 544 } 545 546 /** 547 * @brief An API to create a synchronus PEL with inventory path callout. 548 * 549 * This API calls phosphor-logging method to create PEL, and also handles 550 * inventory path callout. In case called with EEPROM path, will look for 551 * JSON at symbolic link and if present will fetch inventory path for that 552 * EEPROM. 553 * 554 * Note: In case of any error in fetching JSON or converting the EEPROM 555 * path, the API will log PEL with path passed in callout parameter. 556 * If inventory/EEPROM path is not provided in the callout, it will create 557 * PEL without call out. Currently only one callout is handled in this API. 558 * 559 * @todo: Symbolic FRU and procedure callout needs to be handled in this 560 * API. 561 * 562 * @param[in] i_errorType - Enum to map with event message name. 563 * @param[in] i_severity - Severity of the event. 564 * @param[in] i_fileName - File name. 565 * @param[in] i_funcName - Function name. 566 * @param[in] i_internalRc - Internal return code. 567 * @param[in] i_description - Error description. 568 * @param[in] i_callouts - Callout information. 569 * @param[in] i_userData1 - Additional user data [optional]. 570 * @param[in] i_userData2 - Additional user data [optional]. 571 * @param[in] i_symFru - Symblolic FRU callout data [optional]. 572 * @param[in] i_procedure - Procedure callout data [optional]. 573 * 574 */ 575 inline void createSyncPelWithInvCallOut( 576 const types::ErrorType& i_errorType, const types::SeverityType& i_severity, 577 const std::string& i_fileName, const std::string& i_funcName, 578 const uint8_t i_internalRc, const std::string& i_description, 579 const std::vector<types::InventoryCalloutData>& i_callouts, 580 const std::optional<std::string> i_userData1, 581 const std::optional<std::string> i_userData2, 582 [[maybe_unused]] const std::optional<std::string> i_symFru, 583 [[maybe_unused]] const std::optional<std::string> i_procedure) 584 { 585 try 586 { 587 if (i_callouts.empty()) 588 { 589 createSyncPel(i_errorType, i_severity, i_fileName, i_funcName, 590 i_internalRc, i_description, i_userData1, i_userData2, 591 i_symFru, i_procedure); 592 logging::logMessage( 593 "Callout list is empty, creating PEL without call out"); 594 return; 595 } 596 597 if (errorMsgMap.find(i_errorType) == errorMsgMap.end()) 598 { 599 throw std::runtime_error("Unsupported error type received"); 600 } 601 602 // Path to hold callout inventory path. 603 std::string l_calloutInvPath; 604 605 uint16_t l_errCode = 0; 606 607 // check if callout path is a valid inventory path. if not, get the JSON 608 // object to get inventory path. 609 if (std::get<0>(i_callouts[0]) 610 .compare(constants::VALUE_0, strlen(constants::pimPath), 611 constants::pimPath) != constants::STR_CMP_SUCCESS) 612 { 613 std::error_code l_ec; 614 // implies json dependent execution. 615 if (std::filesystem::exists(INVENTORY_JSON_SYM_LINK, l_ec)) 616 { 617 if (!l_ec) 618 { 619 nlohmann::json l_parsedJson = jsonUtility::getParsedJson( 620 INVENTORY_JSON_SYM_LINK, l_errCode); 621 622 if (l_errCode) 623 { 624 logging::logMessage( 625 "Failed to parse JSON file [ " + 626 std::string(INVENTORY_JSON_SYM_LINK) + 627 " ], error : " + 628 commonUtility::getErrCodeMsg(l_errCode)); 629 } 630 631 l_calloutInvPath = jsonUtility::getInventoryObjPathFromJson( 632 l_parsedJson, std::get<0>(i_callouts[0]), l_errCode); 633 } 634 else 635 { 636 logging::logMessage( 637 "Error finding symlink. Continue with given path"); 638 } 639 } 640 } 641 642 if (l_calloutInvPath.empty()) 643 { 644 l_calloutInvPath = std::get<0>(i_callouts[0]); 645 646 if (l_errCode) 647 { 648 logging::logMessage( 649 "Failed to get inventory object path from JSON for FRU [" + 650 std::get<0>(i_callouts[0]) + 651 "], error : " + commonUtility::getErrCodeMsg(l_errCode)); 652 } 653 } 654 655 const std::map<std::string, std::string> l_additionalData{ 656 {"FileName", i_fileName}, 657 {"FunctionName", i_funcName}, 658 {"DESCRIPTION", 659 (!i_description.empty() ? i_description : "VPD generic error")}, 660 {"CALLOUT_INVENTORY_PATH", l_calloutInvPath}, 661 {"InteranlRc", std::to_string(i_internalRc)}, 662 {"UserData1", ((i_userData1) ? (*i_userData1) : "").c_str()}, 663 {"UserData2", ((i_userData2) ? (*i_userData2) : "").c_str()}}; 664 665 const std::string& l_severity = 666 (severityMap.find(i_severity) != severityMap.end() 667 ? severityMap.at(i_severity) 668 : severityMap.at(types::SeverityType::Informational)); 669 670 auto l_bus = sdbusplus::bus::new_default(); 671 auto l_method = 672 l_bus.new_method_call(constants::eventLoggingServiceName, 673 constants::eventLoggingObjectPath, 674 constants::eventLoggingInterface, "Create"); 675 l_method.append(errorMsgMap.at(i_errorType), l_severity, 676 l_additionalData); 677 l_bus.call(l_method); 678 } 679 catch (const std::exception& l_ex) 680 { 681 logging::logMessage( 682 "Sync PEL creation with inventory path failed with error: " + 683 std::string(l_ex.what())); 684 } 685 } 686 } // namespace EventLogger 687 } // namespace vpd 688