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