この記事はWanoアドベントカレンダーの14日目の記事です。
TL;DR
- log crateとenv_logger crateで基本的には何でも出来る
-
env_logger
では不十分な場合はcrate.ioで探すか、自分でLog traitを実装する
Rustでログ出力をするにはlogとlogに対応したcrateを使おう
Rustにはログ出力の為の枠組みを定めたlog crateというものがあります。
log crateはLog
traitとdebug
/info
/warn
/error
というprintln
と同じ引数を取れるログ出力の為のマクロを提供していて、debug
やwarn
マクロでログ出力を行っていれば、Log
traitの実装として何を利用するかは自由に選べるようになっています。
このLog
traitを実装したライブラリには次のような物があります。
例えばenv_logger
を使う場合は次の様なコードになります。
use env_logger;
use log::{error, warn, info, debug};
use std::env;
fn main() {
env::set_var("RUST_LOG", "info");
env_logger::init();
debug!("debugです");
info!("infoです");
warn!("warnです");
error!("errorです");
}
env_loggerはその名の通りRUST_LOG
環境変数によって出力するログレベル等を設定する事ができます。
上のコードではinfo
を値に入れていますので、infoレベル以上のログレベルのログだけ出力されます。つまりdebugログは出力されません。
またenv_loggerのようなcrateは多くがinit
関数を提供しています(恐らくlog
crateのドキュメントにこういう関数を提供して初期化処理を隠蔽しましょうと書いてある為)。
これによってロガーの初期化が行われますので、main関数の最初に呼ぶようにしましょう。
上のコードを実行した結果は次の様になります。
[2018-12-15T05:53:53Z INFO playground] infoです
[2018-12-15T05:53:53Z WARN playground] warnです
[2018-12-15T05:53:53Z ERROR playground] errorです
env_loggerの出力をカスタマイズする
env_loggerの標準のフォーマットでは不足がある場合はカスタマイズする事ができます。
ここではログ出力を行ったファイル名と行番号を足してみましょう。
env_loggerには出力フォーマットの設定をする為にBuilder型が提供されています。
この型のformatメソッドを使って出力内容をカスタムします。
use env_logger;
use log::{error, warn, info, debug};
use std::env;
use std::io::Write;
fn main() {
env::set_var("RUST_LOG", "info");
env_logger::Builder::from_default_env()
.format(|buf, record| {
let ts = buf.timestamp();
writeln!(
buf,
"[{} {} {}] {} {}:{}",
ts,
record.level(),
record.target(),
record.args(),
record.file().unwrap_or("unknown"),
record.line().unwrap_or(0),
)
})
.init();
debug!("debugです");
info!("infoです");
warn!("warnです");
error!("errorです");
}
Builder::from_default_env()
でBuilderオブジェクトを生成する事でinit
で初期化した場合と使い勝手を変わらなくすることが出来ます(この他にnew
とfrom_env
というメソッドでもBuilder
オブジェクトを生成できますが、こちらは挙動が少し変わります)。
次にBuilderのformat
メソッドを使ってログのフォーマットを定義します。
formatメソッドはFn(&mut Formatter, &Record) -> Result<()> + Sync + Send
という型のクロージャを引数に取ります。
あとはFormatterとRecordのドキュメントを参照しつつ、writeln
マクロでFormatter
に書き込むコードを書きます。
このコードを実行すると次のような出力になります。
[2018-12-15T06:45:39Z INFO playground] infoです src/main.rs:25
[2018-12-15T06:45:39Z WARN playground] warnです src/main.rs:26
[2018-12-15T06:45:39Z ERROR playground] errorです src/main.rs:27
各行の末尾にファイル名と行番号を追加することが出来ました。
env_loggerでは不十分な場合
crate.ioで必要な機能を持ったcrateを探すか、自分でLog traitを実装するかのどちらかになります。
Log
traitを実装する時は次の3つのメソッドを実装します。
また初期化関数(例えばinit
関数)を提供し、その中でset_logger
(又はset_boxed_logger
)とset_max_level
関数を呼んで自前のロガーとログレベルをセットします。