1use std::error::Error;
4use std::fmt::Debug;
5
6use tracing::field::Field;
7use tracing_subscriber::field::{RecordFields, Visit, VisitOutput};
8use tracing_subscriber::fmt::format::{DefaultVisitor, FormatFields, Writer};
9
10struct ErrorVisitor<'a>(&'a mut dyn Visit);
12
13#[allow(clippy::semicolon_if_nothing_returned)]
16impl<'a> Visit for ErrorVisitor<'a> {
17 fn record_debug(&mut self, _field: &Field, _value: &dyn Debug) {}
19 fn record_f64(&mut self, _field: &Field, _value: f64) {}
20 fn record_i64(&mut self, _field: &Field, _value: i64) {}
21 fn record_u64(&mut self, _field: &Field, _value: u64) {}
22 fn record_i128(&mut self, _field: &Field, _value: i128) {}
23 fn record_u128(&mut self, _field: &Field, _value: u128) {}
24 fn record_bool(&mut self, _field: &Field, _value: bool) {}
25 fn record_str(&mut self, _field: &Field, _value: &str) {}
26 fn record_bytes(&mut self, _field: &Field, _value: &[u8]) {}
27
28 fn record_error(&mut self, field: &Field, value: &(dyn Error + 'static)) {
30 use std::fmt;
31 use tor_error::ErrorReport as _;
32
33 struct DisplayToDebug<T: fmt::Display>(T);
35
36 impl<T: fmt::Display> fmt::Debug for DisplayToDebug<T> {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 fmt::Display::fmt(&self.0, f)
39 }
40 }
41
42 self.0.record_debug(field, &DisplayToDebug(value.report()))
44 }
45}
46
47struct NonErrorVisitor<'a>(&'a mut dyn Visit);
49
50#[allow(clippy::semicolon_if_nothing_returned)]
53impl<'a> Visit for NonErrorVisitor<'a> {
54 fn record_debug(&mut self, field: &Field, value: &dyn Debug) {
56 self.0.record_debug(field, value)
57 }
58 fn record_f64(&mut self, field: &Field, value: f64) {
59 self.0.record_f64(field, value)
60 }
61 fn record_i64(&mut self, field: &Field, value: i64) {
62 self.0.record_i64(field, value)
63 }
64 fn record_u64(&mut self, field: &Field, value: u64) {
65 self.0.record_u64(field, value)
66 }
67 fn record_i128(&mut self, field: &Field, value: i128) {
68 self.0.record_i128(field, value)
69 }
70 fn record_u128(&mut self, field: &Field, value: u128) {
71 self.0.record_u128(field, value)
72 }
73 fn record_bool(&mut self, field: &Field, value: bool) {
74 self.0.record_bool(field, value)
75 }
76 fn record_str(&mut self, field: &Field, value: &str) {
77 self.0.record_str(field, value)
78 }
79 fn record_bytes(&mut self, field: &Field, value: &[u8]) {
80 self.0.record_bytes(field, value)
81 }
82
83 fn record_error(&mut self, _field: &Field, _value: &(dyn Error + 'static)) {}
85}
86
87pub(crate) struct ErrorsLastFieldFormatter;
89
90impl<'writer> FormatFields<'writer> for ErrorsLastFieldFormatter {
91 fn format_fields<R: RecordFields>(
92 &self,
93 mut writer: Writer<'writer>,
94 fields: R,
95 ) -> std::fmt::Result {
96 let mut visitor = DefaultVisitor::new(writer.by_ref(), true);
98
99 fields.record(&mut NonErrorVisitor(&mut visitor));
101 fields.record(&mut ErrorVisitor(&mut visitor));
102
103 visitor.finish()?;
104
105 Ok(())
106 }
107}