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