@@ -142,6 +142,31 @@ impl Config {
142
142
nlog. format = nformat;
143
143
}
144
144
145
+ if let Some ( file_config) = log. file
146
+ // directory must be configured for file logging
147
+ && let Some ( directory) = file_config. directory
148
+ {
149
+ let mut nfile = LogFileConfig :: new ( directory) ;
150
+ if let Some ( rotation) = file_config. rotation {
151
+ nfile. rotation = match rotation. as_str ( ) {
152
+ "never" => tracing_appender:: rolling:: Rotation :: NEVER ,
153
+ "hourly" => tracing_appender:: rolling:: Rotation :: HOURLY ,
154
+ "daily" => tracing_appender:: rolling:: Rotation :: DAILY ,
155
+ _ => return Err ( ConfigError :: InvalidValue ( rotation) ) ,
156
+ } ;
157
+ }
158
+ if let Some ( prefix) = file_config. prefix {
159
+ nfile. prefix = Some ( prefix) ;
160
+ }
161
+ if let Some ( suffix) = file_config. suffix {
162
+ nfile. suffix = Some ( suffix) ;
163
+ }
164
+ if let Some ( max_files) = file_config. max_files {
165
+ nfile. max_files = Some ( max_files) ;
166
+ }
167
+ nlog. file = Some ( nfile) ;
168
+ }
169
+
145
170
if let Some ( config_path) = log. config_path {
146
171
nlog. config_path = Some ( PathBuf :: from ( config_path) ) ;
147
172
}
@@ -210,6 +235,8 @@ pub struct LogConfig {
210
235
pub level : u32 ,
211
236
/// Default logger format configuration
212
237
pub format : LogFormatConfig ,
238
+ /// File appender configuration
239
+ pub file : Option < LogFileConfig > ,
213
240
/// Logging configuration file path
214
241
pub config_path : Option < PathBuf > ,
215
242
}
@@ -221,6 +248,35 @@ pub struct LogFormatConfig {
221
248
pub without_time : bool ,
222
249
}
223
250
251
+ /// File appender configuration for logging
252
+ #[ cfg( feature = "logging" ) ]
253
+ #[ derive( Debug , Clone ) ]
254
+ pub struct LogFileConfig {
255
+ /// Directory to store log files
256
+ pub directory : PathBuf ,
257
+ /// Rotation strategy for log files. Default is `Rotation::NEVER`.
258
+ pub rotation : tracing_appender:: rolling:: Rotation ,
259
+ /// Prefix for log file names. Default is the binary name.
260
+ pub prefix : Option < String > ,
261
+ /// Suffix for log file names. Default is "log".
262
+ pub suffix : Option < String > ,
263
+ /// Maximum number of log files to keep. Default is `None`, meaning no limit.
264
+ pub max_files : Option < usize > ,
265
+ }
266
+
267
+ #[ cfg( feature = "logging" ) ]
268
+ impl LogFileConfig {
269
+ fn new ( directory : impl Into < PathBuf > ) -> Self {
270
+ Self {
271
+ directory : directory. into ( ) ,
272
+ rotation : tracing_appender:: rolling:: Rotation :: NEVER ,
273
+ prefix : None ,
274
+ suffix : None ,
275
+ max_files : None ,
276
+ }
277
+ }
278
+ }
279
+
224
280
/// Runtime mode (Tokio)
225
281
#[ derive( Debug , Clone , Copy , Default ) ]
226
282
pub enum RuntimeMode {
@@ -272,6 +328,7 @@ struct SSConfig {
272
328
struct SSLogConfig {
273
329
level : Option < u32 > ,
274
330
format : Option < SSLogFormat > ,
331
+ file : Option < SSLogFileConfig > ,
275
332
config_path : Option < String > ,
276
333
}
277
334
@@ -281,6 +338,16 @@ struct SSLogFormat {
281
338
without_time : Option < bool > ,
282
339
}
283
340
341
+ #[ cfg( feature = "logging" ) ]
342
+ #[ derive( Deserialize ) ]
343
+ struct SSLogFileConfig {
344
+ directory : Option < String > ,
345
+ rotation : Option < String > ,
346
+ prefix : Option < String > ,
347
+ suffix : Option < String > ,
348
+ max_files : Option < usize > ,
349
+ }
350
+
284
351
#[ derive( Deserialize ) ]
285
352
struct SSRuntimeConfig {
286
353
#[ cfg( feature = "multi-threaded" ) ]
0 commit comments