Skip to main content

qubit_progress/reporter/impls/
logger_progress_reporter.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10use qubit_function::ArcConsumer;
11
12use super::human_readable_progress_reporter::HumanReadableProgressReporter;
13use crate::{
14    model::ProgressEvent,
15    reporter::ProgressReporter,
16};
17
18/// Progress reporter that emits human-readable metric snapshots through `log`.
19pub struct LoggerProgressReporter {
20    /// Log target used for emitted records.
21    target: String,
22    /// Log level used for emitted records.
23    level: log::Level,
24    /// Human-readable reporter that consumes formatted strings.
25    inner: HumanReadableProgressReporter,
26}
27
28impl LoggerProgressReporter {
29    /// Creates a logger reporter at [`log::Level::Info`].
30    ///
31    /// # Parameters
32    ///
33    /// * `target` - Log target used for emitted records.
34    ///
35    /// # Returns
36    ///
37    /// A logger-backed progress reporter.
38    #[inline]
39    pub fn new(target: &str) -> Self {
40        Self::with_target_and_level(target, log::Level::Info)
41    }
42
43    /// Returns a copy configured with a log level.
44    ///
45    /// # Parameters
46    ///
47    /// * `level` - Log level used for emitted records.
48    ///
49    /// # Returns
50    ///
51    /// This reporter configured with `level`.
52    #[inline]
53    #[must_use]
54    pub fn with_level(self, level: log::Level) -> Self {
55        Self::with_target_and_level(self.target.as_str(), level)
56    }
57
58    /// Returns the log target.
59    ///
60    /// # Returns
61    ///
62    /// The target used for emitted log records.
63    #[inline]
64    pub fn target(&self) -> &str {
65        self.target.as_str()
66    }
67
68    /// Returns the log level.
69    ///
70    /// # Returns
71    ///
72    /// The level used for emitted log records.
73    #[inline]
74    pub const fn level(&self) -> log::Level {
75        self.level
76    }
77
78    /// Creates a logger reporter from target and level.
79    ///
80    /// # Parameters
81    ///
82    /// * `target` - Log target used for emitted records.
83    /// * `level` - Log level used for emitted records.
84    ///
85    /// # Returns
86    ///
87    /// A configured logger reporter.
88    fn with_target_and_level(target: &str, level: log::Level) -> Self {
89        let target = target.to_owned();
90        let log_target = target.clone();
91        let consumer = ArcConsumer::new(move |line: &String| {
92            log::log!(target: log_target.as_str(), level, "{line}");
93        });
94        Self {
95            target,
96            level,
97            inner: HumanReadableProgressReporter::new(consumer),
98        }
99    }
100}
101
102impl Default for LoggerProgressReporter {
103    /// Creates a logger reporter with the default target.
104    ///
105    /// # Returns
106    ///
107    /// A logger-backed reporter at [`log::Level::Info`].
108    #[inline]
109    fn default() -> Self {
110        Self::new("qubit_progress")
111    }
112}
113
114impl ProgressReporter for LoggerProgressReporter {
115    /// Logs one line for every metric snapshot in the event.
116    ///
117    /// # Parameters
118    ///
119    /// * `event` - Progress event to log.
120    #[inline]
121    fn report(&self, event: &ProgressEvent) {
122        self.inner.report(event);
123    }
124}