Log and env_logger -- is my initialisation correct, please?

Hi,

I'm looking at logging in Rust. I am starting with a simple one, env_logger crate, and I'm logging directly into the stdout.

I understand that we need to set the RUST_LOG environment variable to some value, such as debug to get log going.

I have the value for RUST_LOG inside my .env file. Upon the executable starting, I read the .env file and set the RUST_LOG environment variable.

Is this acceptable, please?

My complete test project follows below.

Project layout:

project/
|
|-- .env
|-- Cargo.toml
|-- src/
    |
    |-- main.rs
Content of .env file:
RUST_LOG=debug
Content of Cargo.toml:
[package]
name = "learn-env-logger"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
dotenv = "0.15.0"
log = "0.4"
env_logger = "0.10.0"
rand = "0.8.5"
Content of src/main.rs:
use dotenv::dotenv;
use log::{debug, info};
use env_logger;

use std::io;
use rand::Rng;

#[derive(Debug)]
pub struct Config {
    pub rust_log: String,
}

impl Config {
    pub fn init() -> Config {
        Config {
            rust_log: std::env::var("RUST_LOG")
                .expect("RUST_LOG must be specified"),
        }
    }
}

fn main() {
    dotenv().ok();
    let config = Config::init();

    std::env::set_var("RUST_LOG", &config.rust_log);
    env_logger::init();

    info!("Initialisation completed.");

    loop {
        println!("Please type in something: ");

        let mut input = String::new();

        io::stdin()
            .read_line(&mut input)
            .expect("Failed to read line");

        let random_number = rand::thread_rng().gen_range(1..=100);

        if let 0 = random_number % 2 {
            info!("You typed in: {input}");
        }
        else {
            debug!("You typed in: {input}");
        };        
    }
}

The lines:

    dotenv().ok();
    let config = Config::init();

    std::env::set_var("RUST_LOG", &config.rust_log);
    env_logger::init();

is where I'm loading the .env file, and set the value of the RUST_LOG environment variable, and then initialise the logger.

This test project works as I intended. I am just not sure if what I am doing is acceptable.

Thank you and best regards,

...behai.

You don't need to set the RUST_LOG variable again, dotenv does this for you. So the std::env::set_var("RUST_LOG", &config.rust_log); line looks pretty redundant to me. I also don't see a need to keep your Config type around (or at least its rust_log field), but that may be just because this is a minimal example and not your real project which has more fields for additional configuration.

2 Likes

Hi jofas,

Thank you kindly for your helps. You are right both issues.

I just rebuilt without this line:

std::env::set_var("RUST_LOG", &config.rust_log);

And it still works. I must have got something wrong before adding this line, I've read how dotenv works.

Thank you and best regards,

...behai.

1 Like
src/main.rs refactored version:

use dotenv::dotenv;
use log::{debug, info};
use env_logger;

use std::io;
use rand::Rng;

fn main() {
dotenv().ok();

env_logger::init();

info!("Initialisation completed.");

loop {
    println!("Please type in something: ");

    let mut input = String::new();

    io::stdin()
        .read_line(&mut input)
        .expect("Failed to read line");

    let random_number = rand::thread_rng().gen_range(1..=100);

    if let 0 = random_number % 2 {
        info!("You typed in: {input}");
    }
    else {
        debug!("You typed in: {input}");
    };        
}

}