Break out DBus EventLog

As part of a EventLog refactor, break out all code
used for Systems DBus EventLog, in order to make the code base
more maintainable in the long run.

Tested: Only code extraction. Code compiles.

Change-Id: I94de7bf3171fd3963eebec6608438f8d07cee44c
Signed-off-by: Oliver Brewka <oliver.brewka@9elements.com>
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index 6b8d075..015360c 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -15,7 +15,6 @@
 #include "http_body.hpp"
 #include "http_request.hpp"
 #include "http_response.hpp"
-#include "http_utility.hpp"
 #include "human_sort.hpp"
 #include "logging.hpp"
 #include "query.hpp"
@@ -23,7 +22,6 @@
 #include "str_utility.hpp"
 #include "task.hpp"
 #include "task_messages.hpp"
-#include "utils/dbus_event_log_entry.hpp"
 #include "utils/dbus_utils.hpp"
 #include "utils/etag_utils.hpp"
 #include "utils/json_utils.hpp"
@@ -83,43 +81,6 @@
     DUMP_CREATE_INPROGRESS
 };
 
-inline std::string translateSeverityDbusToRedfish(const std::string& s)
-{
-    if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") ||
-        (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") ||
-        (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") ||
-        (s == "xyz.openbmc_project.Logging.Entry.Level.Error"))
-    {
-        return "Critical";
-    }
-    if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") ||
-        (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") ||
-        (s == "xyz.openbmc_project.Logging.Entry.Level.Notice"))
-    {
-        return "OK";
-    }
-    if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning")
-    {
-        return "Warning";
-    }
-    return "";
-}
-
-inline std::optional<bool> getProviderNotifyAction(const std::string& notify)
-{
-    std::optional<bool> notifyAction;
-    if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify")
-    {
-        notifyAction = true;
-    }
-    else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit")
-    {
-        notifyAction = false;
-    }
-
-    return notifyAction;
-}
-
 inline std::string getDumpPath(std::string_view dumpType)
 {
     std::string dbusDumpPath = "/xyz/openbmc_project/dump/";
@@ -553,43 +514,6 @@
         "xyz.openbmc_project.Dump.Entry", "GetFileHandle");
 }
 
-inline void downloadEventLogEntry(
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-    const std::string& systemName, const std::string& entryID,
-    const std::string& dumpType)
-{
-    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 entryPath =
-        sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") /
-        entryID;
-
-    auto downloadEventLogEntryHandler =
-        [asyncResp, entryID,
-         dumpType](const boost::system::error_code& ec,
-                   const sdbusplus::message::unix_fd& unixfd) {
-            log_services_utils::downloadEntryCallback(asyncResp, entryID,
-                                                      dumpType, ec, unixfd);
-        };
-
-    dbus::utility::async_method_call(
-        asyncResp, std::move(downloadEventLogEntryHandler),
-        "xyz.openbmc_project.Logging", entryPath,
-        "xyz.openbmc_project.Logging.Entry", "GetEntry");
-}
-
 inline DumpCreationProgress mapDbusStatusToDumpProgress(
     const std::string& status)
 {
@@ -1138,332 +1062,6 @@
         });
 }
 
-inline void fillEventLogLogEntryFromDbusLogEntry(
-    const DbusEventLogEntry& entry, nlohmann::json& objectToFillOut)
-{
-    objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
-    objectToFillOut["@odata.id"] = boost::urls::format(
-        "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
-        BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
-    objectToFillOut["Name"] = "System Event Log Entry";
-    objectToFillOut["Id"] = std::to_string(entry.Id);
-    objectToFillOut["Message"] = entry.Message;
-    objectToFillOut["Resolved"] = entry.Resolved;
-    std::optional<bool> notifyAction =
-        getProviderNotifyAction(entry.ServiceProviderNotify);
-    if (notifyAction)
-    {
-        objectToFillOut["ServiceProviderNotified"] = *notifyAction;
-    }
-    if ((entry.Resolution != nullptr) && !entry.Resolution->empty())
-    {
-        objectToFillOut["Resolution"] = *entry.Resolution;
-    }
-    objectToFillOut["EntryType"] = "Event";
-    objectToFillOut["Severity"] =
-        translateSeverityDbusToRedfish(entry.Severity);
-    objectToFillOut["Created"] =
-        redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
-    objectToFillOut["Modified"] =
-        redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp);
-    if (entry.Path != nullptr)
-    {
-        objectToFillOut["AdditionalDataURI"] = boost::urls::format(
-            "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
-            BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
-    }
-}
-
-inline void afterLogEntriesGetManagedObjects(
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-    const boost::system::error_code& ec,
-    const dbus::utility::ManagedObjectType& resp)
-{
-    if (ec)
-    {
-        // TODO Handle for specific error code
-        BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
-                         ec);
-        messages::internalError(asyncResp->res);
-        return;
-    }
-    nlohmann::json::array_t entriesArray;
-    for (const auto& objectPath : resp)
-    {
-        dbus::utility::DBusPropertiesMap propsFlattened;
-        auto isEntry =
-            std::ranges::find_if(objectPath.second, [](const auto& object) {
-                return object.first == "xyz.openbmc_project.Logging.Entry";
-            });
-        if (isEntry == objectPath.second.end())
-        {
-            continue;
-        }
-
-        for (const auto& interfaceMap : objectPath.second)
-        {
-            for (const auto& propertyMap : interfaceMap.second)
-            {
-                propsFlattened.emplace_back(propertyMap.first,
-                                            propertyMap.second);
-            }
-        }
-        std::optional<DbusEventLogEntry> optEntry =
-            fillDbusEventLogEntryFromPropertyMap(propsFlattened);
-
-        if (!optEntry.has_value())
-        {
-            messages::internalError(asyncResp->res);
-            return;
-        }
-        fillEventLogLogEntryFromDbusLogEntry(*optEntry,
-                                             entriesArray.emplace_back());
-    }
-
-    redfish::json_util::sortJsonArrayByKey(entriesArray, "Id");
-    asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
-    asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
-}
-
-inline void dBusEventLogEntryCollection(
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
-{
-    // Collections don't include the static data added by SubRoute
-    // because it has a duplicate entry for members
-    asyncResp->res.jsonValue["@odata.type"] =
-        "#LogEntryCollection.LogEntryCollection";
-    asyncResp->res.jsonValue["@odata.id"] =
-        std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
-                    BMCWEB_REDFISH_SYSTEM_URI_NAME);
-    asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
-    asyncResp->res.jsonValue["Description"] =
-        "Collection of System Event Log Entries";
-
-    // DBus implementation of EventLog/Entries
-    // Make call to Logging Service to find all log entry objects
-    sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
-    dbus::utility::getManagedObjects(
-        "xyz.openbmc_project.Logging", path,
-        [asyncResp](const boost::system::error_code& ec,
-                    const dbus::utility::ManagedObjectType& resp) {
-            afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
-        });
-}
-
-inline void requestRoutesDBusEventLogEntryCollection(App& app)
-{
-    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
-        .privileges(redfish::privileges::getLogEntryCollection)
-        .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;
-                }
-                dBusEventLogEntryCollection(asyncResp);
-            });
-}
-
-inline void afterDBusEventLogEntryGet(
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-    const std::string& entryID, const boost::system::error_code& ec,
-    const dbus::utility::DBusPropertiesMap& resp)
-{
-    if (ec.value() == EBADR)
-    {
-        messages::resourceNotFound(asyncResp->res, "EventLogEntry", entryID);
-        return;
-    }
-    if (ec)
-    {
-        BMCWEB_LOG_ERROR("EventLogEntry (DBus) resp_handler got error {}", ec);
-        messages::internalError(asyncResp->res);
-        return;
-    }
-
-    std::optional<DbusEventLogEntry> optEntry =
-        fillDbusEventLogEntryFromPropertyMap(resp);
-
-    if (!optEntry.has_value())
-    {
-        messages::internalError(asyncResp->res);
-        return;
-    }
-
-    fillEventLogLogEntryFromDbusLogEntry(*optEntry, asyncResp->res.jsonValue);
-}
-
-inline void dBusEventLogEntryGet(
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
-{
-    dbus::utility::escapePathForDbus(entryID);
-
-    // DBus implementation of EventLog/Entries
-    // Make call to Logging Service to find all log entry objects
-    dbus::utility::getAllProperties(
-        "xyz.openbmc_project.Logging",
-        "/xyz/openbmc_project/logging/entry/" + entryID, "",
-        std::bind_front(afterDBusEventLogEntryGet, asyncResp, entryID));
-}
-
-inline void dBusEventLogEntryPatch(
-    const crow::Request& req,
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-    const std::string& entryId)
-{
-    std::optional<bool> resolved;
-
-    if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
-    {
-        return;
-    }
-    BMCWEB_LOG_DEBUG("Set Resolved");
-
-    setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
-                    "/xyz/openbmc_project/logging/entry/" + entryId,
-                    "xyz.openbmc_project.Logging.Entry", "Resolved",
-                    resolved.value_or(false));
-}
-
-inline void dBusEventLogEntryDelete(
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
-{
-    BMCWEB_LOG_DEBUG("Do delete single event entries.");
-
-    dbus::utility::escapePathForDbus(entryID);
-
-    // Process response from Logging service.
-    auto respHandler = [asyncResp,
-                        entryID](const boost::system::error_code& ec) {
-        BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
-        if (ec)
-        {
-            if (ec.value() == EBADR)
-            {
-                messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
-                return;
-            }
-            // TODO Handle for specific error code
-            BMCWEB_LOG_ERROR(
-                "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
-            asyncResp->res.result(
-                boost::beast::http::status::internal_server_error);
-            return;
-        }
-
-        messages::success(asyncResp->res);
-    };
-
-    // Make call to Logging service to request Delete Log
-    dbus::utility::async_method_call(
-        asyncResp, respHandler, "xyz.openbmc_project.Logging",
-        "/xyz/openbmc_project/logging/entry/" + entryID,
-        "xyz.openbmc_project.Object.Delete", "Delete");
-}
-
-inline void requestRoutesDBusEventLogEntry(App& app)
-{
-    BMCWEB_ROUTE(
-        app, "/redfish/v1/Systems/<str>/LogServices/EventLog/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& entryId) {
-                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;
-                }
-
-                dBusEventLogEntryGet(asyncResp, entryId);
-            });
-
-    BMCWEB_ROUTE(
-        app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
-        .privileges(redfish::privileges::patchLogEntry)
-        .methods(boost::beast::http::verb::patch)(
-            [&app](const crow::Request& req,
-                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                   const std::string& systemName, const std::string& entryId) {
-                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;
-                }
-
-                dBusEventLogEntryPatch(req, asyncResp, entryId);
-            });
-
-    BMCWEB_ROUTE(
-        app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
-        .privileges(
-            redfish::privileges::
-                deleteLogEntrySubOverComputerSystemLogServiceCollectionLogServiceLogEntryCollection)
-        .methods(boost::beast::http::verb::delete_)(
-            [&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;
-                }
-                dBusEventLogEntryDelete(asyncResp, param);
-            });
-}
-
 inline void handleBMCLogServicesCollectionGet(
     crow::App& app, const crow::Request& req,
     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -1808,25 +1406,6 @@
     downloadDumpEntry(asyncResp, dumpId, dumpType);
 }
 
-inline void handleDBusEventLogEntryDownloadGet(
-    crow::App& app, const std::string& dumpType, const crow::Request& req,
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-    const std::string& systemName, const std::string& entryID)
-{
-    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
-    {
-        return;
-    }
-    if (!http_helpers::isContentTypeAllowed(
-            req.getHeaderValue("Accept"),
-            http_helpers::ContentType::OctetStream, true))
-    {
-        asyncResp->res.result(boost::beast::http::status::bad_request);
-        return;
-    }
-    downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
-}
-
 inline void handleLogServicesDumpCollectDiagnosticDataPost(
     crow::App& app, const std::string& dumpType, const crow::Request& req,
     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -1976,16 +1555,6 @@
             handleLogServicesDumpClearLogPost, std::ref(app), "BMC"));
 }
 
-inline void requestRoutesDBusEventLogEntryDownload(App& app)
-{
-    BMCWEB_ROUTE(
-        app,
-        "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
-        .privileges(redfish::privileges::getLogEntry)
-        .methods(boost::beast::http::verb::get)(std::bind_front(
-            handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
-}
-
 inline void requestRoutesFaultLogDumpService(App& app)
 {
     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/FaultLog/")
@@ -2622,73 +2191,4 @@
                     crashdumpObject, crashdumpPath, iface, method);
             });
 }
-
-inline void dBusLogServiceActionsClear(
-    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
-{
-    BMCWEB_LOG_DEBUG("Do delete all entries.");
-
-    // Process response from Logging service.
-    auto respHandler = [asyncResp](const boost::system::error_code& ec) {
-        BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
-        if (ec)
-        {
-            // TODO Handle for specific error code
-            BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
-            asyncResp->res.result(
-                boost::beast::http::status::internal_server_error);
-            return;
-        }
-
-        messages::success(asyncResp->res);
-    };
-
-    // Make call to Logging service to request Clear Log
-    dbus::utility::async_method_call(
-        asyncResp, respHandler, "xyz.openbmc_project.Logging",
-        "/xyz/openbmc_project/logging",
-        "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
-}
-
-/**
- * DBusLogServiceActionsClear class supports POST method for ClearLog action.
- */
-inline void requestRoutesDBusLogServiceActionsClear(App& app)
-{
-    /**
-     * Function handles POST method request.
-     * The Clear Log actions does not require any parameter.The action deletes
-     * all entries found in the Entries collection for this Log Service.
-     */
-
-    BMCWEB_ROUTE(
-        app,
-        "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
-        .privileges(redfish::privileges::
-                        postLogServiceSubOverComputerSystemLogServiceCollection)
-        .methods(boost::beast::http::verb::post)(
-            [&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;
-                }
-                dBusLogServiceActionsClear(asyncResp);
-            });
-}
-
 } // namespace redfish
diff --git a/redfish-core/lib/systems_logservices_dbus_eventlog.hpp b/redfish-core/lib/systems_logservices_dbus_eventlog.hpp
new file mode 100644
index 0000000..64f87da
--- /dev/null
+++ b/redfish-core/lib/systems_logservices_dbus_eventlog.hpp
@@ -0,0 +1,548 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: Copyright OpenBMC Authors
+// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
+#pragma once
+
+#include "bmcweb_config.h"
+
+#include "app.hpp"
+#include "async_resp.hpp"
+#include "dbus_utility.hpp"
+#include "error_messages.hpp"
+#include "http_body.hpp"
+#include "http_request.hpp"
+#include "http_response.hpp"
+#include "http_utility.hpp"
+#include "logging.hpp"
+#include "query.hpp"
+#include "registries/privilege_registry.hpp"
+#include "utils/dbus_event_log_entry.hpp"
+#include "utils/dbus_utils.hpp"
+#include "utils/json_utils.hpp"
+#include "utils/log_services_utils.hpp"
+#include "utils/time_utils.hpp"
+
+#include <asm-generic/errno.h>
+#include <systemd/sd-bus.h>
+#include <unistd.h>
+
+#include <boost/beast/http/field.hpp>
+#include <boost/beast/http/status.hpp>
+#include <boost/beast/http/verb.hpp>
+#include <boost/system/linux_error.hpp>
+#include <boost/url/format.hpp>
+#include <boost/url/url.hpp>
+#include <sdbusplus/message.hpp>
+#include <sdbusplus/message/native_types.hpp>
+#include <sdbusplus/unpack_properties.hpp>
+
+#include <algorithm>
+#include <format>
+#include <functional>
+#include <memory>
+#include <optional>
+#include <string>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+namespace redfish
+{
+
+inline std::optional<bool> getProviderNotifyAction(const std::string& notify)
+{
+    std::optional<bool> notifyAction;
+    if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Notify")
+    {
+        notifyAction = true;
+    }
+    else if (notify == "xyz.openbmc_project.Logging.Entry.Notify.Inhibit")
+    {
+        notifyAction = false;
+    }
+
+    return notifyAction;
+}
+
+inline std::string translateSeverityDbusToRedfish(const std::string& s)
+{
+    if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") ||
+        (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") ||
+        (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") ||
+        (s == "xyz.openbmc_project.Logging.Entry.Level.Error"))
+    {
+        return "Critical";
+    }
+    if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") ||
+        (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") ||
+        (s == "xyz.openbmc_project.Logging.Entry.Level.Notice"))
+    {
+        return "OK";
+    }
+    if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning")
+    {
+        return "Warning";
+    }
+    return "";
+}
+
+inline void fillEventLogLogEntryFromDbusLogEntry(
+    const DbusEventLogEntry& entry, nlohmann::json& objectToFillOut)
+{
+    objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
+    objectToFillOut["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
+        BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
+    objectToFillOut["Name"] = "System Event Log Entry";
+    objectToFillOut["Id"] = std::to_string(entry.Id);
+    objectToFillOut["Message"] = entry.Message;
+    objectToFillOut["Resolved"] = entry.Resolved;
+    std::optional<bool> notifyAction =
+        getProviderNotifyAction(entry.ServiceProviderNotify);
+    if (notifyAction)
+    {
+        objectToFillOut["ServiceProviderNotified"] = *notifyAction;
+    }
+    if ((entry.Resolution != nullptr) && !entry.Resolution->empty())
+    {
+        objectToFillOut["Resolution"] = *entry.Resolution;
+    }
+    objectToFillOut["EntryType"] = "Event";
+    objectToFillOut["Severity"] =
+        translateSeverityDbusToRedfish(entry.Severity);
+    objectToFillOut["Created"] =
+        redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
+    objectToFillOut["Modified"] =
+        redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp);
+    if (entry.Path != nullptr)
+    {
+        objectToFillOut["AdditionalDataURI"] = boost::urls::format(
+            "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
+            BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
+    }
+}
+
+inline void afterLogEntriesGetManagedObjects(
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const boost::system::error_code& ec,
+    const dbus::utility::ManagedObjectType& resp)
+{
+    if (ec)
+    {
+        // TODO Handle for specific error code
+        BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
+                         ec);
+        messages::internalError(asyncResp->res);
+        return;
+    }
+    nlohmann::json::array_t entriesArray;
+    for (const auto& objectPath : resp)
+    {
+        dbus::utility::DBusPropertiesMap propsFlattened;
+        auto isEntry =
+            std::ranges::find_if(objectPath.second, [](const auto& object) {
+                return object.first == "xyz.openbmc_project.Logging.Entry";
+            });
+        if (isEntry == objectPath.second.end())
+        {
+            continue;
+        }
+
+        for (const auto& interfaceMap : objectPath.second)
+        {
+            for (const auto& propertyMap : interfaceMap.second)
+            {
+                propsFlattened.emplace_back(propertyMap.first,
+                                            propertyMap.second);
+            }
+        }
+        std::optional<DbusEventLogEntry> optEntry =
+            fillDbusEventLogEntryFromPropertyMap(propsFlattened);
+
+        if (!optEntry.has_value())
+        {
+            messages::internalError(asyncResp->res);
+            return;
+        }
+        fillEventLogLogEntryFromDbusLogEntry(*optEntry,
+                                             entriesArray.emplace_back());
+    }
+
+    redfish::json_util::sortJsonArrayByKey(entriesArray, "Id");
+    asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
+    asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
+}
+
+inline void dBusEventLogEntryCollection(
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+    // Collections don't include the static data added by SubRoute
+    // because it has a duplicate entry for members
+    asyncResp->res.jsonValue["@odata.type"] =
+        "#LogEntryCollection.LogEntryCollection";
+    asyncResp->res.jsonValue["@odata.id"] =
+        std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
+                    BMCWEB_REDFISH_SYSTEM_URI_NAME);
+    asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
+    asyncResp->res.jsonValue["Description"] =
+        "Collection of System Event Log Entries";
+
+    // DBus implementation of EventLog/Entries
+    // Make call to Logging Service to find all log entry objects
+    sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
+    dbus::utility::getManagedObjects(
+        "xyz.openbmc_project.Logging", path,
+        [asyncResp](const boost::system::error_code& ec,
+                    const dbus::utility::ManagedObjectType& resp) {
+            afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
+        });
+}
+
+inline void afterDBusEventLogEntryGet(
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& entryID, const boost::system::error_code& ec,
+    const dbus::utility::DBusPropertiesMap& resp)
+{
+    if (ec.value() == EBADR)
+    {
+        messages::resourceNotFound(asyncResp->res, "EventLogEntry", entryID);
+        return;
+    }
+    if (ec)
+    {
+        BMCWEB_LOG_ERROR("EventLogEntry (DBus) resp_handler got error {}", ec);
+        messages::internalError(asyncResp->res);
+        return;
+    }
+
+    std::optional<DbusEventLogEntry> optEntry =
+        fillDbusEventLogEntryFromPropertyMap(resp);
+
+    if (!optEntry.has_value())
+    {
+        messages::internalError(asyncResp->res);
+        return;
+    }
+
+    fillEventLogLogEntryFromDbusLogEntry(*optEntry, asyncResp->res.jsonValue);
+}
+
+inline void dBusEventLogEntryGet(
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
+{
+    dbus::utility::escapePathForDbus(entryID);
+
+    // DBus implementation of EventLog/Entries
+    // Make call to Logging Service to find all log entry objects
+    dbus::utility::getAllProperties(
+        "xyz.openbmc_project.Logging",
+        "/xyz/openbmc_project/logging/entry/" + entryID, "",
+        std::bind_front(afterDBusEventLogEntryGet, asyncResp, entryID));
+}
+
+inline void dBusEventLogEntryPatch(
+    const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& entryId)
+{
+    std::optional<bool> resolved;
+
+    if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
+    {
+        return;
+    }
+    BMCWEB_LOG_DEBUG("Set Resolved");
+
+    setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
+                    "/xyz/openbmc_project/logging/entry/" + entryId,
+                    "xyz.openbmc_project.Logging.Entry", "Resolved",
+                    resolved.value_or(false));
+}
+
+inline void dBusEventLogEntryDelete(
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
+{
+    BMCWEB_LOG_DEBUG("Do delete single event entries.");
+
+    dbus::utility::escapePathForDbus(entryID);
+
+    // Process response from Logging service.
+    auto respHandler = [asyncResp,
+                        entryID](const boost::system::error_code& ec) {
+        BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
+        if (ec)
+        {
+            if (ec.value() == EBADR)
+            {
+                messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
+                return;
+            }
+            // TODO Handle for specific error code
+            BMCWEB_LOG_ERROR(
+                "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
+            asyncResp->res.result(
+                boost::beast::http::status::internal_server_error);
+            return;
+        }
+
+        messages::success(asyncResp->res);
+    };
+
+    // Make call to Logging service to request Delete Log
+    dbus::utility::async_method_call(
+        asyncResp, respHandler, "xyz.openbmc_project.Logging",
+        "/xyz/openbmc_project/logging/entry/" + entryID,
+        "xyz.openbmc_project.Object.Delete", "Delete");
+}
+
+inline void dBusLogServiceActionsClear(
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+    BMCWEB_LOG_DEBUG("Do delete all entries.");
+
+    // Process response from Logging service.
+    auto respHandler = [asyncResp](const boost::system::error_code& ec) {
+        BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
+        if (ec)
+        {
+            // TODO Handle for specific error code
+            BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
+            asyncResp->res.result(
+                boost::beast::http::status::internal_server_error);
+            return;
+        }
+
+        messages::success(asyncResp->res);
+    };
+
+    // Make call to Logging service to request Clear Log
+    dbus::utility::async_method_call(
+        asyncResp, respHandler, "xyz.openbmc_project.Logging",
+        "/xyz/openbmc_project/logging",
+        "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
+}
+
+inline void downloadEventLogEntry(
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& systemName, const std::string& entryID,
+    const std::string& dumpType)
+{
+    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 entryPath =
+        sdbusplus::message::object_path("/xyz/openbmc_project/logging/entry") /
+        entryID;
+
+    auto downloadEventLogEntryHandler =
+        [asyncResp, entryID,
+         dumpType](const boost::system::error_code& ec,
+                   const sdbusplus::message::unix_fd& unixfd) {
+            log_services_utils::downloadEntryCallback(asyncResp, entryID,
+                                                      dumpType, ec, unixfd);
+        };
+
+    dbus::utility::async_method_call(
+        asyncResp, std::move(downloadEventLogEntryHandler),
+        "xyz.openbmc_project.Logging", entryPath,
+        "xyz.openbmc_project.Logging.Entry", "GetEntry");
+}
+
+inline void handleDBusEventLogEntryDownloadGet(
+    crow::App& app, const std::string& dumpType, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& systemName, const std::string& entryID)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+    if (!http_helpers::isContentTypeAllowed(
+            req.getHeaderValue("Accept"),
+            http_helpers::ContentType::OctetStream, true))
+    {
+        asyncResp->res.result(boost::beast::http::status::bad_request);
+        return;
+    }
+    downloadEventLogEntry(asyncResp, systemName, entryID, dumpType);
+}
+
+inline void requestRoutesDBusEventLogEntryCollection(App& app)
+{
+    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
+        .privileges(redfish::privileges::getLogEntryCollection)
+        .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;
+                }
+                dBusEventLogEntryCollection(asyncResp);
+            });
+}
+
+inline void requestRoutesDBusEventLogEntry(App& app)
+{
+    BMCWEB_ROUTE(
+        app, "/redfish/v1/Systems/<str>/LogServices/EventLog/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& entryId) {
+                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;
+                }
+
+                dBusEventLogEntryGet(asyncResp, entryId);
+            });
+
+    BMCWEB_ROUTE(
+        app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
+        .privileges(redfish::privileges::patchLogEntry)
+        .methods(boost::beast::http::verb::patch)(
+            [&app](const crow::Request& req,
+                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                   const std::string& systemName, const std::string& entryId) {
+                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;
+                }
+
+                dBusEventLogEntryPatch(req, asyncResp, entryId);
+            });
+
+    BMCWEB_ROUTE(
+        app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
+        .privileges(
+            redfish::privileges::
+                deleteLogEntrySubOverComputerSystemLogServiceCollectionLogServiceLogEntryCollection)
+        .methods(boost::beast::http::verb::delete_)(
+            [&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;
+                }
+                dBusEventLogEntryDelete(asyncResp, param);
+            });
+}
+
+/**
+ * DBusLogServiceActionsClear class supports POST method for ClearLog action.
+ */
+inline void requestRoutesDBusLogServiceActionsClear(App& app)
+{
+    /**
+     * Function handles POST method request.
+     * The Clear Log actions does not require any parameter.The action deletes
+     * all entries found in the Entries collection for this Log Service.
+     */
+
+    BMCWEB_ROUTE(
+        app,
+        "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
+        .privileges(redfish::privileges::
+                        postLogServiceSubOverComputerSystemLogServiceCollection)
+        .methods(boost::beast::http::verb::post)(
+            [&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;
+                }
+                dBusLogServiceActionsClear(asyncResp);
+            });
+}
+
+inline void requestRoutesDBusEventLogEntryDownload(App& app)
+{
+    BMCWEB_ROUTE(
+        app,
+        "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/attachment/")
+        .privileges(redfish::privileges::getLogEntry)
+        .methods(boost::beast::http::verb::get)(std::bind_front(
+            handleDBusEventLogEntryDownloadGet, std::ref(app), "System"));
+}
+} // namespace redfish
diff --git a/redfish-core/src/redfish.cpp b/redfish-core/src/redfish.cpp
index f189770..9ee2280 100644
--- a/redfish-core/src/redfish.cpp
+++ b/redfish-core/src/redfish.cpp
@@ -43,6 +43,7 @@
 #include "service_root.hpp"
 #include "storage.hpp"
 #include "systems.hpp"
+#include "systems_logservices_dbus_eventlog.hpp"
 #include "systems_logservices_hostlogger.hpp"
 #include "systems_logservices_journal_eventlog.hpp"
 #include "systems_logservices_postcodes.hpp"