1 use super::*; 2 use crate::{ 3 field::{VisitFmt, VisitOutput}, 4 fmt::fmt_layer::{FmtContext, FormattedFields}, 5 registry::LookupSpan, 6 }; 7 8 use std::fmt; 9 use tracing_core::{ 10 field::{self, Field}, 11 Event, Level, Subscriber, 12 }; 13 14 #[cfg(feature = "tracing-log")] 15 use tracing_log::NormalizeEvent; 16 17 use ansi_term::{Colour, Style}; 18 19 /// An excessively pretty, human-readable event formatter. 20 /// 21 /// Unlike the [`Full`], [`Compact`], and [`Json`] formatters, this is a 22 /// multi-line output format. Each individual event may output multiple lines of 23 /// text. 24 /// 25 /// # Example Output 26 /// 27 /// <pre><font color="#4E9A06"><b>:;</b></font> <font color="#4E9A06">cargo</font> run --example fmt-pretty 28 /// <font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 0.08s 29 /// <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt-pretty` 30 /// 2022-02-15T18:44:24.535324Z <font color="#4E9A06"> INFO</font> <font color="#4E9A06"><b>fmt_pretty</b></font><font color="#4E9A06">: preparing to shave yaks, </font><font color="#4E9A06"><b>number_of_yaks</b></font><font color="#4E9A06">: 3</font> 31 /// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt-pretty.rs:16 <font color="#AAAAAA"><i>on</i></font> main 32 /// 33 /// 2022-02-15T18:44:24.535403Z <font color="#4E9A06"> INFO</font> <font color="#4E9A06"><b>fmt_pretty::yak_shave</b></font><font color="#4E9A06">: shaving yaks</font> 34 /// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:41 <font color="#AAAAAA"><i>on</i></font> main 35 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 36 /// 37 /// 2022-02-15T18:44:24.535442Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: hello! I'm gonna shave a yak, </font><font color="#75507B"><b>excitement</b></font><font color="#75507B">: "yay!"</font> 38 /// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:16 <font color="#AAAAAA"><i>on</i></font> main 39 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 1 40 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 41 /// 42 /// 2022-02-15T18:44:24.535469Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: yak shaved successfully</font> 43 /// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:25 <font color="#AAAAAA"><i>on</i></font> main 44 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 1 45 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 46 /// 47 /// 2022-02-15T18:44:24.535502Z <font color="#3465A4">DEBUG</font> <font color="#3465A4"><b>yak_events</b></font><font color="#3465A4">: </font><font color="#3465A4"><b>yak</b></font><font color="#3465A4">: 1, </font><font color="#3465A4"><b>shaved</b></font><font color="#3465A4">: true</font> 48 /// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:46 <font color="#AAAAAA"><i>on</i></font> main 49 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 50 /// 51 /// 2022-02-15T18:44:24.535524Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: </font><font color="#75507B"><b>yaks_shaved</b></font><font color="#75507B">: 1</font> 52 /// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:55 <font color="#AAAAAA"><i>on</i></font> main 53 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 54 /// 55 /// 2022-02-15T18:44:24.535551Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: hello! I'm gonna shave a yak, </font><font color="#75507B"><b>excitement</b></font><font color="#75507B">: "yay!"</font> 56 /// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:16 <font color="#AAAAAA"><i>on</i></font> main 57 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 2 58 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 59 /// 60 /// 2022-02-15T18:44:24.535573Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: yak shaved successfully</font> 61 /// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:25 <font color="#AAAAAA"><i>on</i></font> main 62 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 2 63 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 64 /// 65 /// 2022-02-15T18:44:24.535600Z <font color="#3465A4">DEBUG</font> <font color="#3465A4"><b>yak_events</b></font><font color="#3465A4">: </font><font color="#3465A4"><b>yak</b></font><font color="#3465A4">: 2, </font><font color="#3465A4"><b>shaved</b></font><font color="#3465A4">: true</font> 66 /// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:46 <font color="#AAAAAA"><i>on</i></font> main 67 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 68 /// 69 /// 2022-02-15T18:44:24.535618Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: </font><font color="#75507B"><b>yaks_shaved</b></font><font color="#75507B">: 2</font> 70 /// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:55 <font color="#AAAAAA"><i>on</i></font> main 71 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 72 /// 73 /// 2022-02-15T18:44:24.535644Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: hello! I'm gonna shave a yak, </font><font color="#75507B"><b>excitement</b></font><font color="#75507B">: "yay!"</font> 74 /// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:16 <font color="#AAAAAA"><i>on</i></font> main 75 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 3 76 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 77 /// 78 /// 2022-02-15T18:44:24.535670Z <font color="#C4A000"> WARN</font> <font color="#C4A000"><b>fmt_pretty::yak_shave</b></font><font color="#C4A000">: could not locate yak</font> 79 /// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:18 <font color="#AAAAAA"><i>on</i></font> main 80 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 3 81 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 82 /// 83 /// 2022-02-15T18:44:24.535698Z <font color="#3465A4">DEBUG</font> <font color="#3465A4"><b>yak_events</b></font><font color="#3465A4">: </font><font color="#3465A4"><b>yak</b></font><font color="#3465A4">: 3, </font><font color="#3465A4"><b>shaved</b></font><font color="#3465A4">: false</font> 84 /// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:46 <font color="#AAAAAA"><i>on</i></font> main 85 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 86 /// 87 /// 2022-02-15T18:44:24.535720Z <font color="#CC0000">ERROR</font> <font color="#CC0000"><b>fmt_pretty::yak_shave</b></font><font color="#CC0000">: failed to shave yak, </font><font color="#CC0000"><b>yak</b></font><font color="#CC0000">: 3, </font><font color="#CC0000"><b>error</b></font><font color="#CC0000">: missing yak, </font><font color="#CC0000"><b>error.sources</b></font><font color="#CC0000">: [out of space, out of cash]</font> 88 /// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:51 <font color="#AAAAAA"><i>on</i></font> main 89 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 90 /// 91 /// 2022-02-15T18:44:24.535742Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: </font><font color="#75507B"><b>yaks_shaved</b></font><font color="#75507B">: 2</font> 92 /// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:55 <font color="#AAAAAA"><i>on</i></font> main 93 /// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3 94 /// 95 /// 2022-02-15T18:44:24.535765Z <font color="#4E9A06"> INFO</font> <font color="#4E9A06"><b>fmt_pretty</b></font><font color="#4E9A06">: yak shaving completed, </font><font color="#4E9A06"><b>all_yaks_shaved</b></font><font color="#4E9A06">: false</font> 96 /// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt-pretty.rs:19 <font color="#AAAAAA"><i>on</i></font> main 97 /// </pre> 98 #[derive(Debug, Clone, Eq, PartialEq)] 99 pub struct Pretty { 100 display_location: bool, 101 } 102 103 /// The [visitor] produced by [`Pretty`]'s [`MakeVisitor`] implementation. 104 /// 105 /// [visitor]: field::Visit 106 /// [`MakeVisitor`]: crate::field::MakeVisitor 107 #[derive(Debug)] 108 pub struct PrettyVisitor<'a> { 109 writer: Writer<'a>, 110 is_empty: bool, 111 style: Style, 112 result: fmt::Result, 113 } 114 115 /// An excessively pretty, human-readable [`MakeVisitor`] implementation. 116 /// 117 /// [`MakeVisitor`]: crate::field::MakeVisitor 118 #[derive(Debug)] 119 pub struct PrettyFields { 120 /// A value to override the provided `Writer`'s ANSI formatting 121 /// configuration. 122 /// 123 /// If this is `Some`, we override the `Writer`'s ANSI setting. This is 124 /// necessary in order to continue supporting the deprecated 125 /// `PrettyFields::with_ansi` method. If it is `None`, we don't override the 126 /// ANSI formatting configuration (because the deprecated method was not 127 /// called). 128 // TODO: when `PrettyFields::with_ansi` is removed, we can get rid 129 // of this entirely. 130 ansi: Option<bool>, 131 } 132 133 // === impl Pretty === 134 135 impl Default for Pretty { default() -> Self136 fn default() -> Self { 137 Self { 138 display_location: true, 139 } 140 } 141 } 142 143 impl Pretty { style_for(level: &Level) -> Style144 fn style_for(level: &Level) -> Style { 145 match *level { 146 Level::TRACE => Style::new().fg(Colour::Purple), 147 Level::DEBUG => Style::new().fg(Colour::Blue), 148 Level::INFO => Style::new().fg(Colour::Green), 149 Level::WARN => Style::new().fg(Colour::Yellow), 150 Level::ERROR => Style::new().fg(Colour::Red), 151 } 152 } 153 154 /// Sets whether the event's source code location is displayed. 155 /// 156 /// This defaults to `true`. 157 #[deprecated( 158 since = "0.3.6", 159 note = "all formatters now support configurable source locations. Use `Format::with_source_location` instead." 160 )] with_source_location(self, display_location: bool) -> Self161 pub fn with_source_location(self, display_location: bool) -> Self { 162 Self { 163 display_location, 164 ..self 165 } 166 } 167 } 168 169 impl<C, N, T> FormatEvent<C, N> for Format<Pretty, T> 170 where 171 C: Subscriber + for<'a> LookupSpan<'a>, 172 N: for<'a> FormatFields<'a> + 'static, 173 T: FormatTime, 174 { format_event( &self, ctx: &FmtContext<'_, C, N>, mut writer: Writer<'_>, event: &Event<'_>, ) -> fmt::Result175 fn format_event( 176 &self, 177 ctx: &FmtContext<'_, C, N>, 178 mut writer: Writer<'_>, 179 event: &Event<'_>, 180 ) -> fmt::Result { 181 #[cfg(feature = "tracing-log")] 182 let normalized_meta = event.normalized_metadata(); 183 #[cfg(feature = "tracing-log")] 184 let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); 185 #[cfg(not(feature = "tracing-log"))] 186 let meta = event.metadata(); 187 write!(&mut writer, " ")?; 188 189 // if the `Format` struct *also* has an ANSI color configuration, 190 // override the writer...the API for configuring ANSI color codes on the 191 // `Format` struct is deprecated, but we still need to honor those 192 // configurations. 193 if let Some(ansi) = self.ansi { 194 writer = writer.with_ansi(ansi); 195 } 196 197 self.format_timestamp(&mut writer)?; 198 199 let style = if self.display_level && writer.has_ansi_escapes() { 200 Pretty::style_for(meta.level()) 201 } else { 202 Style::new() 203 }; 204 205 if self.display_level { 206 write!( 207 writer, 208 "{} ", 209 super::FmtLevel::new(meta.level(), writer.has_ansi_escapes()) 210 )?; 211 } 212 213 if self.display_target { 214 let target_style = if writer.has_ansi_escapes() { 215 style.bold() 216 } else { 217 style 218 }; 219 write!( 220 writer, 221 "{}{}{}:", 222 target_style.prefix(), 223 meta.target(), 224 target_style.infix(style) 225 )?; 226 } 227 let line_number = if self.display_line_number { 228 meta.line() 229 } else { 230 None 231 }; 232 233 // If the file name is disabled, format the line number right after the 234 // target. Otherwise, if we also display the file, it'll go on a 235 // separate line. 236 if let (Some(line_number), false, true) = ( 237 line_number, 238 self.display_filename, 239 self.format.display_location, 240 ) { 241 write!( 242 writer, 243 "{}{}{}:", 244 style.prefix(), 245 line_number, 246 style.infix(style) 247 )?; 248 } 249 250 writer.write_char(' ')?; 251 252 let mut v = PrettyVisitor::new(writer.by_ref(), true).with_style(style); 253 event.record(&mut v); 254 v.finish()?; 255 writer.write_char('\n')?; 256 257 let dimmed = if writer.has_ansi_escapes() { 258 Style::new().dimmed().italic() 259 } else { 260 Style::new() 261 }; 262 let thread = self.display_thread_name || self.display_thread_id; 263 264 if let (Some(file), true, true) = ( 265 meta.file(), 266 self.format.display_location, 267 self.display_filename, 268 ) { 269 write!(writer, " {} {}", dimmed.paint("at"), file,)?; 270 271 if let Some(line) = line_number { 272 write!(writer, ":{}", line)?; 273 } 274 writer.write_char(if thread { ' ' } else { '\n' })?; 275 } else if thread { 276 write!(writer, " ")?; 277 }; 278 279 if thread { 280 write!(writer, "{} ", dimmed.paint("on"))?; 281 let thread = std::thread::current(); 282 if self.display_thread_name { 283 if let Some(name) = thread.name() { 284 write!(writer, "{}", name)?; 285 if self.display_thread_id { 286 writer.write_char(' ')?; 287 } 288 } 289 } 290 if self.display_thread_id { 291 write!(writer, "{:?}", thread.id())?; 292 } 293 writer.write_char('\n')?; 294 } 295 296 let bold = writer.bold(); 297 let span = event 298 .parent() 299 .and_then(|id| ctx.span(id)) 300 .or_else(|| ctx.lookup_current()); 301 302 let scope = span.into_iter().flat_map(|span| span.scope()); 303 304 for span in scope { 305 let meta = span.metadata(); 306 if self.display_target { 307 write!( 308 writer, 309 " {} {}::{}", 310 dimmed.paint("in"), 311 meta.target(), 312 bold.paint(meta.name()), 313 )?; 314 } else { 315 write!( 316 writer, 317 " {} {}", 318 dimmed.paint("in"), 319 bold.paint(meta.name()), 320 )?; 321 } 322 323 let ext = span.extensions(); 324 let fields = &ext 325 .get::<FormattedFields<N>>() 326 .expect("Unable to find FormattedFields in extensions; this is a bug"); 327 if !fields.is_empty() { 328 write!(writer, " {} {}", dimmed.paint("with"), fields)?; 329 } 330 writer.write_char('\n')?; 331 } 332 333 writer.write_char('\n') 334 } 335 } 336 337 impl<'writer> FormatFields<'writer> for Pretty { format_fields<R: RecordFields>(&self, writer: Writer<'writer>, fields: R) -> fmt::Result338 fn format_fields<R: RecordFields>(&self, writer: Writer<'writer>, fields: R) -> fmt::Result { 339 let mut v = PrettyVisitor::new(writer, true); 340 fields.record(&mut v); 341 v.finish() 342 } 343 add_fields( &self, current: &'writer mut FormattedFields<Self>, fields: &span::Record<'_>, ) -> fmt::Result344 fn add_fields( 345 &self, 346 current: &'writer mut FormattedFields<Self>, 347 fields: &span::Record<'_>, 348 ) -> fmt::Result { 349 let empty = current.is_empty(); 350 let writer = current.as_writer(); 351 let mut v = PrettyVisitor::new(writer, empty); 352 fields.record(&mut v); 353 v.finish() 354 } 355 } 356 357 // === impl PrettyFields === 358 359 impl Default for PrettyFields { default() -> Self360 fn default() -> Self { 361 Self::new() 362 } 363 } 364 365 impl PrettyFields { 366 /// Returns a new default [`PrettyFields`] implementation. new() -> Self367 pub fn new() -> Self { 368 // By default, don't override the `Writer`'s ANSI colors 369 // configuration. We'll only do this if the user calls the 370 // deprecated `PrettyFields::with_ansi` method. 371 Self { ansi: None } 372 } 373 374 /// Enable ANSI encoding for formatted fields. 375 #[deprecated( 376 since = "0.3.3", 377 note = "Use `fmt::Subscriber::with_ansi` or `fmt::Layer::with_ansi` instead." 378 )] with_ansi(self, ansi: bool) -> Self379 pub fn with_ansi(self, ansi: bool) -> Self { 380 Self { 381 ansi: Some(ansi), 382 ..self 383 } 384 } 385 } 386 387 impl<'a> MakeVisitor<Writer<'a>> for PrettyFields { 388 type Visitor = PrettyVisitor<'a>; 389 390 #[inline] make_visitor(&self, mut target: Writer<'a>) -> Self::Visitor391 fn make_visitor(&self, mut target: Writer<'a>) -> Self::Visitor { 392 if let Some(ansi) = self.ansi { 393 target = target.with_ansi(ansi); 394 } 395 PrettyVisitor::new(target, true) 396 } 397 } 398 399 // === impl PrettyVisitor === 400 401 impl<'a> PrettyVisitor<'a> { 402 /// Returns a new default visitor that formats to the provided `writer`. 403 /// 404 /// # Arguments 405 /// - `writer`: the writer to format to. 406 /// - `is_empty`: whether or not any fields have been previously written to 407 /// that writer. new(writer: Writer<'a>, is_empty: bool) -> Self408 pub fn new(writer: Writer<'a>, is_empty: bool) -> Self { 409 Self { 410 writer, 411 is_empty, 412 style: Style::default(), 413 result: Ok(()), 414 } 415 } 416 with_style(self, style: Style) -> Self417 pub(crate) fn with_style(self, style: Style) -> Self { 418 Self { style, ..self } 419 } 420 write_padded(&mut self, value: &impl fmt::Debug)421 fn write_padded(&mut self, value: &impl fmt::Debug) { 422 let padding = if self.is_empty { 423 self.is_empty = false; 424 "" 425 } else { 426 ", " 427 }; 428 self.result = write!(self.writer, "{}{:?}", padding, value); 429 } 430 bold(&self) -> Style431 fn bold(&self) -> Style { 432 if self.writer.has_ansi_escapes() { 433 self.style.bold() 434 } else { 435 Style::new() 436 } 437 } 438 } 439 440 impl<'a> field::Visit for PrettyVisitor<'a> { record_str(&mut self, field: &Field, value: &str)441 fn record_str(&mut self, field: &Field, value: &str) { 442 if self.result.is_err() { 443 return; 444 } 445 446 if field.name() == "message" { 447 self.record_debug(field, &format_args!("{}", value)) 448 } else { 449 self.record_debug(field, &value) 450 } 451 } 452 record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static))453 fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) { 454 if let Some(source) = value.source() { 455 let bold = self.bold(); 456 self.record_debug( 457 field, 458 &format_args!( 459 "{}, {}{}.sources{}: {}", 460 value, 461 bold.prefix(), 462 field, 463 bold.infix(self.style), 464 ErrorSourceList(source), 465 ), 466 ) 467 } else { 468 self.record_debug(field, &format_args!("{}", value)) 469 } 470 } 471 record_debug(&mut self, field: &Field, value: &dyn fmt::Debug)472 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { 473 if self.result.is_err() { 474 return; 475 } 476 let bold = self.bold(); 477 match field.name() { 478 "message" => self.write_padded(&format_args!("{}{:?}", self.style.prefix(), value,)), 479 // Skip fields that are actually log metadata that have already been handled 480 #[cfg(feature = "tracing-log")] 481 name if name.starts_with("log.") => self.result = Ok(()), 482 name if name.starts_with("r#") => self.write_padded(&format_args!( 483 "{}{}{}: {:?}", 484 bold.prefix(), 485 &name[2..], 486 bold.infix(self.style), 487 value 488 )), 489 name => self.write_padded(&format_args!( 490 "{}{}{}: {:?}", 491 bold.prefix(), 492 name, 493 bold.infix(self.style), 494 value 495 )), 496 }; 497 } 498 } 499 500 impl<'a> VisitOutput<fmt::Result> for PrettyVisitor<'a> { finish(mut self) -> fmt::Result501 fn finish(mut self) -> fmt::Result { 502 write!(&mut self.writer, "{}", self.style.suffix())?; 503 self.result 504 } 505 } 506 507 impl<'a> VisitFmt for PrettyVisitor<'a> { writer(&mut self) -> &mut dyn fmt::Write508 fn writer(&mut self) -> &mut dyn fmt::Write { 509 &mut self.writer 510 } 511 } 512