csskit_lsp/jsonrpc/
tracing_layer.rs1use std::{
2 collections::BTreeMap,
3 sync::{Arc, RwLock},
4};
5
6use crossbeam_channel::Sender;
7use lsp_types::{
8 LogMessageParams, LogTraceParams, MessageType,
9 notification::{LogMessage, LogTrace, Notification as NotificationTrait},
10};
11use serde::Serialize;
12use serde_json::{to_string_pretty, to_value};
13use tracing::{Event, Level, Subscriber, level_filters::LevelFilter};
14use tracing_subscriber::{Layer, layer::Context};
15
16use super::{Message, Notification};
17
18pub struct TracingLayer {
19 pub level: Arc<RwLock<LevelFilter>>,
20 sender: Sender<Message>,
21}
22
23impl TracingLayer {
24 pub fn new(level: Arc<RwLock<LevelFilter>>, sender: Sender<Message>) -> Self {
25 Self { level, sender }
26 }
27}
28#[derive(Default, Serialize)]
32struct MessageVisitor(BTreeMap<String, String>);
33
34impl MessageVisitor {
35 pub fn insert(&mut self, str: &str, string: String) {
36 self.0.insert(str.into(), string);
37 }
38}
39
40impl tracing::field::Visit for MessageVisitor {
41 fn record_f64(&mut self, field: &tracing::field::Field, value: f64) {
42 self.insert(field.name(), format!("{value:?}"));
43 }
44
45 fn record_i64(&mut self, field: &tracing::field::Field, value: i64) {
46 self.insert(field.name(), format!("{value:?}"));
47 }
48
49 fn record_u64(&mut self, field: &tracing::field::Field, value: u64) {
50 self.insert(field.name(), format!("{value:?}"));
51 }
52
53 fn record_bool(&mut self, field: &tracing::field::Field, value: bool) {
54 self.insert(field.name(), format!("{value:?}"));
55 }
56
57 fn record_str(&mut self, field: &tracing::field::Field, value: &str) {
58 self.insert(field.name(), format!("{value:?}"));
59 }
60
61 fn record_error(&mut self, field: &tracing::field::Field, value: &(dyn std::error::Error + 'static)) {
62 self.insert(field.name(), format!("{value:?}"));
63 }
64
65 fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
66 self.insert(field.name(), format!("{value:?}"));
67 }
68}
69
70impl<S> Layer<S> for TracingLayer
71where
72 S: Subscriber,
73{
74 fn on_event(&self, event: &Event, _ctx: Context<'_, S>) {
75 if event.metadata().level() > &(*self.level.read().unwrap()) {
76 return;
77 }
78 let mut fields = MessageVisitor::default();
79 fields.insert("name", event.metadata().name().into());
80 fields.insert("level", event.metadata().level().as_str().into());
81 event.record(&mut fields);
82 let output = serde_json::json!(fields);
83
84 let level = match event.metadata().level() {
85 &Level::ERROR => MessageType::ERROR,
86 &Level::WARN => MessageType::WARNING,
87 &Level::INFO => MessageType::INFO,
88 &Level::DEBUG | &Level::TRACE => {
89 let message = Message::Notification(Notification {
90 method: LogTrace::METHOD.into(),
91 params: to_value(LogTraceParams {
92 verbose: None,
93 message: to_string_pretty(&output).ok().unwrap_or_default(),
94 })
95 .unwrap_or_default(),
96 });
97 self.sender.try_send(message).ok();
98 return;
99 }
100 };
101
102 let message = Message::Notification(Notification {
103 method: LogMessage::METHOD.into(),
104 params: to_value(LogMessageParams {
105 typ: level,
106 message: to_string_pretty(&output).ok().unwrap_or_default(),
107 })
108 .unwrap_or_default(),
109 });
110
111 self.sender.try_send(message).ok();
112 }
113}