blob: d779480e7da8caa27e3861397e72abe3471837c9 [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"
Saqib Khan2bb15192017-02-13 13:19:55 -060011#include <phosphor-logging/elog-errors-HostEvent.hpp>
Adriana Kobylak4ea7f312017-01-10 12:52:34 -060012#include "config.h"
13#include "elog_entry.hpp"
Saqib Khan2bb15192017-02-13 13:19:55 -060014#include <phosphor-logging/log.hpp>
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060015#include "log_manager.hpp"
Adriana Kobylak1db1bd32016-10-10 11:39:20 -050016
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060017namespace phosphor
18{
19namespace logging
20{
Adriana Kobylakd311bc82016-10-16 09:54:40 -050021
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060022void Manager::commit(uint64_t transactionId, std::string errMsg)
Adriana Kobylak1db1bd32016-10-10 11:39:20 -050023{
Adriana Kobylakd311bc82016-10-16 09:54:40 -050024 // TODO Change /tmp path to a permanent location on flash
25 constexpr const auto path = "/tmp/elog";
Adriana Kobylak7298dc22017-01-24 12:21:50 -060026 constexpr const auto transactionIdVar = "TRANSACTION_ID";
Adriana Kobylak1db1bd32016-10-10 11:39:20 -050027
Adriana Kobylakd311bc82016-10-16 09:54:40 -050028 std::string filename{};
29 filename.append(path);
30 // TODO Create error logs in their own separate dir once permanent location
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060031 // on flash is determined. Ex: ../transactionId/1
Adriana Kobylakd311bc82016-10-16 09:54:40 -050032 std::ofstream efile;
33 efile.open(filename);
34 efile << "{" << std::endl;
35
Adriana Kobylakd311bc82016-10-16 09:54:40 -050036 sd_journal *j = nullptr;
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060037 int rc = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
Adriana Kobylakd311bc82016-10-16 09:54:40 -050038 if (rc < 0)
39 {
40 logging::log<logging::level::ERR>("Failed to open journal",
41 logging::entry("DESCRIPTION=%s", strerror(-rc)));
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060042 return;
Adriana Kobylakd311bc82016-10-16 09:54:40 -050043 }
44
Adriana Kobylak7298dc22017-01-24 12:21:50 -060045 std::string transactionIdStr = std::to_string(transactionId);
46 std::vector<std::string> metalist = g_errMetaMap[errMsg];
Adriana Kobylak1f36a882017-02-16 08:36:55 -060047 std::vector<std::string> metalistHostEvent = g_errMetaMapHostEvent[errMsg];
Adriana Kobylak4ea7f312017-01-10 12:52:34 -060048 std::vector<std::string> additionalData;
Adriana Kobylak7298dc22017-01-24 12:21:50 -060049
Adriana Kobylakd311bc82016-10-16 09:54:40 -050050 // Read the journal from the end to get the most recent entry first.
51 // The result from the sd_journal_get_data() is of the form VARIABLE=value.
52 SD_JOURNAL_FOREACH_BACKWARDS(j)
53 {
54 const char *data = nullptr;
55 size_t length = 0;
56
Adriana Kobylak7298dc22017-01-24 12:21:50 -060057 // Look for the transaction id metadata variable
58 rc = sd_journal_get_data(j, transactionIdVar, (const void **)&data,
59 &length);
Adriana Kobylakd311bc82016-10-16 09:54:40 -050060 if (rc < 0)
61 {
Adriana Kobylak7298dc22017-01-24 12:21:50 -060062 // This journal entry does not have the transaction id,
63 // continue to next entry
Adriana Kobylakd311bc82016-10-16 09:54:40 -050064 continue;
65 }
Adriana Kobylak7298dc22017-01-24 12:21:50 -060066
Adriana Kobylakd311bc82016-10-16 09:54:40 -050067 std::string result(data);
Adriana Kobylak7298dc22017-01-24 12:21:50 -060068 if (result.find(transactionIdStr) == std::string::npos)
Adriana Kobylakd311bc82016-10-16 09:54:40 -050069 {
Adriana Kobylak7298dc22017-01-24 12:21:50 -060070 // Requested transaction id not found,
71 // continue to next journal entry.
Adriana Kobylakd311bc82016-10-16 09:54:40 -050072 continue;
73 }
Adriana Kobylakd311bc82016-10-16 09:54:40 -050074 // Match found, write to file
75 // TODO This is a draft format based on the redfish event logs written
76 // in json, the final openbmc format is to be determined
77 efile << "\t{" << std::endl;
78 efile << "\t\"@" << data << "\"," << std::endl;
79
80 // Include the journal message
81 rc = sd_journal_get_data(j, "MESSAGE", (const void **)&data, &length);
82 if (rc < 0)
83 {
84 continue;
85 }
Adriana Kobylak4ea7f312017-01-10 12:52:34 -060086
Adriana Kobylakd311bc82016-10-16 09:54:40 -050087 efile << "\t\"@" << data << "\"," << std::endl;
88
89 // Search for the metadata variables in the current journal entry
Adriana Kobylak7298dc22017-01-24 12:21:50 -060090 for (auto metaVarStr : metalist)
Adriana Kobylakd311bc82016-10-16 09:54:40 -050091 {
Adriana Kobylak7298dc22017-01-24 12:21:50 -060092 rc = sd_journal_get_data(j, metaVarStr.c_str(),
93 (const void **)&data, &length);
Adriana Kobylakd311bc82016-10-16 09:54:40 -050094 if (rc < 0)
95 {
96 // Not found, continue to next metadata variable
97 logging::log<logging::level::INFO>("Failed to find metadata",
Adriana Kobylak7298dc22017-01-24 12:21:50 -060098 logging::entry("META_FIELD=%s", metaVarStr.c_str()));
Adriana Kobylakd311bc82016-10-16 09:54:40 -050099 continue;
100 }
101
102 // Metatdata variable found, write to file
Adriana Kobylak4ea7f312017-01-10 12:52:34 -0600103 additionalData.push_back(std::string(data));
Adriana Kobylakd311bc82016-10-16 09:54:40 -0500104 efile << "\t\"@" << data << "\"," << std::endl;
105 }
106 efile << "\t}" << std::endl;
107
Adriana Kobylak1f36a882017-02-16 08:36:55 -0600108 // TODO Remove once host event error header file is auto-generated.
109 // Tracking with issue openbmc/phosphor-logging#4
110 for (auto metaVarStrHostEvent : metalistHostEvent)
111 {
112 rc = sd_journal_get_data(j, metaVarStrHostEvent.c_str(),
113 (const void **)&data, &length);
114 if (rc < 0)
115 {
116 // Not found, continue to next metadata variable
117 logging::log<logging::level::INFO>("Failed to find metadata",
118 logging::entry("META_FIELD=%s",
119 metaVarStrHostEvent.c_str()));
120 continue;
121 }
122
123 // Metatdata variable found, write to file
124 additionalData.push_back(std::string(data));
125 efile << "\t\"@" << data << "\"," << std::endl;
126 }
127
Adriana Kobylakd311bc82016-10-16 09:54:40 -0500128 // TODO Break only once all metadata fields have been found. Implement
129 // once this function reads the metadata fields from the header file.
130 break;
131 }
132 sd_journal_close(j);
133
Adriana Kobylak4ea7f312017-01-10 12:52:34 -0600134 // Create error Entry dbus object
135 entryId++;
Adriana Kobylakc5f0bbd2017-01-22 14:56:04 -0600136 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
137 std::chrono::system_clock::now().time_since_epoch()).count();
Adriana Kobylak4ea7f312017-01-10 12:52:34 -0600138 auto objPath = std::string(OBJ_ENTRY) + '/' +
Adriana Kobylakc5f0bbd2017-01-22 14:56:04 -0600139 std::to_string(entryId);
Adriana Kobylak4ea7f312017-01-10 12:52:34 -0600140 entries.insert(std::make_pair(entryId, std::make_unique<Entry>(
141 busLog,
142 objPath,
143 entryId,
Adriana Kobylakc5f0bbd2017-01-22 14:56:04 -0600144 ms, // Milliseconds since 1970
Adriana Kobylak4ea7f312017-01-10 12:52:34 -0600145 (Entry::Level)g_errLevelMap[errMsg],
146 std::move(errMsg),
147 std::move(additionalData))));
148
Adriana Kobylakd311bc82016-10-16 09:54:40 -0500149 efile << "}" << std::endl;
150 efile.close();
Adriana Kobylak8f7941e2016-11-14 14:46:23 -0600151 return;
Adriana Kobylak1db1bd32016-10-10 11:39:20 -0500152}
153
Adriana Kobylak8f7941e2016-11-14 14:46:23 -0600154} // namespace logging
155} // namepsace phosphor