xref: /openbmc/phosphor-logging/log_manager.cpp (revision d310378f4fcd7a7bcdfea81c0e7c93351b6f992f)
1 #include <fstream>
2 #include <iostream>
3 #include <cstdio>
4 #include <string>
5 #include <vector>
6 #include <sdbusplus/vtable.hpp>
7 #include <systemd/sd-bus.h>
8 #include <systemd/sd-journal.h>
9 #include "log.hpp"
10 #include "log_manager.hpp"
11 
12 namespace phosphor
13 {
14 namespace logging
15 {
16 
17 void Manager::commit(uint64_t transactionId, std::string errMsg)
18 {
19     // TODO Change /tmp path to a permanent location on flash
20     constexpr const auto path = "/tmp/elog";
21     constexpr const auto msgIdStr = "_PID";
22 
23     // Create log file
24     std::string filename{};
25     filename.append(path);
26     // TODO Create error logs in their own separate dir once permanent location
27     // on flash is determined. Ex: ../transactionId/1
28     std::ofstream efile;
29     efile.open(filename);
30     efile << "{" << std::endl;
31 
32     //const char* metaVar = nullptr;
33     std::vector<const char*> metaList;
34 
35     sd_journal *j = nullptr;
36     int rc = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
37     if (rc < 0)
38     {
39         logging::log<logging::level::ERR>("Failed to open journal",
40                            logging::entry("DESCRIPTION=%s", strerror(-rc)));
41         return;
42     }
43 
44     // Read the journal from the end to get the most recent entry first.
45     // The result from the sd_journal_get_data() is of the form VARIABLE=value.
46     SD_JOURNAL_FOREACH_BACKWARDS(j)
47     {
48         const char *data = nullptr;
49         size_t length = 0;
50 
51         // Search for the msg id
52         rc = sd_journal_get_data(j, msgIdStr, (const void **)&data, &length);
53         if (rc < 0)
54         {
55             // Instance not found, continue to next journal entry
56             continue;
57         }
58         std::string result(data);
59 // TODO String msgid is now an int transaction id. This piece will be
60 // uncommented and reworked with the upcoming change to read the metadata
61 // fields from the header file.
62 #if 0
63         if (result.find(msgid) == std::string::npos)
64         {
65             // Match not found, continue to next journal entry
66             continue;
67         }
68 #endif
69         // Match found, write to file
70         // TODO This is a draft format based on the redfish event logs written
71         // in json, the final openbmc format is to be determined
72         efile << "\t{" << std::endl;
73         efile << "\t\"@" << data << "\"," << std::endl;
74 
75         // Include the journal message
76         rc = sd_journal_get_data(j, "MESSAGE", (const void **)&data, &length);
77         if (rc < 0)
78         {
79             continue;
80         }
81         efile << "\t\"@" << data << "\"," << std::endl;
82 
83         // Search for the metadata variables in the current journal entry
84         for (auto i : metaList)
85         {
86             rc = sd_journal_get_data(j, i, (const void **)&data, &length);
87             if (rc < 0)
88             {
89                 // Not found, continue to next metadata variable
90                 logging::log<logging::level::INFO>("Failed to find metadata",
91                                     logging::entry("META_FIELD=%s", i));
92                 continue;
93             }
94 
95             // Metatdata variable found, write to file
96             efile << "\t\"@" << data << "\"," << std::endl;
97         }
98         efile << "\t}" << std::endl;
99 
100         // TODO Break only once all metadata fields have been found. Implement
101         // once this function reads the metadata fields from the header file.
102         break;
103     }
104     sd_journal_close(j);
105 
106     efile << "}" << std::endl;
107     efile.close();
108     return;
109 }
110 
111 Manager::Manager(sdbusplus::bus::bus &&bus,
112                  const char* busname,
113                  const char* obj) :
114     details::ServerObject<details::ManagerIface>(bus, obj),
115     _bus(std::move(bus)),
116     _manager(sdbusplus::server::manager::manager(_bus, obj))
117 {
118     _bus.request_name(busname);
119 }
120 
121 void Manager::run() noexcept
122 {
123     while(true)
124     {
125         try
126         {
127             _bus.process_discard();
128             _bus.wait();
129         }
130         catch (std::exception &e)
131         {
132             std::cerr << e.what() << std::endl;
133         }
134     }
135 }
136 
137 } // namespace logging
138 } // namepsace phosphor
139