use super::{OwnedKeyValue, Level, BorrowedKeyValue, OwnedKeyValueNode};
use std::sync::Arc;
use std::cell::RefCell;
use std::borrow::Cow;
use std::fmt;
use drain;
use chrono;
thread_local! {
static TL_BUF: RefCell<Vec<u8>> = RefCell::new(Vec::with_capacity(128))
}
#[derive(Clone)]
pub struct Logger {
drain: Arc<drain::Drain>,
values: Arc<OwnedKeyValueNode>,
}
pub trait IntoMsg {
fn as_str(&self) -> Cow<str>;
}
impl<'a> IntoMsg for &'a str {
fn as_str(&self) -> Cow<str> {
Cow::Borrowed(self)
}
}
impl<'a> IntoMsg for String {
fn as_str(&self) -> Cow<str> {
Cow::Borrowed(self.as_str())
}
}
impl<'a> IntoMsg for fmt::Arguments<'a> {
fn as_str(&self) -> Cow<str> {
let mut s = String::new();
fmt::write(&mut s, *self).unwrap();
Cow::Owned(s)
}
}
impl Logger {
pub fn new_root<D: 'static + drain::Drain + Sized>(values: Vec<OwnedKeyValue>, d: D) -> Logger {
Logger {
drain: Arc::new(d),
values: Arc::new(OwnedKeyValueNode::new_root(values)),
}
}
pub fn new(&self, values: Vec<OwnedKeyValue>) -> Logger {
Logger {
drain: self.drain.clone(),
values: Arc::new(OwnedKeyValueNode::new(values, self.values.clone())),
}
}
pub fn log(&self, record: &RecordInfo) {
TL_BUF.with(|buf| {
let mut buf = buf.borrow_mut();
let _ = self.drain.log(&mut *buf, &record, &*self.values);
debug_assert!(buf.is_empty());
});
}
}
pub struct RecordInfo<'a> {
ts: RefCell<Option<chrono::DateTime<chrono::UTC>>>,
level: Level,
msg: &'a IntoMsg,
file: &'a str,
line: u32,
module: &'a str,
values: &'a [BorrowedKeyValue<'a>],
}
impl<'a> RecordInfo<'a> {
#[inline]
pub fn new(level: Level,
msg: &'a IntoMsg,
file: &'a str,
line: u32,
module: &'a str,
values: &'a [BorrowedKeyValue<'a>])
-> Self {
RecordInfo {
ts: RefCell::new(None),
level: level,
msg: msg,
file: file,
line: line,
module: module,
values: values,
}
}
pub fn ts(&self) -> chrono::DateTime<chrono::UTC> {
let mut ts = self.ts.borrow_mut();
match *ts {
None => {
let now = chrono::UTC::now();
*ts = Some(now);
now
}
Some(ts) => ts,
}
}
pub fn set_ts(&self, ts: chrono::DateTime<chrono::UTC>) {
*self.ts.borrow_mut() = Some(ts);
}
pub fn msg(&self) -> Cow<str> {
self.msg.as_str()
}
pub fn level(&self) -> Level {
self.level
}
pub fn line(&self) -> u32 {
self.line
}
pub fn file(&self) -> &str {
self.file
}
pub fn module(&self) -> &str {
self.module
}
pub fn values(&self) -> &'a [BorrowedKeyValue<'a>] {
self.values
}
}