control: Dump flight recorder to a JSON file
A future commit will dump more debug data as opposed to just the flight
recorder. To better support the data all being in the same file, it
will be a JSON file. The first step of that is to write the flight
recorder output to a JSON file.
This also reorganizes the Manager code that does it to prepare for
different data also being in the same file.
An example is:
{
"flight_recorder": [
"Oct 06 05:59:01.183998: main: Startup"
]
}
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: Iaeb55ffde3a30c2345968e1b3fad313b50aff331
diff --git a/control/json/manager.cpp b/control/json/manager.cpp
index 92ef0d0..10bb84d 100644
--- a/control/json/manager.cpp
+++ b/control/json/manager.cpp
@@ -58,6 +58,8 @@
Manager::_objects;
std::unordered_map<std::string, PropertyVariantType> Manager::_parameters;
+const std::string Manager::dumpFile = "/tmp/fan_control_dump.json";
+
Manager::Manager(const sdeventplus::Event& event) :
_bus(util::SDBusPlus::getBus()), _event(event),
_mgr(util::SDBusPlus::getBus(), CONTROL_OBJPATH), _loadAllowed(true),
@@ -95,15 +97,26 @@
void Manager::sigUsr1Handler(sdeventplus::source::Signal&,
const struct signalfd_siginfo*)
{
- _flightRecEventSource = std::make_unique<sdeventplus::source::Defer>(
- _event, std::bind(std::mem_fn(&Manager::dumpFlightRecorder), this,
+ debugDumpEventSource = std::make_unique<sdeventplus::source::Defer>(
+ _event, std::bind(std::mem_fn(&Manager::dumpDebugData), this,
std::placeholders::_1));
}
-void Manager::dumpFlightRecorder(sdeventplus::source::EventBase& /*source*/)
+void Manager::dumpDebugData(sdeventplus::source::EventBase& /*source*/)
{
- FlightRecorder::instance().dump();
- _flightRecEventSource.reset();
+ json data;
+ FlightRecorder::instance().dump(data);
+
+ std::ofstream file{Manager::dumpFile};
+ if (!file)
+ {
+ log<level::ERR>("Could not open file for fan dump");
+ return;
+ }
+
+ file << std::setw(4) << data;
+
+ debugDumpEventSource.reset();
}
void Manager::load()
diff --git a/control/json/manager.hpp b/control/json/manager.hpp
index 86e47dd..92f837e 100644
--- a/control/json/manager.hpp
+++ b/control/json/manager.hpp
@@ -479,6 +479,9 @@
_parameters.erase(name);
}
+ /* The name of the dump file */
+ static const std::string dumpFile;
+
private:
/* The sdbusplus bus object to use */
sdbusplus::bus::bus& _bus;
@@ -525,9 +528,9 @@
/* List of events configured */
std::map<configKey, std::unique_ptr<Event>> _events;
- /* The sdeventplus wrapper around sd_event_add_defer to dump the
- * flight recorder from the event loop after the USR1 signal. */
- std::unique_ptr<sdeventplus::source::Defer> _flightRecEventSource;
+ /* The sdeventplus wrapper around sd_event_add_defer to dump debug
+ * data from the event loop after the USR1 signal. */
+ std::unique_ptr<sdeventplus::source::Defer> debugDumpEventSource;
/**
* @brief A map of parameter names and values that are something
@@ -581,9 +584,9 @@
void setProfiles();
/**
- * @brief Callback from _flightRecEventSource to dump the flight recorder
+ * @brief Callback from debugDumpEventSource to dump debug data
*/
- void dumpFlightRecorder(sdeventplus::source::EventBase&);
+ void dumpDebugData(sdeventplus::source::EventBase&);
};
} // namespace phosphor::fan::control::json
diff --git a/control/json/utils/flight_recorder.cpp b/control/json/utils/flight_recorder.cpp
index 4cc274f..af04834 100644
--- a/control/json/utils/flight_recorder.cpp
+++ b/control/json/utils/flight_recorder.cpp
@@ -21,15 +21,15 @@
#include <algorithm>
#include <ctime>
-#include <fstream>
#include <iomanip>
+#include <sstream>
#include <vector>
constexpr auto maxEntriesPerID = 20;
-constexpr auto outputFile = "/tmp/fan_control.txt";
namespace phosphor::fan::control::json
{
+using json = nlohmann::json;
FlightRecorder& FlightRecorder::instance()
{
@@ -51,7 +51,7 @@
}
}
-void FlightRecorder::dump()
+void FlightRecorder::dump(json& data)
{
using namespace std::chrono;
using Timepoint = time_point<system_clock, microseconds>;
@@ -74,15 +74,6 @@
return std::get<Timepoint>(left) < std::get<Timepoint>(right);
});
- std::ofstream file{outputFile};
-
- if (!file)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- fmt::format("Could not open {} for writing", outputFile).c_str());
- return;
- }
-
auto formatTime = [](const Timepoint& tp) {
std::stringstream ss;
std::time_t tt = system_clock::to_time_t(tp);
@@ -95,10 +86,14 @@
return ss.str();
};
+ auto& fr = data["flight_recorder"];
+ std::stringstream ss;
+
for (const auto& [ts, id, msg] : output)
{
- file << formatTime(ts) << ": " << std::setw(idSize) << id << ": " << msg
- << "\n";
+ ss << formatTime(ts) << ": " << std::setw(idSize) << id << ": " << msg;
+ fr.push_back(ss.str());
+ ss.str("");
}
}
diff --git a/control/json/utils/flight_recorder.hpp b/control/json/utils/flight_recorder.hpp
index 154d5ab..fcc3908 100644
--- a/control/json/utils/flight_recorder.hpp
+++ b/control/json/utils/flight_recorder.hpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
#pragma once
+#include <nlohmann/json.hpp>
+
#include <chrono>
#include <cstdint>
#include <deque>
@@ -23,6 +25,7 @@
namespace phosphor::fan::control::json
{
+using json = nlohmann::json;
/**
* @class FlightRecorder
@@ -61,11 +64,13 @@
void log(const std::string& id, const std::string& message);
/**
- * @brief Writes the flight recorder contents to file.
+ * @brief Writes the flight recorder contents to JSON.
*
* Sorts all messages by timestamp when doing so.
+ *
+ * @param[out] data - Filled in with the flight recorder data
*/
- void dump();
+ void dump(json& data);
private:
FlightRecorder() = default;