• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Xevion / Pac-Man / 17502018700

05 Sep 2025 06:58PM UTC coverage: 31.645%. Remained the same
17502018700

push

github

Xevion
chore: move BufferedWriter into tracing_buffer.rs

0 of 29 new or added lines in 1 file covered. (0.0%)

1081 of 3416 relevant lines covered (31.65%)

796.14 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/platform/tracing_buffer.rs
1
#![allow(dead_code)]
2
//! Buffered tracing setup for handling logs before console attachment.
3

4
use crate::formatter::CustomFormatter;
5
use parking_lot::Mutex;
6
use std::io;
7
use std::io::Write;
8
use std::sync::Arc;
9
use tracing::{debug, Level};
10
use tracing_error::ErrorLayer;
11
use tracing_subscriber::fmt::MakeWriter;
12
use tracing_subscriber::layer::SubscriberExt;
13

14
/// A thread-safe buffered writer that stores logs in memory until flushed.
15
#[derive(Clone)]
16
pub struct BufferedWriter {
17
    buffer: Arc<Mutex<Vec<u8>>>,
18
}
19

20
impl BufferedWriter {
21
    /// Creates a new buffered writer.
NEW
22
    pub fn new() -> Self {
×
NEW
23
        Self {
×
NEW
24
            buffer: Arc::new(Mutex::new(Vec::new())),
×
NEW
25
        }
×
NEW
26
    }
×
27

28
    /// Flushes all buffered content to the provided writer and clears the buffer.
NEW
29
    pub fn flush_to<W: Write>(&self, mut writer: W) -> io::Result<()> {
×
NEW
30
        let mut buffer = self.buffer.lock();
×
NEW
31
        if !buffer.is_empty() {
×
NEW
32
            writer.write_all(&buffer)?;
×
NEW
33
            writer.flush()?;
×
NEW
34
            buffer.clear();
×
NEW
35
        }
×
NEW
36
        Ok(())
×
NEW
37
    }
×
38

39
    /// Returns the current buffer size in bytes.
NEW
40
    pub fn buffer_size(&self) -> usize {
×
NEW
41
        self.buffer.lock().len()
×
NEW
42
    }
×
43
}
44

45
impl Write for BufferedWriter {
NEW
46
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
×
NEW
47
        let mut buffer = self.buffer.lock();
×
NEW
48
        buffer.extend_from_slice(buf);
×
NEW
49
        Ok(buf.len())
×
NEW
50
    }
×
51

NEW
52
    fn flush(&mut self) -> io::Result<()> {
×
NEW
53
        // For buffered writer, flush is a no-op since we're storing in memory
×
NEW
54
        Ok(())
×
NEW
55
    }
×
56
}
57

58
impl Default for BufferedWriter {
NEW
59
    fn default() -> Self {
×
NEW
60
        Self::new()
×
NEW
61
    }
×
62
}
63

64
/// A writer that can switch between buffering and direct output.
65
#[derive(Clone, Default)]
66
pub struct SwitchableWriter {
67
    buffered_writer: BufferedWriter,
68
    direct_mode: std::sync::Arc<parking_lot::Mutex<bool>>,
69
}
70

71
impl SwitchableWriter {
72
    pub fn switch_to_direct_mode(&self) -> io::Result<()> {
×
73
        let buffer_size = {
×
74
            // Acquire the lock
75
            let mut mode = self.direct_mode.lock();
×
76

×
77
            // Get buffer size before flushing for debug logging
×
78
            let buffer_size = self.buffered_writer.buffer_size();
×
79

×
80
            // Flush any buffered content
×
81
            self.buffered_writer.flush_to(io::stdout())?;
×
82

83
            // Switch to direct mode (and drop the lock)
84
            *mode = true;
×
85

×
86
            buffer_size
×
87
        };
×
88

×
89
        // Log how much was buffered (this will now go directly to stdout)
×
90
        debug!("Flushed {buffer_size:?} bytes of buffered logs to console");
×
91

92
        Ok(())
×
93
    }
×
94
}
95

96
impl io::Write for SwitchableWriter {
97
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
×
98
        if *self.direct_mode.lock() {
×
99
            io::stdout().write(buf)
×
100
        } else {
101
            self.buffered_writer.clone().write(buf)
×
102
        }
103
    }
×
104

105
    fn flush(&mut self) -> io::Result<()> {
×
106
        if *self.direct_mode.lock() {
×
107
            io::stdout().flush()
×
108
        } else {
109
            // For buffered mode, flush is a no-op
110
            Ok(())
×
111
        }
112
    }
×
113
}
114

115
/// A make writer that uses the switchable writer.
116
#[derive(Clone)]
117
pub struct SwitchableMakeWriter {
118
    writer: SwitchableWriter,
119
}
120

121
impl SwitchableMakeWriter {
122
    pub fn new(writer: SwitchableWriter) -> Self {
×
123
        Self { writer }
×
124
    }
×
125
}
126

127
impl<'a> MakeWriter<'a> for SwitchableMakeWriter {
128
    type Writer = SwitchableWriter;
129

130
    fn make_writer(&'a self) -> Self::Writer {
×
131
        self.writer.clone()
×
132
    }
×
133
}
134

135
/// Sets up a switchable tracing subscriber that can transition from buffered to direct output.
136
///
137
/// Returns the switchable writer that can be used to control the behavior.
138
pub fn setup_switchable_subscriber() -> SwitchableWriter {
×
139
    let switchable_writer = SwitchableWriter::default();
×
140
    let make_writer = SwitchableMakeWriter::new(switchable_writer.clone());
×
141

×
142
    let _subscriber = tracing_subscriber::fmt()
×
143
        .with_ansi(cfg!(not(target_os = "emscripten")))
×
144
        .with_max_level(Level::DEBUG)
×
145
        .event_format(CustomFormatter)
×
146
        .with_writer(make_writer)
×
147
        .finish()
×
148
        .with(ErrorLayer::default());
×
149

×
150
    tracing::subscriber::set_global_default(_subscriber).expect("Could not set global default switchable subscriber");
×
151

×
152
    switchable_writer
×
153
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc