use std::time::Duration;
use super::{
ProgressReporter,
progress_format::{
format_duration,
progress_percent,
},
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LoggerProgressReporter {
target: String,
level: log::Level,
}
impl LoggerProgressReporter {
#[inline]
pub fn new(target: impl Into<String>) -> Self {
Self {
target: target.into(),
level: log::Level::Info,
}
}
#[inline]
pub fn with_level(self, level: log::Level) -> Self {
Self { level, ..self }
}
#[inline]
pub fn target(&self) -> &str {
self.target.as_str()
}
#[inline]
pub const fn level(&self) -> log::Level {
self.level
}
fn log_line(&self, message: String) {
log::log!(target: self.target.as_str(), self.level, "{message}");
}
fn log_process_speed(&self, completed_count: usize, remaining_count: usize, elapsed: Duration) {
if completed_count == 0 {
self.log_line("No task processed.".to_owned());
return;
}
let elapsed_ms = elapsed.as_secs_f64() * 1000.0;
let speed = elapsed_ms / completed_count as f64;
let tasks_per_minute =
completed_count as f64 * 60.0 * 1000.0 / elapsed_ms.max(f64::EPSILON);
self.log_line(format!(
"Average speed: {speed:.2} ms/task, i.e., {tasks_per_minute:.2} tasks/min"
));
let remaining = Duration::from_secs_f64(remaining_count as f64 * speed / 1000.0);
self.log_line(format!(
"Estimated remaining time: {}",
format_duration(remaining)
));
}
}
impl Default for LoggerProgressReporter {
fn default() -> Self {
Self::new("qubit_batch::progress")
}
}
impl ProgressReporter for LoggerProgressReporter {
fn start(&self, total_count: usize) {
self.log_line(format!("Starting {total_count} tasks..."));
}
fn process(
&self,
total_count: usize,
active_count: usize,
completed_count: usize,
elapsed: Duration,
) {
self.log_line("--------------------------------------------------".to_owned());
self.log_line("Waiting for all batch tasks to finish...".to_owned());
self.log_line(format!("Total tasks: {total_count}"));
self.log_line(format!("Current active tasks: {active_count}"));
self.log_line(format!("Current completed tasks: {completed_count}"));
self.log_line(format!(
"Current tasks in queue: {}",
total_count.saturating_sub(completed_count + active_count)
));
self.log_line(format!(
"Progress: {:.2}%",
progress_percent(completed_count, total_count)
));
self.log_process_speed(
completed_count,
total_count.saturating_sub(completed_count),
elapsed,
);
}
fn finish(&self, total_count: usize, elapsed: Duration) {
self.log_line(format!("All {total_count} tasks are finished."));
self.log_line(format!(
"Processed {total_count} tasks in {}.",
format_duration(elapsed)
));
}
}