Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 02771e1

Browse files
bkchrandresilva
andauthored
Don't log with colors when we are writing to a tty (#7525)
* Don't log with colors when we are writing to a tty This fixes a regression that was introduced by the switch to tracing. Before we killed all colors before writing to a tty, this pr brings the behaviour back. * Remove accidentally added crate * Review feedback * More feedback * Update client/cli/src/logging.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Update client/cli/src/logging.rs Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>
1 parent e26a46a commit 02771e1

File tree

5 files changed

+102
-19
lines changed

5 files changed

+102
-19
lines changed

Cargo.lock

Lines changed: 5 additions & 4 deletions
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 & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"]
1515
[dependencies]
1616
log = "0.4.11"
1717
atty = "0.2.13"
18-
regex = "1.3.4"
18+
regex = "1.4.2"
19+
lazy_static = "1.4.0"
1920
ansi_term = "0.12.1"
2021
tokio = { version = "0.2.21", features = [ "signal", "rt-core", "rt-threaded", "blocking" ] }
2122
futures = "0.3.4"

client/cli/src/lib.rs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,13 @@ use structopt::{
4747
clap::{self, AppSettings},
4848
StructOpt,
4949
};
50-
#[doc(hidden)]
51-
pub use tracing;
5250
use tracing_subscriber::{
5351
filter::Directive, fmt::time::ChronoLocal, layer::SubscriberExt, FmtSubscriber, Layer,
5452
};
5553

5654
pub use logging::PREFIX_LOG_SPAN;
55+
#[doc(hidden)]
56+
pub use tracing;
5757

5858
/// Substrate client CLI
5959
///
@@ -308,8 +308,7 @@ pub fn init_logger(
308308
}
309309
}
310310

311-
let isatty = atty::is(atty::Stream::Stderr);
312-
let enable_color = isatty;
311+
let enable_color = atty::is(atty::Stream::Stderr);
313312
let timer = ChronoLocal::with_format(if simple {
314313
"%Y-%m-%d %H:%M:%S".to_string()
315314
} else {
@@ -321,12 +320,13 @@ pub fn init_logger(
321320
.with_writer(std::io::stderr)
322321
.event_format(logging::EventFormat {
323322
timer,
324-
ansi: enable_color,
325323
display_target: !simple,
326324
display_level: !simple,
327325
display_thread_name: !simple,
326+
enable_color,
328327
})
329-
.finish().with(logging::NodeNameLayer);
328+
.finish()
329+
.with(logging::NodeNameLayer);
330330

331331
if let Some(profiling_targets) = profiling_targets {
332332
let profiling = sc_tracing::ProfilingLayer::new(tracing_receiver, &profiling_targets);
@@ -450,8 +450,7 @@ mod tests {
450450
#[test]
451451
fn prefix_in_log_lines_entrypoint() {
452452
if env::var("ENABLE_LOGGING").is_ok() {
453-
let test_pattern = "test-target=info";
454-
init_logger(&test_pattern, Default::default(), Default::default()).unwrap();
453+
init_logger("", Default::default(), Default::default()).unwrap();
455454
prefix_in_log_lines_process();
456455
}
457456
}
@@ -460,4 +459,35 @@ mod tests {
460459
fn prefix_in_log_lines_process() {
461460
log::info!("{}", EXPECTED_LOG_MESSAGE);
462461
}
462+
463+
/// This is no actual test, it will be used by the `do_not_write_with_colors_on_tty` test.
464+
/// The given test will call the test executable to only execute this test that
465+
/// will only print a log line with some colors in it.
466+
#[test]
467+
fn do_not_write_with_colors_on_tty_entrypoint() {
468+
if env::var("ENABLE_LOGGING").is_ok() {
469+
init_logger("", Default::default(), Default::default()).unwrap();
470+
log::info!("{}", ansi_term::Colour::Yellow.paint(EXPECTED_LOG_MESSAGE));
471+
}
472+
}
473+
474+
#[test]
475+
fn do_not_write_with_colors_on_tty() {
476+
let re = regex::Regex::new(&format!(
477+
r"^\d{{4}}-\d{{2}}-\d{{2}} \d{{2}}:\d{{2}}:\d{{2}} {}$",
478+
EXPECTED_LOG_MESSAGE,
479+
)).unwrap();
480+
let executable = env::current_exe().unwrap();
481+
let output = Command::new(executable)
482+
.env("ENABLE_LOGGING", "1")
483+
.args(&["--nocapture", "do_not_write_with_colors_on_tty_entrypoint"])
484+
.output()
485+
.unwrap();
486+
487+
let output = String::from_utf8(output.stderr).unwrap();
488+
assert!(
489+
re.is_match(output.trim()),
490+
format!("Expected:\n{}\nGot:\n{}", re, output),
491+
);
492+
}
463493
}

client/cli/src/logging.rs

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
// You should have received a copy of the GNU General Public License
1717
// along with this program. If not, see <https://www.gnu.org/licenses/>.
1818

19+
use std::fmt::{self, Write};
1920
use ansi_term::Colour;
20-
use std::fmt;
2121
use tracing::{span::Attributes, Event, Id, Level, Subscriber};
2222
use tracing_log::NormalizeEvent;
2323
use tracing_subscriber::{
@@ -29,16 +29,62 @@ use tracing_subscriber::{
2929
registry::LookupSpan,
3030
Layer,
3131
};
32+
use regex::Regex;
3233

3334
/// Span name used for the logging prefix. See macro `sc_cli::prefix_logs_with!`
3435
pub const PREFIX_LOG_SPAN: &str = "substrate-log-prefix";
3536

37+
/// A writer that may write to `inner_writer` with colors.
38+
///
39+
/// This is used by [`EventFormat`] to kill colors when `enable_color` is `false`.
40+
///
41+
/// It is required to call [`MaybeColorWriter::write`] after all writes are done,
42+
/// because the content of these writes is buffered and will only be written to the
43+
/// `inner_writer` at that point.
44+
struct MaybeColorWriter<'a> {
45+
enable_color: bool,
46+
buffer: String,
47+
inner_writer: &'a mut dyn fmt::Write,
48+
}
49+
50+
impl<'a> fmt::Write for MaybeColorWriter<'a> {
51+
fn write_str(&mut self, buf: &str) -> fmt::Result {
52+
self.buffer.push_str(buf);
53+
Ok(())
54+
}
55+
}
56+
57+
impl<'a> MaybeColorWriter<'a> {
58+
/// Creates a new instance.
59+
fn new(enable_color: bool, inner_writer: &'a mut dyn fmt::Write) -> Self {
60+
Self {
61+
enable_color,
62+
inner_writer,
63+
buffer: String::new(),
64+
}
65+
}
66+
67+
/// Write the buffered content to the `inner_writer`.
68+
fn write(&mut self) -> fmt::Result {
69+
lazy_static::lazy_static! {
70+
static ref RE: Regex = Regex::new("\x1b\\[[^m]+m").expect("Error initializing color regex");
71+
}
72+
73+
if !self.enable_color {
74+
let replaced = RE.replace_all(&self.buffer, "");
75+
self.inner_writer.write_str(&replaced)
76+
} else {
77+
self.inner_writer.write_str(&self.buffer)
78+
}
79+
}
80+
}
81+
3682
pub(crate) struct EventFormat<T = SystemTime> {
3783
pub(crate) timer: T,
38-
pub(crate) ansi: bool,
3984
pub(crate) display_target: bool,
4085
pub(crate) display_level: bool,
4186
pub(crate) display_thread_name: bool,
87+
pub(crate) enable_color: bool,
4288
}
4389

4490
// NOTE: the following code took inspiration from tracing-subscriber
@@ -56,12 +102,13 @@ where
56102
writer: &mut dyn fmt::Write,
57103
event: &Event,
58104
) -> fmt::Result {
105+
let writer = &mut MaybeColorWriter::new(self.enable_color, writer);
59106
let normalized_meta = event.normalized_metadata();
60107
let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());
61-
time::write(&self.timer, writer, self.ansi)?;
108+
time::write(&self.timer, writer, self.enable_color)?;
62109

63110
if self.display_level {
64-
let fmt_level = { FmtLevel::new(meta.level(), self.ansi) };
111+
let fmt_level = { FmtLevel::new(meta.level(), self.enable_color) };
65112
write!(writer, "{} ", fmt_level)?;
66113
}
67114

@@ -94,7 +141,9 @@ where
94141
write!(writer, "{}:", meta.target())?;
95142
}
96143
ctx.format_fields(writer, event)?;
97-
writeln!(writer)
144+
writeln!(writer)?;
145+
146+
writer.write()
98147
}
99148
}
100149

client/informant/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ mod display;
3535
/// The format to print telemetry output in.
3636
#[derive(Clone, Debug)]
3737
pub struct OutputFormat {
38-
/// Enable color output in logs. True by default.
38+
/// Enable color output in logs.
39+
///
40+
/// Is enabled by default.
3941
pub enable_color: bool,
4042
}
4143

0 commit comments

Comments
 (0)