4
4
use core:: fmt;
5
5
use std:: convert:: { From , TryInto } ;
6
6
use std:: fs:: { File , OpenOptions } ;
7
- use std:: io:: { self , LineWriter , Write } ;
7
+ use std:: io:: { self , BufWriter , LineWriter , Write } ;
8
8
use std:: os:: unix:: fs:: OpenOptionsExt ;
9
9
use std:: path:: Path ;
10
10
use std:: str:: FromStr ;
@@ -14,6 +14,7 @@ use libc::O_NONBLOCK;
14
14
use rate_limiter:: { BucketUpdate , RateLimiter , TokenBucket } ;
15
15
use serde:: { Deserialize , Serialize } ;
16
16
use tracing_core:: { Event , Subscriber } ;
17
+ use tracing_flame:: FlameLayer ;
17
18
use tracing_subscriber:: fmt:: format:: { self , FormatEvent , FormatFields } ;
18
19
use tracing_subscriber:: fmt:: { FmtContext , Layer } ;
19
20
use tracing_subscriber:: prelude:: * ;
@@ -278,6 +279,8 @@ pub struct LoggerConfig {
278
279
pub show_log_origin : Option < bool > ,
279
280
/// Use the new logger format.
280
281
pub new_format : Option < bool > ,
282
+ /// The profile file to output.
283
+ pub profile_file : Option < std:: path:: PathBuf > ,
281
284
}
282
285
283
286
/// Error with actions on the `LoggerConfig`.
@@ -294,13 +297,24 @@ pub enum LoggerConfigError {
294
297
Write ( std:: io:: Error ) ,
295
298
}
296
299
300
+ macro_rules! registry {
301
+ ( $( $x: expr) ,* ) => {
302
+ {
303
+ tracing_subscriber:: registry( )
304
+ $(
305
+ . with( $x)
306
+ ) *
307
+ }
308
+ }
309
+ }
310
+
297
311
impl LoggerConfig {
298
312
const INIT_MESSAGE : & str = concat ! ( "Running Firecracker v" , env!( "FIRECRACKER_VERSION" ) , "\n " ) ;
299
313
300
314
/// Initializes the logger.
301
315
pub fn init ( & self ) -> std:: result:: Result < ( ) , LoggerConfigError > {
302
316
let level = tracing:: Level :: from ( self . level . unwrap_or_default ( ) ) ;
303
- let level_filter = tracing_subscriber:: filter:: LevelFilter :: from_level ( level) ;
317
+ let filter = tracing_subscriber:: filter:: LevelFilter :: from_level ( level) ;
304
318
305
319
// In case we open a FIFO, in order to not block the instance if nobody is consuming the
306
320
// message that is flushed to the two pipes, we are opening it with `O_NONBLOCK` flag.
@@ -320,17 +334,11 @@ impl LoggerConfig {
320
334
// Wrap file to satisfy `tracing_subscriber::fmt::MakeWriter`.
321
335
let writer = Mutex :: new ( LineWriter :: new ( file) ) ;
322
336
323
- // Initialize the layers.
324
- if self . new_format . unwrap_or_default ( ) {
325
- tracing_subscriber:: registry ( )
326
- . with ( level_filter)
327
- . with ( new_log ( self , writer) )
328
- . try_init ( )
329
- } else {
330
- tracing_subscriber:: registry ( )
331
- . with ( level_filter)
332
- . with ( old_log ( self , writer) )
333
- . try_init ( )
337
+ match ( self . new_format . unwrap_or_default ( ) , & self . profile_file ) {
338
+ ( true , Some ( p) ) => registry ! ( filter, new_log( self , writer) , flame( p) ) . try_init ( ) ,
339
+ ( false , Some ( p) ) => registry ! ( filter, old_log( self , writer) , flame( p) ) . try_init ( ) ,
340
+ ( true , None ) => registry ! ( filter, new_log( self , writer) ) . try_init ( ) ,
341
+ ( false , None ) => registry ! ( filter, old_log( self , writer) ) . try_init ( ) ,
334
342
}
335
343
. map_err ( LoggerConfigError :: Init ) ?;
336
344
@@ -369,6 +377,18 @@ fn old_log<S: Subscriber + for<'span> LookupSpan<'span>>(
369
377
. with_writer ( writer)
370
378
}
371
379
380
+ fn flame < S : Subscriber + for < ' span > LookupSpan < ' span > > (
381
+ profile_file : & std:: path:: PathBuf ,
382
+ ) -> FlameLayer < S , BufWriter < File > > {
383
+ // We can discard the flush guard as
384
+ // > This type is only needed when using
385
+ // > `tracing::subscriber::set_global_default`, which prevents the drop
386
+ // > implementation of layers from running when the program exits.
387
+ // See https://docs.rs/tracing-flame/0.2.0/tracing_flame/struct.FlushGuard.html
388
+ let ( flame_layer, _guard) = FlameLayer :: with_file ( profile_file) . unwrap ( ) ;
389
+ flame_layer
390
+ }
391
+
372
392
// use std::sync::atomic::AtomicUsize;
373
393
// use std::sync::atomic::Ordering;
374
394
// static GURAD: AtomicUsize = AtomicUsize::new(0);
0 commit comments