Skip to main content

timeseries_table_core/table/
append_report.rs

1//! Append profiling report types used by the CLI benchmark binary.
2
3use std::time::{Duration, Instant};
4
5/// Single append step timing entry.
6#[derive(Debug, Clone)]
7pub struct AppendStep {
8    /// Step name (stable identifier).
9    pub name: String,
10    /// Elapsed wall time in milliseconds.
11    pub elapsed_ms: u128,
12
13    /// Arbitrary key/value annotations captured during the step.
14    pub fields: Vec<(String, String)>,
15}
16
17/// Full append profiling report.
18#[derive(Debug, Clone)]
19pub struct AppendReport {
20    /// Context-level metadata (table, segment, bytes, etc.).
21    pub context: Vec<(String, String)>,
22    /// Per-step timing breakdown.
23    pub steps: Vec<AppendStep>,
24    /// Total elapsed wall time in milliseconds.
25    pub total_ms: u128,
26}
27
28/// Builder for append profiling reports.
29#[derive(Debug)]
30pub struct AppendReportBuilder {
31    start: Instant,
32    context: Vec<(String, String)>,
33    steps: Vec<AppendStep>,
34}
35
36impl Default for AppendReportBuilder {
37    fn default() -> Self {
38        Self::new()
39    }
40}
41
42impl AppendReportBuilder {
43    /// Create a new report builder and start the total timer.
44    pub fn new() -> Self {
45        Self {
46            start: Instant::now(),
47            context: Vec::new(),
48            steps: Vec::new(),
49        }
50    }
51
52    /// Set or update a context key/value pair.
53    pub fn set_context(&mut self, key: &str, value: impl Into<String>) {
54        let value = value.into();
55        if let Some((_, v)) = self.context.iter_mut().find(|(k, _)| k == key) {
56            *v = value;
57        } else {
58            self.context.push((key.to_string(), value));
59        }
60    }
61
62    /// Append a step timing entry.
63    pub fn push_step<I>(&mut self, name: &str, elapsed: Duration, fields: I)
64    where
65        I: IntoIterator<Item = (String, String)>,
66    {
67        self.steps.push(AppendStep {
68            name: name.to_string(),
69            elapsed_ms: elapsed.as_millis(),
70            fields: fields.into_iter().collect(),
71        });
72    }
73
74    /// Finalize the report.
75    pub fn finish(self) -> AppendReport {
76        AppendReport {
77            context: self.context,
78            steps: self.steps,
79            total_ms: self.start.elapsed().as_millis(),
80        }
81    }
82}