dakera_client/
analytics.rs1use serde::{Deserialize, Serialize};
4
5use crate::error::Result;
6use crate::DakeraClient;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct AnalyticsOverview {
15 pub total_queries: u64,
16 pub avg_latency_ms: f64,
17 pub p95_latency_ms: f64,
18 pub p99_latency_ms: f64,
19 pub queries_per_second: f64,
20 pub error_rate: f64,
21 pub cache_hit_rate: f64,
22 pub storage_used_bytes: u64,
23 pub total_vectors: u64,
24 pub total_namespaces: u64,
25 pub uptime_seconds: u64,
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct LatencyAnalytics {
31 pub period: String,
32 pub avg_ms: f64,
33 pub p50_ms: f64,
34 pub p95_ms: f64,
35 pub p99_ms: f64,
36 pub max_ms: f64,
37 #[serde(default)]
38 pub by_operation: std::collections::HashMap<String, OperationLatency>,
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct OperationLatency {
44 pub avg_ms: f64,
45 pub p95_ms: f64,
46 pub count: u64,
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct ThroughputAnalytics {
52 pub period: String,
53 pub total_operations: u64,
54 pub operations_per_second: f64,
55 #[serde(default)]
56 pub by_operation: std::collections::HashMap<String, u64>,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct StorageAnalytics {
62 pub total_bytes: u64,
63 pub index_bytes: u64,
64 pub data_bytes: u64,
65 #[serde(default)]
66 pub by_namespace: std::collections::HashMap<String, NamespaceStorage>,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct NamespaceStorage {
72 pub bytes: u64,
73 pub vector_count: u64,
74}
75
76impl DakeraClient {
81 pub async fn analytics_overview(
83 &self,
84 period: Option<&str>,
85 namespace: Option<&str>,
86 ) -> Result<AnalyticsOverview> {
87 let mut url = format!("{}/v1/analytics/overview", self.base_url);
88 let mut params = Vec::new();
89 if let Some(p) = period {
90 params.push(format!("period={}", p));
91 }
92 if let Some(ns) = namespace {
93 params.push(format!("namespace={}", ns));
94 }
95 if !params.is_empty() {
96 url.push('?');
97 url.push_str(¶ms.join("&"));
98 }
99 let response = self.client.get(&url).send().await?;
100 self.handle_response(response).await
101 }
102
103 pub async fn analytics_latency(
105 &self,
106 period: Option<&str>,
107 namespace: Option<&str>,
108 ) -> Result<LatencyAnalytics> {
109 let mut url = format!("{}/v1/analytics/latency", self.base_url);
110 let mut params = Vec::new();
111 if let Some(p) = period {
112 params.push(format!("period={}", p));
113 }
114 if let Some(ns) = namespace {
115 params.push(format!("namespace={}", ns));
116 }
117 if !params.is_empty() {
118 url.push('?');
119 url.push_str(¶ms.join("&"));
120 }
121 let response = self.client.get(&url).send().await?;
122 self.handle_response(response).await
123 }
124
125 pub async fn analytics_throughput(
127 &self,
128 period: Option<&str>,
129 namespace: Option<&str>,
130 ) -> Result<ThroughputAnalytics> {
131 let mut url = format!("{}/v1/analytics/throughput", self.base_url);
132 let mut params = Vec::new();
133 if let Some(p) = period {
134 params.push(format!("period={}", p));
135 }
136 if let Some(ns) = namespace {
137 params.push(format!("namespace={}", ns));
138 }
139 if !params.is_empty() {
140 url.push('?');
141 url.push_str(¶ms.join("&"));
142 }
143 let response = self.client.get(&url).send().await?;
144 self.handle_response(response).await
145 }
146
147 pub async fn analytics_storage(&self, namespace: Option<&str>) -> Result<StorageAnalytics> {
149 let mut url = format!("{}/v1/analytics/storage", self.base_url);
150 if let Some(ns) = namespace {
151 url.push_str(&format!("?namespace={}", ns));
152 }
153 let response = self.client.get(&url).send().await?;
154 self.handle_response(response).await
155 }
156}