ephem_debugger_rs/
capture.rs1use std::sync::Arc;
16
17use tracing::field::{Field, Visit};
18use tracing::Event;
19use tracing_subscriber::layer::Context;
20use tracing_subscriber::Layer;
21
22use crate::store::LogStore;
23
24pub struct CaptureLayer {
27 store: Arc<LogStore>,
28}
29
30impl CaptureLayer {
31 pub fn new(store: Arc<LogStore>) -> Self {
33 Self { store }
34 }
35}
36
37impl<S> Layer<S> for CaptureLayer
38where
39 S: tracing::Subscriber,
40{
41 fn on_event(&self, event: &Event<'_>, _ctx: Context<'_, S>) {
42 let mut visitor = FieldVisitor::default();
43 event.record(&mut visitor);
44
45 let level = match *event.metadata().level() {
46 tracing::Level::ERROR => "error",
47 tracing::Level::WARN => "warn",
48 tracing::Level::INFO => "info",
49 tracing::Level::DEBUG => "debug",
50 tracing::Level::TRACE => "debug",
51 };
52
53 let mut args: Vec<serde_json::Value> = Vec::new();
54 if let Some(msg) = visitor.message {
55 args.push(serde_json::Value::String(msg));
56 }
57 for (key, value) in visitor.fields {
58 args.push(serde_json::json!({ key: value }));
59 }
60
61 self.store.push_console(level, args, "server");
62 }
63}
64
65#[derive(Default)]
67struct FieldVisitor {
68 message: Option<String>,
69 fields: Vec<(String, String)>,
70}
71
72impl Visit for FieldVisitor {
73 fn record_debug(&mut self, field: &Field, value: &dyn std::fmt::Debug) {
74 let val = format!("{value:?}");
75 if field.name() == "message" {
76 self.message = Some(val);
77 } else {
78 self.fields.push((field.name().to_string(), val));
79 }
80 }
81
82 fn record_str(&mut self, field: &Field, value: &str) {
83 if field.name() == "message" {
84 self.message = Some(value.to_string());
85 } else {
86 self.fields
87 .push((field.name().to_string(), value.to_string()));
88 }
89 }
90
91 fn record_i64(&mut self, field: &Field, value: i64) {
92 self.fields
93 .push((field.name().to_string(), value.to_string()));
94 }
95
96 fn record_u64(&mut self, field: &Field, value: u64) {
97 self.fields
98 .push((field.name().to_string(), value.to_string()));
99 }
100
101 fn record_bool(&mut self, field: &Field, value: bool) {
102 self.fields
103 .push((field.name().to_string(), value.to_string()));
104 }
105
106 fn record_f64(&mut self, field: &Field, value: f64) {
107 self.fields
108 .push((field.name().to_string(), value.to_string()));
109 }
110}