增加了日志功能,修复了bug

This commit is contained in:
zjk
2025-05-19 02:14:11 +08:00
parent 9e1819cd75
commit 50a496e3e2
4 changed files with 222 additions and 20 deletions
+163
View File
@@ -54,6 +54,11 @@ void HttpServer::handleWebSocketEvent(struct mg_connection* c, int ev, void* ev_
}
}
}
} else if (ev == MG_EV_WS_MSG) {
// WebSocket消息处理
struct mg_ws_message *wm = (struct mg_ws_message *) ev_data;
std::string msg(wm->data.buf, wm->data.len);
handleLogRequest(c, msg);
} else if (ev == MG_EV_HTTP_MSG) {
// HTTP请求处理
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
@@ -216,11 +221,18 @@ bool HttpServer::serverThreadFunc() {
// 定期推送系统数据
static uint64_t last_push_time = 0;
static uint64_t last_log_check_time = 0;
uint64_t now = mg_millis();
if (now - last_push_time > 1000) { // 每秒推送一次
last_push_time = now;
pushSystemData();
}
if (now - last_log_check_time > 500) { // 每500ms检查一次日志
last_log_check_time = now;
monitorLogFile();
}
}
return true;
}
@@ -550,3 +562,154 @@ void HttpServer::stop() {
bool HttpServer::isRunning() const {
return running_;
}
void HttpServer::handleLogRequest(struct mg_connection* c, const std::string& msg) {
try {
Json::Value json;
Json::CharReaderBuilder builder;
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
const char* msg_cstr = msg.c_str();
std::string errors;
if (!reader->parse(msg_cstr, msg_cstr + msg.size(), &json, &errors)) {
LOG_F(ERROR, "Failed to parse log request JSON: %s", errors.c_str());
return;
}
std::string type = json["type"].asString();
if (type == "get_logs") {
int page = json["page"].asInt();
int pageSize = json["pageSize"].asInt();
std::string level = json["filter"]["level"].asString();
std::string search = json["filter"]["search"].asString();
bool reverse = json["reverse"].asBool(); // 新增参数,控制是否倒序显示
auto logs = readLogFile(page, pageSize, level, search);
Json::Value response;
response["type"] = "log";
response["page"] = page;
response["pageSize"] = pageSize;
response["total"] = logs.size(); // 返回总条数
response["content"] = Json::arrayValue;
if (reverse) {
// 如果需要倒序,反转日志顺序
for (auto it = logs.rbegin(); it != logs.rend(); ++it) {
response["content"].append(*it);
}
} else {
// 否则按原顺序返回
for (const auto& log : logs) {
response["content"].append(log);
}
}
Json::StreamWriterBuilder builder;
std::string responseStr = Json::writeString(builder, response);
mg_ws_send(c, responseStr.c_str(), responseStr.size(), WEBSOCKET_OP_TEXT);
}
} catch (const std::exception& e) {
LOG_F(ERROR, "Error handling log request: %s", e.what());
}
}
std::vector<std::string> HttpServer::readLogFile(int page, int pageSize, const std::string& level, const std::string& search) {
std::vector<std::string> logs;
std::ifstream file(m_logFilePath);
if (!file.is_open()) {
LOG_F(ERROR, "Failed to open log file: %s", m_logFilePath.c_str());
return logs;
}
// 获取文件大小
file.seekg(0, std::ios::end);
std::streampos fileSize = file.tellg();
file.seekg(0, std::ios::beg);
std::string line;
std::vector<std::string> filteredLogs;
// 读取并过滤所有行
while (std::getline(file, line)) {
// 过滤日志级别和搜索内容
if ((level.empty() || level == "ALL" || line.find(level) != std::string::npos) &&
(search.empty() || line.find(search) != std::string::npos)) {
filteredLogs.push_back(line);
}
}
// 计算总页数
int totalLines = filteredLogs.size();
// 如果没有内容,直接返回空
if (totalLines == 0) {
return logs;
}
// 计算当前页的起始和结束索引
int start = std::max(0, totalLines - (page * pageSize));
int end = std::max(0, totalLines - ((page - 1) * pageSize));
// 返回当前页的日志(已经是倒序的)
return std::vector<std::string>(filteredLogs.begin() + start, filteredLogs.begin() + end);
}
void HttpServer::monitorLogFile() {
static std::streampos lastPos = 0;
std::ifstream file(m_logFilePath);
if (!file.is_open()) {
LOG_F(ERROR, "Failed to open log file for monitoring: %s", m_logFilePath.c_str());
return;
}
// 获取文件大小
file.seekg(0, std::ios::end);
std::streampos currentPos = file.tellg();
// 如果文件大小没有变化,直接返回
if (currentPos == lastPos) {
return;
}
// 如果是第一次读取或文件被截断,从头开始读
if (currentPos < lastPos) {
lastPos = 0;
}
// 移动到上次读取的位置
file.seekg(lastPos);
std::string line;
std::vector<std::string> newLogs;
// 读取新的日志行
while (std::getline(file, line)) {
newLogs.push_back(line);
}
// 更新最后读取位置
lastPos = currentPos;
// 如果有新日志,推送给所有客户端
if (!newLogs.empty()) {
Json::Value json;
json["type"] = "new_log";
json["content"] = Json::arrayValue;
// 只保留最新的100行
size_t start = newLogs.size() > 100 ? newLogs.size() - 100 : 0;
for (size_t i = start; i < newLogs.size(); ++i) {
json["content"].append(newLogs[i]);
}
Json::StreamWriterBuilder builder;
std::string msg = Json::writeString(builder, json);
std::lock_guard<std::mutex> lock(ws_connections_mutex_);
for (auto c : ws_connections_) {
mg_ws_send(c, msg.c_str(), msg.size(), WEBSOCKET_OP_TEXT);
}
}
}