#include #include #include #include #include #include #include #include // 添加:用于localtime_r和时间函数 #include // 添加:用于std::setw和std::setfill #include // 添加:用于std::ostringstream std::atomic stop_logging(false); void signalHandler(int signum) { stop_logging = true; } class HighPrecisionTimeLogger { private: std::ofstream log_file; int log_interval_ms; std::string filename; uint64_t last_timestamp_us; uint64_t second_last_timestamp_us; bool selective_logging; bool in_jump_mode; int jump_remaining; // 获取当前时间戳(微秒) uint64_t getCurrentTimestampUs() { auto now = std::chrono::system_clock::now(); auto duration = now.time_since_epoch(); return std::chrono::duration_cast(duration) .count(); } // 格式化时间戳为可读字符串 std::string formatTimestamp(uint64_t timestamp_us) { time_t seconds = timestamp_us / 1000000; suseconds_t microseconds = timestamp_us % 1000000; struct tm tm_info; localtime_r(&seconds, &tm_info); char buffer[64]; strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tm_info); std::ostringstream oss; oss << buffer << "." << std::setw(6) << std::setfill('0') << microseconds; return oss.str(); } // 检查是否需要日志轮转 void checkLogRotation() { struct stat stat_buf; if (stat(filename.c_str(), &stat_buf) == 0) { // 如果文件超过50MB,进行轮转 if (static_cast(stat_buf.st_size) >= 50 * 1024 * 1024) { log_file.close(); std::string old_filename = filename + ".old"; rename(filename.c_str(), old_filename.c_str()); log_file.open(filename, std::ios::out); } } } public: HighPrecisionTimeLogger(const std::string &fname = "timestamps.log", int interval_ms = 50, bool selective = true) : filename(fname), log_interval_ms(interval_ms), selective_logging(selective), last_timestamp_us(0), second_last_timestamp_us(0), in_jump_mode(false), jump_remaining(0) { log_file.open(filename, std::ios::out); if (!log_file.is_open()) { throw std::runtime_error("无法打开日志文件"); } // 写入表头 log_file << "timestamp,formatted_time,time_jump_detected,interval_us,note" << std::endl; } void startLogging() { signal(SIGINT, signalHandler); signal(SIGTERM, signalHandler); std::cout << "开始记录时间戳,间隔: " << log_interval_ms << "ms" << std::endl; std::cout << "按Ctrl+C停止记录" << std::endl; auto next_log_time = std::chrono::steady_clock::now(); uint64_t expected_interval_us = log_interval_ms * 1000; while (!stop_logging) { uint64_t current_timestamp_us = getCurrentTimestampUs(); std::string formatted_time = formatTimestamp(current_timestamp_us); bool time_jump_detected = false; std::string note = ""; // 时间跳变检测逻辑 if (last_timestamp_us != 0 && second_last_timestamp_us != 0) { // 检测时间回退 if (current_timestamp_us < last_timestamp_us) { time_jump_detected = true; note = "TIME_REGESSION"; } // 检测异常大的间隔(超过预期1.5倍) else { uint64_t actual_interval_us = current_timestamp_us - second_last_timestamp_us; uint64_t threshold_us = expected_interval_us * 1.5; if (actual_interval_us > threshold_us) { time_jump_detected = true; note = "LONG_INTERVAL"; } } } // 更新历史时间戳 if (last_timestamp_us != 0) { second_last_timestamp_us = last_timestamp_us; } last_timestamp_us = current_timestamp_us; // 记录到文件 uint64_t interval = (second_last_timestamp_us == 0) ? 0 : (current_timestamp_us - second_last_timestamp_us); log_file << current_timestamp_us << "," << formatted_time << "," << (time_jump_detected ? "YES" : "NO") << "," << interval << "," << note << std::endl; // 检查日志轮转 checkLogRotation(); // 计算下一个日志时间点 next_log_time += std::chrono::milliseconds(log_interval_ms); std::this_thread::sleep_until(next_log_time); } log_file.close(); std::cout << "记录已停止,数据保存在: " << filename << std::endl; } }; int main(int argc, char *argv[]) { std::string filename = "time_log.csv"; int interval_ms = 50; if (argc >= 2) { interval_ms = std::stoi(argv[1]); } if (argc >= 3) { filename = argv[2]; } try { HighPrecisionTimeLogger logger(filename, interval_ms); logger.startLogging(); } catch (const std::exception &e) { std::cerr << "错误: " << e.what() << std::endl; return 1; } return 0; }