use std::fmt;
use std::time::Instant;
use tracing::{Event, Subscriber};
use tracing_subscriber::EnvFilter;
use tracing_subscriber::fmt::format::Writer;
use tracing_subscriber::fmt::{FmtContext, FormatEvent, FormatFields};
use tracing_subscriber::registry::LookupSpan;
pub(crate) fn init() {
let filter = EnvFilter::from_default_env();
if std::env::var("LSPF_LOG_FORMAT").as_deref() == Ok("json") {
tracing_subscriber::fmt()
.with_writer(std::io::stderr)
.with_env_filter(filter)
.json()
.flatten_event(true)
.with_current_span(true)
.with_span_list(false)
.init();
return;
}
tracing_subscriber::fmt()
.with_writer(std::io::stderr)
.with_env_filter(filter)
.with_ansi(false)
.event_format(Text::new())
.init();
}
struct Text {
start: Instant,
}
impl Text {
fn new() -> Self {
Self {
start: Instant::now(),
}
}
}
impl<S, N> FormatEvent<S, N> for Text
where
S: Subscriber + for<'a> LookupSpan<'a>,
N: for<'a> FormatFields<'a> + 'static,
{
fn format_event(
&self,
ctx: &FmtContext<'_, S, N>,
mut writer: Writer<'_>,
event: &Event<'_>,
) -> fmt::Result {
write!(
writer,
"{:>8.3}s {:<5} ",
self.start.elapsed().as_secs_f64(),
event.metadata().level(),
)?;
if let Some(scope) = ctx.event_scope() {
let mut seen = false;
for span in scope.from_root() {
write!(writer, "{}:", span.metadata().name())?;
seen = true;
}
if seen {
writer.write_char(' ')?;
}
}
ctx.format_fields(writer.by_ref(), event)?;
writeln!(writer)
}
}