logforth_core/append/
stdio.rs

1// Copyright 2024 FastLabs Developers
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::io::Write;
16
17use crate::Diagnostic;
18use crate::Error;
19use crate::Layout;
20use crate::append::Append;
21use crate::layout::PlainTextLayout;
22use crate::record::Record;
23
24/// An appender that writes log records to standard output.
25///
26/// # Examples
27///
28/// ```
29/// use logforth_core::append::Stdout;
30///
31/// let stdout_appender = Stdout::default();
32/// ```
33#[derive(Debug)]
34pub struct Stdout {
35    layout: Box<dyn Layout>,
36}
37
38impl Default for Stdout {
39    fn default() -> Self {
40        Self {
41            layout: Box::new(PlainTextLayout::default()),
42        }
43    }
44}
45
46impl Stdout {
47    /// Set the layout for the [`Stdout`] appender.
48    ///
49    /// Default to [`PlainTextLayout`].
50    ///
51    /// # Examples
52    ///
53    /// ```
54    /// use logforth_core::append::Stdout;
55    /// use logforth_core::layout::PlainTextLayout;
56    ///
57    /// let stdout_appender = Stdout::default().with_layout(PlainTextLayout::default());
58    /// ```
59    pub fn with_layout(mut self, layout: impl Into<Box<dyn Layout>>) -> Self {
60        self.layout = layout.into();
61        self
62    }
63}
64
65impl Append for Stdout {
66    fn append(&self, record: &Record, diags: &[Box<dyn Diagnostic>]) -> Result<(), Error> {
67        let mut bytes = self.layout.format(record, diags)?;
68        bytes.push(b'\n');
69        std::io::stdout()
70            .write_all(&bytes)
71            .map_err(Error::from_io_error)?;
72        Ok(())
73    }
74
75    fn flush(&self) -> Result<(), Error> {
76        std::io::stdout().flush().map_err(Error::from_io_error)?;
77        Ok(())
78    }
79}
80
81/// An appender that writes log records to standard error.
82///
83/// # Examples
84///
85/// ```
86/// use logforth_core::append::Stderr;
87///
88/// let stderr_appender = Stderr::default();
89/// ```
90#[derive(Debug)]
91pub struct Stderr {
92    layout: Box<dyn Layout>,
93}
94
95impl Default for Stderr {
96    fn default() -> Self {
97        Self {
98            layout: Box::new(PlainTextLayout::default()),
99        }
100    }
101}
102
103impl Stderr {
104    /// Set the layout for the [`Stderr`] appender.
105    ///
106    /// Default to [`PlainTextLayout`].
107    ///
108    /// # Examples
109    ///
110    /// ```
111    /// use logforth_core::append::Stderr;
112    /// use logforth_core::layout::PlainTextLayout;
113    ///
114    /// let stderr_appender = Stderr::default().with_layout(PlainTextLayout::default());
115    /// ```
116    pub fn with_layout(mut self, layout: impl Into<Box<dyn Layout>>) -> Self {
117        self.layout = layout.into();
118        self
119    }
120}
121
122impl Append for Stderr {
123    fn append(&self, record: &Record, diags: &[Box<dyn Diagnostic>]) -> Result<(), Error> {
124        let mut bytes = self.layout.format(record, diags)?;
125        bytes.push(b'\n');
126        std::io::stderr()
127            .write_all(&bytes)
128            .map_err(Error::from_io_error)?;
129        Ok(())
130    }
131
132    fn flush(&self) -> Result<(), Error> {
133        std::io::stderr().flush().map_err(Error::from_io_error)?;
134        Ok(())
135    }
136}