Struct Logger

Source
pub struct Logger {
    pub verbose: bool,
    pub quiet: bool,
    pub start_time: Option<Instant>,
}
Expand description

Logger responsible for all user-visible output

Fields§

§verbose: bool§quiet: bool§start_time: Option<Instant>

Implementations§

Source§

impl Logger

Source

pub fn new(verbose: bool) -> Self

Examples found in repository?
examples/basic_usage_demo.rs (line 36)
29async fn main() -> Result<()> {
30    println!("🚀 Docker Image Pusher - Basic Usage Demo");
31    println!("==========================================");
32    println!("This demo corresponds to README Quick Start examples");
33    println!();
34
35    // Initialize logger for verbose output
36    let logger = Logger::new(true);
37    
38    // Configuration from environment
39    let registry_username = env::var("REGISTRY_USERNAME").unwrap_or_else(|_| {
40        println!("⚠️  REGISTRY_USERNAME not set, using demo credentials");
41        "demo_user".to_string()
42    });
43    
44    let registry_password = env::var("REGISTRY_PASSWORD").unwrap_or_else(|_| {
45        println!("⚠️  REGISTRY_PASSWORD not set, using demo credentials");
46        "demo_pass".to_string()
47    });
48    
49    let target_registry = env::var("TARGET_REGISTRY").unwrap_or_else(|_| {
50        "registry.example.com".to_string()
51    });
52
53    let cache_dir = ".cache_basic_demo";
54    
55    // Clean up previous demo
56    let _ = std::fs::remove_dir_all(cache_dir);
57    
58    logger.section("Demo 1: Basic Extract and Push Workflow");
59    println!("📝 Scenario: Extract tar file → Cache → Push to registry");
60    println!("📄 Command equivalent:");
61    println!("   docker-image-pusher extract --file image.tar --verbose");
62    println!("   docker-image-pusher push --source image:tag --target {}/app:v1.0", target_registry);
63    println!();
64    
65    // Demo the basic workflow
66    demo_extract_and_push(&logger, cache_dir, &target_registry, &registry_username, &registry_password).await?;
67    
68    logger.section("Demo 2: Pull and Cache Workflow");
69    println!("📝 Scenario: Pull from registry → Cache locally");
70    println!("📄 Command equivalent:");
71    println!("   docker-image-pusher pull --image nginx:latest --verbose");
72    println!();
73    
74    demo_pull_and_cache(&logger, cache_dir, &registry_username, &registry_password).await?;
75    
76    logger.section("Demo 3: Complete Pull-to-Push Migration");
77    println!("📝 Scenario: Pull from source → Cache → Push to target");
78    println!("📄 Command equivalent:");
79    println!("   docker-image-pusher pull --image alpine:latest");
80    println!("   docker-image-pusher push --source alpine:latest --target {}/alpine:migrated", target_registry);
81    println!();
82    
83    demo_complete_migration(&logger, cache_dir, &target_registry, &registry_username, &registry_password).await?;
84    
85    println!("✅ Basic usage demo completed successfully!");
86    println!("📚 These examples correspond to the README Quick Start section");
87    
88    Ok(())
89}
More examples
Hide additional examples
examples/concurrency_monitoring_demo.rs (line 15)
11async fn main() -> Result<(), Box<dyn std::error::Error>> {
12    println!("🚀 Docker Image Pusher - Concurrency Monitoring Demo");
13    println!("====================================================");
14    
15    let logger = Logger::new(false); // false for non-verbose mode
16    
17    // Create blob handler with different concurrency configurations
18    println!("\n📊 Testing different concurrency configurations:");
19    
20    // Test 1: Default configuration (should be 3 concurrent tasks now)
21    let default_config = PipelineConfig::default();
22    let _blob_handler_default = BlobHandler::with_config(logger.clone(), default_config.clone());
23    
24    println!("✅ Default Configuration:");
25    println!("   - Max concurrent tasks: {}", default_config.max_concurrent);
26    println!("   - Retry attempts: {}", default_config.retry_attempts);
27    println!("   - Timeout: {}s", default_config.timeout_seconds);
28    
29    // Test 2: Conservative configuration (1 concurrent task)
30    let conservative_config = PipelineConfig {
31        max_concurrent: 1,
32        ..PipelineConfig::default()
33    };
34    let _blob_handler_conservative = BlobHandler::with_config(logger.clone(), conservative_config.clone());
35    
36    println!("\n🔒 Conservative Configuration:");
37    println!("   - Max concurrent tasks: {}", conservative_config.max_concurrent);
38    println!("   - This prevents memory exhaustion for very large images");
39    
40    // Test 3: Aggressive configuration (5 concurrent tasks)
41    let aggressive_config = PipelineConfig {
42        max_concurrent: 5,
43        ..PipelineConfig::default()
44    };
45    let _blob_handler_aggressive = BlobHandler::with_config(logger.clone(), aggressive_config.clone());
46    
47    println!("\n⚡ Aggressive Configuration:");
48    println!("   - Max concurrent tasks: {}", aggressive_config.max_concurrent);
49    println!("   - Use with caution - may cause SIGKILL for large blobs");
50    
51    println!("\n🎯 Key Features of Concurrency Monitoring:");
52    println!("   • Real-time active task count in upload logs");
53    println!("   • Adaptive concurrency based on blob sizes:");
54    println!("     - Blobs > 1GB: Max 1 concurrent task");
55    println!("     - Blobs > 500MB: Max 2 concurrent tasks");
56    println!("     - Memory-based scaling for smaller blobs");
57    println!("   • Peak concurrent tasks summary");
58    println!("   • Periodic progress updates every 5 seconds");
59    
60    println!("\n📈 Sample Upload Logs with Concurrency Info:");
61    println!("   Upload task 1: Processing layer blob abcd1234... (150.2 MB) [Active tasks: 1]");
62    println!("   Upload task 2: Processing layer blob efgh5678... (75.8 MB) [Active tasks: 2]");
63    println!("   ✅ Blob abcd1234 uploaded in 15.3s (9.8 MB/s) [Active tasks: 1]");
64    println!("   📊 Upload progress: 2 active tasks, 1 remaining");
65    println!("   ✅ Unified Pipeline completed successfully (avg speed: 12.5 MB/s) [Peak concurrent tasks: 3]");
66    
67    println!("\n🛡️  Memory Protection Benefits:");
68    println!("   • Prevents SIGKILL termination from excessive memory usage");
69    println!("   • 2GB memory limit with intelligent blob size detection");
70    println!("   • Conservative handling of large total image sizes (>10GB)");
71    println!("   • 10MB overhead estimation per concurrent blob");
72    
73    println!("\n✨ Enhanced Error Handling:");
74    println!("   • Individual task failure tracking");
75    println!("   • Active task count shown in error messages");
76    println!("   • Graceful degradation under memory pressure");
77    
78    logger.success("Demo completed successfully! Your blob uploads now have full visibility into concurrent task execution.");
79    
80    Ok(())
81}
Source

pub fn new_quiet() -> Self

Source

pub fn section(&self, title: &str)

Main section heading

Examples found in repository?
examples/basic_usage_demo.rs (line 58)
29async fn main() -> Result<()> {
30    println!("🚀 Docker Image Pusher - Basic Usage Demo");
31    println!("==========================================");
32    println!("This demo corresponds to README Quick Start examples");
33    println!();
34
35    // Initialize logger for verbose output
36    let logger = Logger::new(true);
37    
38    // Configuration from environment
39    let registry_username = env::var("REGISTRY_USERNAME").unwrap_or_else(|_| {
40        println!("⚠️  REGISTRY_USERNAME not set, using demo credentials");
41        "demo_user".to_string()
42    });
43    
44    let registry_password = env::var("REGISTRY_PASSWORD").unwrap_or_else(|_| {
45        println!("⚠️  REGISTRY_PASSWORD not set, using demo credentials");
46        "demo_pass".to_string()
47    });
48    
49    let target_registry = env::var("TARGET_REGISTRY").unwrap_or_else(|_| {
50        "registry.example.com".to_string()
51    });
52
53    let cache_dir = ".cache_basic_demo";
54    
55    // Clean up previous demo
56    let _ = std::fs::remove_dir_all(cache_dir);
57    
58    logger.section("Demo 1: Basic Extract and Push Workflow");
59    println!("📝 Scenario: Extract tar file → Cache → Push to registry");
60    println!("📄 Command equivalent:");
61    println!("   docker-image-pusher extract --file image.tar --verbose");
62    println!("   docker-image-pusher push --source image:tag --target {}/app:v1.0", target_registry);
63    println!();
64    
65    // Demo the basic workflow
66    demo_extract_and_push(&logger, cache_dir, &target_registry, &registry_username, &registry_password).await?;
67    
68    logger.section("Demo 2: Pull and Cache Workflow");
69    println!("📝 Scenario: Pull from registry → Cache locally");
70    println!("📄 Command equivalent:");
71    println!("   docker-image-pusher pull --image nginx:latest --verbose");
72    println!();
73    
74    demo_pull_and_cache(&logger, cache_dir, &registry_username, &registry_password).await?;
75    
76    logger.section("Demo 3: Complete Pull-to-Push Migration");
77    println!("📝 Scenario: Pull from source → Cache → Push to target");
78    println!("📄 Command equivalent:");
79    println!("   docker-image-pusher pull --image alpine:latest");
80    println!("   docker-image-pusher push --source alpine:latest --target {}/alpine:migrated", target_registry);
81    println!();
82    
83    demo_complete_migration(&logger, cache_dir, &target_registry, &registry_username, &registry_password).await?;
84    
85    println!("✅ Basic usage demo completed successfully!");
86    println!("📚 These examples correspond to the README Quick Start section");
87    
88    Ok(())
89}
Source

pub fn subsection(&self, title: &str)

Sub-section heading

Source

pub fn trace(&self, message: &str)

Source

pub fn debug(&self, message: &str)

Source

pub fn verbose(&self, message: &str)

Source

pub fn info(&self, message: &str)

Information message

Examples found in repository?
examples/basic_usage_demo.rs (line 98)
91async fn demo_extract_and_push(
92    logger: &Logger,
93    _cache_dir: &str,
94    target_registry: &str,
95    username: &str,
96    _password: &str,
97) -> Result<()> {
98    logger.info("Creating demo tar file (simulated)...");
99    
100    // In a real scenario, you would have an actual tar file
101    // For demo purposes, we'll simulate the operation
102    println!("📦 Would extract tar file and cache locally");
103    println!("🚀 Would push cached image to: {}/project/app:v1.0", target_registry);
104    
105    // Create registry client for demonstration
106    let registry_url = format!("https://{}", target_registry);
107    let _client = RegistryClientBuilder::new(registry_url)
108        .with_verbose(true)
109        .build()?;
110    
111    logger.info(&format!("Registry client created for: {}", target_registry));
112    logger.info(&format!("Would authenticate with username: {}", username));
113    
114    // Note: In production, you would:
115    // 1. Use ExtractAndCache operation mode with actual tar file
116    // 2. Use PushFromCacheUsingManifest operation mode
117    
118    Ok(())
119}
120
121async fn demo_pull_and_cache(
122    logger: &Logger,
123    cache_dir: &str,
124    _username: &str,
125    _password: &str,
126) -> Result<()> {
127    logger.info("Demonstrating pull and cache workflow...");
128    
129    // Create image manager
130    let mut _image_manager = ImageManager::new(Some(cache_dir), true)?;
131    
132    println!("🔽 Would pull nginx:latest from Docker Hub");
133    println!("💾 Would cache image locally in: {}", cache_dir);
134    
135    // In production, you would use:
136    // let operation = OperationMode::PullAndCache {
137    //     registry_url: "https://registry-1.docker.io".to_string(),
138    //     repository: "library/nginx".to_string(),
139    //     reference: "latest".to_string(),
140    //     cache_dir: cache_dir.to_string(),
141    //     auth_config: Some(auth_config),
142    // };
143    
144    logger.info("Pull and cache operation configured (demo mode)");
145    
146    Ok(())
147}
148
149async fn demo_complete_migration(
150    logger: &Logger,
151    _cache_dir: &str,
152    target_registry: &str,
153    _username: &str,
154    _password: &str,
155) -> Result<()> {
156    logger.info("Demonstrating complete migration workflow...");
157    
158    println!("🔄 Complete migration workflow:");
159    println!("   1. Pull alpine:latest from Docker Hub");
160    println!("   2. Cache locally");
161    println!("   3. Push to target registry: {}/alpine:migrated", target_registry);
162    
163    // This would involve:
164    // 1. PullAndCache operation
165    // 2. PushFromCacheUsingManifest operation
166    
167    logger.info("Migration workflow completed (demo mode)");
168    
169    Ok(())
170}
Source

pub fn success(&self, message: &str)

Success message

Examples found in repository?
examples/concurrency_monitoring_demo.rs (line 78)
11async fn main() -> Result<(), Box<dyn std::error::Error>> {
12    println!("🚀 Docker Image Pusher - Concurrency Monitoring Demo");
13    println!("====================================================");
14    
15    let logger = Logger::new(false); // false for non-verbose mode
16    
17    // Create blob handler with different concurrency configurations
18    println!("\n📊 Testing different concurrency configurations:");
19    
20    // Test 1: Default configuration (should be 3 concurrent tasks now)
21    let default_config = PipelineConfig::default();
22    let _blob_handler_default = BlobHandler::with_config(logger.clone(), default_config.clone());
23    
24    println!("✅ Default Configuration:");
25    println!("   - Max concurrent tasks: {}", default_config.max_concurrent);
26    println!("   - Retry attempts: {}", default_config.retry_attempts);
27    println!("   - Timeout: {}s", default_config.timeout_seconds);
28    
29    // Test 2: Conservative configuration (1 concurrent task)
30    let conservative_config = PipelineConfig {
31        max_concurrent: 1,
32        ..PipelineConfig::default()
33    };
34    let _blob_handler_conservative = BlobHandler::with_config(logger.clone(), conservative_config.clone());
35    
36    println!("\n🔒 Conservative Configuration:");
37    println!("   - Max concurrent tasks: {}", conservative_config.max_concurrent);
38    println!("   - This prevents memory exhaustion for very large images");
39    
40    // Test 3: Aggressive configuration (5 concurrent tasks)
41    let aggressive_config = PipelineConfig {
42        max_concurrent: 5,
43        ..PipelineConfig::default()
44    };
45    let _blob_handler_aggressive = BlobHandler::with_config(logger.clone(), aggressive_config.clone());
46    
47    println!("\n⚡ Aggressive Configuration:");
48    println!("   - Max concurrent tasks: {}", aggressive_config.max_concurrent);
49    println!("   - Use with caution - may cause SIGKILL for large blobs");
50    
51    println!("\n🎯 Key Features of Concurrency Monitoring:");
52    println!("   • Real-time active task count in upload logs");
53    println!("   • Adaptive concurrency based on blob sizes:");
54    println!("     - Blobs > 1GB: Max 1 concurrent task");
55    println!("     - Blobs > 500MB: Max 2 concurrent tasks");
56    println!("     - Memory-based scaling for smaller blobs");
57    println!("   • Peak concurrent tasks summary");
58    println!("   • Periodic progress updates every 5 seconds");
59    
60    println!("\n📈 Sample Upload Logs with Concurrency Info:");
61    println!("   Upload task 1: Processing layer blob abcd1234... (150.2 MB) [Active tasks: 1]");
62    println!("   Upload task 2: Processing layer blob efgh5678... (75.8 MB) [Active tasks: 2]");
63    println!("   ✅ Blob abcd1234 uploaded in 15.3s (9.8 MB/s) [Active tasks: 1]");
64    println!("   📊 Upload progress: 2 active tasks, 1 remaining");
65    println!("   ✅ Unified Pipeline completed successfully (avg speed: 12.5 MB/s) [Peak concurrent tasks: 3]");
66    
67    println!("\n🛡️  Memory Protection Benefits:");
68    println!("   • Prevents SIGKILL termination from excessive memory usage");
69    println!("   • 2GB memory limit with intelligent blob size detection");
70    println!("   • Conservative handling of large total image sizes (>10GB)");
71    println!("   • 10MB overhead estimation per concurrent blob");
72    
73    println!("\n✨ Enhanced Error Handling:");
74    println!("   • Individual task failure tracking");
75    println!("   • Active task count shown in error messages");
76    println!("   • Graceful degradation under memory pressure");
77    
78    logger.success("Demo completed successfully! Your blob uploads now have full visibility into concurrent task execution.");
79    
80    Ok(())
81}
Source

pub fn warning(&self, message: &str)

Warning message

Source

pub fn error(&self, message: &str)

Error message

Source

pub fn step(&self, message: &str)

Step information

Source

pub fn progress(&self, message: &str)

Progress information

Source

pub fn progress_done(&self)

Progress completion

Source

pub fn detail(&self, message: &str)

Detailed information (only shown in verbose mode)

Source

pub fn summary(&self, title: &str, items: &[String])

Source

pub fn summary_kv(&self, title: &str, items: &[(&str, String)])

Key-value pair summary display

Source

pub fn list(&self, title: &str, items: &[String])

Source

pub fn format_size(&self, bytes: u64) -> String

Format file size in human-readable units

Source

pub fn format_duration(&self, duration: Duration) -> String

Format duration in human-readable format

Source

pub fn format_speed(&self, bytes_per_sec: u64) -> String

Format transfer speed in human-readable format

Source

pub fn display_live_progress(&self, progress: &ProgressState)

显示实时进度状态

Source

pub fn display_detailed_progress(&self, progress: &ProgressState)

Display detailed parallel task status

Source

pub fn notify_concurrency_adjustment( &self, old_value: usize, new_value: usize, reason: &str, )

Display concurrency adjustment notification

Source

pub fn notify_task_start( &self, task_type: &str, layer_index: usize, size: u64, priority: u64, )

Display task start notification

Source

pub fn notify_task_complete( &self, task_type: &str, layer_index: usize, duration: Duration, size: u64, )

Display task completion notification

Source

pub fn display_simple_progress( &self, completed: usize, total: usize, message: &str, )

Display simple progress information

Trait Implementations§

Source§

impl Clone for Logger

Source§

fn clone(&self) -> Logger

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Logger

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Logger

§

impl RefUnwindSafe for Logger

§

impl Send for Logger

§

impl Sync for Logger

§

impl Unpin for Logger

§

impl UnwindSafe for Logger

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,