use super::Format;
use super::Level;
use chrono::{Datelike, Timelike};
use serde::Serialize;
use serde_json;
use std::fmt;
use std::fmt::{Debug, Display, Formatter};
use std::io::Write;
const TIME_COLOR: Color = Color::BrightBlack;
const SRC_COLOR: Color = Color::White;
const MSG_COLOR: Color = Color::BrightWhite;
const KEY_COLOR: Color = Color::Cyan;
const VALUE_COLOR: Color = Color::BrightCyan;
#[allow(dead_code)]
enum Color {
Black,
Red,
Green,
Yellow,
Blue,
Magenta,
Cyan,
White,
BrightBlack,
BrightRed,
BrightGreen,
BrightYellow,
BrightBlue,
BrightMagenta,
BrightCyan,
BrightWhite,
Reset,
}
impl Display for Color {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
formatter.write_str(match self {
Color::Black => "\x1b[0m\x1b[30m",
Color::Red => "\x1b[0m\x1b[31m",
Color::Green => "\x1b[0m\x1b[32m",
Color::Yellow => "\x1b[0m\x1b[33m",
Color::Blue => "\x1b[0m\x1b[34m",
Color::Magenta => "\x1b[0m\x1b[35m",
Color::Cyan => "\x1b[0m\x1b[36m",
Color::White => "\x1b[0m\x1b[37m",
Color::BrightBlack => "\x1b[30;1m",
Color::BrightRed => "\x1b[31;1m",
Color::BrightGreen => "\x1b[32;1m",
Color::BrightYellow => "\x1b[33;1m",
Color::BrightBlue => "\x1b[34;1m",
Color::BrightMagenta => "\x1b[35;1m",
Color::BrightCyan => "\x1b[36;1m",
Color::BrightWhite => "\x1b[37;1m",
Color::Reset => "\x1b[0m",
})
}
}
struct SrcName<'a>(&'a str);
impl<'a> Display for SrcName<'a> {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
if self.0.len() > 0 {
write!(formatter, " [{}]", self.0)?;
}
Ok(())
}
}
impl<'a> Debug for SrcName<'a> {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
write!(formatter, "{:?}", self.0)
}
}
pub fn begin_entry<W: Write>(mut writer: W, format: Format, level: Level, src: &str, msg: &str) {
let time = chrono::Utc::now();
let src = SrcName(src);
match format {
Format::Plain => {
write!(
writer,
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}Z {}{} {}",
time.year(),
time.month(),
time.day(),
time.hour(),
time.minute(),
time.second(),
level,
src,
msg,
)
.expect("could not write entry begin");
}
Format::Color => {
write!(
writer,
"{}{:04}-{:02}-{:02} {:02}:{:02}:{:02} {}{}{}{} {}{}",
TIME_COLOR,
time.year(),
time.month(),
time.day(),
time.hour(),
time.minute(),
time.second(),
color(level),
level,
SRC_COLOR,
src,
MSG_COLOR,
msg,
)
.expect("could not write entry begin");
}
Format::Modern => {
write!(
writer,
"{}{:04}-{:02}-{:02} {:02}:{:02}:{:02} {}{}{}{} {}{}",
TIME_COLOR,
time.year(),
time.month(),
time.day(),
time.hour(),
time.minute(),
time.second(),
color(level),
icon(level),
SRC_COLOR,
src,
MSG_COLOR,
msg,
)
.expect("could not write entry begin");
}
Format::Json => {
write!(
writer,
r#"{{"time":"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}Z","level":"{}","src":{:?},"msg":"#,
time.year(),
time.month(),
time.day(),
time.hour(),
time.minute(),
time.second(),
level,
src,
)
.expect("could not write entry begin");
serde_json::to_writer(&mut writer, msg).expect("could not write entry msg");
}
}
}
pub fn context<V: Serialize>(mut writer: impl Write, format: Format, key: &str, value: &V) {
match format {
Format::Plain => {
write!(writer, " {}:", key);
serde_json::to_writer(writer, value).expect("error serializing context");
}
Format::Color | Format::Modern => {
write!(writer, " {}{}:{}", KEY_COLOR, key, VALUE_COLOR);
serde_json::to_writer(writer, value).expect("error serializing context");
}
Format::Json => {
write!(writer, ",{:?}:", key);
serde_json::to_writer(writer, value).expect("error serializing context");
}
}
}
pub fn context_pretty<V: Serialize>(mut writer: impl Write, format: Format, key: &str, value: &V) {
match format {
Format::Plain => {
write!(writer, "\n{}: ", key);
serde_json::to_writer_pretty(writer, value).expect("error serializing context");
}
Format::Color | Format::Modern => {
write!(writer, "\n{}{}:{} ", KEY_COLOR, key, Color::Reset);
serde_json::to_writer_pretty(writer, value).expect("error serializing context");
}
Format::Json => {
write!(writer, ",{:?}:", key);
serde_json::to_writer(writer, value).expect("error serializing context");
}
}
}
pub fn end_entry<W: Write>(mut writer: W, format: Format) {
match format {
Format::Plain => writeln!(writer),
Format::Color | Format::Modern => writeln!(writer, "{}", Color::Reset),
Format::Json => writeln!(writer, "}}"),
}
.expect("could not write end msg");
}
fn color(level: Level) -> Color {
match level {
Level::Trace => Color::White,
Level::Debug => Color::BrightMagenta,
Level::Info => Color::BrightBlue,
Level::Warn => Color::BrightYellow,
Level::Error => Color::BrightRed,
}
}
fn icon(level: Level) -> &'static str {
match level {
Level::Trace => "…",
Level::Debug => "",
Level::Info => "",
Level::Warn => "",
Level::Error => "",
}
}
pub fn simple_entry<W: Write>(
mut writer: W,
format: Format,
level: Level,
src: &str,
msg: &fmt::Arguments,
) {
let time = chrono::Utc::now();
let src = SrcName(src);
match format {
Format::Plain => {
write!(
writer,
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}Z {}{} {}",
time.year(),
time.month(),
time.day(),
time.hour(),
time.minute(),
time.second(),
level,
src,
msg,
)
.expect("could not write entry begin");
}
Format::Color => {
write!(
writer,
"{}{:04}-{:02}-{:02} {:02}:{:02}:{:02} {}{}{}{} {}{}",
TIME_COLOR,
time.year(),
time.month(),
time.day(),
time.hour(),
time.minute(),
time.second(),
color(level),
level,
SRC_COLOR,
src,
MSG_COLOR,
msg,
)
.expect("could not write entry begin");
}
Format::Modern => {
write!(
writer,
"{}{:04}-{:02}-{:02} {:02}:{:02}:{:02} {}{}{}{} {}{}",
TIME_COLOR,
time.year(),
time.month(),
time.day(),
time.hour(),
time.minute(),
time.second(),
color(level),
icon(level),
SRC_COLOR,
src,
MSG_COLOR,
msg,
)
.expect("could not write entry begin");
}
Format::Json => {
write!(
writer,
r#"{{"time":"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}Z","level":"{}","src":{:?},"msg":"#,
time.year(),
time.month(),
time.day(),
time.hour(),
time.minute(),
time.second(),
level,
src,
)
.expect("could not write entry begin");
serde_json::to_writer(&mut writer, msg).expect("could not write entry msg");
}
};
end_entry(writer, format);
}