Skip to main content

luct_scanner/
stats.rs

1use std::collections::BTreeMap;
2
3use crate::{Scanner, ScannerImpl};
4use chrono::DateTime;
5use luct_core::store::AsyncSearchableStoreRead;
6use serde::{Deserialize, Serialize};
7use web_time::{SystemTime, UNIX_EPOCH};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct BasicStatistics {
11    roots_cas: Vec<(String, u64)>,
12    scts: Vec<(String, u64)>,
13}
14
15impl<S: ScannerImpl> Scanner<S> {
16    pub async fn basic_statistics(&self) -> BasicStatistics {
17        let now = DateTime::from_timestamp_millis(
18            SystemTime::now()
19                .duration_since(UNIX_EPOCH)
20                .unwrap()
21                .as_millis() as i64,
22        )
23        .unwrap();
24
25        let reports = self
26            .report_store
27            .filter(|_, value| value.not_after > now)
28            .await;
29
30        let mut roots_cas = BTreeMap::new();
31        let mut scts = BTreeMap::new();
32
33        for (_, report) in reports.into_iter() {
34            roots_cas
35                .entry(report.ca_issuer)
36                .and_modify(|entry| *entry += 1)
37                .or_insert(1);
38
39            for sct in report.scts {
40                if let Some(name) = sct.log_name {
41                    scts.entry(name)
42                        .and_modify(|entry| *entry += 1)
43                        .or_insert(1);
44                }
45            }
46        }
47
48        BasicStatistics {
49            roots_cas: roots_cas.into_iter().collect(),
50            scts: scts.into_iter().collect(),
51        }
52    }
53}