Crates.io | ocli |
lib.rs | ocli |
version | 0.1.2 |
source | src |
created_at | 2024-01-18 19:54:15.212018 |
updated_at | 2024-02-17 14:15:02.303825 |
description | A simple, opinionated logger for command line tools |
homepage | https://github.com/glehmann/ocli/ |
repository | https://github.com/glehmann/ocli.git |
max_upload_size | |
id | 1104504 |
size | 145,060 |
A simple, opinionated logger for command line tools
ocli
aims at a very simple thing: logging for CLI tools done right. It uses the
log
crate and the ansi_term
crate for colors. It provides very few configuration —
at this time, just the expected log level.
stderr
CLI tools are expected to be usable in a pipe. In that context,
the messages addressed to the user must be written on stderr
to have a chance to be read
by the user, independently of the log level.
The program outputs that are meant to be used with a pipe shouldn't go through the logging
system, but instead be printed to stdout
, for example with println!
.
Info
message as plain uncolored textInfo
is expected to be the normal log
level to display messages that are not highlighting a problem and that are not too verbose
for a standard usage of the tool. Because it is intended for messages that are related
to a normal situation, the messages of that level are not prefixed with the log level.
Info
The color depends on the log level, allowing to quickly locate a message at a specific log level
Trace
log levelfor all the
messages, even if they are not at the Trace
log level. The Trace
log level is used
to help the developer understand where a message comes from, in addition to display a larger
amount of messages.
stderr
is not a ttyso the output is not polluted with unreadable characters when stderr
is redirected to a file.
Info
log level#[macro_use] extern crate log;
fn main() {
ocli::init(log::Level::Info).unwrap();
error!("This is printed to stderr, with the 'error: ' prefix colored in red");
warn!("This is printed to stderr, with the 'warn: ' prefix colored in yellow");
info!("This is printed to stderr, without prefix or color");
debug!("This is not printed");
trace!("This is not printed");
}
Trace
log level#[macro_use] extern crate log;
fn main() {
ocli::init(log::Level::Trace).unwrap();
error!("This is printed to stderr, with the 'path(line): error: ' prefix colored in red");
warn!("This is printed to stderr, with the 'path(line): warn: ' prefix colored in yellow");
info!("This is printed to stderr, with the 'path(line): info: ' prefix");
debug!("This is printed to stderr, with the 'path(line): debug: ' prefix colored in blue");
trace!("This is printed to stderr, with the 'path(line): trace: ' prefix colored in magenta");
}
and a more realistic example with hld:
The log level can be configured with a command line argument, using the clap
crate.
Try running it with cargo run --example cli -- --log-level trace
and change the log level
to see the difference.
#[macro_use]
extern crate log;
use clap::Parser;
/// A demo of ocli with clap
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
pub struct Config {
/// Log level
#[arg(short, long, default_value_t = log::Level::Info)]
pub log_level: log::Level,
}
fn main() {
let config = Config::parse();
ocli::init(config.log_level).unwrap();
println!("this is on stdout — try to pipe it to another command like `grep` or `wc`");
error!("log at error level on stderr");
warn!("log at warn level on stderr");
info!("log at info level on stderr");
debug!("log at debug level on stderr");
trace!("log at trace level on stderr");
info!("the logs at any level are meant to inform the user");
info!("while still being able to pipe stdout");
}
The log level can be configured with a command line argument, using the clap-verbosity-flag
crate.
Try running it with cargo run --example verbosity -- -vv
or cargo run --example verbosity -- -q
.
Changing the number of -v
or -q
changes the log level.
#[macro_use]
extern crate log;
use clap::Parser;
use clap_verbosity_flag::{InfoLevel, Verbosity};
/// A demo of ocli with clap
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
pub struct Config {
/// Log level
#[command(flatten)]
pub verbose: Verbosity<InfoLevel>,
}
fn main() {
let config = Config::parse();
if let Some(level) = config.verbose.log_level() {
ocli::init(level).unwrap();
}
println!("this is on stdout — try to pipe it to another command like `grep` or `wc`");
error!("log at error level on stderr");
warn!("log at warn level on stderr");
info!("log at info level on stderr");
debug!("log at debug level on stderr");
trace!("log at trace level on stderr");
info!("the logs at any level are meant to inform the user");
info!("while still being able to pipe stdout");
}
ocli
is distributed under the terms of the MIT license.
See LICENSE for details.