#log-level #log #stderr #logging

buche

Logger that logs to stderr based on verbosity specified

3 unstable releases

0.7.0 Jan 10, 2023
0.6.0 Jan 10, 2023

#617 in Debugging

Download history 11/week @ 2023-12-22 26/week @ 2023-12-29 120/week @ 2024-01-05 220/week @ 2024-01-12 138/week @ 2024-01-19 61/week @ 2024-01-26 156/week @ 2024-02-02 68/week @ 2024-02-09 79/week @ 2024-02-16 122/week @ 2024-02-23 152/week @ 2024-03-01 177/week @ 2024-03-08 141/week @ 2024-03-15 137/week @ 2024-03-22 217/week @ 2024-03-29 99/week @ 2024-04-05

639 downloads per month
Used in genominicus

MIT/Apache

26KB
358 lines

A fork of stderrlog, a logger that aims to provide a simple case of env_logger that just logs to stderr based on verbosity.

Documentation

For a working example for StructOpt, clap, and docopt please see the crate level documentation.

For example binaries showing how module level logging works, please see the large-example crate in examples/.

Usage

Add this to your Cargo.toml:

[dependencies]
buche = "0.6"

and this to your main():

buche::new().verbosity(args.flag_v).quiet(args.flag_q).init().unwrap();

where your args struct is defined as:

struct Args {
    flag_v: usize,
    flag_q: bool,
    ...
}

lib.rs:

A simple logger to provide semantics similar to what is expected of most UNIX utilities by logging to stderr and the higher the verbosity the higher the log level. It supports the ability to provide timestamps at different granularities. As well as colorizing the different log levels.

Simple Use Case

use log::*;

fn main() {
    buche::new().module(module_path!()).init().unwrap();

    error!("some failure");

    // ...
}

StructOpt Example

use log::*;
use structopt::StructOpt;

/// A StructOpt example
#[derive(StructOpt, Debug)]
#[structopt()]
struct Opt {
    /// Silence all output
    #[structopt(short = "q", long = "quiet")]
    quiet: bool,
    /// Verbose mode (-v, -vv, -vvv, etc)
    #[structopt(short = "v", long = "verbose", parse(from_occurrences))]
    verbose: usize,
    /// Timestamp (sec, ms, ns, none)
    #[structopt(short = "t", long = "timestamp")]
    ts: Option<buche::Timestamp>,
}

fn main() {
    let opt = Opt::from_args();

    buche::new()
        .module(module_path!())
        .quiet(opt.quiet)
        .verbosity(opt.verbose)
        .timestamp(opt.ts.unwrap_or(buche::Timestamp::Off))
        .init()
        .unwrap();
    trace!("trace message");
    debug!("debug message");
    info!("info message");
    warn!("warn message");
    error!("error message");
}

docopt Example

use log::*;
use docopt::Docopt;
use serde::Deserialize;

const USAGE: &'static str = "
Usage: program [-q] [-v...]
";

#[derive(Debug, Deserialize)]
struct Args {
    flag_q: bool,
    flag_v: usize,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.deserialize())
                            .unwrap_or_else(|e| e.exit());

    buche::new()
            .module(module_path!())
            .quiet(args.flag_q)
            .timestamp(buche::Timestamp::Second)
            .verbosity(args.flag_v)
            .init()
            .unwrap();
    trace!("trace message");
    debug!("debug message");
    info!("info message");
    warn!("warn message");
    error!("error message");

    // ...
}

clap Example

use clap::{Arg, App, crate_version};
use log::*;
use std::str::FromStr;

fn main() {
    let m = App::new("buche example")
        .version(crate_version!())
        .arg(Arg::with_name("verbosity")
             .short('v')
             .takes_value(true)
             .multiple(true)
             .help("Increase message verbosity"))
        .arg(Arg::with_name("quiet")
             .short('q')
             .help("Silence all output"))
        .arg(Arg::with_name("timestamp")
             .short('t')
             .help("prepend log lines with a timestamp")
             .takes_value(true)
             .possible_values(&["none", "sec", "ms", "ns"]))
        .get_matches();

    let verbose = m.occurrences_of("verbosity") as usize;
    let quiet = m.is_present("quiet");
    let ts = m.value_of("timestamp").map(|v| {
        buche::Timestamp::from_str(v).unwrap_or_else(|_| {
            clap::Error::raw(clap::ErrorKind::InvalidValue, "invalid value for 'timestamp'").exit()
        })
    }).unwrap_or(buche::Timestamp::Off);

    buche::new()
        .module(module_path!())
        .quiet(quiet)
        .verbosity(verbose)
        .timestamp(ts)
        .init()
        .unwrap();
    trace!("trace message");
    debug!("debug message");
    info!("info message");
    warn!("warn message");
    error!("error message");
}

log Compatibility

The 0.5.x versions of buche aim to provide compatibility with applications using log >= 0.4.11.

Rust Compatibility

buche is serious about backwards compat. buche pins the minimum required version of Rust in the CI build. Bumping the minimum version of Rust is a minor breaking change and requires a minor version to be bumped.

The minimum supported Rust version for this release is 1.36.0.

Module Level Logging

buche has the ability to limit the components which can log. Many crates use log but you may not want their output in your application. For example hyper makes heavy use of log but when your application receives -vvvvv to enable the trace!() messages you don't want the output of hyper's trace!() level.

To support this buche includes a module() method allowing you to specify the modules that are allowed to log. The examples above use the module_path!() macro to enable logging only for the binary itself but none of its dependencies. To enable logging from extra crates just add another call to module() with the name of the crate. To enable logging for only a module within that crate specify crate::module to module(). crates and modules will be named the same way would would include them in source code with use (e.g. some-crate would be some_crate).

For a good example of how the module level logging works see the large-example crate under examples, you'll want to run the following binaries to see all the examples:

  • cargo run --bin large-example --
  • cargo run --bin another --
  • cargo run --bin yet --

Features

buche has the following default crate features, which can be disabled to reduce the number of dependencies:

  • timestamps: Provides support for log timestamp prefixes (uses the chrono crate).

Dependencies

~0.2–7.5MB
~17K SLoC