Rustでのログ出力は、共通のインターフェース(クレート)が準備されていて実装は別途選択する仕組みになっている。
https://docs.rs/log/latest/log/ (クレート: logのドキュメント)
フレームワークを利用した場合その実装に合わせたほうが良いが、スクラッチで書いているコマンドラインツール(今取り組んでいるBotのようなプロジェクトでは)最初は適当に実装を選んであとから差し替えできそうということを意味するので、まず一番シンプルなものを選んであとからプロジェクトの複雑さに応じて変更することができそうだ。
共通のインターフェース(ログレベル)
ログレベルは以下の5つ。ログモジュールの初期化時に出力の抑制が可能。あとからライブラリの差し替え可能。
error!
> warn!
> info!
> debug!
> trace!
実際の利用方法は、println!
と同じ書式文字列が使えるのでプリントデバックするならば最初からdebug!
かtrace!
を使っておけばいい。
ライブラリ(実装の種類・選択)
Rustのlogクレートのドキュメントでは以下の6つがシンプルなログ実装として紹介されている。https://docs.rs/log/latest/log/#available-logging-implementations もっと複雑なものもあわせて紹介されているのでみてみてください。
- Simple minimal loggers:
上の方から2つを選ぶと、env_logger
は環境変数でログの出力設定を行う。simple_logger
はCargo.toml
に設定するという特徴がある。
Webをみるとenv_logger
を最初に使うケースが多いようだが、プロジェクト外の環境変数を設定するのはやや面倒に感じられ、プロジェクトファイルで完了する simple_logger
のほうが良さそうに思えたので試してみた (実際には環境変数で初期化する env()
関数も準備されている)
Simple Logger 実行サンプル
Simple Logger ドキュメント: https://github.com/borntyping/rust-simple_logger
Cargo.toml
log = {version = "0.4"}
simple_logger = {version = "3.0"}
インポート(use句)
use log::Log;
use simple_logger::SimpleLogger;
初期化
ログモジュールは1回しか初期化できない(途中で他のLoggerに切り替えられない)。2回初期化したときはエラーになる。main
で最初に1回だけ呼び出せば問題ないが、ユニットテストの中では各テストの中で初期化しなくてはならず、プロセス全体では複数回よばれてしまう。
そこで初期化を複数回呼び出してしまってもOKなように、以下のように戻り値を無視するようにしておく(unwrap()
しない)。
let _ = SimpleLogger::new().init();
この初期化方法だとディフォルトはすべてのログがでるので、以下のようにするとデバックレベルへ変えられる。
let _ = SimpleLogger::new().with_level(LevelFilter::Debug).init();
実行例
use log;
use simple_logger::SimpleLogger;
#[test]
fn test_debug_message() {
SimpleLogger::new().init();
log::debug!("{}", "hello world");
}
2022-10-24T10:00:08.359Z DEBUG [rbot::exchange::ftx::message::test_ftx_message] hello world
ディフォルトだと、時刻+パッケージ名のあとにメッセージが出力される。
実際には 初期化するファイルは別にしてログを出力するプログラムは use log
だけにして依存関係を低くしておくと良い。
コメント