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