1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
#[macro_use] extern crate slog; extern crate slog_async; use std::{fs, io}; use std::cell::RefCell; use std::io::Write as IoWrite; use slog::{Drain, Record, OwnedKVList}; const KMSG_MAX: usize = 1024 - 32; const BUFFER_SIZE: usize = 4096; pub struct Kmsg { fd: RefCell<fs::File>, buffer: RefCell<[u8; BUFFER_SIZE]>, } impl Kmsg { pub fn new() -> Result<Kmsg, io::Error> { let kmsg = fs::OpenOptions::new().write(true).open("/dev/kmsg")?; Ok(Kmsg { fd: RefCell::new(kmsg), buffer: RefCell::new([0; BUFFER_SIZE]), }) } } fn level_to_kern_level(l: slog::Level) -> u8 { match l { slog::Level::Critical => 2, slog::Level::Error => 3, slog::Level::Warning => 4, slog::Level::Info => 6, slog::Level::Debug => 7, slog::Level::Trace => 7, } } impl Drain for Kmsg { type Ok = (); type Err = io::Error; fn log(&self, record: &Record, values: &OwnedKVList) -> Result<Self::Ok, Self::Err> { let mut len = { let mut buf = self.buffer.borrow_mut(); let mut cursor = io::Cursor::new(&mut buf[..]); let klevel = level_to_kern_level(record.level()); write!(&mut cursor, "<{}>{}: {}\n", klevel, record.module(), record.msg())?; cursor.position() as usize }; if len > KMSG_MAX { len = KMSG_MAX; } self.fd .borrow_mut() .write_all(&self.buffer.borrow()[..len])?; self.fd .borrow_mut() .flush()?; Ok(()) } } #[cfg(test)] mod tests { use super::Kmsg; use slog; use slog::Drain; use slog_async; #[test] fn it_works() { let drain = Kmsg::new().unwrap().fuse(); let drain = slog_async::Async::new(drain).build().fuse(); let root = slog::Logger::root(drain, o!()); error!(root, "test 123"); } }