use log::{self, LogRecord, LogLevelFilter, LogMetadata, SetLoggerError};
use std::io::{BufWriter, Write};
use std::net::{TcpStream, ToSocketAddrs};
use std::ops::DerefMut;
use std::sync::{Arc, Mutex, RwLock};
pub type SocketLogFn = fn(&LogRecord, &mut BufWriter<TcpStream>);
pub struct SocketLogger {
rwlck: RwLock<BufWriter<TcpStream>>,
outputfn: Arc<Mutex<SocketLogFn>>,
}
impl SocketLogger {
pub fn new<A: ToSocketAddrs>(addr: A, ofn: SocketLogFn) -> SocketLogger {
let tcps = match TcpStream::connect(addr) {
Ok(tcps) => tcps,
Err(e) => panic!("Unable to initialize SocketLogger! {}", e),
};
SocketLogger {
rwlck: RwLock::new(BufWriter::new(tcps)),
outputfn: Arc::new(Mutex::new(ofn)),
}
}
}
impl log::Log for SocketLogger {
fn enabled(&self, _: &LogMetadata) -> bool {
true
}
fn log(&self, record: &LogRecord) {
if self.enabled(record.metadata()) {
match self.rwlck.write() {
Ok(ref mut w) => {
match self.outputfn.lock() {
Ok(ref mut f) => {
f(record, w.deref_mut());
}
Err(e) => {
println!("Unable to acquire lock! {}", e);
}
};
}
Err(e) => {
println!("Unable to acquire write lock! {:?}", e);
}
}
}
}
}
pub fn init_socket_logger<A: ToSocketAddrs>(level: LogLevelFilter,
logger: SocketLogger)
-> Result<(), SetLoggerError> {
log::set_logger(|max_log_level| {
max_log_level.set(level);
Box::new(logger)
})
}