Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add feature flag to enable ansi colors and RUST_LOG filtering for terminal output #51

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ way to assert that certain things were logged.

The focus is on testing the logging, not on debugging the tests. That's why the
library ensures that the logs do not depend on external state. For example, the
`RUST_LOG` env variable is not used for log filtering.
`RUST_LOG` env variable is not used for log filtering by default.

To disable all log output, even when tests are run with `--nocapture`, enable
the `no-log-printing` feature.

To enable ANSI colors and support for filtering with `RUST_LOG` in the terminal
output, enable the `pretty-log-printing` feature.

Similar crates:

Expand Down
6 changes: 5 additions & 1 deletion tracing-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ categories = ["development-tools::testing"]

[dependencies]
tracing-core = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
tracing-subscriber = { version = "0.3", features = ["env-filter", "registry"] }
tracing-test-macro = { path = "../tracing-test-macro", version = "0.2.5" }

[dev-dependencies]
Expand All @@ -26,3 +26,7 @@ maintenance = { status = "experimental" }
[features]
# Disable hardcoded env filter
no-env-filter = ["tracing-test-macro/no-env-filter"]
# Disables log printing
no-log-printing = []
# Enables pretty log printing with support for RUST_LOG filtering and ansi colors
pretty-log-printing = []
8 changes: 8 additions & 0 deletions tracing-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,14 @@
//! **Note:** Rust "integration tests" (in the `tests/` directory) are each
//! built into a separate crate from the crate they test. As a result,
//! integration tests must use `no-env-filter` to capture and observe logs.
//!
//! ## Controlling log printing
//!
//! To suppress all log output, even when tests are run with `--nocapture`,
//! enable `no-log-printing` feature.
//!
//! To enable color output and support for filtering with `RUST_LOG` in the
//! terminal output, enable the `pretty-log-printing` feature.

pub mod internal;
mod subscriber;
Expand Down
55 changes: 49 additions & 6 deletions tracing-test/src/subscriber.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{
};

use tracing_core::Dispatch;
use tracing_subscriber::{fmt::MakeWriter, FmtSubscriber};
use tracing_subscriber::{fmt::MakeWriter, layer::SubscriberExt, EnvFilter, Layer, Registry};

/// A fake writer that writes into a buffer (behind a mutex).
#[derive(Debug)]
Expand Down Expand Up @@ -33,7 +33,8 @@ impl<'a> io::Write for MockWriter<'a> {
// Lock target buffer
let mut target = self.buf()?;

// Write to stdout in order to show up in tests
// Print to output if no-log-printing is off and pretty-log-printing is off as well.
#[cfg(not(any(feature = "no-log-printing", feature = "pretty-log-printing")))]
print!("{}", String::from_utf8(buf.to_vec()).unwrap());

// Write to buffer
Expand All @@ -53,14 +54,56 @@ impl<'a> MakeWriter<'_> for MockWriter<'a> {
}
}

/// Return a new subscriber that writes to the specified [`MockWriter`].
/// Return a new subscriber that writes to the specified [`MockWriter`] and
/// to standard output.
///
/// [`MockWriter`]: struct.MockWriter.html
pub fn get_subscriber(mock_writer: MockWriter<'static>, env_filter: &str) -> Dispatch {
FmtSubscriber::builder()
.with_env_filter(env_filter)
let filter = EnvFilter::new(env_filter);
let mock_writer_layer = tracing_subscriber::fmt::layer()
.with_writer(mock_writer)
.with_level(true)
.with_ansi(false)
.into()
.with_filter(filter);

#[cfg(not(feature = "pretty-log-printing"))]
let subscriber = Registry::default().with(mock_writer_layer);

#[cfg(feature = "pretty-log-printing")]
let subscriber = {
let print_filter = std::env::var("RUST_LOG").unwrap_or_else(|_| env_filter.to_string());
let print_filter = EnvFilter::new(print_filter);
let print_layer = tracing_subscriber::fmt::layer()
.with_writer(|| TestWriter)
.event_format(tracing_subscriber::fmt::format().with_line_number(true))
.with_level(true)
.with_filter(print_filter);
Registry::default()
.with(mock_writer_layer)
.with(print_layer)
};

subscriber.into()
}

/// A tracing writer that interacts well with test output capture.
///
/// Using this writer will make sure that the output is captured normally and only printed
/// when the test fails.
#[cfg(feature = "pretty-log-printing")]
#[derive(Debug)]
struct TestWriter;

#[cfg(feature = "pretty-log-printing")]
impl std::io::Write for TestWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
print!(
"{}",
std::str::from_utf8(buf).expect("tried to log invalid UTF-8")
);
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
std::io::stdout().flush()
}
}