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}