sc_tracing/logging/layers/
prefix_layer.rs1use tracing::{span::Attributes, Id, Subscriber};
20use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer};
21
22pub const PREFIX_LOG_SPAN: &str = "substrate-log-prefix";
24
25pub struct PrefixLayer;
30
31impl<S> Layer<S> for PrefixLayer
32where
33 S: Subscriber + for<'a> LookupSpan<'a>,
34{
35 fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
36 let span = match ctx.span(id) {
37 Some(span) => span,
38 None => {
39 debug_assert!(
41 false,
42 "newly created span with ID {:?} did not exist in the registry; this is a bug!",
43 id
44 );
45 return
46 },
47 };
48
49 if span.name() != PREFIX_LOG_SPAN {
50 return
51 }
52
53 let mut extensions = span.extensions_mut();
54
55 if extensions.get_mut::<Prefix>().is_none() {
56 let mut s = String::new();
57 let mut v = PrefixVisitor(&mut s);
58 attrs.record(&mut v);
59
60 if !s.is_empty() {
61 let fmt_fields = Prefix(s);
62 extensions.insert(fmt_fields);
63 }
64 }
65 }
66}
67
68struct PrefixVisitor<'a, W: std::fmt::Write>(&'a mut W);
69
70macro_rules! write_node_name {
71 ($method:ident, $type:ty, $format:expr) => {
72 fn $method(&mut self, field: &tracing::field::Field, value: $type) {
73 if field.name() == "name" {
74 let _ = write!(self.0, $format, value);
75 }
76 }
77 };
78}
79
80impl<'a, W: std::fmt::Write> tracing::field::Visit for PrefixVisitor<'a, W> {
81 write_node_name!(record_debug, &dyn std::fmt::Debug, "[{:?}] ");
82 write_node_name!(record_str, &str, "[{}] ");
83 write_node_name!(record_i64, i64, "[{}] ");
84 write_node_name!(record_u64, u64, "[{}] ");
85 write_node_name!(record_bool, bool, "[{}] ");
86}
87
88#[derive(Debug)]
89pub(crate) struct Prefix(String);
90
91impl Prefix {
92 pub(crate) fn as_str(&self) -> &str {
93 self.0.as_str()
94 }
95}