xref: /openbmc/bmcweb/features/redfish/src/dbus_log_watcher.cpp (revision 4a7a15c2d78e41ca571f990e071b9294a9f2a135)
1b26ff34dSEd Tanous #include "dbus_log_watcher.hpp"
2b26ff34dSEd Tanous 
32ac69850SEd Tanous #include "dbus_singleton.hpp"
4b26ff34dSEd Tanous #include "dbus_utility.hpp"
56c58a03eSAlexander Hansen #include "event_logs_object_type.hpp"
6b26ff34dSEd Tanous #include "event_service_manager.hpp"
7b26ff34dSEd Tanous #include "logging.hpp"
8b26ff34dSEd Tanous #include "metric_report.hpp"
96c58a03eSAlexander Hansen #include "utils/dbus_event_log_entry.hpp"
10*4a7a15c2SAlexander Hansen #include "utils/time_utils.hpp"
11b26ff34dSEd Tanous 
122ac69850SEd Tanous #include <sdbusplus/bus/match.hpp>
13b26ff34dSEd Tanous #include <sdbusplus/message.hpp>
14b26ff34dSEd Tanous #include <sdbusplus/message/native_types.hpp>
15b26ff34dSEd Tanous 
16b26ff34dSEd Tanous #include <algorithm>
176c58a03eSAlexander Hansen #include <optional>
18b26ff34dSEd Tanous #include <string>
19b26ff34dSEd Tanous #include <variant>
20b26ff34dSEd Tanous #include <vector>
21b26ff34dSEd Tanous 
22b26ff34dSEd Tanous namespace redfish
23b26ff34dSEd Tanous {
24*4a7a15c2SAlexander Hansen 
256c58a03eSAlexander Hansen static bool eventLogObjectFromDBus(const dbus::utility::DBusPropertiesMap& map,
266c58a03eSAlexander Hansen                                    EventLogObjectsType& event)
276c58a03eSAlexander Hansen {
286c58a03eSAlexander Hansen     std::optional<DbusEventLogEntry> optEntry =
296c58a03eSAlexander Hansen         fillDbusEventLogEntryFromPropertyMap(map);
306c58a03eSAlexander Hansen 
316c58a03eSAlexander Hansen     if (!optEntry.has_value())
326c58a03eSAlexander Hansen     {
336c58a03eSAlexander Hansen         BMCWEB_LOG_ERROR(
346c58a03eSAlexander Hansen             "Could not construct event log entry from dbus properties");
356c58a03eSAlexander Hansen         return false;
366c58a03eSAlexander Hansen     }
376c58a03eSAlexander Hansen     DbusEventLogEntry& entry = optEntry.value();
386c58a03eSAlexander Hansen     event.id = std::to_string(entry.Id);
39*4a7a15c2SAlexander Hansen     event.timestamp = redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
406c58a03eSAlexander Hansen 
416c58a03eSAlexander Hansen     // The order of 'AdditionalData' is not what's specified in an e.g.
426c58a03eSAlexander Hansen     // busctl call to create the Event Log Entry. So it cannot be used
436c58a03eSAlexander Hansen     // to map to the message args. Leaving this branch here for it to be
446c58a03eSAlexander Hansen     // implemented when the mapping is available
456c58a03eSAlexander Hansen 
466c58a03eSAlexander Hansen     return true;
476c58a03eSAlexander Hansen }
486c58a03eSAlexander Hansen 
496c58a03eSAlexander Hansen static void dbusEventLogMatchHandlerSingleEntry(
506c58a03eSAlexander Hansen     const dbus::utility::DBusPropertiesMap& map)
516c58a03eSAlexander Hansen {
526c58a03eSAlexander Hansen     std::vector<EventLogObjectsType> eventRecords;
536c58a03eSAlexander Hansen     EventLogObjectsType& event = eventRecords.emplace_back();
546c58a03eSAlexander Hansen     bool success = eventLogObjectFromDBus(map, event);
556c58a03eSAlexander Hansen     if (!success)
566c58a03eSAlexander Hansen     {
576c58a03eSAlexander Hansen         BMCWEB_LOG_ERROR("Could not parse event log entry from dbus");
586c58a03eSAlexander Hansen         return;
596c58a03eSAlexander Hansen     }
606c58a03eSAlexander Hansen 
616c58a03eSAlexander Hansen     BMCWEB_LOG_DEBUG("Found Event Log Entry Id={}, Timestamp={}, Message={}",
626c58a03eSAlexander Hansen                      event.id, event.timestamp, event.messageId);
636c58a03eSAlexander Hansen     EventServiceManager::sendEventsToSubs(eventRecords);
646c58a03eSAlexander Hansen }
656c58a03eSAlexander Hansen 
666c58a03eSAlexander Hansen static void onDbusEventLogCreated(sdbusplus::message_t& msg)
676c58a03eSAlexander Hansen {
686c58a03eSAlexander Hansen     BMCWEB_LOG_DEBUG("Handling new DBus Event Log Entry");
696c58a03eSAlexander Hansen 
706c58a03eSAlexander Hansen     sdbusplus::message::object_path objectPath;
716c58a03eSAlexander Hansen     dbus::utility::DBusInterfacesMap interfaces;
726c58a03eSAlexander Hansen 
736c58a03eSAlexander Hansen     msg.read(objectPath, interfaces);
746c58a03eSAlexander Hansen 
756c58a03eSAlexander Hansen     for (auto& pair : interfaces)
766c58a03eSAlexander Hansen     {
776c58a03eSAlexander Hansen         BMCWEB_LOG_DEBUG("Found dbus interface {}", pair.first);
786c58a03eSAlexander Hansen         if (pair.first == "xyz.openbmc_project.Logging.Entry")
796c58a03eSAlexander Hansen         {
806c58a03eSAlexander Hansen             const dbus::utility::DBusPropertiesMap& map = pair.second;
816c58a03eSAlexander Hansen             dbusEventLogMatchHandlerSingleEntry(map);
826c58a03eSAlexander Hansen         }
836c58a03eSAlexander Hansen     }
846c58a03eSAlexander Hansen }
856c58a03eSAlexander Hansen 
866c58a03eSAlexander Hansen const std::string propertiesMatchString =
876c58a03eSAlexander Hansen     sdbusplus::bus::match::rules::type::signal() +
886c58a03eSAlexander Hansen     sdbusplus::bus::match::rules::sender("xyz.openbmc_project.Logging") +
896c58a03eSAlexander Hansen     sdbusplus::bus::match::rules::interface(
906c58a03eSAlexander Hansen         "org.freedesktop.DBus.ObjectManager") +
916c58a03eSAlexander Hansen     sdbusplus::bus::match::rules::path("/xyz/openbmc_project/logging") +
926c58a03eSAlexander Hansen     sdbusplus::bus::match::rules::member("InterfacesAdded");
936c58a03eSAlexander Hansen 
946c58a03eSAlexander Hansen DbusEventLogMonitor::DbusEventLogMonitor() :
956c58a03eSAlexander Hansen     dbusEventLogMonitor(*crow::connections::systemBus, propertiesMatchString,
966c58a03eSAlexander Hansen                         onDbusEventLogCreated)
976c58a03eSAlexander Hansen 
986c58a03eSAlexander Hansen {}
996c58a03eSAlexander Hansen 
1002ac69850SEd Tanous static void getReadingsForReport(sdbusplus::message_t& msg)
101b26ff34dSEd Tanous {
102b26ff34dSEd Tanous     if (msg.is_method_error())
103b26ff34dSEd Tanous     {
104b26ff34dSEd Tanous         BMCWEB_LOG_ERROR("TelemetryMonitor Signal error");
105b26ff34dSEd Tanous         return;
106b26ff34dSEd Tanous     }
107b26ff34dSEd Tanous 
108b26ff34dSEd Tanous     sdbusplus::message::object_path path(msg.get_path());
109b26ff34dSEd Tanous     std::string id = path.filename();
110b26ff34dSEd Tanous     if (id.empty())
111b26ff34dSEd Tanous     {
112b26ff34dSEd Tanous         BMCWEB_LOG_ERROR("Failed to get Id from path");
113b26ff34dSEd Tanous         return;
114b26ff34dSEd Tanous     }
115b26ff34dSEd Tanous 
116b26ff34dSEd Tanous     std::string interface;
117b26ff34dSEd Tanous     dbus::utility::DBusPropertiesMap props;
118b26ff34dSEd Tanous     std::vector<std::string> invalidProps;
119b26ff34dSEd Tanous     msg.read(interface, props, invalidProps);
120b26ff34dSEd Tanous 
121b26ff34dSEd Tanous     auto found = std::ranges::find_if(props, [](const auto& x) {
122b26ff34dSEd Tanous         return x.first == "Readings";
123b26ff34dSEd Tanous     });
124b26ff34dSEd Tanous     if (found == props.end())
125b26ff34dSEd Tanous     {
126b26ff34dSEd Tanous         BMCWEB_LOG_INFO("Failed to get Readings from Report properties");
127b26ff34dSEd Tanous         return;
128b26ff34dSEd Tanous     }
129b26ff34dSEd Tanous 
130b26ff34dSEd Tanous     const telemetry::TimestampReadings* readings =
131b26ff34dSEd Tanous         std::get_if<telemetry::TimestampReadings>(&found->second);
132b26ff34dSEd Tanous     if (readings == nullptr)
133b26ff34dSEd Tanous     {
134b26ff34dSEd Tanous         BMCWEB_LOG_INFO("Failed to get Readings from Report properties");
135b26ff34dSEd Tanous         return;
136b26ff34dSEd Tanous     }
137b26ff34dSEd Tanous     EventServiceManager::sendTelemetryReportToSubs(id, *readings);
138b26ff34dSEd Tanous }
1392ac69850SEd Tanous 
1402ac69850SEd Tanous const std::string telemetryMatchStr =
1412ac69850SEd Tanous     "type='signal',member='PropertiesChanged',"
1422ac69850SEd Tanous     "interface='org.freedesktop.DBus.Properties',"
1432ac69850SEd Tanous     "arg0=xyz.openbmc_project.Telemetry.Report";
1442ac69850SEd Tanous 
1452ac69850SEd Tanous DbusTelemetryMonitor::DbusTelemetryMonitor() :
1462ac69850SEd Tanous     matchTelemetryMonitor(*crow::connections::systemBus, telemetryMatchStr,
1472ac69850SEd Tanous                           getReadingsForReport)
1482ac69850SEd Tanous {}
149b26ff34dSEd Tanous } // namespace redfish
150