Tracing_subscriber how to print file name and line

hi, rust expert

I'm trying to add file name and file line number based on tracing_subscriber default output, but I can't find related api.

fn main() {
    tracing_subscriber::fmt::init();
    tracing::error!("hello, world");
}

give me

Jul 09 20:38:04.873 ERROR ruster: hello, world

what I need is

Jul 09 20:38:04.873 ERROR ruster main.rs:3  hello, world

Is there a possible to do that without implementing a custom Subscriber?
Thanks in advance!

An easy way to get file name and line numbers is to use the built-in pretty formatter:

fn main() {
    tracing_subscriber::fmt().pretty().init();
    tracing::error!("hello, world");
}

However, the output uses multiple lines for each log record. Also note that there's a minor formatting bug that's fixed, but not in the current release.

I also wanted a format like you're asking for and ended up implementing a custom FormatEvent like this:

use std::fmt::{Error, Write};

use crossterm::style::Stylize;
use tracing::{subscriber::Subscriber, Event};
use tracing_log::NormalizeEvent;
use tracing_subscriber::{
    fmt::{
        time::{ChronoLocal, FormatTime},
        FmtContext, FormatEvent, FormatFields,
    },
    registry::LookupSpan,
};

fn main() {
    tracing_subscriber::fmt().event_format(SimpleFmt).init();
    tracing::error!("hello, world");
}

struct SimpleFmt;

impl<S, N> FormatEvent<S, N> for SimpleFmt
where
    S: Subscriber + for<'a> LookupSpan<'a>,
    N: for<'a> FormatFields<'a> + 'static,
{
    fn format_event(
        &self,
        ctx: &FmtContext<'_, S, N>,
        writer: &mut dyn Write,
        event: &Event<'_>,
    ) -> Result<(), Error> {
        // Create timestamp
        let time_format = "%b %d %I:%M:%S%.6f %p";
        let mut time_now = String::new();
        ChronoLocal::with_format(time_format.into()).format_time(&mut time_now)?;

        // Get line numbers from log crate events
        let normalized_meta = event.normalized_metadata();
        let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());

        // Write formatted log record
        let message = format!(
            "{} {} {}{}{} ",
            time_now.grey(),
            meta.level().to_string().blue(),
            meta.file().unwrap_or("").to_string().yellow(),
            String::from(":").yellow(),
            meta.line().unwrap_or(0).to_string().yellow(),
        );
        write!(writer, "{}", message).unwrap();
        ctx.format_fields(writer, event)?;
        writeln!(writer)
    }
}
2 Likes

Thanks for your solution. Custom FormatEnv works fine. :slight_smile:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.