codebook_lsp/
lsp_logger.rs1use log::{Level, LevelFilter, Log, Metadata, Record};
2use std::collections::VecDeque;
3use std::sync::{Mutex, OnceLock};
4use tokio::sync::mpsc::{self, Sender};
5use tower_lsp::Client;
6use tower_lsp::lsp_types::MessageType;
7
8const BUFFER_SIZE: usize = 1000;
9
10pub struct LspLogger {
11 sender: Mutex<Option<Sender<LogMessage>>>,
12 level: Mutex<LevelFilter>,
13 buffer: Mutex<VecDeque<LogMessage>>,
15}
16
17struct LogMessage {
18 level: Level,
19 message: String,
20}
21
22impl LogMessage {
23 fn clone(&self) -> Self {
24 LogMessage {
25 level: self.level,
26 message: self.message.clone(),
27 }
28 }
29}
30
31static LOGGER: OnceLock<&'static LspLogger> = OnceLock::new();
33
34impl LspLogger {
35 pub fn init_early(level: LevelFilter) -> Result<(), log::SetLoggerError> {
38 let logger = Box::leak(Box::new(LspLogger {
39 sender: Mutex::new(None),
40 level: Mutex::new(level),
41 buffer: Mutex::new(VecDeque::with_capacity(BUFFER_SIZE)),
42 }));
43
44 let _ = LOGGER.set(logger);
46
47 let logger = LOGGER.get().expect("Logger should be initialized");
49 log::set_logger(*logger).map(|()| log::set_max_level(level))
50 }
51
52 pub fn attach_client(client: Client, level: LevelFilter) {
54 if let Some(logger) = LOGGER.get() {
55 *logger.level.lock().unwrap() = level;
57 log::set_max_level(level);
58
59 let (sender, mut receiver) = mpsc::channel::<LogMessage>(BUFFER_SIZE);
61
62 let buffered_messages: Vec<LogMessage> = {
64 let buffer = logger.buffer.lock().unwrap();
65 buffer.iter().map(|msg| msg.clone()).collect()
66 };
67
68 *logger.sender.lock().unwrap() = Some(sender.clone());
70
71 let client_clone = client.clone();
73 tokio::spawn(async move {
74 while let Some(log_msg) = receiver.recv().await {
75 let lsp_level = match log_msg.level {
76 Level::Error => MessageType::ERROR,
77 Level::Warn => MessageType::WARNING,
78 Level::Info => MessageType::INFO,
79 Level::Debug | Level::Trace => MessageType::LOG,
80 };
81
82 let _ = client_clone.log_message(lsp_level, log_msg.message).await;
84 }
85 });
86
87 for msg in buffered_messages {
89 let _ = sender.try_send(msg);
91 }
92
93 logger.buffer.lock().unwrap().clear();
95 }
96 }
97}
98
99impl Log for LspLogger {
100 fn enabled(&self, metadata: &Metadata) -> bool {
101 metadata.level() <= *self.level.lock().unwrap()
102 }
103
104 fn log(&self, record: &Record) {
105 if !self.enabled(record.metadata()) {
106 return;
107 }
108
109 let message = format!(
111 "[{}] {}: {}",
112 record.target(),
113 record.level(),
114 record.args()
115 );
116
117 let log_msg = LogMessage {
118 level: record.level(),
119 message: message.clone(),
120 };
121
122 let sender_guard = self.sender.lock().unwrap();
124 if let Some(sender) = sender_guard.as_ref() {
125 let _ = sender.try_send(log_msg);
127 } else {
128 eprintln!("{}", message);
130
131 drop(sender_guard);
133
134 let mut buffer = self.buffer.lock().unwrap();
136 if buffer.len() >= BUFFER_SIZE {
137 buffer.pop_front();
139 }
140 buffer.push_back(log_msg);
141 }
142 }
143
144 fn flush(&self) {}
145}