Skip to main content

rflog_parser/
log.rs

1use anyhow::Result;
2use chrono::NaiveTime;
3
4#[derive(Debug, Clone)]
5pub enum LogKind {
6  Out,
7  Err
8}
9
10#[derive(Debug, Clone)]
11pub struct Log {
12  pub log_line: usize,
13  pub kind: LogKind,
14  pub time: Option<NaiveTime>,
15  pub thread: String,
16  pub executor: String,
17  pub data: Vec<String>
18}
19
20pub fn parse(line: usize, log: &str) -> Result<Log> {
21  use regex::Regex;
22
23  let log = log.trim();
24  if log.is_empty() {
25    anyhow::bail!("Пустая строка лога");
26  }
27
28  let kind = if log.starts_with("[OUT]") {
29    LogKind::Out
30  } else if log.starts_with("[ERR]") {
31    LogKind::Err
32  } else {
33    anyhow::bail!("Неизвестный тип лога");
34  };
35
36  // Убираем [OUT] или [ERR] и тримим
37  let content = log
38    .strip_prefix("[OUT]")
39    .or_else(|| log.strip_prefix("[ERR]"))
40    .unwrap()
41    .trim();
42
43  // Если пусто — типа просто "[OUT]" — возвращаем пустой лог
44  if content.is_empty() {
45    return Ok(Log {
46      log_line: line,
47      kind,
48      time: None,
49      thread: String::new(),
50      executor: String::new(),
51      data: vec![],
52    });
53  }
54
55  let re_full = Regex::new(r"^\[(\d{2}:\d{2}:\d{2})] \[([^\]]+)] \[([^\]]+)]\:?\s?(.*)$")?;
56  let re_simple = Regex::new(r"^\[([^\]]+)] \[([^\]]+)] (.+)$")?;
57
58  if let Some(caps) = re_full.captures(content) {
59    let time = Some(NaiveTime::parse_from_str(caps.get(1).unwrap().as_str(), "%H:%M:%S")?);
60    let thread = caps.get(2).unwrap().as_str().to_string();
61    let executor = caps.get(3).unwrap().as_str().to_string();
62    let data_str = caps.get(4).map(|m| m.as_str().trim()).unwrap_or("").to_string();
63    let data = if data_str.is_empty() { vec![] } else { vec![data_str] };
64
65    Ok(Log {
66      log_line: line,
67      kind,
68      time,
69      thread,
70      executor,
71      data,
72    })
73  } else if let Some(caps) = re_simple.captures(content) {
74    let thread = caps.get(1).unwrap().as_str().to_string();
75    let executor = caps.get(2).unwrap().as_str().to_string();
76    let data_str = caps.get(3).unwrap().as_str().to_string();
77
78    Ok(Log {
79      log_line: line,
80      kind,
81      time: None,
82      thread,
83      executor,
84      data: vec![data_str],
85    })
86  } else {
87    // просто continuation-строка
88    Ok(Log {
89      log_line: line,
90      kind,
91      time: None,
92      thread: String::new(),
93      executor: String::new(),
94      data: vec![content.to_string()],
95    })
96  }
97}