/*! # 日志解析器 解析各种格式的日志。 */ use super::{LogEntry, LogLevel, LogSource}; use crate::error::{MonitorError, Result}; use serde_json::Value; /// 日志解析器 pub struct LogParser; impl LogParser { /// 解析JSON格式日志 pub fn parse_json(json_str: &str, node_id: String) -> Result { let value: Value = serde_json::from_str(json_str) .map_err(|e| MonitorError::LogError(format!("解析JSON日志失败: {}", e)))?; let level = match value.get("level").and_then(|v| v.as_str()) { Some("error") | Some("ERROR") => LogLevel::Error, Some("warn") | Some("WARN") | Some("warning") => LogLevel::Warning, Some("info") | Some("INFO") => LogLevel::Info, Some("debug") | Some("DEBUG") => LogLevel::Debug, Some("trace") | Some("TRACE") => LogLevel::Trace, _ => LogLevel::Info, }; let message = value.get("message") .or_else(|| value.get("msg")) .and_then(|v| v.as_str()) .unwrap_or("") .to_string(); Ok(LogEntry::new(level, LogSource::Node, node_id, message)) } /// 解析纯文本日志 pub fn parse_text(text: &str, node_id: String) -> LogEntry { let level = if text.contains("ERROR") { LogLevel::Error } else if text.contains("WARN") { LogLevel::Warning } else { LogLevel::Info }; LogEntry::new(level, LogSource::Node, node_id, text.to_string()) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_parse_json() { let json = r#"{"level":"error","message":"test error"}"#; let entry = LogParser::parse_json(json, "node-1".to_string()); assert!(entry.is_ok()); } #[test] fn test_parse_text() { let text = "ERROR: test error"; let entry = LogParser::parse_text(text, "node-1".to_string()); assert_eq!(entry.level, LogLevel::Error); } }