csskit_lsp/jsonrpc/
tracing_layer.rs

1use 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// lsp_types::notification::LogTrace
29// lsp_types::notification::LogMessage
30
31#[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}