@@ -23,10 +23,12 @@ use dsc_lib::{
23
23
} , resource_manifest:: ResourceManifest
24
24
} ,
25
25
util:: parse_input_to_json,
26
+ util:: get_setting,
26
27
} ;
27
28
use jsonschema:: Validator ;
28
29
use path_absolutize:: Absolutize ;
29
30
use schemars:: { schema_for, schema:: RootSchema } ;
31
+ use serde:: Deserialize ;
30
32
use serde_json:: Value ;
31
33
use std:: collections:: HashMap ;
32
34
use std:: env;
@@ -39,7 +41,7 @@ use syntect::{
39
41
parsing:: SyntaxSet ,
40
42
util:: { as_24_bit_terminal_escaped, LinesWithEndings }
41
43
} ;
42
- use tracing:: { Level , debug, error, warn, trace} ;
44
+ use tracing:: { Level , debug, error, info , warn, trace} ;
43
45
use tracing_subscriber:: { filter:: EnvFilter , layer:: SubscriberExt , Layer } ;
44
46
use tracing_indicatif:: IndicatifLayer ;
45
47
@@ -55,6 +57,27 @@ pub const EXIT_DSC_RESOURCE_NOT_FOUND: i32 = 7;
55
57
pub const DSC_CONFIG_ROOT : & str = "DSC_CONFIG_ROOT" ;
56
58
pub const DSC_TRACE_LEVEL : & str = "DSC_TRACE_LEVEL" ;
57
59
60
+ #[ derive( Deserialize ) ]
61
+ pub struct TracingSetting {
62
+ /// Trace level to use - see pub enum `TraceLevel` in `dsc_lib\src\dscresources\command_resource.rs`
63
+ level : TraceLevel ,
64
+ /// Trace format to use - see pub enum `TraceFormat` in `dsc\src\args.rs`
65
+ format : TraceFormat ,
66
+ /// Whether the 'level' can be overrridden by `DSC_TRACE_LEVEL` environment variable
67
+ #[ serde( rename = "allowOverride" ) ]
68
+ allow_override : bool
69
+ }
70
+
71
+ impl Default for TracingSetting {
72
+ fn default ( ) -> TracingSetting {
73
+ TracingSetting {
74
+ level : TraceLevel :: Warn ,
75
+ format : TraceFormat :: Default ,
76
+ allow_override : true ,
77
+ }
78
+ }
79
+ }
80
+
58
81
/// Get string representation of JSON value.
59
82
///
60
83
/// # Arguments
@@ -268,46 +291,92 @@ pub fn write_output(json: &str, format: &Option<OutputFormat>) {
268
291
}
269
292
}
270
293
271
- pub fn enable_tracing ( trace_level : & Option < TraceLevel > , trace_format : & TraceFormat ) {
272
- let tracing_level = match trace_level {
273
- Some ( level) => level,
274
- None => {
275
- // use DSC_TRACE_LEVEL env var if set
276
- match env:: var ( DSC_TRACE_LEVEL ) {
277
- Ok ( level) => {
278
- match level. to_ascii_uppercase ( ) . as_str ( ) {
279
- "ERROR" => & TraceLevel :: Error ,
280
- "WARN" => & TraceLevel :: Warn ,
281
- "INFO" => & TraceLevel :: Info ,
282
- "DEBUG" => & TraceLevel :: Debug ,
283
- "TRACE" => & TraceLevel :: Trace ,
284
- _ => {
285
- warn ! ( "Invalid DSC_TRACE_LEVEL value '{level}', defaulting to 'warn'" ) ;
286
- & TraceLevel :: Warn
287
- } ,
288
- }
294
+ #[ allow( clippy:: too_many_lines) ]
295
+ pub fn enable_tracing ( trace_level_arg : & Option < TraceLevel > , trace_format_arg : & Option < TraceFormat > ) {
296
+
297
+ let mut policy_is_used = false ;
298
+ let mut tracing_setting = TracingSetting :: default ( ) ;
299
+
300
+ let default_filter = EnvFilter :: try_from_default_env ( )
301
+ . or_else ( |_| EnvFilter :: try_new ( "warn" ) )
302
+ . unwrap_or_default ( )
303
+ . add_directive ( Level :: WARN . into ( ) ) ;
304
+ let default_indicatif_layer = IndicatifLayer :: new ( ) ;
305
+ let default_layer = tracing_subscriber:: fmt:: Layer :: default ( ) . with_writer ( default_indicatif_layer. get_stderr_writer ( ) ) ;
306
+ let default_fmt = default_layer
307
+ . with_ansi ( true )
308
+ . with_level ( true )
309
+ . boxed ( ) ;
310
+ let default_subscriber = tracing_subscriber:: Registry :: default ( ) . with ( default_fmt) . with ( default_filter) . with ( default_indicatif_layer) ;
311
+ let default_guard = tracing:: subscriber:: set_default ( default_subscriber) ;
312
+
313
+ // read setting/policy from files
314
+ if let Ok ( v) = get_setting ( "tracing" ) {
315
+ if v. policy != serde_json:: Value :: Null {
316
+ match serde_json:: from_value :: < TracingSetting > ( v. policy ) {
317
+ Ok ( v) => {
318
+ tracing_setting = v;
319
+ policy_is_used = true ;
320
+ } ,
321
+ Err ( e) => { error ! ( "{e}" ) ; }
322
+ }
323
+ } else if v. setting != serde_json:: Value :: Null {
324
+ match serde_json:: from_value :: < TracingSetting > ( v. setting ) {
325
+ Ok ( v) => {
326
+ tracing_setting = v;
289
327
} ,
290
- Err ( _ ) => & TraceLevel :: Warn ,
328
+ Err ( e ) => { error ! ( "{e}" ) ; }
291
329
}
292
330
}
331
+ } else {
332
+ error ! ( "Could not read 'tracing' setting" ) ;
333
+ }
334
+
335
+ // override with DSC_TRACE_LEVEL env var if permitted
336
+ if tracing_setting. allow_override {
337
+ if let Ok ( level) = env:: var ( DSC_TRACE_LEVEL ) {
338
+ tracing_setting. level = match level. to_ascii_uppercase ( ) . as_str ( ) {
339
+ "ERROR" => TraceLevel :: Error ,
340
+ "WARN" => TraceLevel :: Warn ,
341
+ "INFO" => TraceLevel :: Info ,
342
+ "DEBUG" => TraceLevel :: Debug ,
343
+ "TRACE" => TraceLevel :: Trace ,
344
+ _ => {
345
+ warn ! ( "Invalid DSC_TRACE_LEVEL value '{level}', defaulting to 'warn'" ) ;
346
+ TraceLevel :: Warn
347
+ }
348
+ }
349
+ }
350
+ }
351
+
352
+ // command-line args override setting value, but not policy
353
+ if !policy_is_used {
354
+ if let Some ( v) = trace_level_arg {
355
+ tracing_setting. level = v. clone ( ) ;
356
+ } ;
357
+ if let Some ( v) = trace_format_arg {
358
+ tracing_setting. format = v. clone ( ) ;
359
+ } ;
293
360
} ;
294
361
295
- let tracing_level = match tracing_level {
362
+ // convert to 'tracing' crate type
363
+ let tracing_level = match tracing_setting. level {
296
364
TraceLevel :: Error => Level :: ERROR ,
297
365
TraceLevel :: Warn => Level :: WARN ,
298
366
TraceLevel :: Info => Level :: INFO ,
299
367
TraceLevel :: Debug => Level :: DEBUG ,
300
368
TraceLevel :: Trace => Level :: TRACE ,
301
369
} ;
302
370
371
+ // enable tracing
303
372
let filter = EnvFilter :: try_from_default_env ( )
304
- . or_else ( |_| EnvFilter :: try_new ( "warning " ) )
373
+ . or_else ( |_| EnvFilter :: try_new ( "warn " ) )
305
374
. unwrap_or_default ( )
306
375
. add_directive ( tracing_level. into ( ) ) ;
307
376
let indicatif_layer = IndicatifLayer :: new ( ) ;
308
377
let layer = tracing_subscriber:: fmt:: Layer :: default ( ) . with_writer ( indicatif_layer. get_stderr_writer ( ) ) ;
309
378
let with_source = tracing_level == Level :: DEBUG || tracing_level == Level :: TRACE ;
310
- let fmt = match trace_format {
379
+ let fmt = match tracing_setting . format {
311
380
TraceFormat :: Default => {
312
381
layer
313
382
. with_ansi ( true )
@@ -337,12 +406,14 @@ pub fn enable_tracing(trace_level: &Option<TraceLevel>, trace_format: &TraceForm
337
406
338
407
let subscriber = tracing_subscriber:: Registry :: default ( ) . with ( fmt) . with ( filter) . with ( indicatif_layer) ;
339
408
409
+ drop ( default_guard) ;
340
410
if tracing:: subscriber:: set_global_default ( subscriber) . is_err ( ) {
341
411
eprintln ! ( "Unable to set global default tracing subscriber. Tracing is diabled." ) ;
342
412
}
343
413
344
414
// set DSC_TRACE_LEVEL for child processes
345
415
env:: set_var ( DSC_TRACE_LEVEL , tracing_level. to_string ( ) . to_ascii_lowercase ( ) ) ;
416
+ info ! ( "Trace-level is {:?}" , tracing_setting. level) ;
346
417
}
347
418
348
419
/// Validate the JSON against the schema.
0 commit comments