qubit_progress/reporter/
text_reporter.rs1use std::fmt::Write as _;
11use std::io::Write;
12use std::sync::Mutex;
13use std::sync::PoisonError;
14
15use crate::Event;
16use crate::Reporter;
17use crate::ReporterError;
18
19pub struct TextReporter<W> {
21 writer: Mutex<W>,
23}
24
25impl<W> TextReporter<W> {
26 #[must_use]
28 pub const fn new(writer: W) -> Self {
29 Self {
30 writer: Mutex::new(writer),
31 }
32 }
33
34 pub fn into_inner(self) -> Result<W, PoisonError<W>> {
39 self.writer.into_inner()
40 }
41}
42
43impl<W> Reporter for TextReporter<W>
44where
45 W: Write + Send,
46{
47 fn report(&self, event: &Event) -> Result<(), ReporterError> {
49 let mut line = format_event(event);
50 line.push('\n');
51 let mut writer = self.writer.lock().map_err(|_| {
52 ReporterError::message("text reporter mutex is poisoned")
53 })?;
54 writer
55 .write_all(line.as_bytes())
56 .map_err(ReporterError::new)
57 }
58}
59
60fn format_event(event: &Event) -> String {
62 let mut line = format!(
63 "operation={} sequence={} phase={} elapsed={:?}",
64 event.operation_id(),
65 event.sequence(),
66 event.phase().as_str(),
67 event.elapsed(),
68 );
69 if let Some(stage) = event.stage() {
70 let _ = write!(
71 line,
72 " stage={}({}) position={:?} total={:?}",
73 stage.id().escape_default(),
74 stage.name().escape_default(),
75 stage.position_value(),
76 stage.total(),
77 );
78 }
79 for (key, value) in event.attributes().iter() {
80 let _ = write!(
81 line,
82 " attribute={}({})",
83 key.escape_default(),
84 value.escape_default(),
85 );
86 }
87 for metric in event.metrics() {
88 let _ = write!(
89 line,
90 " metric={}({}) total={:?} completed={} active={} succeeded={} failed={} cancelled={}",
91 metric.id().escape_default(),
92 metric.name().escape_default(),
93 metric.total(),
94 metric.completed(),
95 metric.active(),
96 metric.succeeded(),
97 metric.failed(),
98 metric.cancelled(),
99 );
100 }
101 line
102}