44
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Wanoグループ Advent Calendar 2018

Day 14

Rust:logでログ出力を行う

Posted at

この記事は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と同じ引数を取れるログ出力の為のマクロを提供していて、debugwarnマクロでログ出力を行っていれば、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で初期化した場合と使い勝手を変わらなくすることが出来ます(この他にnewfrom_envというメソッドでもBuilderオブジェクトを生成できますが、こちらは挙動が少し変わります)。

次にBuilderのformatメソッドを使ってログのフォーマットを定義します。
formatメソッドはFn(&mut Formatter, &Record) -> Result<()> + Sync + Sendという型のクロージャを引数に取ります。
あとはFormatterRecordのドキュメントを参照しつつ、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関数を呼んで自前のロガーとログレベルをセットします。

44
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
44
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?