mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-28 14:27:57 +00:00
RPC to allow setting the log filter (#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 <pierre.krieger1708@gmail.com> * 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 <bkchr@users.noreply.github.com> * 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 <bkchr@users.noreply.github.com> * Update client/cli/src/config.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * 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 <bkchr@users.noreply.github.com> * 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 <bkchr@users.noreply.github.com> * 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 <bkchr@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * 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 <mattrutherford@users.noreply.github.com> Co-authored-by: David <dvdplm@gmail.com> Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
@@ -408,22 +408,18 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
|
||||
|
||||
/// Get the tracing targets from the current object (if any)
|
||||
///
|
||||
/// By default this is retrieved from `ImportParams` if it is available. Otherwise its
|
||||
/// By default this is retrieved from [`SharedParams`] if it is available. Otherwise its
|
||||
/// `None`.
|
||||
fn tracing_targets(&self) -> Result<Option<String>> {
|
||||
Ok(self.import_params()
|
||||
.map(|x| x.tracing_targets())
|
||||
.unwrap_or_else(|| Default::default()))
|
||||
Ok(self.shared_params().tracing_targets())
|
||||
}
|
||||
|
||||
/// Get the TracingReceiver value from the current object
|
||||
///
|
||||
/// By default this is retrieved from `ImportParams` if it is available. Otherwise its
|
||||
/// By default this is retrieved from [`SharedParams`] if it is available. Otherwise its
|
||||
/// `TracingReceiver::default()`.
|
||||
fn tracing_receiver(&self) -> Result<TracingReceiver> {
|
||||
Ok(self.import_params()
|
||||
.map(|x| x.tracing_receiver())
|
||||
.unwrap_or_default())
|
||||
Ok(self.shared_params().tracing_receiver())
|
||||
}
|
||||
|
||||
/// Get the node key from the current object
|
||||
@@ -519,6 +515,7 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
|
||||
dev_key_seed: self.dev_key_seed(is_dev)?,
|
||||
tracing_targets: self.tracing_targets()?,
|
||||
tracing_receiver: self.tracing_receiver()?,
|
||||
disable_log_reloading: self.is_log_filter_reloading_disabled()?,
|
||||
chain_spec,
|
||||
max_runtime_instances,
|
||||
announce_block: self.announce_block()?,
|
||||
@@ -538,6 +535,11 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
|
||||
Ok(self.shared_params().log_filters().join(","))
|
||||
}
|
||||
|
||||
/// Is log reloading disabled (enabled by default)
|
||||
fn is_log_filter_reloading_disabled(&self) -> Result<bool> {
|
||||
Ok(self.shared_params().is_log_filter_reloading_disabled())
|
||||
}
|
||||
|
||||
/// Initialize substrate. This must be done only once per process.
|
||||
///
|
||||
/// This method:
|
||||
@@ -549,12 +551,16 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
|
||||
let logger_pattern = self.log_filters()?;
|
||||
let tracing_receiver = self.tracing_receiver()?;
|
||||
let tracing_targets = self.tracing_targets()?;
|
||||
let disable_log_reloading = self.is_log_filter_reloading_disabled()?;
|
||||
|
||||
sp_panic_handler::set(&C::support_url(), &C::impl_version());
|
||||
|
||||
if let Err(e) = init_logger(&logger_pattern, tracing_receiver, tracing_targets) {
|
||||
log::warn!("💬 Problem initializing global logging framework: {:}", e)
|
||||
}
|
||||
init_logger(
|
||||
&logger_pattern,
|
||||
tracing_receiver,
|
||||
tracing_targets,
|
||||
disable_log_reloading,
|
||||
)?;
|
||||
|
||||
if let Some(new_limit) = fdlimit::raise_fd_limit() {
|
||||
if new_limit < RECOMMENDED_OPEN_FILE_DESCRIPTOR_LIMIT {
|
||||
|
||||
@@ -27,7 +27,6 @@ pub mod arg_enums;
|
||||
mod commands;
|
||||
mod config;
|
||||
mod error;
|
||||
mod logging;
|
||||
mod params;
|
||||
mod runner;
|
||||
|
||||
@@ -48,8 +47,13 @@ use structopt::{
|
||||
StructOpt,
|
||||
};
|
||||
use tracing_subscriber::{
|
||||
filter::Directive, fmt::time::ChronoLocal, layer::SubscriberExt, FmtSubscriber, Layer,
|
||||
fmt::time::ChronoLocal,
|
||||
EnvFilter,
|
||||
FmtSubscriber,
|
||||
Layer,
|
||||
layer::SubscriberExt,
|
||||
};
|
||||
pub use sc_tracing::logging;
|
||||
|
||||
pub use logging::PREFIX_LOG_SPAN;
|
||||
#[doc(hidden)]
|
||||
@@ -243,12 +247,16 @@ pub fn init_logger(
|
||||
pattern: &str,
|
||||
tracing_receiver: sc_tracing::TracingReceiver,
|
||||
profiling_targets: Option<String>,
|
||||
disable_log_reloading: bool,
|
||||
) -> std::result::Result<(), String> {
|
||||
fn parse_directives(dirs: impl AsRef<str>) -> Vec<Directive> {
|
||||
dirs.as_ref()
|
||||
.split(',')
|
||||
.filter_map(|s| s.parse().ok())
|
||||
.collect()
|
||||
use sc_tracing::parse_default_directive;
|
||||
|
||||
// Accept all valid directives and print invalid ones
|
||||
fn parse_user_directives(mut env_filter: EnvFilter, dirs: &str) -> std::result::Result<EnvFilter, String> {
|
||||
for dir in dirs.split(',') {
|
||||
env_filter = env_filter.add_directive(parse_default_directive(&dir)?);
|
||||
}
|
||||
Ok(env_filter)
|
||||
}
|
||||
|
||||
if let Err(e) = tracing_log::LogTracer::init() {
|
||||
@@ -257,33 +265,35 @@ pub fn init_logger(
|
||||
))
|
||||
}
|
||||
|
||||
let mut env_filter = tracing_subscriber::EnvFilter::default()
|
||||
// Initialize filter - ensure to use `parse_default_directive` for any defaults to persist
|
||||
// after log filter reloading by RPC
|
||||
let mut env_filter = EnvFilter::default()
|
||||
// Enable info
|
||||
.add_directive(parse_default_directive("info")
|
||||
.expect("provided directive is valid"))
|
||||
// Disable info logging by default for some modules.
|
||||
.add_directive("ws=off".parse().expect("provided directive is valid"))
|
||||
.add_directive("yamux=off".parse().expect("provided directive is valid"))
|
||||
.add_directive("cranelift_codegen=off".parse().expect("provided directive is valid"))
|
||||
.add_directive(parse_default_directive("ws=off")
|
||||
.expect("provided directive is valid"))
|
||||
.add_directive(parse_default_directive("yamux=off")
|
||||
.expect("provided directive is valid"))
|
||||
.add_directive(parse_default_directive("cranelift_codegen=off")
|
||||
.expect("provided directive is valid"))
|
||||
// Set warn logging by default for some modules.
|
||||
.add_directive("cranelift_wasm=warn".parse().expect("provided directive is valid"))
|
||||
.add_directive("hyper=warn".parse().expect("provided directive is valid"))
|
||||
// Enable info for others.
|
||||
.add_directive(tracing_subscriber::filter::LevelFilter::INFO.into());
|
||||
.add_directive(parse_default_directive("cranelift_wasm=warn")
|
||||
.expect("provided directive is valid"))
|
||||
.add_directive(parse_default_directive("hyper=warn")
|
||||
.expect("provided directive is valid"));
|
||||
|
||||
if let Ok(lvl) = std::env::var("RUST_LOG") {
|
||||
if lvl != "" {
|
||||
// We're not sure if log or tracing is available at this moment, so silently ignore the
|
||||
// parse error.
|
||||
for directive in parse_directives(lvl) {
|
||||
env_filter = env_filter.add_directive(directive);
|
||||
}
|
||||
env_filter = parse_user_directives(env_filter, &lvl)?;
|
||||
}
|
||||
}
|
||||
|
||||
if pattern != "" {
|
||||
// We're not sure if log or tracing is available at this moment, so silently ignore the
|
||||
// parse error.
|
||||
for directive in parse_directives(pattern) {
|
||||
env_filter = env_filter.add_directive(directive);
|
||||
}
|
||||
env_filter = parse_user_directives(env_filter, pattern)?;
|
||||
}
|
||||
|
||||
// If we're only logging `INFO` entries then we'll use a simplified logging format.
|
||||
@@ -293,19 +303,16 @@ pub fn init_logger(
|
||||
};
|
||||
|
||||
// Always log the special target `sc_tracing`, overrides global level.
|
||||
// Required because profiling traces are emitted via `sc_tracing`
|
||||
// NOTE: this must be done after we check the `max_level_hint` otherwise
|
||||
// it is always raised to `TRACE`.
|
||||
env_filter = env_filter.add_directive(
|
||||
"sc_tracing=trace"
|
||||
.parse()
|
||||
.expect("provided directive is valid"),
|
||||
parse_default_directive("sc_tracing=trace").expect("provided directive is valid")
|
||||
);
|
||||
|
||||
// Make sure to include profiling targets in the filter
|
||||
if let Some(profiling_targets) = profiling_targets.clone() {
|
||||
for directive in parse_directives(profiling_targets) {
|
||||
env_filter = env_filter.add_directive(directive);
|
||||
}
|
||||
env_filter = parse_user_directives(env_filter, &profiling_targets)?;
|
||||
}
|
||||
|
||||
let enable_color = atty::is(atty::Stream::Stderr);
|
||||
@@ -315,22 +322,42 @@ pub fn init_logger(
|
||||
"%Y-%m-%d %H:%M:%S%.3f".to_string()
|
||||
});
|
||||
|
||||
let subscriber = FmtSubscriber::builder()
|
||||
let subscriber_builder = FmtSubscriber::builder()
|
||||
.with_env_filter(env_filter)
|
||||
.with_writer(std::io::stderr)
|
||||
.with_writer(std::io::stderr as _)
|
||||
.event_format(logging::EventFormat {
|
||||
timer,
|
||||
enable_color,
|
||||
display_target: !simple,
|
||||
display_level: !simple,
|
||||
display_thread_name: !simple,
|
||||
enable_color,
|
||||
})
|
||||
.finish()
|
||||
.with(logging::NodeNameLayer);
|
||||
});
|
||||
if disable_log_reloading {
|
||||
let subscriber = subscriber_builder
|
||||
.finish()
|
||||
.with(logging::NodeNameLayer);
|
||||
initialize_tracing(subscriber, tracing_receiver, profiling_targets)
|
||||
} else {
|
||||
let subscriber_builder = subscriber_builder.with_filter_reloading();
|
||||
let handle = subscriber_builder.reload_handle();
|
||||
sc_tracing::set_reload_handle(handle);
|
||||
let subscriber = subscriber_builder
|
||||
.finish()
|
||||
.with(logging::NodeNameLayer);
|
||||
initialize_tracing(subscriber, tracing_receiver, profiling_targets)
|
||||
}
|
||||
}
|
||||
|
||||
fn initialize_tracing<S>(
|
||||
subscriber: S,
|
||||
tracing_receiver: sc_tracing::TracingReceiver,
|
||||
profiling_targets: Option<String>,
|
||||
) -> std::result::Result<(), String>
|
||||
where
|
||||
S: tracing::Subscriber + Send + Sync + 'static,
|
||||
{
|
||||
if let Some(profiling_targets) = profiling_targets {
|
||||
let profiling = sc_tracing::ProfilingLayer::new(tracing_receiver, &profiling_targets);
|
||||
|
||||
if let Err(e) = tracing::subscriber::set_global_default(subscriber.with(profiling)) {
|
||||
return Err(format!(
|
||||
"Registering Substrate tracing subscriber failed: {:}!", e
|
||||
@@ -339,7 +366,7 @@ pub fn init_logger(
|
||||
} else {
|
||||
if let Err(e) = tracing::subscriber::set_global_default(subscriber) {
|
||||
return Err(format!(
|
||||
"Registering Substrate tracing subscriber failed: {:}!", e
|
||||
"Registering Substrate tracing subscriber failed: {:}!", e
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -356,7 +383,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_logger_filters() {
|
||||
let test_pattern = "afg=debug,sync=trace,client=warn,telemetry,something-with-dash=error";
|
||||
init_logger(&test_pattern, Default::default(), Default::default()).unwrap();
|
||||
init_logger(&test_pattern, Default::default(), Default::default(), false).unwrap();
|
||||
|
||||
tracing::dispatcher::get_default(|dispatcher| {
|
||||
let test_filter = |target, level| {
|
||||
@@ -415,7 +442,7 @@ mod tests {
|
||||
fn log_something_with_dash_target_name() {
|
||||
if env::var("ENABLE_LOGGING").is_ok() {
|
||||
let test_pattern = "test-target=info";
|
||||
init_logger(&test_pattern, Default::default(), Default::default()).unwrap();
|
||||
init_logger(&test_pattern, Default::default(), Default::default(), false).unwrap();
|
||||
|
||||
log::info!(target: "test-target", "{}", EXPECTED_LOG_MESSAGE);
|
||||
}
|
||||
@@ -450,7 +477,8 @@ mod tests {
|
||||
#[test]
|
||||
fn prefix_in_log_lines_entrypoint() {
|
||||
if env::var("ENABLE_LOGGING").is_ok() {
|
||||
init_logger("", Default::default(), Default::default()).unwrap();
|
||||
let test_pattern = "test-target=info";
|
||||
init_logger(&test_pattern, Default::default(), Default::default(), false).unwrap();
|
||||
prefix_in_log_lines_process();
|
||||
}
|
||||
}
|
||||
@@ -466,7 +494,7 @@ mod tests {
|
||||
#[test]
|
||||
fn do_not_write_with_colors_on_tty_entrypoint() {
|
||||
if env::var("ENABLE_LOGGING").is_ok() {
|
||||
init_logger("", Default::default(), Default::default()).unwrap();
|
||||
init_logger("", Default::default(), Default::default(), false).unwrap();
|
||||
log::info!("{}", ansi_term::Colour::Yellow.paint(EXPECTED_LOG_MESSAGE));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,317 +0,0 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2020 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use std::fmt::{self, Write};
|
||||
use ansi_term::Colour;
|
||||
use tracing::{span::Attributes, Event, Id, Level, Subscriber};
|
||||
use tracing_log::NormalizeEvent;
|
||||
use tracing_subscriber::{
|
||||
fmt::{
|
||||
time::{FormatTime, SystemTime},
|
||||
FmtContext, FormatEvent, FormatFields,
|
||||
},
|
||||
layer::Context,
|
||||
registry::LookupSpan,
|
||||
Layer,
|
||||
};
|
||||
use regex::Regex;
|
||||
|
||||
/// Span name used for the logging prefix. See macro `sc_cli::prefix_logs_with!`
|
||||
pub const PREFIX_LOG_SPAN: &str = "substrate-log-prefix";
|
||||
|
||||
/// A writer that may write to `inner_writer` with colors.
|
||||
///
|
||||
/// This is used by [`EventFormat`] to kill colors when `enable_color` is `false`.
|
||||
///
|
||||
/// It is required to call [`MaybeColorWriter::write`] after all writes are done,
|
||||
/// because the content of these writes is buffered and will only be written to the
|
||||
/// `inner_writer` at that point.
|
||||
struct MaybeColorWriter<'a> {
|
||||
enable_color: bool,
|
||||
buffer: String,
|
||||
inner_writer: &'a mut dyn fmt::Write,
|
||||
}
|
||||
|
||||
impl<'a> fmt::Write for MaybeColorWriter<'a> {
|
||||
fn write_str(&mut self, buf: &str) -> fmt::Result {
|
||||
self.buffer.push_str(buf);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MaybeColorWriter<'a> {
|
||||
/// Creates a new instance.
|
||||
fn new(enable_color: bool, inner_writer: &'a mut dyn fmt::Write) -> Self {
|
||||
Self {
|
||||
enable_color,
|
||||
inner_writer,
|
||||
buffer: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Write the buffered content to the `inner_writer`.
|
||||
fn write(&mut self) -> fmt::Result {
|
||||
lazy_static::lazy_static! {
|
||||
static ref RE: Regex = Regex::new("\x1b\\[[^m]+m").expect("Error initializing color regex");
|
||||
}
|
||||
|
||||
if !self.enable_color {
|
||||
let replaced = RE.replace_all(&self.buffer, "");
|
||||
self.inner_writer.write_str(&replaced)
|
||||
} else {
|
||||
self.inner_writer.write_str(&self.buffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct EventFormat<T = SystemTime> {
|
||||
pub(crate) timer: T,
|
||||
pub(crate) display_target: bool,
|
||||
pub(crate) display_level: bool,
|
||||
pub(crate) display_thread_name: bool,
|
||||
pub(crate) enable_color: bool,
|
||||
}
|
||||
|
||||
// NOTE: the following code took inspiration from tracing-subscriber
|
||||
//
|
||||
// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/format/mod.rs#L449
|
||||
impl<S, N, T> FormatEvent<S, N> for EventFormat<T>
|
||||
where
|
||||
S: Subscriber + for<'a> LookupSpan<'a>,
|
||||
N: for<'a> FormatFields<'a> + 'static,
|
||||
T: FormatTime,
|
||||
{
|
||||
fn format_event(
|
||||
&self,
|
||||
ctx: &FmtContext<S, N>,
|
||||
writer: &mut dyn fmt::Write,
|
||||
event: &Event,
|
||||
) -> fmt::Result {
|
||||
let writer = &mut MaybeColorWriter::new(self.enable_color, writer);
|
||||
let normalized_meta = event.normalized_metadata();
|
||||
let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());
|
||||
time::write(&self.timer, writer, self.enable_color)?;
|
||||
|
||||
if self.display_level {
|
||||
let fmt_level = { FmtLevel::new(meta.level(), self.enable_color) };
|
||||
write!(writer, "{} ", fmt_level)?;
|
||||
}
|
||||
|
||||
if self.display_thread_name {
|
||||
let current_thread = std::thread::current();
|
||||
match current_thread.name() {
|
||||
Some(name) => {
|
||||
write!(writer, "{} ", FmtThreadName::new(name))?;
|
||||
}
|
||||
// fall-back to thread id when name is absent and ids are not enabled
|
||||
None => {
|
||||
write!(writer, "{:0>2?} ", current_thread.id())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Custom code to display node name
|
||||
if let Some(span) = ctx.lookup_current() {
|
||||
let parents = span.parents();
|
||||
for span in std::iter::once(span).chain(parents) {
|
||||
let exts = span.extensions();
|
||||
if let Some(node_name) = exts.get::<NodeName>() {
|
||||
write!(writer, "{}", node_name.as_str())?;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.display_target {
|
||||
write!(writer, "{}:", meta.target())?;
|
||||
}
|
||||
ctx.format_fields(writer, event)?;
|
||||
writeln!(writer)?;
|
||||
|
||||
writer.write()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct NodeNameLayer;
|
||||
|
||||
impl<S> Layer<S> for NodeNameLayer
|
||||
where
|
||||
S: Subscriber + for<'a> LookupSpan<'a>,
|
||||
{
|
||||
fn new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
|
||||
let span = ctx
|
||||
.span(id)
|
||||
.expect("new_span has been called for this span; qed");
|
||||
|
||||
if span.name() != PREFIX_LOG_SPAN {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut extensions = span.extensions_mut();
|
||||
|
||||
if extensions.get_mut::<NodeName>().is_none() {
|
||||
let mut s = String::new();
|
||||
let mut v = NodeNameVisitor(&mut s);
|
||||
attrs.record(&mut v);
|
||||
|
||||
if !s.is_empty() {
|
||||
let fmt_fields = NodeName(s);
|
||||
extensions.insert(fmt_fields);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct NodeNameVisitor<'a, W: std::fmt::Write>(&'a mut W);
|
||||
|
||||
macro_rules! write_node_name {
|
||||
($method:ident, $type:ty, $format:expr) => {
|
||||
fn $method(&mut self, field: &tracing::field::Field, value: $type) {
|
||||
if field.name() == "name" {
|
||||
write!(self.0, $format, value).expect("no way to return the err; qed");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<'a, W: std::fmt::Write> tracing::field::Visit for NodeNameVisitor<'a, W> {
|
||||
write_node_name!(record_debug, &dyn std::fmt::Debug, "[{:?}] ");
|
||||
write_node_name!(record_str, &str, "[{}] ");
|
||||
write_node_name!(record_i64, i64, "[{}] ");
|
||||
write_node_name!(record_u64, u64, "[{}] ");
|
||||
write_node_name!(record_bool, bool, "[{}] ");
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NodeName(String);
|
||||
|
||||
impl NodeName {
|
||||
fn as_str(&self) -> &str {
|
||||
self.0.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
struct FmtLevel<'a> {
|
||||
level: &'a Level,
|
||||
ansi: bool,
|
||||
}
|
||||
|
||||
impl<'a> FmtLevel<'a> {
|
||||
pub(crate) fn new(level: &'a Level, ansi: bool) -> Self {
|
||||
Self { level, ansi }
|
||||
}
|
||||
}
|
||||
|
||||
const TRACE_STR: &str = "TRACE";
|
||||
const DEBUG_STR: &str = "DEBUG";
|
||||
const INFO_STR: &str = " INFO";
|
||||
const WARN_STR: &str = " WARN";
|
||||
const ERROR_STR: &str = "ERROR";
|
||||
|
||||
impl<'a> fmt::Display for FmtLevel<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.ansi {
|
||||
match *self.level {
|
||||
Level::TRACE => write!(f, "{}", Colour::Purple.paint(TRACE_STR)),
|
||||
Level::DEBUG => write!(f, "{}", Colour::Blue.paint(DEBUG_STR)),
|
||||
Level::INFO => write!(f, "{}", Colour::Green.paint(INFO_STR)),
|
||||
Level::WARN => write!(f, "{}", Colour::Yellow.paint(WARN_STR)),
|
||||
Level::ERROR => write!(f, "{}", Colour::Red.paint(ERROR_STR)),
|
||||
}
|
||||
} else {
|
||||
match *self.level {
|
||||
Level::TRACE => f.pad(TRACE_STR),
|
||||
Level::DEBUG => f.pad(DEBUG_STR),
|
||||
Level::INFO => f.pad(INFO_STR),
|
||||
Level::WARN => f.pad(WARN_STR),
|
||||
Level::ERROR => f.pad(ERROR_STR),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct FmtThreadName<'a> {
|
||||
name: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> FmtThreadName<'a> {
|
||||
pub(crate) fn new(name: &'a str) -> Self {
|
||||
Self { name }
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: the following code has been duplicated from tracing-subscriber
|
||||
//
|
||||
// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/format/mod.rs#L845
|
||||
impl<'a> fmt::Display for FmtThreadName<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use std::sync::atomic::{
|
||||
AtomicUsize,
|
||||
Ordering::{AcqRel, Acquire, Relaxed},
|
||||
};
|
||||
|
||||
// Track the longest thread name length we've seen so far in an atomic,
|
||||
// so that it can be updated by any thread.
|
||||
static MAX_LEN: AtomicUsize = AtomicUsize::new(0);
|
||||
let len = self.name.len();
|
||||
// Snapshot the current max thread name length.
|
||||
let mut max_len = MAX_LEN.load(Relaxed);
|
||||
|
||||
while len > max_len {
|
||||
// Try to set a new max length, if it is still the value we took a
|
||||
// snapshot of.
|
||||
match MAX_LEN.compare_exchange(max_len, len, AcqRel, Acquire) {
|
||||
// We successfully set the new max value
|
||||
Ok(_) => break,
|
||||
// Another thread set a new max value since we last observed
|
||||
// it! It's possible that the new length is actually longer than
|
||||
// ours, so we'll loop again and check whether our length is
|
||||
// still the longest. If not, we'll just use the newer value.
|
||||
Err(actual) => max_len = actual,
|
||||
}
|
||||
}
|
||||
|
||||
// pad thread name using `max_len`
|
||||
write!(f, "{:>width$}", self.name, width = max_len)
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: the following code has been duplicated from tracing-subscriber
|
||||
//
|
||||
// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/time/mod.rs#L252
|
||||
mod time {
|
||||
use ansi_term::Style;
|
||||
use std::fmt;
|
||||
use tracing_subscriber::fmt::time::FormatTime;
|
||||
|
||||
pub(crate) fn write<T>(timer: T, writer: &mut dyn fmt::Write, with_ansi: bool) -> fmt::Result
|
||||
where
|
||||
T: FormatTime,
|
||||
{
|
||||
if with_ansi {
|
||||
let style = Style::new().dimmed();
|
||||
write!(writer, "{}", style.prefix())?;
|
||||
timer.format_time(writer)?;
|
||||
write!(writer, "{}", style.suffix())?;
|
||||
} else {
|
||||
timer.format_time(writer)?;
|
||||
}
|
||||
writer.write_char(' ')?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::arg_enums::{
|
||||
ExecutionStrategy, TracingReceiver, WasmExecutionMethod, DEFAULT_EXECUTION_BLOCK_CONSTRUCTION,
|
||||
ExecutionStrategy, WasmExecutionMethod, DEFAULT_EXECUTION_BLOCK_CONSTRUCTION,
|
||||
DEFAULT_EXECUTION_IMPORT_BLOCK, DEFAULT_EXECUTION_IMPORT_BLOCK_VALIDATOR,
|
||||
DEFAULT_EXECUTION_OFFCHAIN_WORKER, DEFAULT_EXECUTION_OTHER, DEFAULT_EXECUTION_SYNCING,
|
||||
};
|
||||
@@ -73,32 +73,9 @@ pub struct ImportParams {
|
||||
default_value = "67108864"
|
||||
)]
|
||||
pub state_cache_size: usize,
|
||||
|
||||
/// Comma separated list of targets for tracing.
|
||||
#[structopt(long = "tracing-targets", value_name = "TARGETS")]
|
||||
pub tracing_targets: Option<String>,
|
||||
|
||||
/// Receiver to process tracing messages.
|
||||
#[structopt(
|
||||
long = "tracing-receiver",
|
||||
value_name = "RECEIVER",
|
||||
possible_values = &TracingReceiver::variants(),
|
||||
case_insensitive = true,
|
||||
default_value = "Log"
|
||||
)]
|
||||
pub tracing_receiver: TracingReceiver,
|
||||
}
|
||||
|
||||
impl ImportParams {
|
||||
/// Receiver to process tracing messages.
|
||||
pub fn tracing_receiver(&self) -> sc_service::TracingReceiver {
|
||||
self.tracing_receiver.clone().into()
|
||||
}
|
||||
|
||||
/// Comma separated list of targets for tracing.
|
||||
pub fn tracing_targets(&self) -> Option<String> {
|
||||
self.tracing_targets.clone()
|
||||
}
|
||||
|
||||
/// Specify the state cache size.
|
||||
pub fn state_cache_size(&self) -> usize {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
use sc_service::config::BasePath;
|
||||
use std::path::PathBuf;
|
||||
use structopt::StructOpt;
|
||||
use crate::arg_enums::TracingReceiver;
|
||||
|
||||
/// Shared parameters used by all `CoreParams`.
|
||||
#[derive(Debug, StructOpt)]
|
||||
@@ -44,6 +45,28 @@ pub struct SharedParams {
|
||||
/// By default, all targets log `info`. The global log level can be set with -l<level>.
|
||||
#[structopt(short = "l", long, value_name = "LOG_PATTERN")]
|
||||
pub log: Vec<String>,
|
||||
|
||||
/// Disable feature to dynamically update and reload the log filter.
|
||||
///
|
||||
/// By default this feature is enabled, however it leads to a small performance decrease.
|
||||
/// The `system_addLogFilter` and `system_resetLogFilter` RPCs will have no effect with this
|
||||
/// option set.
|
||||
#[structopt(long = "disable-log-reloading")]
|
||||
pub disable_log_reloading: bool,
|
||||
|
||||
/// Sets a custom profiling filter. Syntax is the same as for logging: <target>=<level>
|
||||
#[structopt(long = "tracing-targets", value_name = "TARGETS")]
|
||||
pub tracing_targets: Option<String>,
|
||||
|
||||
/// Receiver to process tracing messages.
|
||||
#[structopt(
|
||||
long = "tracing-receiver",
|
||||
value_name = "RECEIVER",
|
||||
possible_values = &TracingReceiver::variants(),
|
||||
case_insensitive = true,
|
||||
default_value = "Log"
|
||||
)]
|
||||
pub tracing_receiver: TracingReceiver,
|
||||
}
|
||||
|
||||
impl SharedParams {
|
||||
@@ -75,4 +98,19 @@ impl SharedParams {
|
||||
pub fn log_filters(&self) -> &[String] {
|
||||
&self.log
|
||||
}
|
||||
|
||||
/// Is log reloading disabled
|
||||
pub fn is_log_filter_reloading_disabled(&self) -> bool {
|
||||
self.disable_log_reloading
|
||||
}
|
||||
|
||||
/// Receiver to process tracing messages.
|
||||
pub fn tracing_receiver(&self) -> sc_service::TracingReceiver {
|
||||
self.tracing_receiver.clone().into()
|
||||
}
|
||||
|
||||
/// Comma separated list of targets for tracing.
|
||||
pub fn tracing_targets(&self) -> Option<String> {
|
||||
self.tracing_targets.clone()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user