blob: ef1cae80da9886234d8f0b9c10c850f6ff09a6a1 [file] [log] [blame]
Adriana Kobylakd311bc82016-10-16 09:54:40 -05001#include <fstream>
2#include <iostream>
Adriana Kobylakc5f0bbd2017-01-22 14:56:04 -06003#include <chrono>
Adriana Kobylakd311bc82016-10-16 09:54:40 -05004#include <cstdio>
5#include <string>
6#include <vector>
Adriana Kobylak1db1bd32016-10-10 11:39:20 -05007#include <sdbusplus/vtable.hpp>
8#include <systemd/sd-bus.h>
Adriana Kobylakd311bc82016-10-16 09:54:40 -05009#include <systemd/sd-journal.h>
Adriana Kobylak7298dc22017-01-24 12:21:50 -060010#include "elog-lookup.cpp"
Adriana Kobylak4ea7f312017-01-10 12:52:34 -060011#include "config.h"
12#include "elog_entry.hpp"
Adriana Kobylak1db1bd32016-10-10 11:39:20 -050013#include "log.hpp"
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060014#include "log_manager.hpp"
Adriana Kobylak1db1bd32016-10-10 11:39:20 -050015
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060016namespace phosphor
17{
18namespace logging
19{
Adriana Kobylakd311bc82016-10-16 09:54:40 -050020
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060021void Manager::commit(uint64_t transactionId, std::string errMsg)
Adriana Kobylak1db1bd32016-10-10 11:39:20 -050022{
Adriana Kobylakd311bc82016-10-16 09:54:40 -050023 // TODO Change /tmp path to a permanent location on flash
24 constexpr const auto path = "/tmp/elog";
Adriana Kobylak7298dc22017-01-24 12:21:50 -060025 constexpr const auto transactionIdVar = "TRANSACTION_ID";
Adriana Kobylak1db1bd32016-10-10 11:39:20 -050026
Adriana Kobylakd311bc82016-10-16 09:54:40 -050027 std::string filename{};
28 filename.append(path);
29 // TODO Create error logs in their own separate dir once permanent location
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060030 // on flash is determined. Ex: ../transactionId/1
Adriana Kobylakd311bc82016-10-16 09:54:40 -050031 std::ofstream efile;
32 efile.open(filename);
33 efile << "{" << std::endl;
34
Adriana Kobylakd311bc82016-10-16 09:54:40 -050035 sd_journal *j = nullptr;
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060036 int rc = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
Adriana Kobylakd311bc82016-10-16 09:54:40 -050037 if (rc < 0)
38 {
39 logging::log<logging::level::ERR>("Failed to open journal",
40 logging::entry("DESCRIPTION=%s", strerror(-rc)));
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060041 return;
Adriana Kobylakd311bc82016-10-16 09:54:40 -050042 }
43
Adriana Kobylak7298dc22017-01-24 12:21:50 -060044 std::string transactionIdStr = std::to_string(transactionId);
45 std::vector<std::string> metalist = g_errMetaMap[errMsg];
Adriana Kobylak4ea7f312017-01-10 12:52:34 -060046 std::vector<std::string> additionalData;
Adriana Kobylak7298dc22017-01-24 12:21:50 -060047
Adriana Kobylakd311bc82016-10-16 09:54:40 -050048 // Read the journal from the end to get the most recent entry first.
49 // The result from the sd_journal_get_data() is of the form VARIABLE=value.
50 SD_JOURNAL_FOREACH_BACKWARDS(j)
51 {
52 const char *data = nullptr;
53 size_t length = 0;
54
Adriana Kobylak7298dc22017-01-24 12:21:50 -060055 // Look for the transaction id metadata variable
56 rc = sd_journal_get_data(j, transactionIdVar, (const void **)&data,
57 &length);
Adriana Kobylakd311bc82016-10-16 09:54:40 -050058 if (rc < 0)
59 {
Adriana Kobylak7298dc22017-01-24 12:21:50 -060060 // This journal entry does not have the transaction id,
61 // continue to next entry
Adriana Kobylakd311bc82016-10-16 09:54:40 -050062 continue;
63 }
Adriana Kobylak7298dc22017-01-24 12:21:50 -060064
Adriana Kobylakd311bc82016-10-16 09:54:40 -050065 std::string result(data);
Adriana Kobylak7298dc22017-01-24 12:21:50 -060066 if (result.find(transactionIdStr) == std::string::npos)
Adriana Kobylakd311bc82016-10-16 09:54:40 -050067 {
Adriana Kobylak7298dc22017-01-24 12:21:50 -060068 // Requested transaction id not found,
69 // continue to next journal entry.
Adriana Kobylakd311bc82016-10-16 09:54:40 -050070 continue;
71 }
Adriana Kobylakd311bc82016-10-16 09:54:40 -050072 // Match found, write to file
73 // TODO This is a draft format based on the redfish event logs written
74 // in json, the final openbmc format is to be determined
75 efile << "\t{" << std::endl;
76 efile << "\t\"@" << data << "\"," << std::endl;
77
78 // Include the journal message
79 rc = sd_journal_get_data(j, "MESSAGE", (const void **)&data, &length);
80 if (rc < 0)
81 {
82 continue;
83 }
Adriana Kobylak4ea7f312017-01-10 12:52:34 -060084
Adriana Kobylakd311bc82016-10-16 09:54:40 -050085 efile << "\t\"@" << data << "\"," << std::endl;
86
87 // Search for the metadata variables in the current journal entry
Adriana Kobylak7298dc22017-01-24 12:21:50 -060088 for (auto metaVarStr : metalist)
Adriana Kobylakd311bc82016-10-16 09:54:40 -050089 {
Adriana Kobylak7298dc22017-01-24 12:21:50 -060090 rc = sd_journal_get_data(j, metaVarStr.c_str(),
91 (const void **)&data, &length);
Adriana Kobylakd311bc82016-10-16 09:54:40 -050092 if (rc < 0)
93 {
94 // Not found, continue to next metadata variable
95 logging::log<logging::level::INFO>("Failed to find metadata",
Adriana Kobylak7298dc22017-01-24 12:21:50 -060096 logging::entry("META_FIELD=%s", metaVarStr.c_str()));
Adriana Kobylakd311bc82016-10-16 09:54:40 -050097 continue;
98 }
99
100 // Metatdata variable found, write to file
Adriana Kobylak4ea7f312017-01-10 12:52:34 -0600101 additionalData.push_back(std::string(data));
Adriana Kobylakd311bc82016-10-16 09:54:40 -0500102 efile << "\t\"@" << data << "\"," << std::endl;
103 }
104 efile << "\t}" << std::endl;
105
106 // TODO Break only once all metadata fields have been found. Implement
107 // once this function reads the metadata fields from the header file.
108 break;
109 }
110 sd_journal_close(j);
111
Adriana Kobylak4ea7f312017-01-10 12:52:34 -0600112 // Create error Entry dbus object
113 entryId++;
Adriana Kobylakc5f0bbd2017-01-22 14:56:04 -0600114 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
115 std::chrono::system_clock::now().time_since_epoch()).count();
Adriana Kobylak4ea7f312017-01-10 12:52:34 -0600116 auto objPath = std::string(OBJ_ENTRY) + '/' +
Adriana Kobylakc5f0bbd2017-01-22 14:56:04 -0600117 std::to_string(entryId);
Adriana Kobylak4ea7f312017-01-10 12:52:34 -0600118 entries.insert(std::make_pair(entryId, std::make_unique<Entry>(
119 busLog,
120 objPath,
121 entryId,
Adriana Kobylakc5f0bbd2017-01-22 14:56:04 -0600122 ms, // Milliseconds since 1970
Adriana Kobylak4ea7f312017-01-10 12:52:34 -0600123 (Entry::Level)g_errLevelMap[errMsg],
124 std::move(errMsg),
125 std::move(additionalData))));
126
Adriana Kobylakd311bc82016-10-16 09:54:40 -0500127 efile << "}" << std::endl;
128 efile.close();
Adriana Kobylak8f7941e2016-11-14 14:46:23 -0600129 return;
Adriana Kobylak1db1bd32016-10-10 11:39:20 -0500130}
131
Adriana Kobylak8f7941e2016-11-14 14:46:23 -0600132} // namespace logging
133} // namepsace phosphor