eis/TestProject/play_gruond/time_jump_detector.cc000

167 lines
5.0 KiB
Plaintext
Raw Normal View History

#include <atomic>
#include <chrono>
#include <csignal>
#include <fstream>
#include <iostream>
#include <sys/stat.h>
#include <thread>
#include <ctime> // 添加用于localtime_r和时间函数
#include <iomanip> // 添加用于std::setw和std::setfill
#include <sstream> // 添加用于std::ostringstream
std::atomic<bool> 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<std::chrono::microseconds>(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<size_t>(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;
}