Add journal traces to occ-control PELs
When creating a PEL, the last lines of the journal for the app will get
saved into the PEL for additional debug.
Change-Id: Ifa05a00ffdc57833859d719d0e7d8b81ccadb5c8
Signed-off-by: Chris Cain <cjcain@us.ibm.com>
diff --git a/occ_ffdc.hpp b/occ_ffdc.hpp
index a2b1200..61bd714 100644
--- a/occ_ffdc.hpp
+++ b/occ_ffdc.hpp
@@ -2,13 +2,76 @@
#include "config.h"
+#include "file.hpp"
#include "occ_errors.hpp"
+#include <systemd/sd-journal.h>
+
+#include <nlohmann/json.hpp>
+#include <xyz/openbmc_project/Logging/Create/server.hpp>
+
+using FFDCFormat =
+ sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat;
+using FFDCFiles = std::vector<
+ std::tuple<FFDCFormat, uint8_t, uint8_t, sdbusplus::message::unix_fd>>;
+
namespace open_power
{
namespace occ
{
+/** @class FFDCFile
+ * @brief Represents a single file that will get opened when created and
+ * deleted when the object is destructed
+ */
+class FFDCFile
+{
+ public:
+ FFDCFile() = delete;
+ FFDCFile(const FFDCFile&) = delete;
+ FFDCFile& operator=(const FFDCFile&) = delete;
+ FFDCFile(FFDCFile&&) = delete;
+ FFDCFile& operator=(FFDCFile&&) = delete;
+
+ /**
+ * @brief Constructor
+ *
+ * Opens the file and saves the descriptor
+ *
+ * @param[in] name - The filename
+ */
+ explicit FFDCFile(const std::filesystem::path& name);
+
+ /**
+ * @brief Destructor - Deletes the file
+ */
+ ~FFDCFile()
+ {
+ std::filesystem::remove(_name);
+ }
+
+ /**
+ * @brief Returns the file descriptor
+ *
+ * @return int - The descriptor
+ */
+ int fd()
+ {
+ return _fd();
+ }
+
+ private:
+ /**
+ * @brief The file descriptor holder
+ */
+ FileDescriptor _fd;
+
+ /**
+ * @brief The filename
+ */
+ const std::filesystem::path _name;
+};
+
/** @class FFDC
* @brief Monitors for SBE FFDC availability
*/
@@ -64,6 +127,20 @@
static void createOCCResetPEL(unsigned int instance, const char* path,
int err, const char* callout);
+ /**
+ * @brief Create a file containing the latest journal traces for the
+ * specified executable and add it to the file list.
+ *
+ * @param[in] fileList - where to add the new file
+ * @param[in] executable - name of app to collect
+ * @param[in] lines - number of journal lines to save
+ *
+ * @return std::unique_ptr<FFDCFile> - The file object
+ */
+ static std::unique_ptr<FFDCFile>
+ addJournalEntries(FFDCFiles& fileList, const std::string& executable,
+ unsigned int lines);
+
private:
/** @brief OCC instance number. Ex, 0,1, etc */
unsigned int instance;
@@ -79,6 +156,77 @@
* content denotes an error condition
*/
void analyzeEvent() override;
+
+ /**
+ * @brief Returns an FFDCFile containing the JSON data
+ *
+ * @param[in] ffdcData - The JSON data to write to a file
+ *
+ * @return std::unique_ptr<FFDCFile> - The file object
+ */
+ static std::unique_ptr<FFDCFile>
+ makeJsonFFDCFile(const nlohmann::json& ffdcData);
+
+ /**
+ * @brief Returns a JSON structure containing the previous N journal
+ * entries.
+ *
+ * @param[in] numLines - Number of lines of journal to retrieve
+ * @param[in] executable - name of app to collect for
+ *
+ * @return JSON object that was created
+ */
+ static nlohmann::json getJournalEntries(int numLines,
+ std::string executable);
+
+ /**
+ * @brief Gets the realtime (wallclock) timestamp for the current journal
+ * entry.
+ *
+ * @param journal current journal entry
+ * @return timestamp as a date/time string
+ */
+ static std::string getTimeStamp(sd_journal* journal);
+
+ /**
+ * @brief Gets the value of the specified field for the current journal
+ * entry.
+ *
+ * Returns an empty string if the current journal entry does not have the
+ * specified field.
+ *
+ * @param journal current journal entry
+ * @param field journal field name
+ * @return field value
+ */
+ static std::string getFieldValue(sd_journal* journal,
+ const std::string& field);
+};
+
+/**
+ * @class JournalCloser
+ * @brief Automatically closes the journal when the object goes out of scope.
+ */
+class JournalCloser
+{
+ public:
+ // Specify which compiler-generated methods we want
+ JournalCloser() = delete;
+ JournalCloser(const JournalCloser&) = delete;
+ JournalCloser(JournalCloser&&) = delete;
+ JournalCloser& operator=(const JournalCloser&) = delete;
+ JournalCloser& operator=(JournalCloser&&) = delete;
+
+ JournalCloser(sd_journal* journal) : journal{journal}
+ {}
+
+ ~JournalCloser()
+ {
+ sd_journal_close(journal);
+ }
+
+ private:
+ sd_journal* journal{nullptr};
};
} // namespace occ