1b26ff34dSEd Tanous #include "dbus_log_watcher.hpp"
2b26ff34dSEd Tanous 
32ac69850SEd Tanous #include "dbus_singleton.hpp"
4b26ff34dSEd Tanous #include "dbus_utility.hpp"
5*6c58a03eSAlexander 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"
9*6c58a03eSAlexander Hansen #include "utils/dbus_event_log_entry.hpp"
10b26ff34dSEd Tanous 
112ac69850SEd Tanous #include <sdbusplus/bus/match.hpp>
12b26ff34dSEd Tanous #include <sdbusplus/message.hpp>
13b26ff34dSEd Tanous #include <sdbusplus/message/native_types.hpp>
14b26ff34dSEd Tanous 
15b26ff34dSEd Tanous #include <algorithm>
16*6c58a03eSAlexander Hansen #include <optional>
17b26ff34dSEd Tanous #include <string>
18b26ff34dSEd Tanous #include <variant>
19b26ff34dSEd Tanous #include <vector>
20b26ff34dSEd Tanous 
21b26ff34dSEd Tanous namespace redfish
22b26ff34dSEd Tanous {
eventLogObjectFromDBus(const dbus::utility::DBusPropertiesMap & map,EventLogObjectsType & event)23*6c58a03eSAlexander Hansen static bool eventLogObjectFromDBus(const dbus::utility::DBusPropertiesMap& map,
24*6c58a03eSAlexander Hansen                                    EventLogObjectsType& event)
25*6c58a03eSAlexander Hansen {
26*6c58a03eSAlexander Hansen     std::optional<DbusEventLogEntry> optEntry =
27*6c58a03eSAlexander Hansen         fillDbusEventLogEntryFromPropertyMap(map);
28*6c58a03eSAlexander Hansen 
29*6c58a03eSAlexander Hansen     if (!optEntry.has_value())
30*6c58a03eSAlexander Hansen     {
31*6c58a03eSAlexander Hansen         BMCWEB_LOG_ERROR(
32*6c58a03eSAlexander Hansen             "Could not construct event log entry from dbus properties");
33*6c58a03eSAlexander Hansen         return false;
34*6c58a03eSAlexander Hansen     }
35*6c58a03eSAlexander Hansen     DbusEventLogEntry& entry = optEntry.value();
36*6c58a03eSAlexander Hansen     event.id = std::to_string(entry.Id);
37*6c58a03eSAlexander Hansen 
38*6c58a03eSAlexander Hansen     // The order of 'AdditionalData' is not what's specified in an e.g.
39*6c58a03eSAlexander Hansen     // busctl call to create the Event Log Entry. So it cannot be used
40*6c58a03eSAlexander Hansen     // to map to the message args. Leaving this branch here for it to be
41*6c58a03eSAlexander Hansen     // implemented when the mapping is available
42*6c58a03eSAlexander Hansen 
43*6c58a03eSAlexander Hansen     return true;
44*6c58a03eSAlexander Hansen }
45*6c58a03eSAlexander Hansen 
dbusEventLogMatchHandlerSingleEntry(const dbus::utility::DBusPropertiesMap & map)46*6c58a03eSAlexander Hansen static void dbusEventLogMatchHandlerSingleEntry(
47*6c58a03eSAlexander Hansen     const dbus::utility::DBusPropertiesMap& map)
48*6c58a03eSAlexander Hansen {
49*6c58a03eSAlexander Hansen     std::vector<EventLogObjectsType> eventRecords;
50*6c58a03eSAlexander Hansen     EventLogObjectsType& event = eventRecords.emplace_back();
51*6c58a03eSAlexander Hansen     bool success = eventLogObjectFromDBus(map, event);
52*6c58a03eSAlexander Hansen     if (!success)
53*6c58a03eSAlexander Hansen     {
54*6c58a03eSAlexander Hansen         BMCWEB_LOG_ERROR("Could not parse event log entry from dbus");
55*6c58a03eSAlexander Hansen         return;
56*6c58a03eSAlexander Hansen     }
57*6c58a03eSAlexander Hansen 
58*6c58a03eSAlexander Hansen     BMCWEB_LOG_DEBUG("Found Event Log Entry Id={}, Timestamp={}, Message={}",
59*6c58a03eSAlexander Hansen                      event.id, event.timestamp, event.messageId);
60*6c58a03eSAlexander Hansen     EventServiceManager::sendEventsToSubs(eventRecords);
61*6c58a03eSAlexander Hansen }
62*6c58a03eSAlexander Hansen 
onDbusEventLogCreated(sdbusplus::message_t & msg)63*6c58a03eSAlexander Hansen static void onDbusEventLogCreated(sdbusplus::message_t& msg)
64*6c58a03eSAlexander Hansen {
65*6c58a03eSAlexander Hansen     BMCWEB_LOG_DEBUG("Handling new DBus Event Log Entry");
66*6c58a03eSAlexander Hansen 
67*6c58a03eSAlexander Hansen     sdbusplus::message::object_path objectPath;
68*6c58a03eSAlexander Hansen     dbus::utility::DBusInterfacesMap interfaces;
69*6c58a03eSAlexander Hansen 
70*6c58a03eSAlexander Hansen     msg.read(objectPath, interfaces);
71*6c58a03eSAlexander Hansen 
72*6c58a03eSAlexander Hansen     for (auto& pair : interfaces)
73*6c58a03eSAlexander Hansen     {
74*6c58a03eSAlexander Hansen         BMCWEB_LOG_DEBUG("Found dbus interface {}", pair.first);
75*6c58a03eSAlexander Hansen         if (pair.first == "xyz.openbmc_project.Logging.Entry")
76*6c58a03eSAlexander Hansen         {
77*6c58a03eSAlexander Hansen             const dbus::utility::DBusPropertiesMap& map = pair.second;
78*6c58a03eSAlexander Hansen             dbusEventLogMatchHandlerSingleEntry(map);
79*6c58a03eSAlexander Hansen         }
80*6c58a03eSAlexander Hansen     }
81*6c58a03eSAlexander Hansen }
82*6c58a03eSAlexander Hansen 
83*6c58a03eSAlexander Hansen const std::string propertiesMatchString =
84*6c58a03eSAlexander Hansen     sdbusplus::bus::match::rules::type::signal() +
85*6c58a03eSAlexander Hansen     sdbusplus::bus::match::rules::sender("xyz.openbmc_project.Logging") +
86*6c58a03eSAlexander Hansen     sdbusplus::bus::match::rules::interface(
87*6c58a03eSAlexander Hansen         "org.freedesktop.DBus.ObjectManager") +
88*6c58a03eSAlexander Hansen     sdbusplus::bus::match::rules::path("/xyz/openbmc_project/logging") +
89*6c58a03eSAlexander Hansen     sdbusplus::bus::match::rules::member("InterfacesAdded");
90*6c58a03eSAlexander Hansen 
DbusEventLogMonitor()91*6c58a03eSAlexander Hansen DbusEventLogMonitor::DbusEventLogMonitor() :
92*6c58a03eSAlexander Hansen     dbusEventLogMonitor(*crow::connections::systemBus, propertiesMatchString,
93*6c58a03eSAlexander Hansen                         onDbusEventLogCreated)
94*6c58a03eSAlexander Hansen 
95*6c58a03eSAlexander Hansen {}
96*6c58a03eSAlexander Hansen 
getReadingsForReport(sdbusplus::message_t & msg)972ac69850SEd Tanous static void getReadingsForReport(sdbusplus::message_t& msg)
98b26ff34dSEd Tanous {
99b26ff34dSEd Tanous     if (msg.is_method_error())
100b26ff34dSEd Tanous     {
101b26ff34dSEd Tanous         BMCWEB_LOG_ERROR("TelemetryMonitor Signal error");
102b26ff34dSEd Tanous         return;
103b26ff34dSEd Tanous     }
104b26ff34dSEd Tanous 
105b26ff34dSEd Tanous     sdbusplus::message::object_path path(msg.get_path());
106b26ff34dSEd Tanous     std::string id = path.filename();
107b26ff34dSEd Tanous     if (id.empty())
108b26ff34dSEd Tanous     {
109b26ff34dSEd Tanous         BMCWEB_LOG_ERROR("Failed to get Id from path");
110b26ff34dSEd Tanous         return;
111b26ff34dSEd Tanous     }
112b26ff34dSEd Tanous 
113b26ff34dSEd Tanous     std::string interface;
114b26ff34dSEd Tanous     dbus::utility::DBusPropertiesMap props;
115b26ff34dSEd Tanous     std::vector<std::string> invalidProps;
116b26ff34dSEd Tanous     msg.read(interface, props, invalidProps);
117b26ff34dSEd Tanous 
118b26ff34dSEd Tanous     auto found = std::ranges::find_if(props, [](const auto& x) {
119b26ff34dSEd Tanous         return x.first == "Readings";
120b26ff34dSEd Tanous     });
121b26ff34dSEd Tanous     if (found == props.end())
122b26ff34dSEd Tanous     {
123b26ff34dSEd Tanous         BMCWEB_LOG_INFO("Failed to get Readings from Report properties");
124b26ff34dSEd Tanous         return;
125b26ff34dSEd Tanous     }
126b26ff34dSEd Tanous 
127b26ff34dSEd Tanous     const telemetry::TimestampReadings* readings =
128b26ff34dSEd Tanous         std::get_if<telemetry::TimestampReadings>(&found->second);
129b26ff34dSEd Tanous     if (readings == nullptr)
130b26ff34dSEd Tanous     {
131b26ff34dSEd Tanous         BMCWEB_LOG_INFO("Failed to get Readings from Report properties");
132b26ff34dSEd Tanous         return;
133b26ff34dSEd Tanous     }
134b26ff34dSEd Tanous     EventServiceManager::sendTelemetryReportToSubs(id, *readings);
135b26ff34dSEd Tanous }
1362ac69850SEd Tanous 
1372ac69850SEd Tanous const std::string telemetryMatchStr =
1382ac69850SEd Tanous     "type='signal',member='PropertiesChanged',"
1392ac69850SEd Tanous     "interface='org.freedesktop.DBus.Properties',"
1402ac69850SEd Tanous     "arg0=xyz.openbmc_project.Telemetry.Report";
1412ac69850SEd Tanous 
DbusTelemetryMonitor()1422ac69850SEd Tanous DbusTelemetryMonitor::DbusTelemetryMonitor() :
1432ac69850SEd Tanous     matchTelemetryMonitor(*crow::connections::systemBus, telemetryMatchStr,
1442ac69850SEd Tanous                           getReadingsForReport)
1452ac69850SEd Tanous {}
146b26ff34dSEd Tanous } // namespace redfish
147