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}