atomic_bomb_engine/models/
assert_error_stats.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use std::hash::{Hash, Hasher};
4use std::sync::Arc;
5use tokio::sync::Mutex;
6use url::Url;
7
8#[derive(Debug, Eq, Clone, Serialize, Deserialize)]
9pub struct AssertErrKey {
10    pub name: String,
11    pub msg: String,
12    pub url: String,
13    pub host: String,
14    pub path: String,
15}
16
17impl PartialEq for AssertErrKey {
18    fn eq(&self, other: &Self) -> bool {
19        self.name == other.name && self.url == other.url && self.msg == other.msg
20    }
21}
22
23impl Hash for AssertErrKey {
24    fn hash<H: Hasher>(&self, state: &mut H) {
25        format!("{:?}{:?}{:?}", self.name, self.url, self.msg).hash(state);
26    }
27}
28
29#[derive(Clone, Debug)]
30pub struct AssertErrorStats {
31    pub(crate) errors: Arc<Mutex<HashMap<AssertErrKey, u32>>>,
32}
33
34impl AssertErrorStats {
35    pub(crate) fn new() -> Self {
36        AssertErrorStats {
37            errors: Arc::new(Mutex::new(HashMap::new())),
38        }
39    }
40
41    // 增加一个错误和对应的出现次数
42    pub(crate) async fn increment(&self, name: String, msg: String, url_s: String) {
43        let url = url_s.clone();
44        let mut host = "-".to_string();
45        let mut path = "-".to_string();
46        if let Ok(u) = Url::parse(&url_s) {
47            host = match u.host() {
48                None => "-".to_string(),
49                Some(h) => h.to_string(),
50            };
51            path = u.path().to_string();
52        };
53
54        let mut errors = self.errors.lock().await;
55        *errors
56            .entry(AssertErrKey {
57                name,
58                msg,
59                url,
60                host,
61                path,
62            })
63            .or_insert(0) += 1;
64    }
65}