70 lines
2.0 KiB
Rust
70 lines
2.0 KiB
Rust
/*!
|
|
# 日志解析器
|
|
|
|
解析各种格式的日志。
|
|
*/
|
|
|
|
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<LogEntry> {
|
|
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);
|
|
}
|
|
}
|