Rustで使えるロガーを調べてみます。この記事ではいくつかある実装のうち、
- env_logger
- simple_logger
- stderrlog
を動かしてみました。
log crate
Rustのlog crateにinfo!
等のマクロが定義されてますが、用途に応じてその実装を選べる作りになっているようです。
log実装の一覧
Available loggin implementationsの転載です。
- Simple minimal loggers:
- env_logger
- simple_logger
- simplelog
- pretty_env_logger
- stderrlog
- flexi_logger
- Complex configurable frameworks:
- log4rs
- fern
- Adaptors for other facilities:
- syslog
- slog-stdlog_
env_logger
logの実装でどれを使えばいいのか分かりませんが、crates.ioによるとenv_logger
のダウンロード数が圧倒的に多いようです。
#[macro_use]
extern crate log;
extern crate env_logger as logger;
use log::Level;
use std::env;
fn main() {
env::set_var("RUST_LOG", "info");
// env::set_var("RUST_LOG", "trace");
logger::init();
debug!("this is a debug {}", "message");
error!("this is printed by default");
if log_enabled!(Level::Info) {
let x = 3 * 4; // expensive computation
info!("the answer was: {}", x);
}
}
実行ファイルの名前がmainとすると、次のような実行結果が得られます。env_logger
のデフォルトログレベルはError
で、標準エラー出力に書き出されます。ソースコードの中で環境変数のRUST_LOG
をInfo
に設定しているため、ここではerror
とinfo
は出力されていますが、debug
は何も出ませんね。
$ ./main
[2019-03-24T14:16:11Z ERROR log_sample] this is printed by default
[2019-03-24T14:16:11Z INFO log_sample] the answer was: 12
simple_logger
crateの名前の通り、シンプルに標準出力に書き出します
#[macro_use]
extern crate log;
extern crate simple_logger as logger;
use log::Level;
fn main() {
// logger::init().unwrap();
logger::init_with_level(Level::Info).unwrap();
debug!("this is a debug {}", "message");
error!("this is printed by default");
if log_enabled!(Level::Info) {
let x = 3 * 4; // expensive computation
info!("the answer was: {}", x);
}
}
実行ファイルの名前がmainとすると、次のような実行結果が得られます。simple_logger
のデフォルトログレベルはtraceですが、そのレベルは簡単に変更できるみたいです。多くのloggerの実装ではこのようなinit関数が用意されているとのことです。
$ ./main
2019-03-24 23:32:48 ERROR [log_sample] this is printed by default
2019-03-24 23:32:48 INFO [log_sample] the answer was: 12
stderrlog
もう一つくらい、stderrlog試してみます。
#[macro_use]
extern crate log;
extern crate stderrlog as logger;
use log::Level;
fn main() {
logger::new()
.module(module_path!())
.verbosity(2)
.init()
.unwrap();
debug!("this is a debug {}", "message");
error!("this is printed by default");
if log_enabled!(Level::Info) {
let x = 3 * 4; // expensive computation
info!("the answer was: {}", x);
}
}
実行結果は次のようになります。タイムスタンプを入れたりもっと細かい設定もできますが、ここではサボっています。実行結果は次のようになります。
$ ./main
ERROR - this is printed by default
INFO - the answer was: 12
注意点としては、stderrlog
のverbosityがログレベルに相当するのですが、log
crateのLovelとは微妙にずれているのでverbosity(Level::Info as usize)
等とすると期待する結果とずれてしまいました。ソースコードで確認しといたほうが良さそうですね。
補足(?)
use ... as logger
とすればダックタイピングになるかなと期待したのですが、実装ごとに初期化に必要な手順が異なってるのでほとんど意味がありませんでしたorz