Skip to main content

nexus_sdk/
performance.rs

1//! Performance monitoring operations
2
3use crate::client::NexusClient;
4use crate::error::{NexusError, Result};
5use serde::Deserialize;
6
7/// Query statistics summary
8#[derive(Debug, Clone, Deserialize)]
9pub struct QueryStatisticsSummary {
10    /// Total queries executed
11    pub total_queries: u64,
12    /// Successful queries
13    pub successful_queries: u64,
14    /// Failed queries
15    pub failed_queries: u64,
16    /// Total execution time in milliseconds
17    pub total_execution_time_ms: u64,
18    /// Average execution time in milliseconds
19    pub average_execution_time_ms: u64,
20    /// Minimum execution time in milliseconds
21    pub min_execution_time_ms: u64,
22    /// Maximum execution time in milliseconds
23    pub max_execution_time_ms: u64,
24    /// Number of slow queries logged
25    pub slow_query_count: usize,
26}
27
28/// Query pattern statistics
29#[derive(Debug, Clone, Deserialize)]
30pub struct QueryPatternStats {
31    /// Query pattern
32    pub pattern: String,
33    /// Number of times this pattern was executed
34    pub count: u64,
35    /// Average execution time in milliseconds
36    pub avg_time_ms: u64,
37    /// Minimum execution time in milliseconds
38    pub min_time_ms: u64,
39    /// Maximum execution time in milliseconds
40    pub max_time_ms: u64,
41    /// Number of successful executions
42    pub success_count: u64,
43    /// Number of failed executions
44    pub failure_count: u64,
45}
46
47/// Query statistics response
48#[derive(Debug, Clone, Deserialize)]
49pub struct QueryStatisticsResponse {
50    /// Overall statistics
51    pub statistics: QueryStatisticsSummary,
52    /// Pattern statistics
53    pub patterns: Vec<QueryPatternStats>,
54}
55
56/// Slow query record
57#[derive(Debug, Clone, Deserialize)]
58pub struct SlowQueryRecord {
59    /// Query string
60    pub query: String,
61    /// Execution time in milliseconds
62    pub execution_time_ms: u64,
63    /// Timestamp
64    pub timestamp: String,
65    /// Whether the query was successful
66    pub success: bool,
67    /// Error message if failed
68    #[serde(skip_serializing_if = "Option::is_none")]
69    pub error: Option<String>,
70    /// Number of rows returned
71    pub rows_returned: u64,
72}
73
74/// Slow queries response
75#[derive(Debug, Clone, Deserialize)]
76pub struct SlowQueriesResponse {
77    /// Number of slow queries
78    pub count: usize,
79    /// Slow query records
80    pub queries: Vec<SlowQueryRecord>,
81}
82
83/// Plan cache statistics
84#[derive(Debug, Clone, Deserialize)]
85pub struct PlanCacheStatistics {
86    /// Number of cached plans
87    pub cached_plans: usize,
88    /// Maximum cache size
89    pub max_size: usize,
90    /// Current memory usage in bytes
91    pub current_memory_bytes: u64,
92    /// Maximum memory usage in bytes
93    pub max_memory_bytes: u64,
94    /// Cache hit rate (0.0 to 1.0)
95    pub hit_rate: f64,
96}
97
98/// Plan cache statistics response
99#[derive(Debug, Clone, Deserialize)]
100pub struct PlanCacheStatisticsResponse {
101    /// Number of cached plans
102    pub cached_plans: usize,
103    /// Maximum cache size
104    pub max_size: usize,
105    /// Current memory usage in bytes
106    pub current_memory_bytes: u64,
107    /// Maximum memory usage in bytes
108    pub max_memory_bytes: u64,
109    /// Cache hit rate (0.0 to 1.0)
110    pub hit_rate: f64,
111}
112
113impl NexusClient {
114    /// Get query statistics
115    ///
116    /// # Example
117    ///
118    /// ```no_run
119    /// # use nexus_sdk::NexusClient;
120    /// # #[tokio::main]
121    /// # async fn main() -> Result<(), nexus_sdk::NexusError> {
122    /// # let client = NexusClient::new("http://localhost:15474")?;
123    /// let stats = client.get_query_statistics().await?;
124    /// tracing::info!("Total queries: {}", stats.statistics.total_queries);
125    /// tracing::info!("Average execution time: {}ms", stats.statistics.average_execution_time_ms);
126    /// # Ok(())
127    /// # }
128    /// ```
129    pub async fn get_query_statistics(&self) -> Result<QueryStatisticsResponse> {
130        let url = self.get_base_url().join("/performance/statistics")?;
131        let mut request_builder = self.get_client().get(url);
132
133        request_builder = self.add_auth_headers(request_builder)?;
134
135        let response = self.execute_with_retry(request_builder).await?;
136        let status = response.status();
137
138        if status.is_success() {
139            let result: QueryStatisticsResponse = response.json().await?;
140            Ok(result)
141        } else {
142            let error_text = response
143                .text()
144                .await
145                .unwrap_or_else(|_| "Unknown error".to_string());
146            Err(NexusError::Api {
147                message: error_text,
148                status: status.as_u16(),
149            })
150        }
151    }
152
153    /// Get slow queries
154    ///
155    /// # Example
156    ///
157    /// ```no_run
158    /// # use nexus_sdk::NexusClient;
159    /// # #[tokio::main]
160    /// # async fn main() -> Result<(), nexus_sdk::NexusError> {
161    /// # let client = NexusClient::new("http://localhost:15474")?;
162    /// let slow_queries = client.get_slow_queries().await?;
163    /// tracing::info!("Found {} slow queries", slow_queries.count);
164    /// for query in slow_queries.queries {
165    ///     tracing::info!("Query: {} ({}ms)", query.query, query.execution_time_ms);
166    /// }
167    /// # Ok(())
168    /// # }
169    /// ```
170    pub async fn get_slow_queries(&self) -> Result<SlowQueriesResponse> {
171        let url = self.get_base_url().join("/performance/slow-queries")?;
172        let mut request_builder = self.get_client().get(url);
173
174        request_builder = self.add_auth_headers(request_builder)?;
175
176        let response = self.execute_with_retry(request_builder).await?;
177        let status = response.status();
178
179        if status.is_success() {
180            let result: SlowQueriesResponse = response.json().await?;
181            Ok(result)
182        } else {
183            let error_text = response
184                .text()
185                .await
186                .unwrap_or_else(|_| "Unknown error".to_string());
187            Err(NexusError::Api {
188                message: error_text,
189                status: status.as_u16(),
190            })
191        }
192    }
193
194    /// Get plan cache statistics
195    ///
196    /// # Example
197    ///
198    /// ```no_run
199    /// # use nexus_sdk::NexusClient;
200    /// # #[tokio::main]
201    /// # async fn main() -> Result<(), nexus_sdk::NexusError> {
202    /// # let client = NexusClient::new("http://localhost:15474")?;
203    /// let cache_stats = client.get_plan_cache_statistics().await?;
204    /// tracing::info!("Cached plans: {}", cache_stats.cached_plans);
205    /// tracing::info!("Hit rate: {:.2}%", cache_stats.hit_rate * 100.0);
206    /// # Ok(())
207    /// # }
208    /// ```
209    pub async fn get_plan_cache_statistics(&self) -> Result<PlanCacheStatisticsResponse> {
210        let url = self.get_base_url().join("/performance/plan-cache")?;
211        let mut request_builder = self.get_client().get(url);
212
213        request_builder = self.add_auth_headers(request_builder)?;
214
215        let response = self.execute_with_retry(request_builder).await?;
216        let status = response.status();
217
218        if status.is_success() {
219            let result: PlanCacheStatisticsResponse = response.json().await?;
220            Ok(result)
221        } else {
222            let error_text = response
223                .text()
224                .await
225                .unwrap_or_else(|_| "Unknown error".to_string());
226            Err(NexusError::Api {
227                message: error_text,
228                status: status.as_u16(),
229            })
230        }
231    }
232
233    /// Clear plan cache
234    ///
235    /// # Example
236    ///
237    /// ```no_run
238    /// # use nexus_sdk::NexusClient;
239    /// # #[tokio::main]
240    /// # async fn main() -> Result<(), nexus_sdk::NexusError> {
241    /// # let client = NexusClient::new("http://localhost:15474")?;
242    /// let response = client.clear_plan_cache().await?;
243    /// tracing::info!("Plan cache cleared: {:?}", response);
244    /// # Ok(())
245    /// # }
246    /// ```
247    pub async fn clear_plan_cache(&self) -> Result<serde_json::Value> {
248        let url = self.get_base_url().join("/performance/plan-cache/clear")?;
249        let mut request_builder = self.get_client().post(url);
250
251        request_builder = self.add_auth_headers(request_builder)?;
252
253        let response = self.execute_with_retry(request_builder).await?;
254        let status = response.status();
255
256        if status.is_success() {
257            let result: serde_json::Value = response.json().await?;
258            Ok(result)
259        } else {
260            let error_text = response
261                .text()
262                .await
263                .unwrap_or_else(|_| "Unknown error".to_string());
264            Err(NexusError::Api {
265                message: error_text,
266                status: status.as_u16(),
267            })
268        }
269    }
270}