docker_image_pusher/upload/
stats.rs

1//! Upload statistics and monitoring
2
3use std::time::{Duration, Instant};
4use std::sync::Arc;
5use tokio::sync::Mutex;
6
7#[derive(Debug, Clone)]
8pub struct UploadStats {
9    pub total_layers: usize,
10    pub completed_layers: usize,
11    pub failed_layers: usize,
12    pub total_bytes: u64,
13    pub uploaded_bytes: u64,
14    pub start_time: Instant,
15    pub concurrent_uploads: usize,
16    pub avg_speed: u64,
17    pub peak_speed: u64,
18}
19
20impl UploadStats {
21    pub fn new(total_layers: usize, total_bytes: u64, concurrent_uploads: usize) -> Self {
22        Self {
23            total_layers,
24            completed_layers: 0,
25            failed_layers: 0,
26            total_bytes,
27            uploaded_bytes: 0,
28            start_time: Instant::now(),
29            concurrent_uploads,
30            avg_speed: 0,
31            peak_speed: 0,
32        }
33    }
34
35    pub fn add_completed_layer(&mut self, layer_size: u64) {
36        self.completed_layers += 1;
37        self.uploaded_bytes += layer_size;
38        self.update_speeds();
39    }
40
41    pub fn add_failed_layer(&mut self) {
42        self.failed_layers += 1;
43    }
44
45    fn update_speeds(&mut self) {
46        let elapsed = self.start_time.elapsed().as_secs();
47        if elapsed > 0 {
48            let current_speed = self.uploaded_bytes / elapsed;
49            self.avg_speed = current_speed;
50            if current_speed > self.peak_speed {
51                self.peak_speed = current_speed;
52            }
53        }
54    }
55
56    pub fn completion_percentage(&self) -> f64 {
57        if self.total_layers == 0 {
58            100.0
59        } else {
60            (self.completed_layers as f64 / self.total_layers as f64) * 100.0
61        }
62    }
63
64    pub fn estimated_time_remaining(&self) -> Option<Duration> {
65        if self.avg_speed > 0 && self.uploaded_bytes < self.total_bytes {
66            let remaining_bytes = self.total_bytes - self.uploaded_bytes;
67            let remaining_seconds = remaining_bytes / self.avg_speed;
68            Some(Duration::from_secs(remaining_seconds))
69        } else {
70            None
71        }
72    }
73}
74
75pub type SharedStats = Arc<Mutex<UploadStats>>;