use chrono::{DateTime, Utc};
use std::{fmt, time::SystemTime};
use tracing_core::{Event, Subscriber};
use tracing_subscriber::fmt::{
format::{self, FormatEvent, FormatFields},
FmtContext, FormattedFields,
};
use tracing_subscriber::registry::LookupSpan;
fn format_time(time: SystemTime) -> String {
let datetime: DateTime<Utc> = time.into();
datetime.format("%Y-%m-%d %H:%M:%S").to_string()
}
pub struct LogsFileFormatter;
impl<S, N> FormatEvent<S, N> for LogsFileFormatter
where
S: Subscriber + for<'a> LookupSpan<'a>,
N: for<'a> FormatFields<'a> + 'static,
{
fn format_event(
&self,
ctx: &FmtContext<'_, S, N>,
mut writer: format::Writer<'_>,
event: &Event<'_>,
) -> fmt::Result {
let metadata = event.metadata();
let time = SystemTime::now();
write!(
&mut writer,
"[{}] [{}] {}: ",
format_time(time),
metadata.level(),
metadata.target()
)?;
if let Some(scope) = ctx.event_scope() {
for span in scope.from_root() {
write!(writer, "{}", span.name())?;
let ext = span.extensions();
let fields = &ext
.get::<FormattedFields<N>>()
.expect("will never be `None`");
if !fields.is_empty() {
write!(writer, "{{{}}}", fields)?;
}
write!(writer, ": ")?;
}
}
ctx.field_format().format_fields(writer.by_ref(), event)?;
writeln!(writer)
}
}