use log::{self, LogRecord, LogLevelFilter, LogMetadata, SetLoggerError};
use rusqlite::SqliteConnection;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
pub type SqliteLogFn = fn(&LogRecord, &mut SqliteConnection);
pub struct SqliteLogger {
conn: Arc<Mutex<SqliteConnection>>,
outputfn: Arc<Mutex<SqliteLogFn>>,
}
impl SqliteLogger {
pub fn new(path: Option<PathBuf>, create: bool, ofn: SqliteLogFn) -> SqliteLogger {
let conn = match path {
Some(ref pb) => {
match SqliteConnection::open(pb) {
Ok(c) => c,
Err(e) => {
panic!("Unable to initialize sqlite logger! {}", e);
}
}
}
None => {
match SqliteConnection::open_in_memory() {
Ok(c) => c,
Err(e) => {
panic!("Unable to initialize sqlite logger! {}", e);
}
}
}
};
if create {
match conn.execute(r"DROP TABLE log", &[]) {
Ok(_) => {}
Err(e) => {
println!("{}", e);
}
}
match conn.execute(r"CREATE TABLE log (
id INTEGER PRIMARY KEY,
created TEXT NOT NULL,
level TEXT NOT NULL,
line TEXT NOT NULL,
module TEXT NOT NULL,
message TEXT NOT NULL
)",
&[]) {
Ok(_) => {}
Err(e) => panic!("Unable to create log table! {}", e),
}
}
SqliteLogger {
conn: Arc::new(Mutex::new(conn)),
outputfn: Arc::new(Mutex::new(ofn)),
}
}
}
impl log::Log for SqliteLogger {
fn enabled(&self, _: &LogMetadata) -> bool {
true
}
fn log(&self, record: &LogRecord) {
if self.enabled(record.metadata()) {
match self.conn.lock() {
Ok(ref mut conn) => {
match self.outputfn.lock() {
Ok(ref mut f) => {
f(record, conn);
}
Err(e) => {
println!("Unable to acquire lock! {}", e);
}
};
}
Err(e) => {
println!("Unable to acquire mutex lock! {:?}", e);
}
}
}
}
}
pub fn init_sqlite_logger(level: LogLevelFilter,
logger: SqliteLogger)
-> Result<(), SetLoggerError> {
log::set_logger(|max_log_level| {
max_log_level.set(level);
Box::new(logger)
})
}