docker_image_pusher/logging/
mod.rs1use std::io::{self, Write};
7use std::time::{Duration, Instant};
8
9#[derive(Debug, Clone)]
11pub struct Logger {
12 pub verbose: bool,
13 pub quiet: bool,
14 pub start_time: Option<Instant>,
15}
16
17impl Logger {
18 pub fn new(verbose: bool) -> Self {
19 Self {
20 verbose,
21 quiet: false,
22 start_time: Some(Instant::now()),
23 }
24 }
25
26 pub fn new_quiet() -> Self {
27 Self {
28 verbose: false,
29 quiet: true,
30 start_time: Some(Instant::now()),
31 }
32 }
33
34 pub fn section(&self, title: &str) {
36 if !self.quiet {
37 println!("\n=== {} ===", title);
38 }
39 }
40
41 pub fn subsection(&self, title: &str) {
43 if !self.quiet {
44 println!("\n--- {} ---", title);
45 }
46 }
47
48 pub fn trace(&self, message: &str) {
50 if self.verbose && !self.quiet {
51 println!("š TRACE: {}", message);
52 }
53 }
54
55 pub fn debug(&self, message: &str) {
56 if self.verbose && !self.quiet {
57 println!("š DEBUG: {}", message);
58 }
59 }
60
61 pub fn verbose(&self, message: &str) {
62 if self.verbose && !self.quiet {
63 println!("š {}", message);
64 }
65 }
66
67 pub fn info(&self, message: &str) {
69 if !self.quiet {
70 println!("ā¹ļø {}", message);
71 }
72 }
73
74 pub fn success(&self, message: &str) {
76 if !self.quiet {
77 println!("ā
{}", message);
78 }
79 }
80
81 pub fn warning(&self, message: &str) {
83 if !self.quiet {
84 println!("ā ļø WARNING: {}", message);
85 }
86 }
87
88 pub fn error(&self, message: &str) {
90 eprintln!("ā ERROR: {}", message);
91 }
92
93 pub fn step(&self, message: &str) {
95 if !self.quiet {
96 println!("ā¶ļø {}", message);
97 }
98 }
99
100 pub fn progress(&self, message: &str) {
102 if !self.quiet {
103 print!("ā³ {}...", message);
104 let _ = io::stdout().flush();
105 }
106 }
107
108 pub fn progress_done(&self) {
110 if !self.quiet {
111 println!(" Done");
112 }
113 }
114
115 pub fn detail(&self, message: &str) {
117 if self.verbose && !self.quiet {
118 println!(" {}", message);
119 }
120 }
121
122 pub fn summary(&self, title: &str, items: &[String]) {
124 if !self.quiet {
125 println!("\nš {}", title);
126 println!("{}", "ā".repeat(title.len() + 3));
127
128 for item in items {
129 println!(" ⢠{}", item);
130 }
131
132 if items.is_empty() {
133 println!(" (No items to display)");
134 }
135 }
136 }
137
138 pub fn summary_kv(&self, title: &str, items: &[(&str, String)]) {
140 if !self.quiet {
141 self.subsection(title);
142 for (key, value) in items {
143 println!(" {}: {}", key, value);
144 }
145 }
146 }
147
148 pub fn list(&self, title: &str, items: &[String]) {
150 if !self.quiet {
151 self.subsection(title);
152 for (i, item) in items.iter().enumerate() {
153 println!(" {}. {}", i + 1, item);
154 }
155
156 if items.is_empty() {
157 println!(" (No items to display)");
158 }
159 }
160 }
161
162 pub fn format_size(&self, bytes: u64) -> String {
164 if bytes < 1024 {
165 format!("{} B", bytes)
166 } else if bytes < 1024 * 1024 {
167 format!("{:.1} KB", bytes as f64 / 1024.0)
168 } else if bytes < 1024 * 1024 * 1024 {
169 format!("{:.1} MB", bytes as f64 / (1024.0 * 1024.0))
170 } else {
171 format!("{:.1} GB", bytes as f64 / (1024.0 * 1024.0 * 1024.0))
172 }
173 }
174
175 pub fn format_duration(&self, duration: Duration) -> String {
177 let secs = duration.as_secs();
178 if secs < 60 {
179 format!("{}s", secs)
180 } else if secs < 3600 {
181 format!("{}m{}s", secs / 60, secs % 60)
182 } else {
183 format!("{}h{}m{}s", secs / 3600, (secs % 3600) / 60, secs % 60)
184 }
185 }
186
187 pub fn format_speed(&self, bytes_per_sec: u64) -> String {
189 format!("{}/s", self.format_size(bytes_per_sec))
190 }
191}