use std::fs::File;
use std::fs::OpenOptions;
use std::fs;
use std::io::Write;
use std::fmt;
use std::path::PathBuf;
use time;
pub struct Logger {
log_dir: PathBuf,
fds: Vec<(LogDest, File)>,
debug_fd: File,
}
pub struct LogFile<'a> {
fd: &'a File,
}
impl<'a> LogFile<'a> {
pub fn write_line(&mut self, args: fmt::Arguments) {
let now = time::now();
write!(self.fd, "[{}] ", now.rfc822()).unwrap();
self.fd.write_fmt(args).unwrap();
writeln!(self.fd, "").unwrap();
}
}
enum LogDest {
Chan { serv: String, chan: String },
ServerRaw(String),
}
fn init_log_file(file: &mut Write) {
let now = time::now();
writeln!(file, "\nLogs started on {}\n", now.rfc822()).unwrap();
}
impl Logger {
pub fn new(log_dir: PathBuf) -> Logger {
let _ = fs::create_dir(&log_dir);
let debug_logs = {
let mut log_dir = log_dir.clone();
log_dir.push("debug.log");
let mut file = OpenOptions::new().append(true).create(true).open(log_dir).unwrap();
init_log_file(&mut file);
file
};
Logger {
log_dir: log_dir,
fds: vec![],
debug_fd: debug_logs,
}
}
pub fn get_chan_logs(&mut self, serv_: &str, chan_: &str) -> LogFile {
let pos = self.fds.iter().position(|&(ref dest, _)| {
if let &LogDest::Chan { ref serv, ref chan } = dest {
serv == serv_ && chan == chan_
} else {
false
}
});
match pos {
Some(idx) => LogFile { fd: &mut self.fds[idx].1 },
None => {
let mut log_path = self.log_dir.clone();
log_path.push(format!("{}_{}.log", serv_, chan_));
let mut file = OpenOptions::new().append(true).create(true).open(log_path).unwrap();
init_log_file(&mut file);
let idx = self.fds.len();
self.fds.push((LogDest::Chan { serv: serv_.to_owned(), chan: chan_.to_owned() }, file));
LogFile { fd: &mut self.fds[idx].1 }
}
}
}
pub fn get_raw_serv_logs(&mut self, serv_: &str) -> LogFile {
let pos = self.fds.iter().position(|&(ref dest, _)| {
if let &LogDest::ServerRaw(ref serv) = dest {
serv == serv_
} else {
false
}
});
match pos {
Some(idx) => LogFile { fd: &mut self.fds[idx].1 },
None => {
let mut log_path = self.log_dir.clone();
log_path.push(format!("{}_raw.log", serv_));
let mut file = OpenOptions::new().append(true).create(true).open(log_path).unwrap();
init_log_file(&mut file);
let idx = self.fds.len();
self.fds.push((LogDest::ServerRaw(serv_.to_owned()), file));
LogFile { fd: &mut self.fds[idx].1 }
}
}
}
pub fn get_debug_logs(&mut self) -> LogFile {
LogFile { fd: &mut self.debug_fd }
}
}