Break out hostlogger

Similar to what we've done elsewhere, break out hostlogger into its own
file.

Tested: Code compiles.

Change-Id: Ib9a48577878f57eb7ed4e3cf6b84a58a3ec203f6
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index 46ceae1..f9a68e7 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -2007,230 +2007,6 @@
     return true;
 }
 
-inline void fillHostLoggerEntryJson(std::string_view logEntryID,
-                                    std::string_view msg,
-                                    nlohmann::json::object_t& logEntryJson)
-{
-    // Fill in the log entry with the gathered data.
-    logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
-    logEntryJson["@odata.id"] = boost::urls::format(
-        "/redfish/v1/Systems/{}/LogServices/HostLogger/Entries/{}",
-        BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
-    logEntryJson["Name"] = "Host Logger Entry";
-    logEntryJson["Id"] = logEntryID;
-    logEntryJson["Message"] = msg;
-    logEntryJson["EntryType"] = log_entry::LogEntryType::Oem;
-    logEntryJson["Severity"] = log_entry::EventSeverity::OK;
-    logEntryJson["OemRecordFormat"] = "Host Logger Entry";
-}
-
-inline void requestRoutesSystemHostLogger(App& app)
-{
-    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/HostLogger/")
-        .privileges(redfish::privileges::getLogService)
-        .methods(boost::beast::http::verb::get)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                   const std::string& systemName) {
-                if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-                {
-                    return;
-                }
-                if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
-                {
-                    // Option currently returns no systems.  TBD
-                    messages::resourceNotFound(asyncResp->res, "ComputerSystem",
-                                               systemName);
-                    return;
-                }
-                if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
-                {
-                    messages::resourceNotFound(asyncResp->res, "ComputerSystem",
-                                               systemName);
-                    return;
-                }
-                asyncResp->res.jsonValue["@odata.id"] =
-                    std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
-                                BMCWEB_REDFISH_SYSTEM_URI_NAME);
-                asyncResp->res.jsonValue["@odata.type"] =
-                    "#LogService.v1_2_0.LogService";
-                asyncResp->res.jsonValue["Name"] = "Host Logger Service";
-                asyncResp->res.jsonValue["Description"] = "Host Logger Service";
-                asyncResp->res.jsonValue["Id"] = "HostLogger";
-                asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
-                    "/redfish/v1/Systems/{}/LogServices/HostLogger/Entries",
-                    BMCWEB_REDFISH_SYSTEM_URI_NAME);
-            });
-}
-
-inline void requestRoutesSystemHostLoggerCollection(App& app)
-{
-    BMCWEB_ROUTE(app,
-                 "/redfish/v1/Systems/<str>/LogServices/HostLogger/Entries/")
-        .privileges(redfish::privileges::getLogEntry)
-        .methods(
-            boost::beast::http::verb::
-                get)([&app](const crow::Request& req,
-                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                            const std::string& systemName) {
-            query_param::QueryCapabilities capabilities = {
-                .canDelegateTop = true,
-                .canDelegateSkip = true,
-            };
-            query_param::Query delegatedQuery;
-            if (!redfish::setUpRedfishRouteWithDelegation(
-                    app, req, asyncResp, delegatedQuery, capabilities))
-            {
-                return;
-            }
-            if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
-            {
-                // Option currently returns no systems.  TBD
-                messages::resourceNotFound(asyncResp->res, "ComputerSystem",
-                                           systemName);
-                return;
-            }
-            if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
-            {
-                messages::resourceNotFound(asyncResp->res, "ComputerSystem",
-                                           systemName);
-                return;
-            }
-            asyncResp->res.jsonValue["@odata.id"] = std::format(
-                "/redfish/v1/Systems/{}/LogServices/HostLogger/Entries",
-                BMCWEB_REDFISH_SYSTEM_URI_NAME);
-            asyncResp->res.jsonValue["@odata.type"] =
-                "#LogEntryCollection.LogEntryCollection";
-            asyncResp->res.jsonValue["Name"] = "HostLogger Entries";
-            asyncResp->res.jsonValue["Description"] =
-                "Collection of HostLogger Entries";
-            nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
-            logEntryArray = nlohmann::json::array();
-            asyncResp->res.jsonValue["Members@odata.count"] = 0;
-
-            std::vector<std::filesystem::path> hostLoggerFiles;
-            if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles))
-            {
-                BMCWEB_LOG_DEBUG("Failed to get host log file path");
-                return;
-            }
-            // If we weren't provided top and skip limits, use the defaults.
-            size_t skip = delegatedQuery.skip.value_or(0);
-            size_t top =
-                delegatedQuery.top.value_or(query_param::Query::maxTop);
-            size_t logCount = 0;
-            // This vector only store the entries we want to expose that
-            // control by skip and top.
-            std::vector<std::string> logEntries;
-            if (!getHostLoggerEntries(hostLoggerFiles, skip, top, logEntries,
-                                      logCount))
-            {
-                messages::internalError(asyncResp->res);
-                return;
-            }
-            // If vector is empty, that means skip value larger than total
-            // log count
-            if (logEntries.empty())
-            {
-                asyncResp->res.jsonValue["Members@odata.count"] = logCount;
-                return;
-            }
-            if (!logEntries.empty())
-            {
-                for (size_t i = 0; i < logEntries.size(); i++)
-                {
-                    nlohmann::json::object_t hostLogEntry;
-                    fillHostLoggerEntryJson(std::to_string(skip + i),
-                                            logEntries[i], hostLogEntry);
-                    logEntryArray.emplace_back(std::move(hostLogEntry));
-                }
-
-                asyncResp->res.jsonValue["Members@odata.count"] = logCount;
-                if (skip + top < logCount)
-                {
-                    asyncResp->res.jsonValue["Members@odata.nextLink"] =
-                        std::format(
-                            "/redfish/v1/Systems/{}/LogServices/HostLogger/Entries?$skip=",
-                            BMCWEB_REDFISH_SYSTEM_URI_NAME) +
-                        std::to_string(skip + top);
-                }
-            }
-        });
-}
-
-inline void requestRoutesSystemHostLoggerLogEntry(App& app)
-{
-    BMCWEB_ROUTE(
-        app, "/redfish/v1/Systems/<str>/LogServices/HostLogger/Entries/<str>/")
-        .privileges(redfish::privileges::getLogEntry)
-        .methods(boost::beast::http::verb::get)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                   const std::string& systemName, const std::string& param) {
-                if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-                {
-                    return;
-                }
-                if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
-                {
-                    // Option currently returns no systems.  TBD
-                    messages::resourceNotFound(asyncResp->res, "ComputerSystem",
-                                               systemName);
-                    return;
-                }
-                if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
-                {
-                    messages::resourceNotFound(asyncResp->res, "ComputerSystem",
-                                               systemName);
-                    return;
-                }
-                std::string_view targetID = param;
-
-                uint64_t idInt = 0;
-
-                auto [ptr, ec] =
-                    std::from_chars(targetID.begin(), targetID.end(), idInt);
-                if (ec != std::errc{} || ptr != targetID.end())
-                {
-                    messages::resourceNotFound(asyncResp->res, "LogEntry",
-                                               param);
-                    return;
-                }
-
-                std::vector<std::filesystem::path> hostLoggerFiles;
-                if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles))
-                {
-                    BMCWEB_LOG_DEBUG("Failed to get host log file path");
-                    return;
-                }
-
-                size_t logCount = 0;
-                size_t top = 1;
-                std::vector<std::string> logEntries;
-                // We can get specific entry by skip and top. For example, if we
-                // want to get nth entry, we can set skip = n-1 and top = 1 to
-                // get that entry
-                if (!getHostLoggerEntries(hostLoggerFiles, idInt, top,
-                                          logEntries, logCount))
-                {
-                    messages::internalError(asyncResp->res);
-                    return;
-                }
-
-                if (!logEntries.empty())
-                {
-                    nlohmann::json::object_t hostLogEntry;
-                    fillHostLoggerEntryJson(targetID, logEntries[0],
-                                            hostLogEntry);
-                    asyncResp->res.jsonValue.update(hostLogEntry);
-                    return;
-                }
-
-                // Requested ID was not found
-                messages::resourceNotFound(asyncResp->res, "LogEntry", param);
-            });
-}
-
 inline void handleBMCLogServicesCollectionGet(
     crow::App& app, const crow::Request& req,
     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
diff --git a/redfish-core/lib/systems_logservices_hostlogger.hpp b/redfish-core/lib/systems_logservices_hostlogger.hpp
new file mode 100644
index 0000000..1dde09c
--- /dev/null
+++ b/redfish-core/lib/systems_logservices_hostlogger.hpp
@@ -0,0 +1,250 @@
+#pragma once
+
+#include "app.hpp"
+#include "generated/enums/log_entry.hpp"
+#include "query.hpp"
+#include "registries/openbmc_message_registry.hpp"
+#include "registries/privilege_registry.hpp"
+#include "utils/time_utils.hpp"
+
+#include <cstdint>
+#include <memory>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+namespace redfish
+{
+
+inline void fillHostLoggerEntryJson(std::string_view logEntryID,
+                                    std::string_view msg,
+                                    nlohmann::json::object_t& logEntryJson)
+{
+    // Fill in the log entry with the gathered data.
+    logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
+    logEntryJson["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Systems/{}/LogServices/HostLogger/Entries/{}",
+        BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
+    logEntryJson["Name"] = "Host Logger Entry";
+    logEntryJson["Id"] = logEntryID;
+    logEntryJson["Message"] = msg;
+    logEntryJson["EntryType"] = log_entry::LogEntryType::Oem;
+    logEntryJson["Severity"] = log_entry::EventSeverity::OK;
+    logEntryJson["OemRecordFormat"] = "Host Logger Entry";
+}
+
+inline void requestRoutesSystemHostLogger(App& app)
+{
+    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/HostLogger/")
+        .privileges(redfish::privileges::getLogService)
+        .methods(boost::beast::http::verb::get)(
+            [&app](const crow::Request& req,
+                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                   const std::string& systemName) {
+                if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+                {
+                    return;
+                }
+                if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+                {
+                    // Option currently returns no systems.  TBD
+                    messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+                                               systemName);
+                    return;
+                }
+                if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+                {
+                    messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+                                               systemName);
+                    return;
+                }
+                asyncResp->res.jsonValue["@odata.id"] =
+                    std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
+                                BMCWEB_REDFISH_SYSTEM_URI_NAME);
+                asyncResp->res.jsonValue["@odata.type"] =
+                    "#LogService.v1_2_0.LogService";
+                asyncResp->res.jsonValue["Name"] = "Host Logger Service";
+                asyncResp->res.jsonValue["Description"] = "Host Logger Service";
+                asyncResp->res.jsonValue["Id"] = "HostLogger";
+                asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
+                    "/redfish/v1/Systems/{}/LogServices/HostLogger/Entries",
+                    BMCWEB_REDFISH_SYSTEM_URI_NAME);
+            });
+}
+
+inline void requestRoutesSystemHostLoggerCollection(App& app)
+{
+    BMCWEB_ROUTE(app,
+                 "/redfish/v1/Systems/<str>/LogServices/HostLogger/Entries/")
+        .privileges(redfish::privileges::getLogEntry)
+        .methods(
+            boost::beast::http::verb::
+                get)([&app](const crow::Request& req,
+                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                            const std::string& systemName) {
+            query_param::QueryCapabilities capabilities = {
+                .canDelegateTop = true,
+                .canDelegateSkip = true,
+            };
+            query_param::Query delegatedQuery;
+            if (!redfish::setUpRedfishRouteWithDelegation(
+                    app, req, asyncResp, delegatedQuery, capabilities))
+            {
+                return;
+            }
+            if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+            {
+                // Option currently returns no systems.  TBD
+                messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+                                           systemName);
+                return;
+            }
+            if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+            {
+                messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+                                           systemName);
+                return;
+            }
+            asyncResp->res.jsonValue["@odata.id"] = std::format(
+                "/redfish/v1/Systems/{}/LogServices/HostLogger/Entries",
+                BMCWEB_REDFISH_SYSTEM_URI_NAME);
+            asyncResp->res.jsonValue["@odata.type"] =
+                "#LogEntryCollection.LogEntryCollection";
+            asyncResp->res.jsonValue["Name"] = "HostLogger Entries";
+            asyncResp->res.jsonValue["Description"] =
+                "Collection of HostLogger Entries";
+            nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
+            logEntryArray = nlohmann::json::array();
+            asyncResp->res.jsonValue["Members@odata.count"] = 0;
+
+            std::vector<std::filesystem::path> hostLoggerFiles;
+            if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles))
+            {
+                BMCWEB_LOG_DEBUG("Failed to get host log file path");
+                return;
+            }
+            // If we weren't provided top and skip limits, use the defaults.
+            size_t skip = delegatedQuery.skip.value_or(0);
+            size_t top =
+                delegatedQuery.top.value_or(query_param::Query::maxTop);
+            size_t logCount = 0;
+            // This vector only store the entries we want to expose that
+            // control by skip and top.
+            std::vector<std::string> logEntries;
+            if (!getHostLoggerEntries(hostLoggerFiles, skip, top, logEntries,
+                                      logCount))
+            {
+                messages::internalError(asyncResp->res);
+                return;
+            }
+            // If vector is empty, that means skip value larger than total
+            // log count
+            if (logEntries.empty())
+            {
+                asyncResp->res.jsonValue["Members@odata.count"] = logCount;
+                return;
+            }
+            if (!logEntries.empty())
+            {
+                for (size_t i = 0; i < logEntries.size(); i++)
+                {
+                    nlohmann::json::object_t hostLogEntry;
+                    fillHostLoggerEntryJson(std::to_string(skip + i),
+                                            logEntries[i], hostLogEntry);
+                    logEntryArray.emplace_back(std::move(hostLogEntry));
+                }
+
+                asyncResp->res.jsonValue["Members@odata.count"] = logCount;
+                if (skip + top < logCount)
+                {
+                    asyncResp->res.jsonValue["Members@odata.nextLink"] =
+                        std::format(
+                            "/redfish/v1/Systems/{}/LogServices/HostLogger/Entries?$skip=",
+                            BMCWEB_REDFISH_SYSTEM_URI_NAME) +
+                        std::to_string(skip + top);
+                }
+            }
+        });
+}
+
+inline void requestRoutesSystemHostLoggerLogEntry(App& app)
+{
+    BMCWEB_ROUTE(
+        app, "/redfish/v1/Systems/<str>/LogServices/HostLogger/Entries/<str>/")
+        .privileges(redfish::privileges::getLogEntry)
+        .methods(boost::beast::http::verb::get)(
+            [&app](const crow::Request& req,
+                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                   const std::string& systemName, const std::string& param) {
+                if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+                {
+                    return;
+                }
+                if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+                {
+                    // Option currently returns no systems.  TBD
+                    messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+                                               systemName);
+                    return;
+                }
+                if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+                {
+                    messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+                                               systemName);
+                    return;
+                }
+                std::string_view targetID = param;
+
+                uint64_t idInt = 0;
+
+                auto [ptr, ec] =
+                    std::from_chars(targetID.begin(), targetID.end(), idInt);
+                if (ec != std::errc{} || ptr != targetID.end())
+                {
+                    messages::resourceNotFound(asyncResp->res, "LogEntry",
+                                               param);
+                    return;
+                }
+
+                std::vector<std::filesystem::path> hostLoggerFiles;
+                if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles))
+                {
+                    BMCWEB_LOG_DEBUG("Failed to get host log file path");
+                    return;
+                }
+
+                size_t logCount = 0;
+                size_t top = 1;
+                std::vector<std::string> logEntries;
+                // We can get specific entry by skip and top. For example, if we
+                // want to get nth entry, we can set skip = n-1 and top = 1 to
+                // get that entry
+                if (!getHostLoggerEntries(hostLoggerFiles, idInt, top,
+                                          logEntries, logCount))
+                {
+                    messages::internalError(asyncResp->res);
+                    return;
+                }
+
+                if (!logEntries.empty())
+                {
+                    nlohmann::json::object_t hostLogEntry;
+                    fillHostLoggerEntryJson(targetID, logEntries[0],
+                                            hostLogEntry);
+                    asyncResp->res.jsonValue.update(hostLogEntry);
+                    return;
+                }
+
+                // Requested ID was not found
+                messages::resourceNotFound(asyncResp->res, "LogEntry", param);
+            });
+}
+
+inline void requestRoutesSystemsLogServiceHostlogger(App& app)
+{
+    requestRoutesSystemHostLogger(app);
+    requestRoutesSystemHostLoggerCollection(app);
+    requestRoutesSystemHostLoggerLogEntry(app);
+}
+
+} // namespace redfish
diff --git a/redfish-core/src/redfish.cpp b/redfish-core/src/redfish.cpp
index 95f50ca..61f2762 100644
--- a/redfish-core/src/redfish.cpp
+++ b/redfish-core/src/redfish.cpp
@@ -39,6 +39,7 @@
 #include "service_root.hpp"
 #include "storage.hpp"
 #include "systems.hpp"
+#include "systems_logservices_hostlogger.hpp"
 #include "systems_logservices_postcodes.hpp"
 #include "task.hpp"
 #include "telemetry_service.hpp"
@@ -183,9 +184,7 @@
 
     if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
     {
-        requestRoutesSystemHostLogger(app);
-        requestRoutesSystemHostLoggerCollection(app);
-        requestRoutesSystemHostLoggerLogEntry(app);
+        requestRoutesSystemsLogServiceHostlogger(app);
     }
 
     requestRoutesMessageRegistryFileCollection(app);