3535
3636use std:: env:: { self , VarError } ;
3737use std:: fmt:: { self , Display } ;
38+ use std:: fs:: File ;
3839use std:: io:: { self , IsTerminal } ;
40+ use std:: sync:: Mutex ;
3941
4042use tracing:: dispatcher:: SetGlobalDefaultError ;
4143use tracing:: { Event , Subscriber } ;
4244use tracing_subscriber:: filter:: { Directive , EnvFilter , LevelFilter } ;
4345use tracing_subscriber:: fmt:: FmtContext ;
4446use tracing_subscriber:: fmt:: format:: { self , FmtSpan , FormatEvent , FormatFields } ;
47+ use tracing_subscriber:: fmt:: writer:: BoxMakeWriter ;
4548use tracing_subscriber:: layer:: SubscriberExt ;
4649use tracing_subscriber:: { Layer , Registry } ;
4750// Re-export tracing
@@ -56,6 +59,7 @@ pub struct LoggerConfig {
5659 pub verbose_thread_ids : Result < String , VarError > ,
5760 pub backtrace : Result < String , VarError > ,
5861 pub json : Result < String , VarError > ,
62+ pub output_target : Result < String , VarError > ,
5963 pub wraptree : Result < String , VarError > ,
6064 pub lines : Result < String , VarError > ,
6165}
@@ -71,6 +75,7 @@ impl LoggerConfig {
7175 wraptree : env:: var ( format ! ( "{env}_WRAPTREE" ) ) ,
7276 lines : env:: var ( format ! ( "{env}_LINES" ) ) ,
7377 json : env:: var ( format ! ( "{env}_FORMAT_JSON" ) ) ,
78+ output_target : env:: var ( format ! ( "{env}_OUTPUT_TARGET" ) ) ,
7479 }
7580 }
7681}
@@ -143,6 +148,17 @@ where
143148 Err ( _) => false ,
144149 } ;
145150
151+ let output_target: BoxMakeWriter = match cfg. output_target {
152+ Ok ( v) => match File :: options ( ) . create ( true ) . write ( true ) . truncate ( true ) . open ( & v) {
153+ Ok ( i) => BoxMakeWriter :: new ( Mutex :: new ( i) ) ,
154+ Err ( e) => {
155+ eprintln ! ( "couldn't open {v} as a log target: {e:?}" ) ;
156+ BoxMakeWriter :: new ( io:: stderr)
157+ }
158+ } ,
159+ Err ( _) => BoxMakeWriter :: new ( io:: stderr) ,
160+ } ;
161+
146162 let layer = if json {
147163 let format = tracing_subscriber:: fmt:: format ( )
148164 . json ( )
@@ -152,7 +168,7 @@ where
152168 let fmt_layer = tracing_subscriber:: fmt:: layer ( )
153169 . json ( )
154170 . event_format ( format)
155- . with_writer ( io :: stderr )
171+ . with_writer ( output_target )
156172 . with_target ( true )
157173 . with_ansi ( false )
158174 . with_thread_ids ( verbose_thread_ids)
@@ -161,7 +177,7 @@ where
161177 Layer :: boxed ( fmt_layer)
162178 } else {
163179 let mut layer = tracing_tree:: HierarchicalLayer :: default ( )
164- . with_writer ( io :: stderr )
180+ . with_writer ( output_target )
165181 . with_ansi ( color_logs)
166182 . with_targets ( true )
167183 . with_verbose_exit ( verbose_entry_exit)
0 commit comments