Skip to main content

linkrs_metrics/
metrics.rs

1//! Lightweight query metrics
2//!
3//! Lightweight query metrics for return to the client, with precision in the range of microseconds.
4
5use std::collections::HashMap;
6use std::time::{Duration, Instant};
7
8/// Lightweight query metrics
9///
10/// Query execution metrics used for returning to the client, with precision in the range of microseconds.
11/// Differences from QueryProfile:
12/// QueryMetrics: A lightweight component designed to provide results to the client in a very short time (within milliseconds).
13/// QueryProfile: Provides detailed monitoring data for internal analysis and logging (in milliseconds).
14#[derive(Debug, Clone)]
15pub struct QueryMetrics {
16    /// Analysis time (in microseconds)
17    pub parse_time_us: u64,
18    /// Verification time (in microseconds)
19    pub validate_time_us: u64,
20    /// Planning time (in microseconds)
21    pub plan_time_us: u64,
22    /// Optimized time (in microseconds)
23    pub optimize_time_us: u64,
24    /// Execution time (in microseconds)
25    pub execute_time_us: u64,
26    /// Total time (microseconds)
27    pub total_time_us: u64,
28    /// Number of planned nodes
29    pub plan_node_count: usize,
30    /// Number of result rows
31    pub result_row_count: usize,
32    /// Timestamp
33    pub timestamp: Instant,
34}
35
36impl Default for QueryMetrics {
37    fn default() -> Self {
38        Self {
39            parse_time_us: 0,
40            validate_time_us: 0,
41            plan_time_us: 0,
42            optimize_time_us: 0,
43            execute_time_us: 0,
44            total_time_us: 0,
45            plan_node_count: 0,
46            result_row_count: 0,
47            timestamp: Instant::now(),
48        }
49    }
50}
51
52impl QueryMetrics {
53    pub fn new() -> Self {
54        Self::default()
55    }
56
57    pub fn record_parse_time(&mut self, duration: Duration) {
58        self.parse_time_us = duration.as_micros() as u64;
59    }
60
61    pub fn record_validate_time(&mut self, duration: Duration) {
62        self.validate_time_us = duration.as_micros() as u64;
63    }
64
65    pub fn record_plan_time(&mut self, duration: Duration) {
66        self.plan_time_us = duration.as_micros() as u64;
67    }
68
69    pub fn record_optimize_time(&mut self, duration: Duration) {
70        self.optimize_time_us = duration.as_micros() as u64;
71    }
72
73    pub fn record_execute_time(&mut self, duration: Duration) {
74        self.execute_time_us = duration.as_micros() as u64;
75    }
76
77    pub fn record_total_time(&mut self, duration: Duration) {
78        self.total_time_us = duration.as_micros() as u64;
79    }
80
81    pub fn set_plan_node_count(&mut self, count: usize) {
82        self.plan_node_count = count;
83    }
84
85    pub fn set_result_row_count(&mut self, count: usize) {
86        self.result_row_count = count;
87    }
88
89    pub fn to_map(&self) -> HashMap<String, u64> {
90        let mut map = HashMap::new();
91        map.insert("parse_time_us".to_string(), self.parse_time_us);
92        map.insert("validate_time_us".to_string(), self.validate_time_us);
93        map.insert("plan_time_us".to_string(), self.plan_time_us);
94        map.insert("optimize_time_us".to_string(), self.optimize_time_us);
95        map.insert("execute_time_us".to_string(), self.execute_time_us);
96        map.insert("total_time_us".to_string(), self.total_time_us);
97        map.insert("plan_node_count".to_string(), self.plan_node_count as u64);
98        map.insert("result_row_count".to_string(), self.result_row_count as u64);
99        map
100    }
101}
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106
107    #[test]
108    fn test_query_metrics_default() {
109        let metrics = QueryMetrics::default();
110        assert_eq!(metrics.parse_time_us, 0);
111        assert_eq!(metrics.total_time_us, 0);
112    }
113
114    #[test]
115    fn test_record_parse_time() {
116        let mut metrics = QueryMetrics::new();
117        metrics.record_parse_time(Duration::from_micros(100));
118        assert_eq!(metrics.parse_time_us, 100);
119    }
120
121    #[test]
122    fn test_to_map() {
123        let mut metrics = QueryMetrics::new();
124        metrics.parse_time_us = 100;
125        metrics.total_time_us = 1000;
126
127        let map = metrics.to_map();
128        assert_eq!(map.get("parse_time_us"), Some(&100));
129        assert_eq!(map.get("total_time_us"), Some(&1000));
130    }
131}