Skip to content

Commit 1b925f4

Browse files
mattrutherforddvdplmtomakabkchr
authored andcommitted
RPC to allow setting the log filter (paritytech#7474)
* Add filter reload handle * add RPC, move logging module from cli to tracing * remove dup fn * working example * Update client/rpc-api/src/system/mod.rs Co-authored-by: Pierre Krieger <[email protected]> * Prefer "set" to "reload" * Re-enable the commented out features of the logger * Remove duplicate code * cleanup * unneeded lvar * Bump to latest patch release * Add new CLI option to disable log filter reloading, Move profiling CLI options to SharedParams * Apply suggestions from code review Co-authored-by: Bastian Köcher <[email protected]> * Applied suggestions from reviews * Fix calls to init_logger() * Handle errors when parsing logging directives * Deny `system_setLogFilter` RPC by default * One more time * Don't ignore parse errors for log directives set via CLI or RPC * Improve docs * Apply suggestions from code review Co-authored-by: Bastian Köcher <[email protected]> * Update client/cli/src/config.rs Co-authored-by: Bastian Köcher <[email protected]> * fix merge errors * include default directives with system_setLogFilter RPC, implement system_rawSetLogFilter RPC to exclude defaults * docs etc... * update test * refactor: rename fn * Add a test for system_set_log_filter – NOTE: the code should likely change to return an error when bad directives are passed * Update client/cli/src/lib.rs Co-authored-by: Bastian Köcher <[email protected]> * Address review grumbles * Add doc note on panicking behaviour * print all invalid directives before panic * change RPCs to: addLogFilter and resetLogFilter * make CLI log directives default * add comments * restore previous behaviour to panic when hard-coded directives are invalid * change/refactor directive parsing * fix line width * add test for log filter reloading * Apply suggestions from code review Co-authored-by: Bastian Köcher <[email protected]> * finish up suggestions from code review * improve test * change expect message * change fn name * Apply suggestions from code review Co-authored-by: Bastian Köcher <[email protected]> * Apply suggestions from code review Co-authored-by: Bastian Köcher <[email protected]> * add docs, remove unused fn * propagate Err on invalid log directive * Update tracing-subscriber version * Improve docs for `disable_log_reloading` CLI param Co-authored-by: Matt <[email protected]> Co-authored-by: David <[email protected]> Co-authored-by: Pierre Krieger <[email protected]> Co-authored-by: Bastian Köcher <[email protected]>
1 parent d78553b commit 1b925f4

File tree

18 files changed

+365
-97
lines changed

18 files changed

+365
-97
lines changed

Cargo.lock

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/cli/Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ targets = ["x86_64-unknown-linux-gnu"]
1616
log = "0.4.11"
1717
atty = "0.2.13"
1818
regex = "1.4.2"
19-
lazy_static = "1.4.0"
20-
ansi_term = "0.12.1"
2119
tokio = { version = "0.2.21", features = [ "signal", "rt-core", "rt-threaded", "blocking" ] }
2220
futures = "0.3.4"
2321
fdlimit = "0.2.1"
@@ -47,7 +45,7 @@ chrono = "0.4.10"
4745
serde = "1.0.111"
4846
tracing = "0.1.22"
4947
tracing-log = "0.1.1"
50-
tracing-subscriber = "0.2.10"
48+
tracing-subscriber = "0.2.15"
5149
sc-cli-proc-macro = { version = "2.0.0", path = "./proc-macro" }
5250
thiserror = "1.0.21"
5351

@@ -56,6 +54,7 @@ rpassword = "5.0.0"
5654

5755
[dev-dependencies]
5856
tempfile = "3.1.0"
57+
ansi_term = "0.12.1"
5958

6059
[features]
6160
wasmtime = [

client/cli/src/config.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -408,22 +408,18 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
408408

409409
/// Get the tracing targets from the current object (if any)
410410
///
411-
/// By default this is retrieved from `ImportParams` if it is available. Otherwise its
411+
/// By default this is retrieved from [`SharedParams`] if it is available. Otherwise its
412412
/// `None`.
413413
fn tracing_targets(&self) -> Result<Option<String>> {
414-
Ok(self.import_params()
415-
.map(|x| x.tracing_targets())
416-
.unwrap_or_else(|| Default::default()))
414+
Ok(self.shared_params().tracing_targets())
417415
}
418416

419417
/// Get the TracingReceiver value from the current object
420418
///
421-
/// By default this is retrieved from `ImportParams` if it is available. Otherwise its
419+
/// By default this is retrieved from [`SharedParams`] if it is available. Otherwise its
422420
/// `TracingReceiver::default()`.
423421
fn tracing_receiver(&self) -> Result<TracingReceiver> {
424-
Ok(self.import_params()
425-
.map(|x| x.tracing_receiver())
426-
.unwrap_or_default())
422+
Ok(self.shared_params().tracing_receiver())
427423
}
428424

429425
/// Get the node key from the current object
@@ -519,6 +515,7 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
519515
dev_key_seed: self.dev_key_seed(is_dev)?,
520516
tracing_targets: self.tracing_targets()?,
521517
tracing_receiver: self.tracing_receiver()?,
518+
disable_log_reloading: self.is_log_filter_reloading_disabled()?,
522519
chain_spec,
523520
max_runtime_instances,
524521
announce_block: self.announce_block()?,
@@ -538,6 +535,11 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
538535
Ok(self.shared_params().log_filters().join(","))
539536
}
540537

538+
/// Is log reloading disabled (enabled by default)
539+
fn is_log_filter_reloading_disabled(&self) -> Result<bool> {
540+
Ok(self.shared_params().is_log_filter_reloading_disabled())
541+
}
542+
541543
/// Initialize substrate. This must be done only once per process.
542544
///
543545
/// This method:
@@ -549,12 +551,16 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
549551
let logger_pattern = self.log_filters()?;
550552
let tracing_receiver = self.tracing_receiver()?;
551553
let tracing_targets = self.tracing_targets()?;
554+
let disable_log_reloading = self.is_log_filter_reloading_disabled()?;
552555

553556
sp_panic_handler::set(&C::support_url(), &C::impl_version());
554557

555-
if let Err(e) = init_logger(&logger_pattern, tracing_receiver, tracing_targets) {
556-
log::warn!("💬 Problem initializing global logging framework: {:}", e)
557-
}
558+
init_logger(
559+
&logger_pattern,
560+
tracing_receiver,
561+
tracing_targets,
562+
disable_log_reloading,
563+
)?;
558564

559565
if let Some(new_limit) = fdlimit::raise_fd_limit() {
560566
if new_limit < RECOMMENDED_OPEN_FILE_DESCRIPTOR_LIMIT {

client/cli/src/lib.rs

Lines changed: 69 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ pub mod arg_enums;
2727
mod commands;
2828
mod config;
2929
mod error;
30-
mod logging;
3130
mod params;
3231
mod runner;
3332

@@ -48,8 +47,13 @@ use structopt::{
4847
StructOpt,
4948
};
5049
use tracing_subscriber::{
51-
filter::Directive, fmt::time::ChronoLocal, layer::SubscriberExt, FmtSubscriber, Layer,
50+
fmt::time::ChronoLocal,
51+
EnvFilter,
52+
FmtSubscriber,
53+
Layer,
54+
layer::SubscriberExt,
5255
};
56+
pub use sc_tracing::logging;
5357

5458
pub use logging::PREFIX_LOG_SPAN;
5559
#[doc(hidden)]
@@ -243,12 +247,16 @@ pub fn init_logger(
243247
pattern: &str,
244248
tracing_receiver: sc_tracing::TracingReceiver,
245249
profiling_targets: Option<String>,
250+
disable_log_reloading: bool,
246251
) -> std::result::Result<(), String> {
247-
fn parse_directives(dirs: impl AsRef<str>) -> Vec<Directive> {
248-
dirs.as_ref()
249-
.split(',')
250-
.filter_map(|s| s.parse().ok())
251-
.collect()
252+
use sc_tracing::parse_default_directive;
253+
254+
// Accept all valid directives and print invalid ones
255+
fn parse_user_directives(mut env_filter: EnvFilter, dirs: &str) -> std::result::Result<EnvFilter, String> {
256+
for dir in dirs.split(',') {
257+
env_filter = env_filter.add_directive(parse_default_directive(&dir)?);
258+
}
259+
Ok(env_filter)
252260
}
253261

254262
if let Err(e) = tracing_log::LogTracer::init() {
@@ -257,33 +265,35 @@ pub fn init_logger(
257265
))
258266
}
259267

260-
let mut env_filter = tracing_subscriber::EnvFilter::default()
268+
// Initialize filter - ensure to use `parse_default_directive` for any defaults to persist
269+
// after log filter reloading by RPC
270+
let mut env_filter = EnvFilter::default()
271+
// Enable info
272+
.add_directive(parse_default_directive("info")
273+
.expect("provided directive is valid"))
261274
// Disable info logging by default for some modules.
262-
.add_directive("ws=off".parse().expect("provided directive is valid"))
263-
.add_directive("yamux=off".parse().expect("provided directive is valid"))
264-
.add_directive("cranelift_codegen=off".parse().expect("provided directive is valid"))
275+
.add_directive(parse_default_directive("ws=off")
276+
.expect("provided directive is valid"))
277+
.add_directive(parse_default_directive("yamux=off")
278+
.expect("provided directive is valid"))
279+
.add_directive(parse_default_directive("cranelift_codegen=off")
280+
.expect("provided directive is valid"))
265281
// Set warn logging by default for some modules.
266-
.add_directive("cranelift_wasm=warn".parse().expect("provided directive is valid"))
267-
.add_directive("hyper=warn".parse().expect("provided directive is valid"))
268-
// Enable info for others.
269-
.add_directive(tracing_subscriber::filter::LevelFilter::INFO.into());
282+
.add_directive(parse_default_directive("cranelift_wasm=warn")
283+
.expect("provided directive is valid"))
284+
.add_directive(parse_default_directive("hyper=warn")
285+
.expect("provided directive is valid"));
270286

271287
if let Ok(lvl) = std::env::var("RUST_LOG") {
272288
if lvl != "" {
273-
// We're not sure if log or tracing is available at this moment, so silently ignore the
274-
// parse error.
275-
for directive in parse_directives(lvl) {
276-
env_filter = env_filter.add_directive(directive);
277-
}
289+
env_filter = parse_user_directives(env_filter, &lvl)?;
278290
}
279291
}
280292

281293
if pattern != "" {
282294
// We're not sure if log or tracing is available at this moment, so silently ignore the
283295
// parse error.
284-
for directive in parse_directives(pattern) {
285-
env_filter = env_filter.add_directive(directive);
286-
}
296+
env_filter = parse_user_directives(env_filter, pattern)?;
287297
}
288298

289299
// If we're only logging `INFO` entries then we'll use a simplified logging format.
@@ -293,19 +303,16 @@ pub fn init_logger(
293303
};
294304

295305
// Always log the special target `sc_tracing`, overrides global level.
306+
// Required because profiling traces are emitted via `sc_tracing`
296307
// NOTE: this must be done after we check the `max_level_hint` otherwise
297308
// it is always raised to `TRACE`.
298309
env_filter = env_filter.add_directive(
299-
"sc_tracing=trace"
300-
.parse()
301-
.expect("provided directive is valid"),
310+
parse_default_directive("sc_tracing=trace").expect("provided directive is valid")
302311
);
303312

304313
// Make sure to include profiling targets in the filter
305314
if let Some(profiling_targets) = profiling_targets.clone() {
306-
for directive in parse_directives(profiling_targets) {
307-
env_filter = env_filter.add_directive(directive);
308-
}
315+
env_filter = parse_user_directives(env_filter, &profiling_targets)?;
309316
}
310317

311318
let enable_color = atty::is(atty::Stream::Stderr);
@@ -315,22 +322,42 @@ pub fn init_logger(
315322
"%Y-%m-%d %H:%M:%S%.3f".to_string()
316323
});
317324

318-
let subscriber = FmtSubscriber::builder()
325+
let subscriber_builder = FmtSubscriber::builder()
319326
.with_env_filter(env_filter)
320-
.with_writer(std::io::stderr)
327+
.with_writer(std::io::stderr as _)
321328
.event_format(logging::EventFormat {
322329
timer,
330+
enable_color,
323331
display_target: !simple,
324332
display_level: !simple,
325333
display_thread_name: !simple,
326-
enable_color,
327-
})
328-
.finish()
329-
.with(logging::NodeNameLayer);
334+
});
335+
if disable_log_reloading {
336+
let subscriber = subscriber_builder
337+
.finish()
338+
.with(logging::NodeNameLayer);
339+
initialize_tracing(subscriber, tracing_receiver, profiling_targets)
340+
} else {
341+
let subscriber_builder = subscriber_builder.with_filter_reloading();
342+
let handle = subscriber_builder.reload_handle();
343+
sc_tracing::set_reload_handle(handle);
344+
let subscriber = subscriber_builder
345+
.finish()
346+
.with(logging::NodeNameLayer);
347+
initialize_tracing(subscriber, tracing_receiver, profiling_targets)
348+
}
349+
}
330350

351+
fn initialize_tracing<S>(
352+
subscriber: S,
353+
tracing_receiver: sc_tracing::TracingReceiver,
354+
profiling_targets: Option<String>,
355+
) -> std::result::Result<(), String>
356+
where
357+
S: tracing::Subscriber + Send + Sync + 'static,
358+
{
331359
if let Some(profiling_targets) = profiling_targets {
332360
let profiling = sc_tracing::ProfilingLayer::new(tracing_receiver, &profiling_targets);
333-
334361
if let Err(e) = tracing::subscriber::set_global_default(subscriber.with(profiling)) {
335362
return Err(format!(
336363
"Registering Substrate tracing subscriber failed: {:}!", e
@@ -339,7 +366,7 @@ pub fn init_logger(
339366
} else {
340367
if let Err(e) = tracing::subscriber::set_global_default(subscriber) {
341368
return Err(format!(
342-
"Registering Substrate tracing subscriber failed: {:}!", e
369+
"Registering Substrate tracing subscriber failed: {:}!", e
343370
))
344371
}
345372
}
@@ -356,7 +383,7 @@ mod tests {
356383
#[test]
357384
fn test_logger_filters() {
358385
let test_pattern = "afg=debug,sync=trace,client=warn,telemetry,something-with-dash=error";
359-
init_logger(&test_pattern, Default::default(), Default::default()).unwrap();
386+
init_logger(&test_pattern, Default::default(), Default::default(), false).unwrap();
360387

361388
tracing::dispatcher::get_default(|dispatcher| {
362389
let test_filter = |target, level| {
@@ -415,7 +442,7 @@ mod tests {
415442
fn log_something_with_dash_target_name() {
416443
if env::var("ENABLE_LOGGING").is_ok() {
417444
let test_pattern = "test-target=info";
418-
init_logger(&test_pattern, Default::default(), Default::default()).unwrap();
445+
init_logger(&test_pattern, Default::default(), Default::default(), false).unwrap();
419446

420447
log::info!(target: "test-target", "{}", EXPECTED_LOG_MESSAGE);
421448
}
@@ -450,7 +477,8 @@ mod tests {
450477
#[test]
451478
fn prefix_in_log_lines_entrypoint() {
452479
if env::var("ENABLE_LOGGING").is_ok() {
453-
init_logger("", Default::default(), Default::default()).unwrap();
480+
let test_pattern = "test-target=info";
481+
init_logger(&test_pattern, Default::default(), Default::default(), false).unwrap();
454482
prefix_in_log_lines_process();
455483
}
456484
}
@@ -466,7 +494,7 @@ mod tests {
466494
#[test]
467495
fn do_not_write_with_colors_on_tty_entrypoint() {
468496
if env::var("ENABLE_LOGGING").is_ok() {
469-
init_logger("", Default::default(), Default::default()).unwrap();
497+
init_logger("", Default::default(), Default::default(), false).unwrap();
470498
log::info!("{}", ansi_term::Colour::Yellow.paint(EXPECTED_LOG_MESSAGE));
471499
}
472500
}

client/cli/src/params/import_params.rs

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
// along with this program. If not, see <https://www.gnu.org/licenses/>.
1818

1919
use crate::arg_enums::{
20-
ExecutionStrategy, TracingReceiver, WasmExecutionMethod, DEFAULT_EXECUTION_BLOCK_CONSTRUCTION,
20+
ExecutionStrategy, WasmExecutionMethod, DEFAULT_EXECUTION_BLOCK_CONSTRUCTION,
2121
DEFAULT_EXECUTION_IMPORT_BLOCK, DEFAULT_EXECUTION_IMPORT_BLOCK_VALIDATOR,
2222
DEFAULT_EXECUTION_OFFCHAIN_WORKER, DEFAULT_EXECUTION_OTHER, DEFAULT_EXECUTION_SYNCING,
2323
};
@@ -73,32 +73,9 @@ pub struct ImportParams {
7373
default_value = "67108864"
7474
)]
7575
pub state_cache_size: usize,
76-
77-
/// Comma separated list of targets for tracing.
78-
#[structopt(long = "tracing-targets", value_name = "TARGETS")]
79-
pub tracing_targets: Option<String>,
80-
81-
/// Receiver to process tracing messages.
82-
#[structopt(
83-
long = "tracing-receiver",
84-
value_name = "RECEIVER",
85-
possible_values = &TracingReceiver::variants(),
86-
case_insensitive = true,
87-
default_value = "Log"
88-
)]
89-
pub tracing_receiver: TracingReceiver,
9076
}
9177

9278
impl ImportParams {
93-
/// Receiver to process tracing messages.
94-
pub fn tracing_receiver(&self) -> sc_service::TracingReceiver {
95-
self.tracing_receiver.clone().into()
96-
}
97-
98-
/// Comma separated list of targets for tracing.
99-
pub fn tracing_targets(&self) -> Option<String> {
100-
self.tracing_targets.clone()
101-
}
10279

10380
/// Specify the state cache size.
10481
pub fn state_cache_size(&self) -> usize {

0 commit comments

Comments
 (0)