|
12 | 12 | // See the License for the specific language governing permissions and |
13 | 13 | // limitations under the License. |
14 | 14 |
|
| 15 | +use std::path::PathBuf; |
| 16 | +use std::time::Duration; |
| 17 | + |
15 | 18 | use log::Record; |
16 | 19 |
|
17 | | -use crate::append::rolling_file::RollingFileWriter; |
| 20 | +use crate::append::rolling_file::rolling::RollingFileWriter; |
| 21 | +use crate::append::rolling_file::rolling::RollingFileWriterBuilder; |
| 22 | +use crate::append::rolling_file::Rotation; |
18 | 23 | use crate::append::Append; |
19 | 24 | use crate::layout::TextLayout; |
20 | 25 | use crate::non_blocking::NonBlocking; |
| 26 | +use crate::non_blocking::NonBlockingBuilder; |
21 | 27 | use crate::Diagnostic; |
| 28 | +use crate::DropGuard; |
22 | 29 | use crate::Layout; |
23 | 30 |
|
24 | | -/// An appender that writes log records to rolling files. |
| 31 | +/// A builder to configure and create an [`RollingFile`] appender. |
25 | 32 | #[derive(Debug)] |
26 | | -pub struct RollingFile { |
| 33 | +pub struct RollingFileBuilder { |
| 34 | + builder: RollingFileWriterBuilder, |
27 | 35 | layout: Box<dyn Layout>, |
28 | | - writer: NonBlocking<RollingFileWriter>, |
| 36 | + |
| 37 | + // non-blocking options |
| 38 | + thread_name: String, |
| 39 | + buffered_lines_limit: Option<usize>, |
| 40 | + shutdown_timeout: Option<Duration>, |
29 | 41 | } |
30 | 42 |
|
31 | | -impl RollingFile { |
32 | | - /// Creates a new [`RollingFile`] appender. |
33 | | - /// |
34 | | - /// This appender by default uses [`TextLayout`] to format log records. |
35 | | - pub fn new(writer: NonBlocking<RollingFileWriter>) -> Self { |
| 43 | +impl RollingFileBuilder { |
| 44 | + /// Create a new builder. |
| 45 | + pub fn new(basedir: impl Into<PathBuf>) -> Self { |
36 | 46 | Self { |
| 47 | + builder: RollingFileWriterBuilder::new(basedir), |
37 | 48 | layout: Box::new(TextLayout::default().no_color()), |
38 | | - writer, |
| 49 | + |
| 50 | + thread_name: "logforth-rolling-file".to_string(), |
| 51 | + buffered_lines_limit: None, |
| 52 | + shutdown_timeout: None, |
39 | 53 | } |
40 | 54 | } |
41 | 55 |
|
42 | | - /// Sets the layout used to format log records. |
43 | | - pub fn with_layout(mut self, layout: impl Into<Box<dyn Layout>>) -> Self { |
| 56 | + /// Build the [`RollingFile`] appender. |
| 57 | + /// |
| 58 | + /// # Errors |
| 59 | + /// |
| 60 | + /// Returns an error if the log directory cannot be created. |
| 61 | + pub fn build(self) -> anyhow::Result<(RollingFile, DropGuard)> { |
| 62 | + let RollingFileBuilder { |
| 63 | + builder, |
| 64 | + layout, |
| 65 | + thread_name, |
| 66 | + buffered_lines_limit, |
| 67 | + shutdown_timeout, |
| 68 | + } = self; |
| 69 | + let writer = builder.build()?; |
| 70 | + let (non_blocking, guard) = NonBlockingBuilder::new(thread_name, writer) |
| 71 | + .buffered_lines_limit(buffered_lines_limit) |
| 72 | + .shutdown_timeout(shutdown_timeout) |
| 73 | + .build(); |
| 74 | + Ok((RollingFile::new(non_blocking, layout), Box::new(guard))) |
| 75 | + } |
| 76 | + |
| 77 | + /// Sets the layout for the logs. |
| 78 | + /// |
| 79 | + /// Default to [`TextLayout`]. |
| 80 | + /// |
| 81 | + /// # Examples |
| 82 | + /// |
| 83 | + /// ``` |
| 84 | + /// use logforth::append::rolling_file::RollingFileBuilder; |
| 85 | + /// use logforth::layout::JsonLayout; |
| 86 | + /// |
| 87 | + /// let builder = RollingFileBuilder::new("my_service"); |
| 88 | + /// builder.layout(JsonLayout::default()); |
| 89 | + /// ``` |
| 90 | + pub fn layout(mut self, layout: impl Into<Box<dyn Layout>>) -> Self { |
44 | 91 | self.layout = layout.into(); |
45 | 92 | self |
46 | 93 | } |
| 94 | + |
| 95 | + /// Sets the buffer size of pending messages. |
| 96 | + pub fn buffered_lines_limit(mut self, buffered_lines_limit: Option<usize>) -> Self { |
| 97 | + self.buffered_lines_limit = buffered_lines_limit; |
| 98 | + self |
| 99 | + } |
| 100 | + |
| 101 | + /// Sets the shutdown timeout before the worker guard dropped. |
| 102 | + pub fn shutdown_timeout(mut self, shutdown_timeout: Option<Duration>) -> Self { |
| 103 | + self.shutdown_timeout = shutdown_timeout; |
| 104 | + self |
| 105 | + } |
| 106 | + |
| 107 | + /// Sets the thread name for the background sender thread. |
| 108 | + pub fn thread_name(mut self, thread_name: impl Into<String>) -> Self { |
| 109 | + self.thread_name = thread_name.into(); |
| 110 | + self |
| 111 | + } |
| 112 | + |
| 113 | + /// Sets the rotation policy. |
| 114 | + pub fn rotation(mut self, rotation: Rotation) -> Self { |
| 115 | + self.builder = self.builder.rotation(rotation); |
| 116 | + self |
| 117 | + } |
| 118 | + |
| 119 | + /// Sets the filename prefix. |
| 120 | + pub fn filename_prefix(mut self, prefix: impl Into<String>) -> Self { |
| 121 | + self.builder = self.builder.filename_prefix(prefix); |
| 122 | + self |
| 123 | + } |
| 124 | + |
| 125 | + /// Sets the filename suffix. |
| 126 | + pub fn filename_suffix(mut self, suffix: impl Into<String>) -> Self { |
| 127 | + self.builder = self.builder.filename_suffix(suffix); |
| 128 | + self |
| 129 | + } |
| 130 | + |
| 131 | + /// Sets the maximum number of log files to keep. |
| 132 | + pub fn max_log_files(mut self, n: usize) -> Self { |
| 133 | + self.builder = self.builder.max_log_files(n); |
| 134 | + self |
| 135 | + } |
| 136 | + |
| 137 | + /// Sets the maximum size of a log file in bytes. |
| 138 | + pub fn max_file_size(mut self, n: usize) -> Self { |
| 139 | + self.builder = self.builder.max_file_size(n); |
| 140 | + self |
| 141 | + } |
| 142 | +} |
| 143 | + |
| 144 | +/// An appender that writes log records to rolling files. |
| 145 | +#[derive(Debug)] |
| 146 | +pub struct RollingFile { |
| 147 | + layout: Box<dyn Layout>, |
| 148 | + writer: NonBlocking<RollingFileWriter>, |
| 149 | +} |
| 150 | + |
| 151 | +impl RollingFile { |
| 152 | + fn new(writer: NonBlocking<RollingFileWriter>, layout: Box<dyn Layout>) -> Self { |
| 153 | + Self { layout, writer } |
| 154 | + } |
47 | 155 | } |
48 | 156 |
|
49 | 157 | impl Append for RollingFile { |
|
0 commit comments