blob: 06beaa6eab49f17ece9272db3861012fd5df4aa7 [file] [log] [blame]
Adriana Kobylakd311bc82016-10-16 09:54:40 -05001#include <fstream>
2#include <iostream>
3#include <cstdio>
4#include <string>
5#include <vector>
Adriana Kobylak1db1bd32016-10-10 11:39:20 -05006#include <sdbusplus/vtable.hpp>
7#include <systemd/sd-bus.h>
Adriana Kobylakd311bc82016-10-16 09:54:40 -05008#include <systemd/sd-journal.h>
Adriana Kobylak7298dc22017-01-24 12:21:50 -06009#include "elog-lookup.cpp"
Adriana Kobylak1db1bd32016-10-10 11:39:20 -050010#include "log.hpp"
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060011#include "log_manager.hpp"
Adriana Kobylak1db1bd32016-10-10 11:39:20 -050012
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060013namespace phosphor
14{
15namespace logging
16{
Adriana Kobylakd311bc82016-10-16 09:54:40 -050017
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060018void Manager::commit(uint64_t transactionId, std::string errMsg)
Adriana Kobylak1db1bd32016-10-10 11:39:20 -050019{
Adriana Kobylakd311bc82016-10-16 09:54:40 -050020 // TODO Change /tmp path to a permanent location on flash
21 constexpr const auto path = "/tmp/elog";
Adriana Kobylak7298dc22017-01-24 12:21:50 -060022 constexpr const auto transactionIdVar = "TRANSACTION_ID";
Adriana Kobylak1db1bd32016-10-10 11:39:20 -050023
Adriana Kobylakd311bc82016-10-16 09:54:40 -050024 // Create log file
25 std::string filename{};
26 filename.append(path);
27 // TODO Create error logs in their own separate dir once permanent location
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060028 // on flash is determined. Ex: ../transactionId/1
Adriana Kobylakd311bc82016-10-16 09:54:40 -050029 std::ofstream efile;
30 efile.open(filename);
31 efile << "{" << std::endl;
32
Adriana Kobylakd311bc82016-10-16 09:54:40 -050033 sd_journal *j = nullptr;
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060034 int rc = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
Adriana Kobylakd311bc82016-10-16 09:54:40 -050035 if (rc < 0)
36 {
37 logging::log<logging::level::ERR>("Failed to open journal",
38 logging::entry("DESCRIPTION=%s", strerror(-rc)));
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060039 return;
Adriana Kobylakd311bc82016-10-16 09:54:40 -050040 }
41
Adriana Kobylak7298dc22017-01-24 12:21:50 -060042 std::string transactionIdStr = std::to_string(transactionId);
43 std::vector<std::string> metalist = g_errMetaMap[errMsg];
44
Adriana Kobylakd311bc82016-10-16 09:54:40 -050045 // Read the journal from the end to get the most recent entry first.
46 // The result from the sd_journal_get_data() is of the form VARIABLE=value.
47 SD_JOURNAL_FOREACH_BACKWARDS(j)
48 {
49 const char *data = nullptr;
50 size_t length = 0;
51
Adriana Kobylak7298dc22017-01-24 12:21:50 -060052 // Look for the transaction id metadata variable
53 rc = sd_journal_get_data(j, transactionIdVar, (const void **)&data,
54 &length);
Adriana Kobylakd311bc82016-10-16 09:54:40 -050055 if (rc < 0)
56 {
Adriana Kobylak7298dc22017-01-24 12:21:50 -060057 // This journal entry does not have the transaction id,
58 // continue to next entry
Adriana Kobylakd311bc82016-10-16 09:54:40 -050059 continue;
60 }
Adriana Kobylak7298dc22017-01-24 12:21:50 -060061
Adriana Kobylakd311bc82016-10-16 09:54:40 -050062 std::string result(data);
Adriana Kobylak7298dc22017-01-24 12:21:50 -060063 if (result.find(transactionIdStr) == std::string::npos)
Adriana Kobylakd311bc82016-10-16 09:54:40 -050064 {
Adriana Kobylak7298dc22017-01-24 12:21:50 -060065 // Requested transaction id not found,
66 // continue to next journal entry.
Adriana Kobylakd311bc82016-10-16 09:54:40 -050067 continue;
68 }
Adriana Kobylakd311bc82016-10-16 09:54:40 -050069 // 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
Adriana Kobylak7298dc22017-01-24 12:21:50 -060084 for (auto metaVarStr : metalist)
Adriana Kobylakd311bc82016-10-16 09:54:40 -050085 {
Adriana Kobylak7298dc22017-01-24 12:21:50 -060086 rc = sd_journal_get_data(j, metaVarStr.c_str(),
87 (const void **)&data, &length);
Adriana Kobylakd311bc82016-10-16 09:54:40 -050088 if (rc < 0)
89 {
90 // Not found, continue to next metadata variable
91 logging::log<logging::level::INFO>("Failed to find metadata",
Adriana Kobylak7298dc22017-01-24 12:21:50 -060092 logging::entry("META_FIELD=%s", metaVarStr.c_str()));
Adriana Kobylakd311bc82016-10-16 09:54:40 -050093 continue;
94 }
95
96 // Metatdata variable found, write to file
97 efile << "\t\"@" << data << "\"," << std::endl;
98 }
99 efile << "\t}" << std::endl;
100
101 // TODO Break only once all metadata fields have been found. Implement
102 // once this function reads the metadata fields from the header file.
103 break;
104 }
105 sd_journal_close(j);
106
107 efile << "}" << std::endl;
108 efile.close();
Adriana Kobylak8f7941e2016-11-14 14:46:23 -0600109 return;
Adriana Kobylak1db1bd32016-10-10 11:39:20 -0500110}
111
Adriana Kobylak8f7941e2016-11-14 14:46:23 -0600112Manager::Manager(sdbusplus::bus::bus &&bus,
113 const char* busname,
114 const char* obj) :
115 details::ServerObject<details::ManagerIface>(bus, obj),
116 _bus(std::move(bus)),
117 _manager(sdbusplus::server::manager::manager(_bus, obj))
Adriana Kobylak1db1bd32016-10-10 11:39:20 -0500118{
Adriana Kobylak8f7941e2016-11-14 14:46:23 -0600119 _bus.request_name(busname);
120}
Adriana Kobylak1db1bd32016-10-10 11:39:20 -0500121
Adriana Kobylak8f7941e2016-11-14 14:46:23 -0600122void Manager::run() noexcept
Adriana Kobylak1db1bd32016-10-10 11:39:20 -0500123{
Adriana Kobylak8f7941e2016-11-14 14:46:23 -0600124 while(true)
Adriana Kobylak1db1bd32016-10-10 11:39:20 -0500125 {
Adriana Kobylak8f7941e2016-11-14 14:46:23 -0600126 try
Adriana Kobylak1db1bd32016-10-10 11:39:20 -0500127 {
Adriana Kobylak8f7941e2016-11-14 14:46:23 -0600128 _bus.process_discard();
129 _bus.wait();
130 }
131 catch (std::exception &e)
132 {
133 std::cerr << e.what() << std::endl;
Adriana Kobylak1db1bd32016-10-10 11:39:20 -0500134 }
135 }
Adriana Kobylak1db1bd32016-10-10 11:39:20 -0500136}
137
Adriana Kobylak8f7941e2016-11-14 14:46:23 -0600138} // namespace logging
139} // namepsace phosphor
Adriana Kobylak7298dc22017-01-24 12:21:50 -0600140