LoginSignup
0
1

More than 1 year has passed since last update.

Rustのloggerについて(fernクレート)

Last updated at Posted at 2023-01-17

概要

  • Rustの標準的なロギングの仕組みはlogクレートが中心
    • logクレートはcrates.ioにおいて歴代ダウンロード数が10位のメジャーなクレート
  • logクレートはロギングに必要なAPIを定義しつつも、ロガーの実装は他のクレートに委ねるファサードパターン
    • アプリケーション・ライブラリ向けには5種類のログレベルに応じたロギング用のマクロ
    • ロガーを実装するクレート向けには実装すべきtrait Log
  • logクレートにはNopLoggerという何もしないロガーが定義
    • 他のクレートから log::set_logger() が呼ばれるまでは、このNopLoggerを設定
      • メッセージに対して何もしません
    • ロガークレートの init という関数から log::set_logger() が呼び出され、ロガーの切り替えができるようになっている
      • ロガーの切り替えはプログラム中、一度しかできない
  • 非同期処理のロギングはtracingクレートで実装

ロガーを実装しているクレート

クレート メリット デメリット
env_logger 環境変数で出力するログを変更可能 出力先が標準エラーに固定
simplelog 出力先の制御が可能 ログのフォーマットは変更不可
fern 出力先やフォーマット・ログのレベルを設定可能 設定が複雑

toml

[package]
name = "application"
version = "0.1.0"
edition = "2021"

[dependencies]
fern = "0.6.1"
log = "0.4.17"
chrono = "0.4.23"

fern 実装例

logファイル 備考
application.log INFO 以上を記録
emmergency.log ERRORを記録
install
$ cargo add log
$ cargo add fern
$ cargo add chrono
ディレクトリ構造
.
├── Cargo.toml
└── src
    ├── lib.rs
    └── main.rs
main.rs
fn init_logger() {
    let base_config = fern::Dispatch::new();

    let console_config = fern::Dispatch::new()
        .level(log::LevelFilter::Trace)
        .format(|out, message, record| {
            out.finish(format_args! {
                "[{}] {}:{} {} {}",
                record.level(),
                record.file().unwrap(),
                record.line().unwrap(),
                chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
                message
            })
        })
        .chain(std::io::stdout());

    let application_config = fern::Dispatch::new()
        .level(log::LevelFilter::Info)
        .format(|out, message, record| {
            out.finish(format_args! {
                "[{}] {}:{} {} {}",
                record.level(),
                record.file().unwrap(),
                record.line().unwrap(),
                chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
                message
            })
        })
        .chain(fern::log_file("application.log").unwrap());

    let emergency_config = fern::Dispatch::new()
        .level(log::LevelFilter::Error)
        .format(|out, message, record| {
            out.finish(format_args! {
                "[{}] {}:{} {} {}",
                record.level(),
                record.file().unwrap(),
                record.line().unwrap(),
                chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
                message
            })
        })
        .chain(fern::log_file("emergency.log").unwrap());

    base_config
        .chain(console_config)
        .chain(application_config)
        .chain(emergency_config)
        .apply()
        .unwrap();
}

fn main() {
    init_logger();

    log::trace!("トレース");
    log::debug!("デバッグ");
    log::info!("情報");
    log::warn!("警告");
    log::error!("エラー");
}

実行結果
$ cargo run
[TRACE] src/main.rs:57 2022-12-12 16:34:26 トレース
[DEBUG] src/main.rs:58 2022-12-12 16:34:26 デバッグ
[INFO] src/main.rs:59 2022-12-12 16:34:26 情報
[WARN] src/main.rs:60 2022-12-12 16:34:26 警告
[ERROR] src/main.rs:61 2022-12-12 16:34:26 エラー
application.log
[INFO] src/main.rs:59 2022-12-12 16:34:26 情報
[WARN] src/main.rs:60 2022-12-12 16:34:26 警告
[ERROR] src/main.rs:61 2022-12-12 16:34:26 エラー
emergency.log
[ERROR] src/main.rs:61 2022-12-12 16:34:26 エラー

参考

0
1
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
0
1