Break out journal utils

A number of the journald utilities are distinct from Redfish, and could
be reused.  Functions moved are copy/paste with no modifications.

Tested:
Journald LogService GET still functions correctly
Redfish service validator fails no new checks.

Change-Id: Icf1c28152e14f3e0c1c5203aac50c40d56bb272e
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/redfish-core/include/utils/journal_utils.hpp b/redfish-core/include/utils/journal_utils.hpp
new file mode 100644
index 0000000..af8f3a7
--- /dev/null
+++ b/redfish-core/include/utils/journal_utils.hpp
@@ -0,0 +1,148 @@
+#pragma once
+
+#include "logging.hpp"
+#include "utils/time_utils.hpp"
+
+#include <systemd/sd-journal.h>
+
+#include <nlohmann/json.hpp>
+
+#include <string>
+#include <string_view>
+
+namespace redfish
+{
+
+inline int getJournalMetadata(sd_journal* journal, const char* field,
+                              std::string_view& contents)
+{
+    const char* data = nullptr;
+    size_t length = 0;
+    int ret = 0;
+    // Get the metadata from the requested field of the journal entry
+    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+    const void** dataVoid = reinterpret_cast<const void**>(&data);
+
+    ret = sd_journal_get_data(journal, field, dataVoid, &length);
+    if (ret < 0)
+    {
+        return ret;
+    }
+    contents = std::string_view(data, length);
+    // Only use the content after the "=" character.
+    contents.remove_prefix(std::min(contents.find('=') + 1, contents.size()));
+    return ret;
+}
+
+inline int getJournalMetadataInt(sd_journal* journal, const char* field,
+                                 long int& contents)
+{
+    std::string_view metadata;
+    // Get the metadata from the requested field of the journal entry
+    int ret = getJournalMetadata(journal, field, metadata);
+    if (ret < 0)
+    {
+        return ret;
+    }
+    std::from_chars_result res =
+        std::from_chars(&*metadata.begin(), &*metadata.end(), contents);
+    if (res.ec != std::error_code{} || res.ptr != &*metadata.end())
+    {
+        return -1;
+    }
+    return 0;
+}
+
+inline bool getEntryTimestamp(sd_journal* journal, std::string& entryTimestamp)
+{
+    int ret = 0;
+    uint64_t timestamp = 0;
+    ret = sd_journal_get_realtime_usec(journal, &timestamp);
+    if (ret < 0)
+    {
+        BMCWEB_LOG_ERROR("Failed to read entry timestamp: {}", ret);
+        return false;
+    }
+    entryTimestamp = redfish::time_utils::getDateTimeUintUs(timestamp);
+    return true;
+}
+
+inline bool fillBMCJournalLogEntryJson(
+    sd_journal* journal, nlohmann::json::object_t& bmcJournalLogEntryJson)
+{
+    char* cursor = nullptr;
+    int ret = sd_journal_get_cursor(journal, &cursor);
+    if (ret < 0)
+    {
+        return false;
+    }
+    std::unique_ptr<char*> cursorptr = std::make_unique<char*>(cursor);
+    std::string bmcJournalLogEntryID(cursor);
+
+    // Get the Log Entry contents
+    std::string message;
+    std::string_view syslogID;
+    ret = getJournalMetadata(journal, "SYSLOG_IDENTIFIER", syslogID);
+    if (ret < 0)
+    {
+        BMCWEB_LOG_DEBUG("Failed to read SYSLOG_IDENTIFIER field: {}", ret);
+    }
+    if (!syslogID.empty())
+    {
+        message += std::string(syslogID) + ": ";
+    }
+
+    std::string_view msg;
+    ret = getJournalMetadata(journal, "MESSAGE", msg);
+    if (ret < 0)
+    {
+        BMCWEB_LOG_ERROR("Failed to read MESSAGE field: {}", ret);
+        return false;
+    }
+    message += std::string(msg);
+
+    // Get the severity from the PRIORITY field
+    long int severity = 8; // Default to an invalid priority
+    ret = getJournalMetadataInt(journal, "PRIORITY", severity);
+    if (ret < 0)
+    {
+        BMCWEB_LOG_DEBUG("Failed to read PRIORITY field: {}", ret);
+    }
+
+    // Get the Created time from the timestamp
+    std::string entryTimeStr;
+    if (!getEntryTimestamp(journal, entryTimeStr))
+    {
+        return false;
+    }
+
+    // Fill in the log entry with the gathered data
+    bmcJournalLogEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
+
+    std::string entryIdBase64 =
+        crow::utility::base64encode(bmcJournalLogEntryID);
+
+    bmcJournalLogEntryJson["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Managers/{}/LogServices/Journal/Entries/{}",
+        BMCWEB_REDFISH_MANAGER_URI_NAME, entryIdBase64);
+    bmcJournalLogEntryJson["Name"] = "BMC Journal Entry";
+    bmcJournalLogEntryJson["Id"] = entryIdBase64;
+    bmcJournalLogEntryJson["Message"] = std::move(message);
+    bmcJournalLogEntryJson["EntryType"] = log_entry::LogEntryType::Oem;
+    log_entry::EventSeverity severityEnum = log_entry::EventSeverity::OK;
+    if (severity <= 2)
+    {
+        severityEnum = log_entry::EventSeverity::Critical;
+    }
+    else if (severity <= 4)
+    {
+        severityEnum = log_entry::EventSeverity::Warning;
+    }
+
+    bmcJournalLogEntryJson["Severity"] = severityEnum;
+    bmcJournalLogEntryJson["OemRecordFormat"] = "BMC Journal Entry";
+    bmcJournalLogEntryJson["Created"] = std::move(entryTimeStr);
+    return true;
+}
+
+} // namespace redfish
diff --git a/redfish-core/lib/manager_logservices_journal.hpp b/redfish-core/lib/manager_logservices_journal.hpp
index 0a90390..e5bc35e 100644
--- a/redfish-core/lib/manager_logservices_journal.hpp
+++ b/redfish-core/lib/manager_logservices_journal.hpp
@@ -6,6 +6,7 @@
 #include "query.hpp"
 #include "registries/base_message_registry.hpp"
 #include "registries/privilege_registry.hpp"
+#include "utils/journal_utils.hpp"
 #include "utils/time_utils.hpp"
 
 #include <systemd/sd-journal.h>
@@ -20,138 +21,6 @@
 namespace redfish
 {
 
-inline int getJournalMetadata(sd_journal* journal, const char* field,
-                              std::string_view& contents)
-{
-    const char* data = nullptr;
-    size_t length = 0;
-    int ret = 0;
-    // Get the metadata from the requested field of the journal entry
-    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-    const void** dataVoid = reinterpret_cast<const void**>(&data);
-
-    ret = sd_journal_get_data(journal, field, dataVoid, &length);
-    if (ret < 0)
-    {
-        return ret;
-    }
-    contents = std::string_view(data, length);
-    // Only use the content after the "=" character.
-    contents.remove_prefix(std::min(contents.find('=') + 1, contents.size()));
-    return ret;
-}
-
-inline int getJournalMetadataInt(sd_journal* journal, const char* field,
-                                 long int& contents)
-{
-    std::string_view metadata;
-    // Get the metadata from the requested field of the journal entry
-    int ret = getJournalMetadata(journal, field, metadata);
-    if (ret < 0)
-    {
-        return ret;
-    }
-    std::from_chars_result res =
-        std::from_chars(&*metadata.begin(), &*metadata.end(), contents);
-    if (res.ec != std::error_code{} || res.ptr != &*metadata.end())
-    {
-        return -1;
-    }
-    return 0;
-}
-
-inline bool getEntryTimestamp(sd_journal* journal, std::string& entryTimestamp)
-{
-    int ret = 0;
-    uint64_t timestamp = 0;
-    ret = sd_journal_get_realtime_usec(journal, &timestamp);
-    if (ret < 0)
-    {
-        BMCWEB_LOG_ERROR("Failed to read entry timestamp: {}", ret);
-        return false;
-    }
-    entryTimestamp = redfish::time_utils::getDateTimeUintUs(timestamp);
-    return true;
-}
-
-inline bool fillBMCJournalLogEntryJson(
-    sd_journal* journal, nlohmann::json::object_t& bmcJournalLogEntryJson)
-{
-    char* cursor = nullptr;
-    int ret = sd_journal_get_cursor(journal, &cursor);
-    if (ret < 0)
-    {
-        return false;
-    }
-    std::unique_ptr<char*> cursorptr = std::make_unique<char*>(cursor);
-    std::string bmcJournalLogEntryID(cursor);
-
-    // Get the Log Entry contents
-    std::string message;
-    std::string_view syslogID;
-    ret = getJournalMetadata(journal, "SYSLOG_IDENTIFIER", syslogID);
-    if (ret < 0)
-    {
-        BMCWEB_LOG_DEBUG("Failed to read SYSLOG_IDENTIFIER field: {}", ret);
-    }
-    if (!syslogID.empty())
-    {
-        message += std::string(syslogID) + ": ";
-    }
-
-    std::string_view msg;
-    ret = getJournalMetadata(journal, "MESSAGE", msg);
-    if (ret < 0)
-    {
-        BMCWEB_LOG_ERROR("Failed to read MESSAGE field: {}", ret);
-        return false;
-    }
-    message += std::string(msg);
-
-    // Get the severity from the PRIORITY field
-    long int severity = 8; // Default to an invalid priority
-    ret = getJournalMetadataInt(journal, "PRIORITY", severity);
-    if (ret < 0)
-    {
-        BMCWEB_LOG_DEBUG("Failed to read PRIORITY field: {}", ret);
-    }
-
-    // Get the Created time from the timestamp
-    std::string entryTimeStr;
-    if (!getEntryTimestamp(journal, entryTimeStr))
-    {
-        return false;
-    }
-
-    // Fill in the log entry with the gathered data
-    bmcJournalLogEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
-
-    std::string entryIdBase64 =
-        crow::utility::base64encode(bmcJournalLogEntryID);
-
-    bmcJournalLogEntryJson["@odata.id"] = boost::urls::format(
-        "/redfish/v1/Managers/{}/LogServices/Journal/Entries/{}",
-        BMCWEB_REDFISH_MANAGER_URI_NAME, entryIdBase64);
-    bmcJournalLogEntryJson["Name"] = "BMC Journal Entry";
-    bmcJournalLogEntryJson["Id"] = entryIdBase64;
-    bmcJournalLogEntryJson["Message"] = std::move(message);
-    bmcJournalLogEntryJson["EntryType"] = log_entry::LogEntryType::Oem;
-    log_entry::EventSeverity severityEnum = log_entry::EventSeverity::OK;
-    if (severity <= 2)
-    {
-        severityEnum = log_entry::EventSeverity::Critical;
-    }
-    else if (severity <= 4)
-    {
-        severityEnum = log_entry::EventSeverity::Warning;
-    }
-
-    bmcJournalLogEntryJson["Severity"] = severityEnum;
-    bmcJournalLogEntryJson["OemRecordFormat"] = "BMC Journal Entry";
-    bmcJournalLogEntryJson["Created"] = std::move(entryTimeStr);
-    return true;
-}
-
 inline void handleManagersLogServiceJournalGet(
     App& app, const crow::Request& req,
     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,