1use std::time::Instant;
6
7#[derive(uniffi::Record)]
9pub struct LabeledTimingSample {
10 pub label: String,
11 pub value: u64,
13}
14
15impl LabeledTimingSample {
16 fn new(label: String, value: u64) -> Self {
17 Self { label, value }
18 }
19}
20
21#[derive(Default, uniffi::Record)]
25pub struct SuggestIngestionMetrics {
26 pub ingestion_times: Vec<LabeledTimingSample>,
28 pub download_times: Vec<LabeledTimingSample>,
30}
31
32impl SuggestIngestionMetrics {
33 pub fn measure_ingest<F, T>(&mut self, record_type: impl Into<String>, operation: F) -> T
37 where
38 F: FnOnce(&mut MetricsContext) -> T,
39 {
40 let timer = Instant::now();
41 let record_type = record_type.into();
42 let mut context = MetricsContext::default();
43 let result = operation(&mut context);
44 let elapsed = timer.elapsed().as_micros() as u64;
45 match context {
46 MetricsContext::Uninstrumented => (),
47 MetricsContext::Instrumented { download_time } => {
48 self.ingestion_times.push(LabeledTimingSample::new(
49 record_type.clone(),
50 elapsed - download_time,
51 ));
52 self.download_times
53 .push(LabeledTimingSample::new(record_type, download_time));
54 }
55 }
56 result
57 }
58}
59
60#[derive(Default)]
62pub enum MetricsContext {
63 #[default]
66 Uninstrumented,
67 Instrumented { download_time: u64 },
71}
72
73impl MetricsContext {
74 pub fn measure_download<F, T>(&mut self, operation: F) -> T
79 where
80 F: FnOnce() -> T,
81 {
82 let timer = Instant::now();
83 let result = operation();
84 let elasped = timer.elapsed().as_micros() as u64;
85 match self {
86 Self::Uninstrumented => {
87 *self = Self::Instrumented {
88 download_time: elasped,
89 }
90 }
91 Self::Instrumented { download_time } => *download_time += elasped,
92 }
93 result
94 }
95}
96
97#[derive(Default)]
101pub struct SuggestQueryMetrics {
102 pub times: Vec<LabeledTimingSample>,
103}
104
105impl SuggestQueryMetrics {
106 pub fn measure_query<F, T>(&mut self, provider: impl Into<String>, operation: F) -> T
107 where
108 F: FnOnce() -> T,
109 {
110 let provider = provider.into();
111 let timer = Instant::now();
112 let result = std::hint::black_box(operation());
115 let elapsed = timer.elapsed().as_micros() as u64;
116 self.times.push(LabeledTimingSample::new(provider, elapsed));
117 result
118 }
119}