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