1 #pragma once 2 3 #include <config.h> 4 5 #include <common/utils.hpp> 6 #include <phosphor-logging/lg2.hpp> 7 8 #include <fstream> 9 #include <iomanip> 10 #include <iostream> 11 #include <vector> 12 13 PHOSPHOR_LOG2_USING; 14 15 namespace pldm 16 { 17 namespace flightrecorder 18 { 19 using ReqOrResponse = bool; 20 using FlightRecorderData = std::vector<uint8_t>; 21 using FlightRecorderTimeStamp = std::string; 22 using FlightRecorderRecord = 23 std::tuple<FlightRecorderTimeStamp, ReqOrResponse, FlightRecorderData>; 24 using FlightRecorderCassette = std::vector<FlightRecorderRecord>; 25 static constexpr auto flightRecorderDumpPath = "/tmp/pldm_flight_recorder"; 26 27 /** @class FlightRecorder 28 * 29 * The class for implementing the PLDM flight recorder logic. This class 30 * handles the insertion of the data into the recorder and also provides 31 * API's to dump the flight recorder into a file. 32 */ 33 34 class FlightRecorder 35 { 36 private: 37 FlightRecorder() : index(0) 38 { 39 flightRecorderPolicy = FLIGHT_RECORDER_MAX_ENTRIES ? true : false; 40 if (flightRecorderPolicy) 41 { 42 tapeRecorder = FlightRecorderCassette(FLIGHT_RECORDER_MAX_ENTRIES); 43 } 44 } 45 46 protected: 47 int index; 48 FlightRecorderCassette tapeRecorder; 49 bool flightRecorderPolicy; 50 51 public: 52 FlightRecorder(const FlightRecorder&) = delete; 53 FlightRecorder(FlightRecorder&&) = delete; 54 FlightRecorder& operator=(const FlightRecorder&) = delete; 55 FlightRecorder& operator=(FlightRecorder&&) = delete; 56 ~FlightRecorder() = default; 57 58 static FlightRecorder& GetInstance() 59 { 60 static FlightRecorder flightRecorder; 61 return flightRecorder; 62 } 63 64 /** @brief Add records to the flightRecorder 65 * 66 * @param[in] buffer - The request/respose byte buffer 67 * @param[in] isRequest - bool that captures if it is a request message or 68 * a response message 69 * 70 * @return void 71 */ 72 void saveRecord(const FlightRecorderData& buffer, ReqOrResponse isRequest) 73 { 74 // if the flight recorder policy is enabled, then only insert the 75 // messages into the flight recorder, if not this function will be just 76 // a no-op 77 if (flightRecorderPolicy) 78 { 79 int currentIndex = index++; 80 tapeRecorder[currentIndex] = std::make_tuple( 81 pldm::utils::getCurrentSystemTime(), isRequest, buffer); 82 index = (currentIndex == FLIGHT_RECORDER_MAX_ENTRIES - 1) ? 0 83 : index; 84 } 85 } 86 87 /** @brief play flight recorder 88 * 89 * @return void 90 */ 91 92 void playRecorder() 93 { 94 if (flightRecorderPolicy) 95 { 96 std::ofstream recorderOutputFile(flightRecorderDumpPath); 97 info("Dumping the flight recorder into : {DUMP_PATH}", "DUMP_PATH", 98 flightRecorderDumpPath); 99 for (const auto& message : tapeRecorder) 100 { 101 recorderOutputFile << std::get<FlightRecorderTimeStamp>(message) 102 << " : "; 103 if (std::get<ReqOrResponse>(message)) 104 { 105 recorderOutputFile << "Tx : \n"; 106 } 107 else 108 { 109 recorderOutputFile << "Rx : \n"; 110 } 111 for (const auto& word : std::get<FlightRecorderData>(message)) 112 { 113 recorderOutputFile << std::setfill('0') << std::setw(2) 114 << std::hex << (unsigned)word << " "; 115 } 116 recorderOutputFile << std::endl; 117 } 118 recorderOutputFile.close(); 119 } 120 else 121 { 122 error("Fight recorder policy is disabled"); 123 } 124 } 125 }; 126 127 } // namespace flightrecorder 128 } // namespace pldm 129