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}