-
Notifications
You must be signed in to change notification settings - Fork 734
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
.with_ansi(false) doesnt work #3116
Comments
People working on this do so in their spare time. I don't think this attitude is constructive. Can you try using the |
I think it worked like that as I remember, but this is not a solution.
I know, that's why I didn't add that the documentation is awful as well as the testing. The problem is behind sorting, when console layer with ANSI is the last it works correctly:
I guess it should be marked as a bug. |
I have this issue too, this is a small code to reproduce: use anyhow::{anyhow, Result};
use tracing::{error, info, instrument};
use tracing_appender::rolling::{RollingFileAppender, Rotation};
use tracing_subscriber::fmt::format::FmtSpan;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::Registry;
#[derive(Debug)]
struct TaskContext {
task_id: String,
task_type: String,
}
#[instrument(err)]
async fn risky_operation2(value: i32) -> Result<i32> {
info!("1");
if value < 0 {
info!("2");
Err(anyhow!("Value must be positive"))
} else {
Ok(value * 2)
}
}
#[instrument(err, skip(context), fields(task_id = %context.task_id, task_type = %context.task_type))]
async fn process_task(context: TaskContext) -> Result<()> {
info!("Starting task processing");
if let Err(e) = do_work(&context).await {
error!(
task_id = %context.task_id,
error = %e,
"Task processing failed"
);
return Ok(());
}
info!("Task processing completed");
Ok(())
}
#[tokio::main]
async fn main() {
// Set up rolling file appender
let file_appender = RollingFileAppender::new(
Rotation::DAILY, // or HOURLY, MINUTELY, etc.
"logs", // directory to store log files
"prefix.log", // prefix for log files
);
// Create a file writing layer
let (non_blocking_appender, _guard) = tracing_appender::non_blocking(file_appender);
let file_layer = tracing_subscriber::fmt::layer()
.with_line_number(true)
.with_thread_ids(true)
.with_target(true)
.with_ansi(false) // disable ANSI escape codes in file output
.with_writer(non_blocking_appender)
.with_span_events(FmtSpan::FULL);
// Create a console layer
let console_layer = tracing_subscriber::fmt::layer()
.with_line_number(true)
.with_thread_ids(true)
.with_target(true)
.with_ansi(true)
.with_span_events(FmtSpan::FULL);
// Combine layers
let subscriber = Registry::default().with(console_layer).with(file_layer);
// Set the subscriber as the default
tracing::subscriber::set_global_default(subscriber).expect("Failed to set tracing subscriber");
for i in 0..3 {
let context = TaskContext {
task_id: format!("task-{}", i),
task_type: "processing".to_string(),
};
tokio::spawn(process_task(context));
}
// Wait for some time to let tasks complete
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
}
#[instrument(err, skip(context), fields(task_id = %context.task_id, task_type = %context.task_type))]
async fn do_work(context: &TaskContext) -> Result<(), Box<dyn std::error::Error>> {
// Simulate some work
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
Ok(())
} [package]
name = "t1"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1"
tokio = { version = "1.0", features = ["full"] }
tracing = "0.1"
tracing-appender = "0.2"
tracing-subscriber = { version = "0.3", features = ["env-filter"] } |
In this example, I have a This should be a bug. |
@kzhui125 many people reported it before but the maintainers are ignoring the issue. |
The documentation and testing could use some work, that's another discussion in itself. There are tons of opportunities for contributing here within that space. FWIW the multi-writer example exhibits the same observed behavior. After trying to understand how things are layered in the code examples above, I'm conflicted. On one hand, @mladedav's suggestion should work. On the other hand, I don't think it should be expected to work because of how layering is designed today. Objectively, if I'm layering something then I would expect some of that span data to be inherent to other layered subscribers. Since the formatted fields are rendered and stored in the span's extensions, it sort of makes sense why we see the behavior described above. If I remember the purpose of a Registry correctly, I'm more suspicious that this is where the problem lies. The purpose of a Registry is to store span data that other subscribers can consume (extensions)... Could the layers be hacked together to make it work? Sure, but it feels unwieldy and makes the layering even hard to reason with. Layering should be used for filtering and massaging the data to a sink of subscribers that expect the same written format. Layering doesn't seem appropriate to build a sink of subscribers that expect the data to be written in their own respective format. Vector's approach to collecting, transforming, and dispatching telemetry is sort of what I'm expecting here. One could say that a program should only log to stdout and have a downstream aggregator do the dirty work of transforming and shipping your data. Then this isn't even a problem anymore. To each their own though. I say all of this as an outside user of this crate, I would like a maintainer to chime in here, and please correct me if I'm wrong. |
Possibly related (maybe even duplicate) #3065 (comment). |
I was wrong here. The example works as expected, but you must use tracing v0.2 which is unreleased at this point in time. I used the commit 91fedc1 to test it with the modified example below. //! NOTE: This is pre-release documentation for the upcoming tracing 0.2.0 ecosystem. For the
//! release examples, please see the `v0.1.x` branch instead.
//!
//! An example demonstrating how `fmt::Subcriber` can write to multiple
//! destinations (in this instance, `stdout` and a file) simultaneously.
#[path = "fmt/yak_shave.rs"]
mod yak_shave;
use std::io;
use tracing_subscriber::{fmt, subscribe::CollectExt, EnvFilter};
fn main() {
let dir = tempfile::tempdir().expect("Failed to create tempdir");
let file_appender = tracing_appender::rolling::hourly(dir.path(), "example.log");
let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender);
let collector = tracing_subscriber::registry()
.with(EnvFilter::from_default_env().add_directive(tracing::Level::TRACE.into()))
.with(
fmt::Subscriber::new()
.with_ansi(true)
.with_writer(io::stdout),
)
.with(
fmt::Subscriber::new()
.with_ansi(false)
.with_writer(non_blocking),
);
tracing::collect::set_global_default(collector).expect("Unable to set a global collector");
let number_of_yaks = 3;
// this creates a new event, outside of any spans.
tracing::info!(number_of_yaks, "preparing to shave yaks");
let number_shaved = yak_shave::shave_all(number_of_yaks);
tracing::info!(
all_yaks_shaved = number_shaved == number_of_yaks,
"yak shaving completed."
);
// prints the contents of the log file to stdout
for entry in std::fs::read_dir(dir.path()).expect("failed to read log dir") {
let entry = entry.unwrap();
let path = entry.path();
println!("contents of {:?}:", path);
println!("{}", std::fs::read_to_string(path).unwrap());
}
} |
You can also just put the |
I have a weird symbols added to a log file, I guess its some prettification for terminal output
But I expected it should be this
Thats my log writing setup
Cargo.toml
How I can remove those characters?
And in how many years till a simple problem like this will be fixed? Its not the first time it mentioned
The text was updated successfully, but these errors were encountered: