diff --git a/src/core/debug.rs b/src/core/debug.rs index 123cf820..c904f23c 100644 --- a/src/core/debug.rs +++ b/src/core/debug.rs @@ -17,7 +17,7 @@ pub use crate::{result::DebugInspect, utils::debug::*}; macro_rules! debug_event { ( $level:expr, $($x:tt)+ ) => { if $crate::debug::logging() { - ::tracing::event!( $level, $($x)+ ) + ::tracing::event!( $level, _debug = true, $($x)+ ) } else { ::tracing::debug!( $($x)+ ) } diff --git a/src/core/log/console.rs b/src/core/log/console.rs new file mode 100644 index 00000000..0bc44fa7 --- /dev/null +++ b/src/core/log/console.rs @@ -0,0 +1,94 @@ +use tracing::{ + field::{Field, Visit}, + Event, Level, Subscriber, +}; +use tracing_subscriber::{ + field::RecordFields, + fmt, + fmt::{ + format::{Compact, DefaultVisitor, Format, Full, Pretty, Writer}, + FmtContext, FormatEvent, FormatFields, + }, + registry::LookupSpan, +}; + +use crate::{Config, Result}; + +pub struct ConsoleFormat { + _compact: Format, + full: Format, + pretty: Format, +} + +struct ConsoleVisitor<'a> { + visitor: DefaultVisitor<'a>, +} + +impl ConsoleFormat { + #[must_use] + pub fn new(config: &Config) -> Self { + Self { + _compact: fmt::format().compact(), + + full: Format::::default() + .with_thread_ids(config.log_thread_ids) + .with_ansi(config.log_colors), + + pretty: fmt::format() + .pretty() + .with_ansi(config.log_colors) + .with_thread_names(true) + .with_thread_ids(true) + .with_target(true) + .with_file(true) + .with_line_number(true) + .with_source_location(true), + } + } +} + +impl FormatEvent for ConsoleFormat +where + S: Subscriber + for<'a> LookupSpan<'a>, + N: for<'a> FormatFields<'a> + 'static, +{ + fn format_event( + &self, + ctx: &FmtContext<'_, S, N>, + writer: Writer<'_>, + event: &Event<'_>, + ) -> Result<(), std::fmt::Error> { + let is_debug = + cfg!(debug_assertions) && event.fields().any(|field| field.name() == "_debug"); + + match *event.metadata().level() { + | Level::ERROR if !is_debug => self.pretty.format_event(ctx, writer, event), + | _ => self.full.format_event(ctx, writer, event), + } + } +} + +impl<'writer> FormatFields<'writer> for ConsoleFormat { + fn format_fields(&self, writer: Writer<'writer>, fields: R) -> Result<(), std::fmt::Error> + where + R: RecordFields, + { + let mut visitor = ConsoleVisitor { + visitor: DefaultVisitor::<'_>::new(writer, true), + }; + + fields.record(&mut visitor); + + Ok(()) + } +} + +impl Visit for ConsoleVisitor<'_> { + fn record_debug(&mut self, field: &Field, value: &dyn std::fmt::Debug) { + if field.name().starts_with('_') { + return; + } + + self.visitor.record_debug(field, value); + } +} diff --git a/src/core/log/mod.rs b/src/core/log/mod.rs index 48b7f0f3..0c51a383 100644 --- a/src/core/log/mod.rs +++ b/src/core/log/mod.rs @@ -2,12 +2,14 @@ pub mod capture; pub mod color; +mod console; pub mod fmt; pub mod fmt_span; mod reload; mod suppress; pub use capture::Capture; +pub use console::ConsoleFormat; pub use reload::{LogLevelReloadHandles, ReloadHandle}; pub use suppress::Suppress; pub use tracing::Level; diff --git a/src/main/logging.rs b/src/main/logging.rs index e8a18b10..85945e8a 100644 --- a/src/main/logging.rs +++ b/src/main/logging.rs @@ -3,11 +3,11 @@ use std::sync::Arc; use conduwuit::{ config::Config, debug_warn, err, - log::{capture, fmt_span, LogLevelReloadHandles}, + log::{capture, fmt_span, ConsoleFormat, LogLevelReloadHandles}, result::UnwrapOrErr, Result, }; -use tracing_subscriber::{layer::SubscriberExt, reload, EnvFilter, Layer, Registry}; +use tracing_subscriber::{fmt, layer::SubscriberExt, reload, EnvFilter, Layer, Registry}; #[cfg(feature = "perf_measurements")] pub(crate) type TracingFlameGuard = @@ -26,10 +26,12 @@ pub(crate) fn init( .with_regex(config.log_filter_regex) .parse(&config.log) .map_err(|e| err!(Config("log", "{e}.")))?; - let console_layer = tracing_subscriber::fmt::Layer::new() - .with_ansi(config.log_colors) + let console_layer = fmt::Layer::new() .with_span_events(console_span_events) - .with_thread_ids(config.log_thread_ids); + .event_format(ConsoleFormat::new(config)) + .fmt_fields(ConsoleFormat::new(config)) + .map_writer(|w| w); + let (console_reload_filter, console_reload_handle) = reload::Layer::new(console_filter.clone()); reload_handles.add("console", Box::new(console_reload_handle));