When i learning rust,i have a problem in use tracing to log

if code write as follow, it will work:

use std::time::Duration;
use tokio::time::sleep;
use tracing::{info, instrument};
#[tokio::main]
async fn main() {
    let file_writer = tracing_appender::rolling::daily("logs", "log.txt");
    let (non_blocking_writer, _guard) = tracing_appender::non_blocking(file_writer);
    tracing_subscriber::fmt()
        .with_writer(non_blocking_writer)
        .with_ansi(false)
        .init();
    wait().await;
    info!("Starting server...")
}
#[instrument]
async fn wait() {
    sleep(Duration::from_secs(1)).await;
    info!("record after 1s");
}

but if i create a function to wrap tracing init,it will not work:

use std::time::Duration;
use tokio::time::sleep;
use tracing::{info, instrument};
#[tokio::main]
async fn main() {
    init();
    wait().await;
    info!("Starting server...")
}
#[instrument]
async fn wait() {
    sleep(Duration::from_secs(1)).await;
    info!("record after 1s");
}
fn init() {
    let file_writer = tracing_appender::rolling::daily("logs", "log.txt");
    let (non_blocking_writer, _guard) = tracing_appender::non_blocking(file_writer);
    tracing_subscriber::fmt()
        .with_writer(non_blocking_writer)
        .with_ansi(false)
        .init();
}

what problem,it‘s lifetime problem? when the function excuted ,this scope will drop? if i still want wrap it into a function ,how to modify it.

the problem is the _guard object. the appender is destructed when the _guard is dropped. if you want to use an init function, you should make sure the _guard is NOT dropped when the function returns. two common appraches includes:

  1. leak the guard object so it will never get dropped, e.g. use mem::forget()

  2. return the guard object to the caller, and let the caller decide how to deal with it.

oh ! it work, thanks :grinning: