tracing_bunyan_formatter/
storage_layer.rs1use std::collections::HashMap;
2use std::fmt;
3use std::time::Instant;
4use tracing::field::{Field, Visit};
5use tracing::span::{Attributes, Record};
6use tracing::{Id, Subscriber};
7use tracing_subscriber::layer::Context;
8use tracing_subscriber::Layer;
9
10#[derive(Clone, Debug)]
16pub struct JsonStorageLayer;
17
18#[derive(Clone, Debug)]
29pub struct JsonStorage<'a> {
30 values: HashMap<&'a str, serde_json::Value>,
31}
32
33impl<'a> JsonStorage<'a> {
34 pub fn values(&self) -> &HashMap<&'a str, serde_json::Value> {
36 &self.values
37 }
38}
39
40impl Default for JsonStorage<'_> {
42 fn default() -> Self {
43 Self {
44 values: HashMap::new(),
45 }
46 }
47}
48
49impl Visit for JsonStorage<'_> {
51 fn record_i64(&mut self, field: &Field, value: i64) {
53 self.values
54 .insert(field.name(), serde_json::Value::from(value));
55 }
56
57 fn record_u64(&mut self, field: &Field, value: u64) {
59 self.values
60 .insert(field.name(), serde_json::Value::from(value));
61 }
62
63 fn record_f64(&mut self, field: &Field, value: f64) {
65 self.values
66 .insert(field.name(), serde_json::Value::from(value));
67 }
68
69 fn record_bool(&mut self, field: &Field, value: bool) {
71 self.values
72 .insert(field.name(), serde_json::Value::from(value));
73 }
74
75 fn record_str(&mut self, field: &Field, value: &str) {
77 self.values
78 .insert(field.name(), serde_json::Value::from(value));
79 }
80
81 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
82 match field.name() {
83 name if name.starts_with("log.") => (),
85 name if name.starts_with("r#") => {
86 self.values
87 .insert(&name[2..], serde_json::Value::from(format!("{:?}", value)));
88 }
89 name => {
90 self.values
91 .insert(name, serde_json::Value::from(format!("{:?}", value)));
92 }
93 };
94 }
95
96 #[cfg(all(tracing_unstable, feature = "valuable"))]
97 #[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))]
98 fn record_value(&mut self, field: &Field, value: valuable::Value<'_>) {
99 let serializable = valuable_serde::Serializable::new(value);
100
101 match serde_json::to_value(serializable) {
102 Ok(json_value) => {
103 self.values.insert(field.name(), json_value);
104 }
105 Err(error) => {
106 tracing::debug!(
107 parent: None,
113 ?error,
114 field_name = field.name(),
115 "serde_json serialization error while recording valuable field."
116 );
117 }
118 }
119 }
120}
121
122impl<S: Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>> Layer<S>
123 for JsonStorageLayer
124{
125 fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
129 let span = ctx.span(id).expect("Span not found, this is a bug");
130
131 let mut visitor = if let Some(parent_span) = span.parent() {
133 let mut extensions = parent_span.extensions_mut();
137 extensions
138 .get_mut::<JsonStorage>()
139 .map(|v| v.to_owned())
140 .unwrap_or_default()
141 } else {
142 JsonStorage::default()
143 };
144
145 let mut extensions = span.extensions_mut();
146
147 attrs.record(&mut visitor);
150 extensions.insert(visitor);
152 }
153
154 fn on_record(&self, span: &Id, values: &Record<'_>, ctx: Context<'_, S>) {
155 let span = ctx.span(span).expect("Span not found, this is a bug");
156
157 let mut extensions = span.extensions_mut();
161 let visitor = extensions
162 .get_mut::<JsonStorage>()
163 .expect("Visitor not found on 'record', this is a bug");
164 values.record(visitor);
166 }
167
168 fn on_enter(&self, span: &Id, ctx: Context<'_, S>) {
170 let span = ctx.span(span).expect("Span not found, this is a bug");
171
172 let mut extensions = span.extensions_mut();
173 if extensions.get_mut::<Instant>().is_none() {
174 extensions.insert(Instant::now());
175 }
176 }
177
178 fn on_close(&self, span: Id, ctx: Context<'_, S>) {
180 let span = ctx.span(&span).expect("Span not found, this is a bug");
181
182 let elapsed_milliseconds = {
185 let extensions = span.extensions();
186 extensions
187 .get::<Instant>()
188 .map(|i| i.elapsed().as_millis())
189 .unwrap_or(0)
192 };
193
194 #[cfg(not(feature = "arbitrary-precision"))]
195 let elapsed_milliseconds: u64 = {
198 use std::convert::TryInto;
199
200 elapsed_milliseconds.try_into().unwrap_or_default()
201 };
202
203 let mut extensions_mut = span.extensions_mut();
204 let visitor = extensions_mut
205 .get_mut::<JsonStorage>()
206 .expect("Visitor not found on 'record', this is a bug");
207
208 if let Ok(elapsed) = serde_json::to_value(elapsed_milliseconds) {
209 visitor.values.insert("elapsed_milliseconds", elapsed);
210 }
211 }
212}