tracing_systemd/
systemd_layer.rs1use std::collections::BTreeMap;
2
3mod helper_structs;
5
6mod impls;
7
8use crate::formatting::*;
9
10use helper_structs::*;
11#[cfg(feature = "sd-journal")]
12use sd_journal::*;
13
14pub struct SystemdLayer {
24 #[cfg(feature = "colored")]
25 use_color: bool,
26
27 log_thread_id: bool,
28 span_separator: &'static str,
29 message_separator: &'static str,
30 level_separator: &'static str,
31 log_target: bool,
32 #[cfg(feature = "sd-journal")]
33 use_sd_journal: bool,
34 function_bracket_left: &'static str,
35 function_bracket_right: &'static str,
36 arguments_equality: &'static str,
37 arguments_separator: &'static str,
38 use_level_prefix: bool,
39 thread_id_prefix: &'static str,
40 thread_id_suffix: &'static str,
41}
42
43impl<S> tracing_subscriber::Layer<S> for SystemdLayer
45where
46 S: tracing::Subscriber,
47 S: for<'a> tracing_subscriber::registry::LookupSpan<'a>,
48{
49 fn on_event(&self, event: &tracing::Event<'_>, ctx: tracing_subscriber::layer::Context<'_, S>) {
50 let scope = ctx.event_scope(event).unwrap();
51 let mut spans = vec![];
52
53 for span in scope.from_root() {
54 let extensions = span.extensions();
55 let storage = extensions.get::<SystemdFieldStorage>().unwrap();
56 let data = &storage.0;
57 spans.push(serde_json::json!({
58 "target": event.metadata().target(),
59 "name": span.name(),
60 "level": event.metadata().level().to_string(),
61 "fields": data,
62 }));
63 }
64
65 let mut fields = BTreeMap::new();
66 let mut visitor = SystemdVisitor(&mut fields);
67 event.record(&mut visitor);
68
69 let output = serde_json::json!({
70 "target": event.metadata().target(),
71 "name": event.metadata().name(),
72 "level": event.metadata().level().to_string(),
73 "fields": fields,
74 "spans": spans,
75 });
76
77 let full_string = self.build_full_string(&output);
78
79 #[cfg(feature = "sd-journal")]
80 {
81 match self.get_use_sd_journal() {
82 true => {
83 let level = journal_level_from_tracing_level(event.metadata().level());
84 Journal::log_message(level, full_string).unwrap();
85 }
86
87 false => match self.get_use_level_prefix() {
88 true => {
89 let prefix = prefix_from_tracing_level(event.metadata().level());
90 println!("{}{}", prefix, full_string);
91 }
92 false => {
93 println!("{}", full_string);
94 }
95 },
96 }
97 }
98
99 #[cfg(not(feature = "sd-journal"))]
100 {
101 match self.get_use_level_prefix() {
102 true => {
103 let prefix = prefix_from_tracing_level(event.metadata().level());
104 println!("{}{}", prefix, full_string)
105 }
106 false => {
107 println!("{}", full_string);
108 }
109 }
110
111 println!("{}", full_string);
112 }
113 }
114
115 fn on_new_span(
116 &self,
117 attrs: &tracing::span::Attributes,
118 id: &tracing::span::Id,
119 ctx: tracing_subscriber::layer::Context<'_, S>,
120 ) {
121 let mut fields = BTreeMap::new();
122 let mut visitor = SystemdVisitor(&mut fields);
123 attrs.record(&mut visitor);
124
125 let storage = SystemdFieldStorage(fields);
126 let span = ctx.span(id).unwrap();
127 let mut extensions = span.extensions_mut();
128 extensions.insert(storage);
129 }
130}