Skip to main content

spring_lsp/
status.rs

1//! 服务器状态查询模块
2//!
3//! 本模块提供服务器状态查询功能,包括:
4//! - 服务器运行状态
5//! - 性能指标(文档数量、内存使用等)
6//! - 错误统计
7//!
8//! ## 使用示例
9//!
10//! ```rust,no_run
11//! use spring_lsp::status::ServerStatus;
12//!
13//! let status = ServerStatus::new();
14//! status.increment_document_count();
15//! status.record_error();
16//!
17//! let metrics = status.get_metrics();
18//! println!("Documents: {}", metrics.document_count);
19//! println!("Errors: {}", metrics.error_count);
20//! ```
21
22use serde::{Deserialize, Serialize};
23use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
24use std::sync::Arc;
25use std::time::{Duration, Instant};
26
27/// 服务器状态跟踪器
28///
29/// 使用原子操作跟踪服务器状态和性能指标,确保线程安全
30#[derive(Clone)]
31pub struct ServerStatus {
32    /// 服务器启动时间
33    start_time: Arc<Instant>,
34    /// 打开的文档数量
35    document_count: Arc<AtomicUsize>,
36    /// 总请求数
37    request_count: Arc<AtomicU64>,
38    /// 总错误数
39    error_count: Arc<AtomicU64>,
40    /// 补全请求数
41    completion_count: Arc<AtomicU64>,
42    /// 悬停请求数
43    hover_count: Arc<AtomicU64>,
44    /// 诊断发布数
45    diagnostic_count: Arc<AtomicU64>,
46}
47
48impl ServerStatus {
49    /// 创建新的服务器状态跟踪器
50    pub fn new() -> Self {
51        Self {
52            start_time: Arc::new(Instant::now()),
53            document_count: Arc::new(AtomicUsize::new(0)),
54            request_count: Arc::new(AtomicU64::new(0)),
55            error_count: Arc::new(AtomicU64::new(0)),
56            completion_count: Arc::new(AtomicU64::new(0)),
57            hover_count: Arc::new(AtomicU64::new(0)),
58            diagnostic_count: Arc::new(AtomicU64::new(0)),
59        }
60    }
61
62    /// 增加文档计数
63    pub fn increment_document_count(&self) {
64        self.document_count.fetch_add(1, Ordering::Relaxed);
65    }
66
67    /// 减少文档计数
68    pub fn decrement_document_count(&self) {
69        self.document_count.fetch_sub(1, Ordering::Relaxed);
70    }
71
72    /// 记录请求
73    pub fn record_request(&self) {
74        self.request_count.fetch_add(1, Ordering::Relaxed);
75    }
76
77    /// 记录错误
78    pub fn record_error(&self) {
79        self.error_count.fetch_add(1, Ordering::Relaxed);
80    }
81
82    /// 记录补全请求
83    pub fn record_completion(&self) {
84        self.completion_count.fetch_add(1, Ordering::Relaxed);
85    }
86
87    /// 记录悬停请求
88    pub fn record_hover(&self) {
89        self.hover_count.fetch_add(1, Ordering::Relaxed);
90    }
91
92    /// 记录诊断发布
93    pub fn record_diagnostic(&self) {
94        self.diagnostic_count.fetch_add(1, Ordering::Relaxed);
95    }
96
97    /// 获取服务器运行时长
98    pub fn uptime(&self) -> Duration {
99        self.start_time.elapsed()
100    }
101
102    /// 获取性能指标
103    pub fn get_metrics(&self) -> ServerMetrics {
104        let uptime = self.uptime();
105
106        ServerMetrics {
107            uptime_seconds: uptime.as_secs(),
108            document_count: self.document_count.load(Ordering::Relaxed),
109            request_count: self.request_count.load(Ordering::Relaxed),
110            error_count: self.error_count.load(Ordering::Relaxed),
111            completion_count: self.completion_count.load(Ordering::Relaxed),
112            hover_count: self.hover_count.load(Ordering::Relaxed),
113            diagnostic_count: self.diagnostic_count.load(Ordering::Relaxed),
114            requests_per_second: if uptime.as_secs() > 0 {
115                self.request_count.load(Ordering::Relaxed) as f64 / uptime.as_secs() as f64
116            } else {
117                0.0
118            },
119            error_rate: if self.request_count.load(Ordering::Relaxed) > 0 {
120                self.error_count.load(Ordering::Relaxed) as f64
121                    / self.request_count.load(Ordering::Relaxed) as f64
122            } else {
123                0.0
124            },
125        }
126    }
127
128    /// 重置所有计数器(用于测试)
129    #[cfg(test)]
130    pub fn reset(&self) {
131        self.document_count.store(0, Ordering::Relaxed);
132        self.request_count.store(0, Ordering::Relaxed);
133        self.error_count.store(0, Ordering::Relaxed);
134        self.completion_count.store(0, Ordering::Relaxed);
135        self.hover_count.store(0, Ordering::Relaxed);
136        self.diagnostic_count.store(0, Ordering::Relaxed);
137    }
138}
139
140impl Default for ServerStatus {
141    fn default() -> Self {
142        Self::new()
143    }
144}
145
146/// 服务器性能指标
147///
148/// 包含服务器运行状态和性能统计信息
149#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct ServerMetrics {
151    /// 运行时长(秒)
152    pub uptime_seconds: u64,
153    /// 当前打开的文档数量
154    pub document_count: usize,
155    /// 总请求数
156    pub request_count: u64,
157    /// 总错误数
158    pub error_count: u64,
159    /// 补全请求数
160    pub completion_count: u64,
161    /// 悬停请求数
162    pub hover_count: u64,
163    /// 诊断发布数
164    pub diagnostic_count: u64,
165    /// 每秒请求数
166    pub requests_per_second: f64,
167    /// 错误率(错误数/总请求数)
168    pub error_rate: f64,
169}
170
171impl ServerMetrics {
172    /// 格式化为人类可读的字符串
173    pub fn format(&self) -> String {
174        format!(
175            "Server Status:\n\
176             - Uptime: {}s\n\
177             - Documents: {}\n\
178             - Requests: {} ({:.2} req/s)\n\
179             - Errors: {} ({:.2}% error rate)\n\
180             - Completions: {}\n\
181             - Hovers: {}\n\
182             - Diagnostics: {}",
183            self.uptime_seconds,
184            self.document_count,
185            self.request_count,
186            self.requests_per_second,
187            self.error_count,
188            self.error_rate * 100.0,
189            self.completion_count,
190            self.hover_count,
191            self.diagnostic_count
192        )
193    }
194}
195
196#[cfg(test)]
197mod tests {
198    use super::*;
199    use std::thread;
200    use std::time::Duration;
201
202    #[test]
203    fn test_server_status_creation() {
204        let status = ServerStatus::new();
205        let metrics = status.get_metrics();
206
207        assert_eq!(metrics.document_count, 0);
208        assert_eq!(metrics.request_count, 0);
209        assert_eq!(metrics.error_count, 0);
210        assert_eq!(metrics.completion_count, 0);
211        assert_eq!(metrics.hover_count, 0);
212        assert_eq!(metrics.diagnostic_count, 0);
213    }
214
215    #[test]
216    fn test_document_count() {
217        let status = ServerStatus::new();
218
219        status.increment_document_count();
220        status.increment_document_count();
221        assert_eq!(status.get_metrics().document_count, 2);
222
223        status.decrement_document_count();
224        assert_eq!(status.get_metrics().document_count, 1);
225    }
226
227    #[test]
228    fn test_request_tracking() {
229        let status = ServerStatus::new();
230
231        status.record_request();
232        status.record_request();
233        status.record_request();
234
235        let metrics = status.get_metrics();
236        assert_eq!(metrics.request_count, 3);
237    }
238
239    #[test]
240    fn test_error_tracking() {
241        let status = ServerStatus::new();
242
243        status.record_request();
244        status.record_request();
245        status.record_error();
246
247        let metrics = status.get_metrics();
248        assert_eq!(metrics.error_count, 1);
249        assert_eq!(metrics.error_rate, 0.5); // 1 error / 2 requests
250    }
251
252    #[test]
253    fn test_completion_tracking() {
254        let status = ServerStatus::new();
255
256        status.record_completion();
257        status.record_completion();
258
259        let metrics = status.get_metrics();
260        assert_eq!(metrics.completion_count, 2);
261    }
262
263    #[test]
264    fn test_hover_tracking() {
265        let status = ServerStatus::new();
266
267        status.record_hover();
268        status.record_hover();
269        status.record_hover();
270
271        let metrics = status.get_metrics();
272        assert_eq!(metrics.hover_count, 3);
273    }
274
275    #[test]
276    fn test_diagnostic_tracking() {
277        let status = ServerStatus::new();
278
279        status.record_diagnostic();
280
281        let metrics = status.get_metrics();
282        assert_eq!(metrics.diagnostic_count, 1);
283    }
284
285    #[test]
286    fn test_uptime() {
287        let status = ServerStatus::new();
288
289        // 等待一小段时间
290        thread::sleep(Duration::from_millis(100));
291
292        let uptime = status.uptime();
293        assert!(uptime.as_millis() >= 100);
294    }
295
296    #[test]
297    fn test_requests_per_second() {
298        let status = ServerStatus::new();
299
300        // 等待至少 1 秒以获得有意义的 RPS
301        thread::sleep(Duration::from_secs(1));
302
303        status.record_request();
304        status.record_request();
305
306        let metrics = status.get_metrics();
307        // RPS 应该接近 2(可能略小,因为等待了 1 秒多一点)
308        assert!(metrics.requests_per_second > 0.0);
309        assert!(metrics.requests_per_second <= 2.0);
310    }
311
312    #[test]
313    fn test_metrics_format() {
314        let status = ServerStatus::new();
315
316        status.increment_document_count();
317        status.record_request();
318        status.record_completion();
319
320        let metrics = status.get_metrics();
321        let formatted = metrics.format();
322
323        assert!(formatted.contains("Server Status:"));
324        assert!(formatted.contains("Documents: 1"));
325        assert!(formatted.contains("Requests: 1"));
326        assert!(formatted.contains("Completions: 1"));
327    }
328
329    #[test]
330    fn test_concurrent_updates() {
331        let status = ServerStatus::new();
332        let status_clone = status.clone();
333
334        // 在多个线程中并发更新
335        let handle1 = thread::spawn(move || {
336            for _ in 0..100 {
337                status_clone.record_request();
338            }
339        });
340
341        let status_clone2 = status.clone();
342        let handle2 = thread::spawn(move || {
343            for _ in 0..100 {
344                status_clone2.record_request();
345            }
346        });
347
348        handle1.join().unwrap();
349        handle2.join().unwrap();
350
351        let metrics = status.get_metrics();
352        assert_eq!(metrics.request_count, 200);
353    }
354
355    #[test]
356    fn test_zero_division_safety() {
357        let status = ServerStatus::new();
358
359        // 没有请求时,错误率应该是 0
360        let metrics = status.get_metrics();
361        assert_eq!(metrics.error_rate, 0.0);
362
363        // 运行时间为 0 时,RPS 应该是 0
364        // 注意:由于 Instant::now() 的精度,这个测试可能不稳定
365        // 但代码应该能处理这种情况
366        assert!(metrics.requests_per_second >= 0.0);
367    }
368
369    #[test]
370    fn test_reset() {
371        let status = ServerStatus::new();
372
373        status.increment_document_count();
374        status.record_request();
375        status.record_error();
376
377        status.reset();
378
379        let metrics = status.get_metrics();
380        assert_eq!(metrics.document_count, 0);
381        assert_eq!(metrics.request_count, 0);
382        assert_eq!(metrics.error_count, 0);
383    }
384}