|  |  |  | #include "system/loggerd/logger.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <fstream>
 | 
					
						
							|  |  |  | #include <map>
 | 
					
						
							|  |  |  | #include <vector>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "common/params.h"
 | 
					
						
							|  |  |  | #include "common/swaglog.h"
 | 
					
						
							|  |  |  | #include "common/version.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ***** log metadata *****
 | 
					
						
							|  |  |  | kj::Array<capnp::word> logger_build_init_data() {
 | 
					
						
							|  |  |  |   uint64_t wall_time = nanos_since_epoch();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   MessageBuilder msg;
 | 
					
						
							|  |  |  |   auto init = msg.initEvent().initInitData();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   init.setWallTimeNanos(wall_time);
 | 
					
						
							|  |  |  |   init.setVersion(COMMA_VERSION);
 | 
					
						
							|  |  |  |   init.setDirty(!getenv("CLEAN"));
 | 
					
						
							|  |  |  |   init.setDeviceType(Hardware::get_device_type());
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // log kernel args
 | 
					
						
							|  |  |  |   std::ifstream cmdline_stream("/proc/cmdline");
 | 
					
						
							|  |  |  |   std::vector<std::string> kernel_args;
 | 
					
						
							|  |  |  |   std::string buf;
 | 
					
						
							|  |  |  |   while (cmdline_stream >> buf) {
 | 
					
						
							|  |  |  |     kernel_args.push_back(buf);
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   auto lkernel_args = init.initKernelArgs(kernel_args.size());
 | 
					
						
							|  |  |  |   for (int i=0; i<kernel_args.size(); i++) {
 | 
					
						
							|  |  |  |     lkernel_args.set(i, kernel_args[i]);
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   init.setKernelVersion(util::read_file("/proc/version"));
 | 
					
						
							|  |  |  |   init.setOsVersion(util::read_file("/VERSION"));
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // log params
 | 
					
						
							|  |  |  |   auto params = Params();
 | 
					
						
							|  |  |  |   std::map<std::string, std::string> params_map = params.readAll();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   init.setGitCommit(params_map["GitCommit"]);
 | 
					
						
							|  |  |  |   init.setGitBranch(params_map["GitBranch"]);
 | 
					
						
							|  |  |  |   init.setGitRemote(params_map["GitRemote"]);
 | 
					
						
							|  |  |  |   init.setPassive(false);
 | 
					
						
							|  |  |  |   init.setDongleId(params_map["DongleId"]);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   auto lparams = init.initParams().initEntries(params_map.size());
 | 
					
						
							|  |  |  |   int j = 0;
 | 
					
						
							|  |  |  |   for (auto& [key, value] : params_map) {
 | 
					
						
							|  |  |  |     auto lentry = lparams[j];
 | 
					
						
							|  |  |  |     lentry.setKey(key);
 | 
					
						
							|  |  |  |     if ( !(params.getKeyType(key) & DONT_LOG) ) {
 | 
					
						
							|  |  |  |       lentry.setValue(capnp::Data::Reader((const kj::byte*)value.data(), value.size()));
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     j++;
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // log commands
 | 
					
						
							|  |  |  |   std::vector<std::string> log_commands = {
 | 
					
						
							|  |  |  |     "df -h",  // usage for all filesystems
 | 
					
						
							|  |  |  |   };
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   auto hw_logs = Hardware::get_init_logs();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   auto commands = init.initCommands().initEntries(log_commands.size() + hw_logs.size());
 | 
					
						
							|  |  |  |   for (int i = 0; i < log_commands.size(); i++) {
 | 
					
						
							|  |  |  |     auto lentry = commands[i];
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     lentry.setKey(log_commands[i]);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const std::string result = util::check_output(log_commands[i]);
 | 
					
						
							|  |  |  |     lentry.setValue(capnp::Data::Reader((const kj::byte*)result.data(), result.size()));
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int i = log_commands.size();
 | 
					
						
							|  |  |  |   for (auto &[key, value] : hw_logs) {
 | 
					
						
							|  |  |  |     auto lentry = commands[i];
 | 
					
						
							|  |  |  |     lentry.setKey(key);
 | 
					
						
							|  |  |  |     lentry.setValue(capnp::Data::Reader((const kj::byte*)value.data(), value.size()));
 | 
					
						
							|  |  |  |     i++;
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return capnp::messageToFlatArray(msg);
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::string logger_get_route_name() {
 | 
					
						
							|  |  |  |   char route_name[64] = {'\0'};
 | 
					
						
							|  |  |  |   time_t rawtime = time(NULL);
 | 
					
						
							|  |  |  |   struct tm timeinfo;
 | 
					
						
							|  |  |  |   localtime_r(&rawtime, &timeinfo);
 | 
					
						
							|  |  |  |   strftime(route_name, sizeof(route_name), "%Y-%m-%d--%H-%M-%S", &timeinfo);
 | 
					
						
							|  |  |  |   return route_name;
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void log_sentinel(LoggerState *log, SentinelType type, int eixt_signal = 0) {
 | 
					
						
							|  |  |  |   MessageBuilder msg;
 | 
					
						
							|  |  |  |   auto sen = msg.initEvent().initSentinel();
 | 
					
						
							|  |  |  |   sen.setType(type);
 | 
					
						
							|  |  |  |   sen.setSignal(eixt_signal);
 | 
					
						
							|  |  |  |   log->write(msg.toBytes(), true);
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | LoggerState::LoggerState(const std::string &log_root) {
 | 
					
						
							|  |  |  |   route_name = logger_get_route_name();
 | 
					
						
							|  |  |  |   route_path = log_root + "/" + route_name;
 | 
					
						
							|  |  |  |   init_data = logger_build_init_data();
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | LoggerState::~LoggerState() {
 | 
					
						
							|  |  |  |   if (rlog) {
 | 
					
						
							|  |  |  |     log_sentinel(this, SentinelType::END_OF_ROUTE, exit_signal);
 | 
					
						
							|  |  |  |     std::remove(lock_file.c_str());
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool LoggerState::next() {
 | 
					
						
							|  |  |  |   if (rlog) {
 | 
					
						
							|  |  |  |     log_sentinel(this, SentinelType::END_OF_SEGMENT);
 | 
					
						
							|  |  |  |     std::remove(lock_file.c_str());
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   segment_path = route_path + "--" + std::to_string(++part);
 | 
					
						
							|  |  |  |   bool ret = util::create_directories(segment_path, 0775);
 | 
					
						
							|  |  |  |   assert(ret == true);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const std::string rlog_path = segment_path + "/rlog";
 | 
					
						
							|  |  |  |   lock_file = rlog_path + ".lock";
 | 
					
						
							|  |  |  |   std::ofstream{lock_file};
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   rlog.reset(new RawFile(rlog_path));
 | 
					
						
							|  |  |  |   qlog.reset(new RawFile(segment_path + "/qlog"));
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // log init data & sentinel type.
 | 
					
						
							|  |  |  |   write(init_data.asBytes(), true);
 | 
					
						
							|  |  |  |   log_sentinel(this, part > 0 ? SentinelType::START_OF_SEGMENT : SentinelType::START_OF_ROUTE);
 | 
					
						
							|  |  |  |   return true;
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void LoggerState::write(uint8_t* data, size_t size, bool in_qlog) {
 | 
					
						
							|  |  |  |   rlog->write(data, size);
 | 
					
						
							|  |  |  |   if (in_qlog) qlog->write(data, size);
 | 
					
						
							|  |  |  | }
 |