timber_rust/factory/
std.rs

1use crate::service::{StandardWriteMessageFormatter, WriteMessageFormatter};
2use crate::{Concurrency, DirectLogger, Logger, QueuedLogger, service};
3
4/// A factory for creating loggers that write directly to the standard output (stdout).
5///
6/// `CoutWrite` provides a high-level builder for console logging. It is the most
7/// common choice for CLI applications and containerized environments (like Docker or K8s)
8/// where logs are expected to be captured from the process's stdout stream.
9///
10/// ### Default Configuration
11/// - **Max Retries**: `3` (Standard resilience against transient I/O pressure).
12/// - **Worker Count**: `1` (Ensures logs appear in chronological order).
13pub struct CoutWrite {
14    max_retries: usize,
15    worker_count: usize,
16}
17
18impl CoutWrite {
19    /// Returns the currently configured maximum retry attempts.
20    pub fn get_max_retries(&self) -> usize {
21        self.max_retries
22    }
23
24    /// Returns the currently configured background worker count.
25    pub fn get_worker_count(&self) -> usize {
26        self.worker_count
27    }
28
29    /// Updates the maximum number of retry attempts for the console service.
30    ///
31    /// This is useful if the terminal or pipe is under heavy load and requires
32    /// multiple attempts to flush data.
33    pub fn max_retries(self, max_retries: usize) -> Self {
34        Self {
35            max_retries,
36            ..self
37        }
38    }
39
40    /// Updates the background worker count for asynchronous console logging.
41    ///
42    /// **Note:** Using a worker count of 1 is highly recommended for console output
43    /// to prevent log lines from overlapping or appearing out of order.
44    pub fn worker_count(self, worker_count: usize) -> Self {
45        Self {
46            worker_count,
47            ..self
48        }
49    }
50
51    /// Finalizes the logger using the [`StandardWriteMessageFormatter`] and a [`Concurrency`] strategy.
52    pub fn build(self, concurrency: Concurrency) -> Logger {
53        match concurrency {
54            Concurrency::Sync => Logger::new(self.build_impl_direct()),
55            Concurrency::Async => Logger::new(self.build_impl_queued()),
56        }
57    }
58
59    /// Finalizes the logger using a custom [`WriteMessageFormatter`] and a [`Concurrency`] strategy.
60    ///
61    /// Use this to apply custom styling, colors, or structured formats (like JSON)
62    /// to the console output.
63    pub fn build_with_formatter<MF>(self, concurrency: Concurrency, formatter: MF) -> Logger
64    where
65        MF: WriteMessageFormatter + 'static,
66    {
67        match concurrency {
68            Concurrency::Sync => Logger::new(self.build_impl_direct_with_formatter(formatter)),
69            Concurrency::Async => Logger::new(self.build_impl_queued_with_formatter(formatter)),
70        }
71    }
72
73    /// Builds the underlying [`DirectLogger`] implementation for stdout.
74    pub fn build_impl_direct(self) -> Box<DirectLogger> {
75        let max_retries = self.max_retries;
76        DirectLogger::new(self.build_service(), max_retries)
77    }
78
79    /// Builds the underlying [`QueuedLogger`] implementation for stdout.
80    pub fn build_impl_queued(self) -> Box<QueuedLogger> {
81        let max_retries = self.max_retries;
82        let worker_count = self.worker_count;
83        QueuedLogger::new(self.build_service(), max_retries, worker_count)
84    }
85
86    /// Builds a [`DirectLogger`] with a specific formatter.
87    pub fn build_impl_direct_with_formatter<MF>(self, formatter: MF) -> Box<DirectLogger>
88    where
89        MF: WriteMessageFormatter + 'static,
90    {
91        let max_retries = self.max_retries;
92        DirectLogger::new(self.build_service_with_formatter(formatter), max_retries)
93    }
94
95    /// Builds a [`QueuedLogger`] with a specific formatter.
96    pub fn build_impl_queued_with_formatter<MF>(self, formatter: MF) -> Box<QueuedLogger>
97    where
98        MF: WriteMessageFormatter + 'static,
99    {
100        let max_retries = self.max_retries;
101        let worker_count = self.worker_count;
102        QueuedLogger::new(
103            self.build_service_with_formatter(formatter),
104            max_retries,
105            worker_count,
106        )
107    }
108
109    /// Internal helper to construct the [`service::CoutWrite`] service with a custom formatter.
110    pub fn build_service_with_formatter<MF>(self, formatter: MF) -> Box<service::CoutWrite<MF>>
111    where
112        MF: WriteMessageFormatter + 'static,
113    {
114        service::CoutWrite::with_formatter(formatter)
115    }
116
117    /// Internal helper to construct the [`service::CoutWrite`] service with the standard formatter.
118    pub fn build_service(self) -> Box<service::CoutWrite<StandardWriteMessageFormatter>> {
119        service::CoutWrite::new()
120    }
121}
122
123impl Default for CoutWrite {
124    /// Provides sensible defaults for console logging.
125    ///
126    /// - **max_retries**: `3`
127    /// - **worker_count**: `1` (Preserves sequential terminal output).
128    fn default() -> Self {
129        Self {
130            max_retries: 3,
131            worker_count: 1,
132        }
133    }
134}
135
136/// A factory for creating loggers that write directly to the standard error (stderr).
137///
138/// `CerrWrite` provides a high-level builder for console logging. This is the
139/// recommended choice for professional CLI applications, as it ensures that
140/// diagnostic information (logs) does not interfere with the primary data
141/// stream sent to stdout.
142///
143/// ### Default Configuration
144/// - **Max Retries**: `3` (Resilience against transient I/O blocks or terminal pressure).
145/// - **Worker Count**: `1` (Ensures logs appear in strict chronological order).
146pub struct CerrWrite {
147    max_retries: usize,
148    worker_count: usize,
149}
150
151impl CerrWrite {
152    /// Returns the currently configured maximum retry attempts.
153    pub fn get_max_retries(&self) -> usize {
154        self.max_retries
155    }
156
157    /// Returns the currently configured background worker count.
158    pub fn get_worker_count(&self) -> usize {
159        self.worker_count
160    }
161
162    /// Updates the maximum number of retry attempts for the stderr service.
163    ///
164    /// Useful if the error stream is being redirected to a file or pipe that
165    /// may experience intermittent congestion.
166    pub fn max_retries(self, max_retries: usize) -> Self {
167        Self {
168            max_retries,
169            ..self
170        }
171    }
172
173    /// Updates the background worker count for asynchronous error logging.
174    ///
175    /// **Note:** Using a worker count of 1 is strongly advised for stderr
176    /// to prevent terminal interleaving and preserve message order.
177    pub fn worker_count(self, worker_count: usize) -> Self {
178        Self {
179            worker_count,
180            ..self
181        }
182    }
183
184    /// Finalizes the logger using the [`StandardWriteMessageFormatter`] and a [`Concurrency`] strategy.
185    pub fn build(self, concurrency: Concurrency) -> Logger {
186        match concurrency {
187            Concurrency::Sync => Logger::new(self.build_impl_direct()),
188            Concurrency::Async => Logger::new(self.build_impl_queued()),
189        }
190    }
191
192    /// Finalizes the logger using a custom [`WriteMessageFormatter`] and a [`Concurrency`] strategy.
193    ///
194    /// This is frequently used to apply "error red" ANSI styling or specialized
195    /// headers specifically for diagnostic output.
196    pub fn build_with_formatter<MF>(self, concurrency: Concurrency, formatter: MF) -> Logger
197    where
198        MF: WriteMessageFormatter + 'static,
199    {
200        match concurrency {
201            Concurrency::Sync => Logger::new(self.build_impl_direct_with_formatter(formatter)),
202            Concurrency::Async => Logger::new(self.build_impl_queued_with_formatter(formatter)),
203        }
204    }
205
206    /// Builds the underlying [`DirectLogger`] implementation for stderr.
207    pub fn build_impl_direct(self) -> Box<DirectLogger> {
208        let max_retries = self.max_retries;
209        DirectLogger::new(self.build_service(), max_retries)
210    }
211
212    /// Builds the underlying [`QueuedLogger`] implementation for stderr.
213    pub fn build_impl_queued(self) -> Box<QueuedLogger> {
214        let max_retries = self.max_retries;
215        let worker_count = self.worker_count;
216        QueuedLogger::new(self.build_service(), max_retries, worker_count)
217    }
218
219    /// Builds a [`DirectLogger`] with a specific formatter for stderr.
220    pub fn build_impl_direct_with_formatter<MF>(self, formatter: MF) -> Box<DirectLogger>
221    where
222        MF: WriteMessageFormatter + 'static,
223    {
224        let max_retries = self.max_retries;
225        DirectLogger::new(self.build_service_with_formatter(formatter), max_retries)
226    }
227
228    /// Builds a [`QueuedLogger`] with a specific formatter for stderr.
229    pub fn build_impl_queued_with_formatter<MF>(self, formatter: MF) -> Box<QueuedLogger>
230    where
231        MF: WriteMessageFormatter + 'static,
232    {
233        let max_retries = self.max_retries;
234        let worker_count = self.worker_count;
235        QueuedLogger::new(
236            self.build_service_with_formatter(formatter),
237            max_retries,
238            worker_count,
239        )
240    }
241
242    /// Internal helper to construct the [`service::CerrWrite`] service with a custom formatter.
243    pub fn build_service_with_formatter<MF>(self, formatter: MF) -> Box<service::CerrWrite<MF>>
244    where
245        MF: WriteMessageFormatter + 'static,
246    {
247        service::CerrWrite::with_formatter(formatter)
248    }
249
250    /// Internal helper to construct the [`service::CerrWrite`] service with the standard formatter.
251    pub fn build_service(self) -> Box<service::CerrWrite<StandardWriteMessageFormatter>> {
252        service::CerrWrite::new()
253    }
254}
255
256impl Default for CerrWrite {
257    /// Provides sensible defaults for error console logging.
258    ///
259    /// - **max_retries**: `3`
260    /// - **worker_count**: `1` (Preserves sequential terminal output).
261    fn default() -> Self {
262        Self {
263            max_retries: 3,
264            worker_count: 1,
265        }
266    }
267}