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}