ipfrs_cli/commands/
stats.rs1use anyhow::Result;
13
14use crate::output::{self, format_bytes, print_header, print_kv};
15use crate::progress;
16
17pub async fn stats_repo(format: &str) -> Result<()> {
19 use ipfrs_storage::{BlockStoreConfig, BlockStoreTrait, SledBlockStore};
20
21 let config = BlockStoreConfig::default();
23 let storage_path = config.path.clone();
24 let store = SledBlockStore::new(config)?;
25
26 let cids = store.list_cids()?;
28 let num_blocks = cids.len();
29
30 let mut total_size: u64 = 0;
32 for cid in &cids {
33 if let Some(block) = store.get(cid).await? {
34 total_size += block.size();
35 }
36 }
37
38 match format {
39 "json" => {
40 println!("{{");
41 println!(" \"num_blocks\": {},", num_blocks);
42 println!(" \"total_size\": {},", total_size);
43 println!(" \"storage_path\": \"{}\"", storage_path.display());
44 println!("}}");
45 }
46 _ => {
47 print_header("IPFRS Repository Statistics");
48 print_kv("Number of blocks", &num_blocks.to_string());
49 print_kv("Total size", &format_bytes(total_size));
50 print_kv("Storage path", &storage_path.display().to_string());
51
52 if num_blocks > 0 {
53 let avg_size = total_size / num_blocks as u64;
54 print_kv("Average block size", &format_bytes(avg_size));
55 }
56 }
57 }
58
59 Ok(())
60}
61
62pub async fn stats_bw(format: &str) -> Result<()> {
64 use ipfrs::{Node, NodeConfig};
65
66 let pb = progress::spinner("Collecting bandwidth statistics");
67 let mut node = Node::new(NodeConfig::default())?;
68 node.start().await?;
69
70 let stats = node.network_stats()?;
71 progress::finish_spinner_success(&pb, "Statistics collected");
72
73 match format {
74 "json" => {
75 println!("{{");
76 println!(" \"total_in\": {},", stats.bytes_received);
77 println!(" \"total_out\": {},", stats.bytes_sent);
78 println!(" \"rate_in\": 0,");
79 println!(" \"rate_out\": 0");
80 println!("}}");
81 }
82 _ => {
83 print_header("Bandwidth Statistics");
84 print_kv("Total received", &format_bytes(stats.bytes_received));
85 print_kv("Total sent", &format_bytes(stats.bytes_sent));
86 print_kv("Connected peers", &stats.connected_peers.to_string());
87 }
88 }
89
90 node.stop().await?;
91 Ok(())
92}
93
94pub async fn stats_bitswap(format: &str) -> Result<()> {
96 use ipfrs::{Node, NodeConfig};
97
98 let pb = progress::spinner("Collecting bitswap statistics");
99 let mut node = Node::new(NodeConfig::default())?;
100 node.start().await?;
101
102 let stats = node.bitswap_stats()?;
103 progress::finish_spinner_success(&pb, "Statistics collected");
104
105 match format {
106 "json" => {
107 println!("{{");
108 println!(" \"want_list_size\": {},", stats.want_list_size);
109 println!(" \"have_list_size\": {},", stats.have_list_size);
110 println!(" \"pending_requests\": {},", stats.pending_requests);
111 println!(
112 " \"peers_with_pending_requests\": {}",
113 stats.peers_with_pending_requests
114 );
115 println!("}}");
116 }
117 _ => {
118 print_header("Bitswap Statistics");
119 print_kv("Want list size", &stats.want_list_size.to_string());
120 print_kv("Have list size", &stats.have_list_size.to_string());
121 print_kv("Pending requests", &stats.pending_requests.to_string());
122 print_kv(
123 "Peers with requests",
124 &stats.peers_with_pending_requests.to_string(),
125 );
126 }
127 }
128
129 node.stop().await?;
130 Ok(())
131}
132
133pub fn print_info() {
135 println!("IPFRS - Inter-Planet File RUST System");
136 println!("Version: 0.3.0 (The Fast & The Wise)");
137 println!();
138 println!("Architecture:");
139 println!(" Logical Layer:");
140 println!(" - Semantic Router (Vector Search / Logic Solver)");
141 println!(" - Differentiable Storage (Gradient Tracking)");
142 println!();
143 println!(" Physical Layer:");
144 println!(" - TensorSwap (Optimized Tensor Streaming)");
145 println!(" - Rust Native Store (Sled / ParityDB)");
146 println!(" - Network Stack (libp2p / QUIC)");
147 println!();
148 println!("Technology Stack:");
149 println!(" - Runtime: Tokio async");
150 println!(" - Network: libp2p, QUIC");
151 println!(" - Storage: Sled");
152 println!(" - Zero-Copy: Apache Arrow, Safetensors");
153 println!(" - Vector Search: HNSW");
154}
155
156pub fn print_version() {
158 println!("ipfrs {}", env!("CARGO_PKG_VERSION"));
159}
160
161pub async fn show_id(format: &str) -> Result<()> {
163 use ipfrs::{Node, NodeConfig};
164
165 let mut node = Node::new(NodeConfig::default())?;
166 node.start().await?;
167
168 let peer_id = node.peer_id()?;
169 let stats = node.network_stats()?;
170
171 match format {
172 "json" => {
173 println!("{{");
174 println!(" \"peer_id\": \"{}\",", peer_id);
175 println!(" \"addresses\": [");
176 for (i, addr) in stats.listen_addrs.iter().enumerate() {
177 if i > 0 {
178 println!(",");
179 }
180 print!(" \"{}\"", addr);
181 }
182 println!();
183 println!(" ]");
184 println!("}}");
185 }
186 _ => {
187 println!("Peer ID: {}", peer_id);
188 println!("Addresses:");
189 for addr in &stats.listen_addrs {
190 println!(" {}", addr);
191 }
192 }
193 }
194
195 node.stop().await?;
196 Ok(())
197}
198
199pub async fn ping_peer(peer_id: &str, count: u32) -> Result<()> {
201 use ipfrs::{Node, NodeConfig};
202 use std::time::Instant;
203
204 let mut node = Node::new(NodeConfig::default())?;
205 node.start().await?;
206
207 output::info(&format!("PING {} ({} pings)", peer_id, count));
208
209 let mut successful = 0u32;
210 let mut total_time = std::time::Duration::ZERO;
211
212 for i in 0..count {
213 let start = Instant::now();
214 match node.ping(peer_id).await {
215 Ok(_) => {
216 let elapsed = start.elapsed();
217 total_time += elapsed;
218 successful += 1;
219 println!("seq={} time={:.2}ms", i + 1, elapsed.as_secs_f64() * 1000.0);
220 }
221 Err(e) => {
222 println!("seq={} error: {}", i + 1, e);
223 }
224 }
225
226 if i < count - 1 {
227 tokio::time::sleep(std::time::Duration::from_secs(1)).await;
228 }
229 }
230
231 println!();
232 println!("--- {} ping statistics ---", peer_id);
233 println!(
234 "{} packets transmitted, {} received, {:.1}% packet loss",
235 count,
236 successful,
237 ((count - successful) as f64 / count as f64) * 100.0
238 );
239
240 if successful > 0 {
241 let avg_time = total_time.as_secs_f64() * 1000.0 / successful as f64;
242 println!("rtt avg = {:.2}ms", avg_time);
243 }
244
245 node.stop().await?;
246 Ok(())
247}