use time;
use std::io::Write;
use std::fmt::Display;
use std::collections::HashMap;
use Priority;
use errors::*;
use facility::Facility;
#[allow(non_camel_case_types)]
#[derive(Copy,Clone)]
pub enum Severity {
LOG_EMERG,
LOG_ALERT,
LOG_CRIT,
LOG_ERR,
LOG_WARNING,
LOG_NOTICE,
LOG_INFO,
LOG_DEBUG
}
pub trait LogFormat<T> {
fn format<W: Write>(&self, w: &mut W, severity: Severity, message: T) -> Result<()>;
fn emerg<W: Write>(&mut self, w: &mut W, message: T) -> Result<()> {
self.format(w, Severity::LOG_EMERG, message)
}
fn alert<W: Write>(&mut self, w: &mut W, message: T) -> Result<()> {
self.format(w, Severity::LOG_ALERT, message)
}
fn crit<W: Write>(&mut self, w: &mut W, message: T) -> Result<()> {
self.format(w, Severity::LOG_CRIT, message)
}
fn err<W: Write>(&mut self, w: &mut W, message: T) -> Result<()> {
self.format(w, Severity::LOG_ERR, message)
}
fn warning<W: Write>(&mut self, w: &mut W, message: T) -> Result<()> {
self.format(w, Severity::LOG_WARNING, message)
}
fn notice<W: Write>(&mut self, w: &mut W, message: T) -> Result<()> {
self.format(w, Severity::LOG_NOTICE, message)
}
fn info<W: Write>(&mut self, w: &mut W, message: T) -> Result<()> {
self.format(w, Severity::LOG_INFO, message)
}
fn debug<W: Write>(&mut self, w: &mut W, message: T) -> Result<()> {
self.format(w, Severity::LOG_DEBUG, message)
}
}
#[derive(Clone,Debug)]
pub struct Formatter3164 {
pub facility: Facility,
pub hostname: Option<String>,
pub process: String,
pub pid: i32,
}
impl<T: Display> LogFormat<T> for Formatter3164 {
fn format<W: Write>(&self, w: &mut W, severity: Severity, message: T) -> Result<()> {
if let Some(ref hostname) = self.hostname {
write!(w, "<{}>{} {} {}[{}]: {}",
encode_priority(severity, self.facility),
time::now().strftime("%b %d %T").unwrap(),
hostname, self.process, self.pid, message).chain_err(|| ErrorKind::Format)
} else {
write!(w, "<{}>{} {}[{}]: {}",
encode_priority(severity, self.facility),
time::now().strftime("%b %d %T").unwrap(),
self.process, self.pid, message).chain_err(|| ErrorKind::Format)
}
}
}
pub type StructuredData = HashMap<String, HashMap<String, String>>;
#[derive(Clone,Debug)]
pub struct Formatter5424 {
pub facility: Facility,
pub hostname: Option<String>,
pub process: String,
pub pid: i32,
}
impl Formatter5424 {
pub fn format_5424_structured_data(&self, data: StructuredData) -> String {
if data.is_empty() {
"-".to_string()
} else {
let mut res = String::new();
for (id, params) in &data {
res = res + "["+id;
for (name,value) in params {
res = res + " " + name + "=\"" + value + "\"";
}
res += "]";
}
res
}
}
}
impl<T: Display> LogFormat<(i32, StructuredData, T)> for Formatter5424 {
fn format<W: Write>(&self, w: &mut W, severity: Severity, log_message: (i32, StructuredData, T)) -> Result<()> {
let (message_id, data, message) = log_message;
write!(w, "<{}> {} {} {} {} {} {} {} {}",
encode_priority(severity, self.facility),
1,
time::now_utc().rfc3339(),
self.hostname.as_ref().map(|x| &x[..]).unwrap_or("localhost"),
self.process, self.pid, message_id,
self.format_5424_structured_data(data), message).chain_err(|| ErrorKind::Format)
}
}
fn encode_priority(severity: Severity, facility: Facility) -> Priority {
facility as u8 | severity as u8
}