blob: d8f233c0461d83f5cc5ebc654ad795b87aa74bbd [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>
Adriana Kobylakfbe88722017-02-22 16:49:59 -06005#include <set>
Adriana Kobylakd311bc82016-10-16 09:54:40 -05006#include <string>
7#include <vector>
Adriana Kobylak1db1bd32016-10-10 11:39:20 -05008#include <sdbusplus/vtable.hpp>
9#include <systemd/sd-bus.h>
Adriana Kobylakd311bc82016-10-16 09:54:40 -050010#include <systemd/sd-journal.h>
Adriana Kobylak7298dc22017-01-24 12:21:50 -060011#include "elog-lookup.cpp"
Saqib Khan2bb15192017-02-13 13:19:55 -060012#include <phosphor-logging/elog-errors-HostEvent.hpp>
Adriana Kobylak4ea7f312017-01-10 12:52:34 -060013#include "config.h"
14#include "elog_entry.hpp"
Saqib Khan2bb15192017-02-13 13:19:55 -060015#include <phosphor-logging/log.hpp>
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060016#include "log_manager.hpp"
Adriana Kobylak1db1bd32016-10-10 11:39:20 -050017
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060018namespace phosphor
19{
20namespace logging
21{
Adriana Kobylakd311bc82016-10-16 09:54:40 -050022
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060023void Manager::commit(uint64_t transactionId, std::string errMsg)
Adriana Kobylak1db1bd32016-10-10 11:39:20 -050024{
Adriana Kobylak7298dc22017-01-24 12:21:50 -060025 constexpr const auto transactionIdVar = "TRANSACTION_ID";
Adriana Kobylak67218992017-02-28 12:53:37 -060026 constexpr const auto transactionIdVarSize = strlen(transactionIdVar);
Adriana Kobylak1db1bd32016-10-10 11:39:20 -050027
Adriana Kobylakd311bc82016-10-16 09:54:40 -050028 sd_journal *j = nullptr;
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060029 int rc = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
Adriana Kobylakd311bc82016-10-16 09:54:40 -050030 if (rc < 0)
31 {
32 logging::log<logging::level::ERR>("Failed to open journal",
33 logging::entry("DESCRIPTION=%s", strerror(-rc)));
Adriana Kobylak8f7941e2016-11-14 14:46:23 -060034 return;
Adriana Kobylakd311bc82016-10-16 09:54:40 -050035 }
36
Adriana Kobylak7298dc22017-01-24 12:21:50 -060037 std::string transactionIdStr = std::to_string(transactionId);
Adriana Kobylakfbe88722017-02-22 16:49:59 -060038 std::set<std::string> metalist(g_errMetaMap[errMsg].begin(),
39 g_errMetaMap[errMsg].end());
Adriana Kobylak9aa7d782017-02-18 09:20:49 -060040 const auto& metalistHostEvent = g_errMetaMapHostEvent[errMsg];
Adriana Kobylak4ea7f312017-01-10 12:52:34 -060041 std::vector<std::string> additionalData;
Adriana Kobylak7298dc22017-01-24 12:21:50 -060042
Adriana Kobylak9aa7d782017-02-18 09:20:49 -060043 // TODO Remove once host event error header file is auto-generated.
44 // Also make metalist a const variable.
45 // Tracking with issue openbmc/phosphor-logging#4
46 for (auto& metaVarStrHostEvent : metalistHostEvent)
Adriana Kobylakd311bc82016-10-16 09:54:40 -050047 {
Adriana Kobylakfbe88722017-02-22 16:49:59 -060048 metalist.insert(metaVarStrHostEvent);
Adriana Kobylakd311bc82016-10-16 09:54:40 -050049 }
Adriana Kobylak9aa7d782017-02-18 09:20:49 -060050
Adriana Kobylakfbe88722017-02-22 16:49:59 -060051 // Read the journal from the end to get the most recent entry first.
52 // The result from the sd_journal_get_data() is of the form VARIABLE=value.
53 SD_JOURNAL_FOREACH_BACKWARDS(j)
Adriana Kobylak9aa7d782017-02-18 09:20:49 -060054 {
Adriana Kobylakfbe88722017-02-22 16:49:59 -060055 const char *data = nullptr;
56 size_t length = 0;
Adriana Kobylak9aa7d782017-02-18 09:20:49 -060057
Adriana Kobylakfbe88722017-02-22 16:49:59 -060058 // Look for the transaction id metadata variable
59 rc = sd_journal_get_data(j, transactionIdVar, (const void **)&data,
60 &length);
61 if (rc < 0)
Adriana Kobylak9aa7d782017-02-18 09:20:49 -060062 {
Adriana Kobylakfbe88722017-02-22 16:49:59 -060063 // This journal entry does not have the TRANSACTION_ID
64 // metadata variable.
65 continue;
66 }
Adriana Kobylak9aa7d782017-02-18 09:20:49 -060067
Adriana Kobylak67218992017-02-28 12:53:37 -060068 // The metadata field result will be TRANSACTION_ID=1234. Skip the
69 // TRANSACTION_ID piece and (=) sign to get the id number to compare.
70 if (strcmp((data + transactionIdVarSize + 1),
71 transactionIdStr.c_str()) != 0)
Adriana Kobylakfbe88722017-02-22 16:49:59 -060072 {
73 // The value of the TRANSACTION_ID metadata is not the requested
74 // transaction id number.
75 continue;
76 }
77
78 // Search for all metadata variables in the current journal entry.
79 for (auto i = metalist.cbegin(); i != metalist.cend();)
80 {
81 rc = sd_journal_get_data(j, (*i).c_str(),
82 (const void **)&data, &length);
Adriana Kobylak9aa7d782017-02-18 09:20:49 -060083 if (rc < 0)
84 {
Adriana Kobylakfbe88722017-02-22 16:49:59 -060085 // Metadata variable not found, check next metadata variable.
86 i++;
Adriana Kobylak9aa7d782017-02-18 09:20:49 -060087 continue;
88 }
89
Adriana Kobylakfbe88722017-02-22 16:49:59 -060090 // Metadata variable found, save it and remove it from the set.
91 additionalData.emplace_back(data, length);
92 i = metalist.erase(i);
93 }
94 if (metalist.empty())
95 {
96 // All metadata variables found, break out of journal loop.
Adriana Kobylak9aa7d782017-02-18 09:20:49 -060097 break;
98 }
Adriana Kobylakfbe88722017-02-22 16:49:59 -060099 }
100 if (!metalist.empty())
101 {
102 // Not all the metadata variables were found in the journal.
103 for (auto& metaVarStr : metalist)
Adriana Kobylak9aa7d782017-02-18 09:20:49 -0600104 {
Adriana Kobylak9aa7d782017-02-18 09:20:49 -0600105 logging::log<logging::level::INFO>("Failed to find metadata",
106 logging::entry("META_FIELD=%s", metaVarStr.c_str()));
Adriana Kobylak9aa7d782017-02-18 09:20:49 -0600107 }
108 }
109
Adriana Kobylakd311bc82016-10-16 09:54:40 -0500110 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))));
Adriana Kobylak8f7941e2016-11-14 14:46:23 -0600126 return;
Adriana Kobylak1db1bd32016-10-10 11:39:20 -0500127}
128
Adriana Kobylak8f7941e2016-11-14 14:46:23 -0600129} // namespace logging
130} // namepsace phosphor