Skip to main content

torrust_tracker_deployer_lib/presentation/cli/views/sinks/
file.rs

1//! File output sink implementation
2
3use std::io::Write;
4
5use super::super::{OutputMessage, OutputSink};
6
7// ============================================================================
8// Example Sink Implementations
9// ============================================================================
10
11/// Example: File sink that writes all output to a file
12///
13/// This is an example implementation showing how to create a custom sink
14/// that writes to a file. In production, you might want to add buffering,
15/// rotation, or other features.
16///
17/// # Examples
18///
19/// ```rust,ignore
20/// use torrust_tracker_deployer_lib::presentation::cli::views::{FileSink, UserOutput, VerbosityLevel, CompositeSink, StandardSink};
21///
22/// // Write to both console and file
23/// let composite = CompositeSink::new(vec![
24///     Box::new(StandardSink::default_console()),
25///     Box::new(FileSink::new("output.log").unwrap()),
26/// ]);
27/// let mut output = UserOutput::with_sink(VerbosityLevel::Normal, Box::new(composite));
28/// ```
29pub struct FileSink {
30    file: std::fs::File,
31}
32
33impl FileSink {
34    /// Create a new file sink
35    ///
36    /// Opens or creates the file at the given path in append mode.
37    ///
38    /// # Errors
39    ///
40    /// Returns an error if the file cannot be opened or created.
41    ///
42    /// # Examples
43    ///
44    /// ```rust,ignore
45    /// use torrust_tracker_deployer_lib::presentation::cli::views::FileSink;
46    ///
47    /// let sink = FileSink::new("output.log")?;
48    /// ```
49    pub fn new(path: &str) -> std::io::Result<Self> {
50        let file = std::fs::OpenOptions::new()
51            .create(true)
52            .append(true)
53            .open(path)?;
54        Ok(Self { file })
55    }
56}
57
58impl OutputSink for FileSink {
59    fn write_message(&mut self, _message: &dyn OutputMessage, formatted: &str) {
60        writeln!(self.file, "{formatted}").ok();
61    }
62}