use crate::error::{Error, ParserError, Result};
use log::{debug, info, warn};
use std::path::{Path, PathBuf};
#[derive(Debug)]
pub struct SqllogParser {
path: PathBuf,
}
impl SqllogParser {
pub fn new(path: impl AsRef<Path>) -> Self {
Self {
path: path.as_ref().to_path_buf(),
}
}
#[must_use]
pub fn path(&self) -> &Path {
&self.path
}
pub fn log_files(&self) -> Result<Vec<PathBuf>> {
self.scan_log_files()
}
fn scan_log_files(&self) -> Result<Vec<PathBuf>> {
let path = &self.path;
if !path.exists() {
return Err(Error::Parser(ParserError::PathNotFound {
path: path.clone(),
}));
}
let mut log_files = Vec::new();
if path.is_file() {
info!("Parsing single log file: {}", path.display());
log_files.push(path.clone());
} else if path.is_dir() {
info!("Scanning log directory: {}", path.display());
let entries = std::fs::read_dir(path).map_err(|e| {
Error::Parser(ParserError::ReadDirFailed {
path: path.clone(),
reason: e.to_string(),
})
})?;
for entry in entries {
let entry = entry.map_err(|e| {
Error::Parser(ParserError::ReadDirFailed {
path: path.clone(),
reason: e.to_string(),
})
})?;
let entry_path = entry.path();
if entry_path.is_file() && entry_path.extension().is_some_and(|ext| ext == "log") {
debug!("Found log file: {}", entry_path.display());
log_files.push(entry_path);
}
}
if log_files.is_empty() {
warn!("No .log files found in directory {}", path.display());
} else {
info!("Found {} log files", log_files.len());
}
} else {
return Err(Error::Parser(ParserError::InvalidPath {
path: path.clone(),
reason: "既不是文件也不是目录".to_string(),
}));
}
Ok(log_files)
}
}