Skip to main content

rat_quickdns/builder/
metrics.rs

1//! DNS解析器性能指标模块
2//! 
3//! 本模块提供DNS上游服务器的性能指标收集、统计和分析功能
4
5use std::time::{Duration, Instant};
6
7/// 上游服务器性能指标
8#[derive(Debug, Clone)]
9pub struct PerformanceMetrics {
10    /// 总查询次数
11    pub total_queries: u64,
12    
13    /// 成功查询次数
14    pub successful_queries: u64,
15    
16    /// 失败查询次数
17    pub failed_queries: u64,
18    
19    /// 连续失败次数
20    pub consecutive_failures: u32,
21    
22    /// 平均延迟
23    pub avg_latency: Duration,
24    
25    /// 最后成功时间
26    pub last_success_time: Option<Instant>,
27    
28    /// 最后失败时间
29    pub last_failure_time: Option<Instant>,
30    
31    /// CDN准确性评分 (0.0-1.0)
32    pub cdn_accuracy_score: f64,
33}
34
35impl Default for PerformanceMetrics {
36    fn default() -> Self {
37        Self {
38            total_queries: 0,
39            successful_queries: 0,
40            failed_queries: 0,
41            consecutive_failures: 0,
42            avg_latency: Duration::from_millis(100), // 默认100ms
43            last_success_time: None,
44            last_failure_time: None,
45            cdn_accuracy_score: 0.8, // 默认80%准确率
46        }
47    }
48}
49
50impl PerformanceMetrics {
51    /// 创建新的性能指标实例
52    pub fn new() -> Self {
53        Self::default()
54    }
55    
56    /// 计算成功率
57    pub fn success_rate(&self) -> f64 {
58        if self.total_queries == 0 {
59            0.0
60        } else {
61            self.successful_queries as f64 / self.total_queries as f64
62        }
63    }
64    
65    /// 计算失败率
66    pub fn failure_rate(&self) -> f64 {
67        1.0 - self.success_rate()
68    }
69    
70    /// 是否可用(基于连续失败次数)- 修正术语,更准确描述服务器可用性
71    pub fn is_available(&self) -> bool {
72        self.consecutive_failures < 10
73    }
74    
75    /// 获取延迟等级描述
76    pub fn latency_grade(&self) -> &'static str {
77        let ms = self.avg_latency.as_millis();
78        match ms {
79            0..=50 => "优秀",
80            51..=100 => "良好",
81            101..=200 => "一般",
82            201..=500 => "较差",
83            _ => "很差",
84        }
85    }
86    
87    /// 更新成功查询指标
88    pub fn record_success(&mut self, latency: Duration, cdn_accurate: bool) {
89        self.total_queries += 1;
90        self.successful_queries += 1;
91        self.consecutive_failures = 0;
92        self.last_success_time = Some(Instant::now());
93        
94        // 更新平均延迟(指数移动平均)
95        if self.total_queries == 1 {
96            self.avg_latency = latency;
97        } else {
98            let alpha = 0.1; // 平滑因子
99            let old_latency_ms = self.avg_latency.as_millis() as f64;
100            let new_latency_ms = latency.as_millis() as f64;
101            let smoothed_latency_ms = old_latency_ms * (1.0 - alpha) + new_latency_ms * alpha;
102            self.avg_latency = Duration::from_millis(smoothed_latency_ms as u64);
103        }
104        
105        // 更新CDN准确性评分
106        let current_score = self.cdn_accuracy_score * (self.successful_queries - 1) as f64;
107        let new_score = if cdn_accurate { 1.0 } else { 0.0 };
108        self.cdn_accuracy_score = (current_score + new_score) / self.successful_queries as f64;
109    }
110    
111    /// 更新失败查询指标
112    pub fn record_failure(&mut self) {
113        self.total_queries += 1;
114        self.failed_queries += 1;
115        self.consecutive_failures += 1;
116        self.last_failure_time = Some(Instant::now());
117    }
118    
119    /// 重置指标
120    pub fn reset(&mut self) {
121        *self = Self::default();
122    }
123    
124    /// 获取综合评分 (0.0-1.0)
125    pub fn overall_score(&self) -> f64 {
126        let success_weight = 0.4;
127        let latency_weight = 0.3;
128        let cdn_weight = 0.2;
129        let availability_weight = 0.1;
130        
131        let success_score = self.success_rate();
132        
133        let latency_score = if self.avg_latency.as_millis() > 0 {
134            (1000.0 / (self.avg_latency.as_millis() as f64 + 100.0)).min(1.0)
135        } else {
136            1.0
137        };
138        
139        let cdn_score = self.cdn_accuracy_score;
140        
141        let availability_score = if self.is_available() { 1.0 } else { 0.0 };
142        
143        success_score * success_weight
144            + latency_score * latency_weight
145            + cdn_score * cdn_weight
146            + availability_score * availability_weight
147    }
148}