1use fmt::Display;
2use std::{
3 fmt,
4 io::{self, Write},
5};
6use tracing::{
7 event::Event,
8 field::Field,
9 field::Visit,
10 span::{Attributes, Id, Record},
11 Metadata, Subscriber,
12};
13use tracing_subscriber::{layer::Context, registry::LookupSpan};
14
15use crate::ohos::{OHOSWriter, CappedTag};
16
17pub struct Layer {
22 domain: u16,
23 tag: CappedTag,
24}
25
26impl Layer {
27 pub fn new(domain: u16, tag: &str) -> io::Result<Self> {
29 let tag = CappedTag::new(tag.as_bytes())?;
30 Ok(Self { domain, tag })
31 }
32}
33
34impl<S> tracing_subscriber::Layer<S> for Layer
35where
36 S: Subscriber + for<'span> LookupSpan<'span>,
37{
38 fn on_new_span(&self, attrs: &Attributes, id: &Id, ctx: Context<S>) {
39 let span = ctx.span(id).expect("unknown span");
40 let mut buf = Vec::with_capacity(256);
41
42 let depth = span.parent().into_iter().flat_map(|x| x.scope()).count();
43
44 write!(buf, "s{}_name: ", depth).unwrap();
45 write_value(&mut buf, span.name());
46 put_metadata(&mut buf, span.metadata(), Some(depth));
47
48 attrs.record(&mut SpanVisitor::new(&mut buf, depth));
49
50 span.extensions_mut().insert(SpanFields(buf));
51 }
52
53 fn on_record(&self, id: &Id, values: &Record, ctx: Context<S>) {
54 let span = ctx.span(id).expect("unknown span");
55 let depth = span.parent().into_iter().flat_map(|x| x.scope()).count();
56 let mut exts = span.extensions_mut();
57 let buf = &mut exts.get_mut::<SpanFields>().expect("missing fields").0;
58 values.record(&mut SpanVisitor::new(buf, depth));
59 }
60
61 fn on_event(&self, event: &Event, ctx: Context<S>) {
62 let mut writer = OHOSWriter::new(event.metadata().level(), self.domain, &self.tag); let _ = write!(&mut writer, "{}: ", event.metadata().target());
66
67 let maybe_scope = ctx
69 .current_span()
70 .id()
71 .and_then(|id| ctx.span_scope(id).map(|x| x.from_root()));
72 if let Some(scope) = maybe_scope {
73 for span in scope {
74 let exts = span.extensions();
75 if let Some(fields) = exts.get::<SpanFields>() {
76 let _ = writer.write_all(&fields.0[..]);
77 }
78 }
79 }
80
81 event.record(&mut writer);
85 }
86}
87struct SpanFields(Vec<u8>);
88
89struct SpanVisitor<'a> {
90 buf: &'a mut Vec<u8>,
91 depth: usize,
92}
93
94impl<'a> SpanVisitor<'a> {
95 fn new(buf: &'a mut Vec<u8>, depth: usize) -> Self {
96 Self { buf, depth }
97 }
98}
99
100impl Visit for SpanVisitor<'_> {
101 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
102 write!(self.buf, "s{}_", self.depth).unwrap();
103 write_debug(&mut self.buf, field.name(), value);
104 }
105}
106
107impl Visit for OHOSWriter<'_> {
108 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
109 if field.name() == "message" {
110 let _ = write!(self, "{:?}", value);
112 } else {
113 let _ = write_debug(self, field.name(), value);
114 }
115 }
116}
117
118fn put_metadata(mut buf: impl io::Write, meta: &Metadata, span: Option<usize>) {
119 write_name_with_value(&mut buf, "target", meta.target(), span);
120 if let Some(file) = meta.file() {
121 write_name_with_value(&mut buf, "file", file, span);
122 }
123 if let Some(line) = meta.line() {
124 write_name_with_value(&mut buf, "line", line, span);
125 }
126}
127
128fn write_debug(mut buf: impl io::Write, name: &str, value: &dyn fmt::Debug) {
129 let _ = write!(&mut buf, "{}={:?}", name, value);
130}
131
132fn write_name_with_value<T>(mut buf: impl io::Write, name: &str, value: T, span: Option<usize>)
133where
134 T: Display,
135{
136 if let Some(n) = span {
137 let _ = write!(&mut buf, "s{}_", n);
138 }
139 let _ = write!(buf, "{}={}", name, value);
140}
141
142fn write_value<T>(mut buf: impl io::Write, value: T)
143where
144 T: Display,
145{
146 let _ = write!(&mut buf, "{}", value);
147}