tracing_json/layers/storage/
json_storage.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)]
11pub struct JsonStorageLayer;
12
13#[derive(Clone, Debug)]
14pub struct JsonStorage<'a> {
15 values: HashMap<&'a str, serde_json::Value>,
16}
17
18impl<'a> JsonStorage<'a> {
19 pub fn values(&self) -> &HashMap<&'a str, serde_json::Value> {
21 &self.values
22 }
23}
24
25impl Default for JsonStorage<'_> {
27 fn default() -> Self {
28 Self {
29 values: HashMap::new(),
30 }
31 }
32}
33
34impl Visit for JsonStorage<'_> {
36 fn record_i64(&mut self, field: &Field, value: i64) {
38 self.values
39 .insert(&field.name(), serde_json::Value::from(value));
40 }
41
42 fn record_u64(&mut self, field: &Field, value: u64) {
44 self.values
45 .insert(&field.name(), serde_json::Value::from(value));
46 }
47
48 fn record_bool(&mut self, field: &Field, value: bool) {
50 self.values
51 .insert(&field.name(), serde_json::Value::from(value));
52 }
53
54 fn record_str(&mut self, field: &Field, value: &str) {
56 self.values
57 .insert(&field.name(), serde_json::Value::from(value));
58 }
59
60 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
61 match field.name() {
62 name if name.starts_with("log.") => (),
64 name if name.starts_with("r#") => {
65 self.values
66 .insert(&name[2..], serde_json::Value::from(format!("{:?}", value)));
67 }
68 name => {
69 self.values
70 .insert(name, serde_json::Value::from(format!("{:?}", value)));
71 }
72 };
73 }
74}
75
76impl<S: Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>> Layer<S>
77 for JsonStorageLayer
78{
79 fn new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
83 let span = ctx.span(id).expect("Span not found, this is a bug");
84
85 let mut visitor = if let Some(parent_span) = span.parent() {
87 let mut extensions = parent_span.extensions_mut();
91 extensions
92 .get_mut::<JsonStorage>()
93 .map(|v| v.to_owned())
94 .unwrap_or_default()
95 } else {
96 JsonStorage::default()
97 };
98
99 let mut extensions = span.extensions_mut();
100
101 attrs.record(&mut visitor);
104 extensions.insert(visitor);
106 }
107
108 fn on_record(&self, span: &Id, values: &Record<'_>, ctx: Context<'_, S>) {
109 let span = ctx.span(span).expect("Span not found, this is a bug");
110
111 let mut extensions = span.extensions_mut();
115 let visitor = extensions
116 .get_mut::<JsonStorage>()
117 .expect("Visitor not found on 'record', this is a bug");
118 values.record(visitor);
120 }
121
122 fn on_enter(&self, span: &Id, ctx: Context<'_, S>) {
124 let span = ctx.span(span).expect("Span not found, this is a bug");
125
126 let mut extensions = span.extensions_mut();
127 if extensions.get_mut::<Instant>().is_none() {
128 extensions.insert(Instant::now());
129 }
130 }
131
132 fn on_close(&self, span: Id, ctx: Context<'_, S>) {
134 let span = ctx.span(&span).expect("Span not found, this is a bug");
135
136 let elapsed = {
139 let extensions = span.extensions();
140 extensions
141 .get::<Instant>()
142 .expect("Timestamp not found on 'record', this is a bug")
143 .elapsed()
144 };
145
146 let mut extensions_mut = span.extensions_mut();
147 let visitor = extensions_mut
148 .get_mut::<JsonStorage>()
149 .expect("Timestamp not found on 'record', this is a bug");
150
151 if let Ok(elapsed) = serde_json::to_value(elapsed.as_millis()) {
152 visitor.values.insert("elapsed_milliseconds", elapsed);
153 }
154 }
155}