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 { 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 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 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 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 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 1422ac69850SEd Tanous DbusTelemetryMonitor::DbusTelemetryMonitor() : 1432ac69850SEd Tanous matchTelemetryMonitor(*crow::connections::systemBus, telemetryMatchStr, 1442ac69850SEd Tanous getReadingsForReport) 1452ac69850SEd Tanous {} 146b26ff34dSEd Tanous } // namespace redfish 147