PEL: Still create PEL when error not in registry

When an OpenBMC event log is created for an error that isn't in the PEL
message registry, the code will now find a registry entry using another
default error name.  This default PEL will contain the severity and any
callouts specified by the original event log, and its message used by
peltool and possibly Redfish will state that the actual meaning for the
error is unknown.

The error name property that was missing from the registry will be
placed in the JSON UserData section that hold the AdditionalData
property fields under the key ERROR_NAME.

Doing this allows one to see all errors on a system just by looking at
PELs, and not miss important ones just because a developer doesn't have
their error in the registry yet.

When these are seen, it may be a good idea to create bug reports as a
reminder that the missing error needs to be added.

Change-Id: Ifa3db21af96745dd651da5f5af0ab970a952f46a
diff --git a/extensions/openpower-pels/manager.cpp b/extensions/openpower-pels/manager.cpp
index d7fbcad..c8b5872 100644
--- a/extensions/openpower-pels/manager.cpp
+++ b/extensions/openpower-pels/manager.cpp
@@ -44,8 +44,11 @@
 {
 constexpr auto rawPEL = "RAWPEL";
 constexpr auto esel = "ESEL";
+constexpr auto error = "ERROR_NAME";
 } // namespace additional_data
 
+constexpr auto defaultLogMessage = "xyz.openbmc_project.Logging.Error.Default";
+
 Manager::~Manager()
 {
     if (_pelFileDeleteFD != -1)
@@ -286,43 +289,53 @@
                         const FFDCEntries& ffdc)
 {
     auto entry = _registry.lookup(message, rg::LookupType::name);
+    auto pelFFDC = convertToPelFFDC(ffdc);
+    AdditionalData ad{additionalData};
     std::string msg;
 
-    if (entry)
+    if (!entry)
     {
-        AdditionalData ad{additionalData};
-
-        auto pelFFDC = convertToPelFFDC(ffdc);
-
-        auto pel = std::make_unique<openpower::pels::PEL>(
-            *entry, obmcLogID, timestamp, severity, ad, pelFFDC, *_dataIface);
-
-        _repo.add(pel);
-
-        if (_repo.sizeWarning())
-        {
-            scheduleRepoPrune();
-        }
-
-        auto src = pel->primarySRC();
-        if (src)
-        {
-            using namespace std::literals::string_literals;
-            auto id = getNumberString("0x%08X", pel->id());
-            msg = "Created PEL "s + id + " with SRC "s + (*src)->asciiString();
-            while (msg.back() == ' ')
-            {
-                msg.pop_back();
-            }
-            log<level::INFO>(msg.c_str());
-        }
-    }
-    else
-    {
-        // TODO ibm-openbmc/dev/1151: Create a new PEL for this case.
-        // For now, just trace it.
+        // Instead, get the default entry that means there is no
+        // other matching entry.  This error will still use the
+        // AdditionalData values of the original error, and this
+        // code will add the error message value that wasn't found
+        // to this AD.  This way, there will at least be a PEL,
+        // possibly with callouts, to allow users to debug the
+        // issue that caused the error even without its own PEL.
         msg = "Event not found in PEL message registry: " + message;
         log<level::INFO>(msg.c_str());
+
+        entry = _registry.lookup(defaultLogMessage, rg::LookupType::name);
+        if (!entry)
+        {
+            log<level::ERR>("Default event not found in PEL message registry");
+            return;
+        }
+
+        ad.add(additional_data::error, message);
+    }
+
+    auto pel = std::make_unique<openpower::pels::PEL>(
+        *entry, obmcLogID, timestamp, severity, ad, pelFFDC, *_dataIface);
+
+    _repo.add(pel);
+
+    if (_repo.sizeWarning())
+    {
+        scheduleRepoPrune();
+    }
+
+    auto src = pel->primarySRC();
+    if (src)
+    {
+        using namespace std::literals::string_literals;
+        auto id = getNumberString("0x%08X", pel->id());
+        msg = "Created PEL "s + id + " with SRC "s + (*src)->asciiString();
+        while (msg.back() == ' ')
+        {
+            msg.pop_back();
+        }
+        log<level::INFO>(msg.c_str());
     }
 }