Dart loggingパッケージ

Dar言語StreamクラスtoSet()メソッドDart

Dart loggingパッケージについてメモ書き。

Dart言語を本番運用で稼働させた時、ログ監視が必要になる。
ふと、「Dartってログ出力どうやるんだろう?」と思ったので調査する。

ネットを検索して出てくるのが、Dart標準の「loggingパッケージ」。
ログパッケージ自体は複数あるが、loggingパッケージはカスタマイズできるらしい。
さっそくこのパッケージを試してみる。

pub.devパッケージサイトで導入手順を確認。
pubspec.yamlに以下を追加。最新バージョンは公式サイトで確認する。

dependencies:
  logging: ^1.1.1

VS Code等の開発環境であれば、ファイルを保存することでパッケージが追加される。
テキストツールで更新しているのであれば「dart pub get」コマンドで追加する。

loggingパッケージをimport。これで準備OK.

import 'package:logging/logging.dart';

続いてコーディング。

import 'package:logging/logging.dart';

// ログメッセージの識別名を設定
final log = Logger('TestLogName');

void main() {
  // ①ログのルートレベルを設定。指定したレベル以上のメッセージが出力される。ALLは全て出力。デフォルトはINFO
  Logger.root.level = Level.ALL;
  // Streamで渡されたデータをlistenで受け取り、printで出力
  Logger.root.onRecord.listen(
    (record) {
      // ②出力メッセージのフォーマットを設定
      print('${record.level.name}: ${record.time}: ${record.message}');
    },
  );
  // ③Streamでメッセージを渡す
  log.info('テストメッセージ1');
  log.severe('テストメッセージ2');
}

②のフォーマットに従ってメッセージが出力される。

INFO: 2023-02-23 21:40:22.275457: テストメッセージ1
SEVERE: 2023-02-23 21:40:22.277489: テストメッセージ2

①のルートレベル設定は以下の通り。
上にいく程ログ出力メッセージが少なくなる。

ルートレベル設定
Level.OFF
Level.SHOUT
Level.SEVERE
Level.WARNING
Level.INFO
Level.CONFIG
Level.FINE
Level.FINER
Level.FINEST

試しにルートレベルを「Level.WARNING」にする。

Logger.root.level = Level.WARNING;

INFOが表示されなくなった。

SEVERE: 2023-02-23 21:58:44.309991: テストメッセージ2

③のStreamでメッセージを渡すlogメソッドは以下の通り。

loggingメソッド
log.shout()
log.severe()
log.warning()
log.info()
log.config()
log.fine()
log.finer()
log.finest()

②の出力メッセージのフォーマットで使用できる値を確認。
pub.devサイトのReadmeに記載がないので、ソースを見ることにする。
loggingパッケージの保存場所はpackage_config.jsonに書いてある。ホームディレクトリ配下の「~/.pub-cache/hosted/pub.dev/logging-1.1.1」となっていた。ディレクトリを開く。

importで読み込んでいるlogging.dartを開く。ここでは以下3ファイルをexportしている。

export 'src/level.dart';
export 'src/log_record.dart';
export 'src/logger.dart';

log_record.dartにフォーマットに使用できる値がコーディングされていた。
「level、message、time」以外に以下が設定されている。
設定値にコメントが付いているので、和訳しておく。

設定値コメント
loggerNameログの記録先。Logger()で設定。
sequenceNumberログのシーケンス番号。出力順に採番される。
errorエラーに関連するメッセージ。
stackTraceエラーに関連するスタックトレース。
zoneLogRecord を生成した呼び出しコードのゾーン。

zoneというのは実行場所のコンテキストらしい。とりあえず試してみる。
先ずはlogメソッドの引数を確認する。

「message」が必須、「error」「stackTrace」がオプション引数となっている。
「error」「stackTrace」は例外処理用だろうね。

出力レベルをALLに戻す。

Logger.root.level = Level.ALL;

②の出力メッセージのフォーマットを変更。

'leve:${record.level.name} time:${record.time} message:${record.message} loggerName:${record.loggerName} sequenceNumber:${record.sequenceNumber} zone:${record.zone} error:${record.error} stackTrace:${record.stackTrace}'

「error」「stackTrace」の出力結果を検証するため、例外処理を追加。
log.severe()はcatch文で実行する。

// 例外処理用のクラス。logTest()は常にエラーを返す
class ErrTest {
  bool logbool = true;
  void logTest() {
    if (logbool) {
      throw Error();
    }
  }
}

// 例外処理検証用
try {
  ErrTest errtest = ErrTest();
  errtest.logTest();
} catch (e, st) {
  // 第2引数にエラー、第3引数にスタックトレースを追加
  log.severe('テストメッセージ2', e, st);
}

ソースコードは以下の通り。

import 'package:logging/logging.dart';

// ログメッセージの識別名を設定
final log = Logger('TestLogName');

void main() {
  // ①ログの出力レベルを設定。指定したレベル以上のメッセージが出力される。ALLは全て出力。デフォルトはINFO
  Logger.root.level = Level.ALL;
  // Streamで渡されたデータをlistenで受け取り、printで出力
  Logger.root.onRecord.listen(
    (record) {
      // ②出力メッセージのフォーマットを設定
      print(
          'leve:${record.level.name} time:${record.time} message:${record.message} loggerName:${record.loggerName} sequenceNumber:${record.sequenceNumber} zone:${record.zone} error:${record.error} stackTrace:${record.stackTrace}');
    },
  );
  // ③Streamでメッセージを渡す
  log.info('テストメッセージ1');

  // 例外処理検証用
  try {
    ErrTest errtest = ErrTest();
    errtest.logTest();
  } catch (e, st) {
  // 第2引数にエラー、第3引数にスタックトレースを追加
    log.severe('テストメッセージ2', e, st);
  }
}

// 例外処理用のクラス。logTest()は常にエラーを返す
class ErrTest {
  bool logbool = true;
  void logTest() {
    if (logbool) {
      throw Error();
    }
  }
}

プログラムを実行する。
ログ出力結果は以下の通り。ログ監視する場合はリダイレクト等でファイルへ出力。

% dart run bin/dev1.dart
leve:INFO time:2023-02-24 23:17:23.063638 message:テストメッセージ1 loggerName:TestLogName sequenceNumber:0 zone:Instance of '_RootZone' error:null stackTrace:null
leve:SEVERE time:2023-02-24 23:17:23.065844 message:テストメッセージ2 loggerName:TestLogName sequenceNumber:1 zone:Instance of '_RootZone' error:Instance of 'Error' stackTrace:#0      ErrTest.logTest (file:///Users/*********/app/dart/dev1/bin/dev1.dart:34:7)
#1      main (file:///Users/*********/app/dart/dev1/bin/dev1.dart:23:13)
#2      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:19)
#3      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:192:26)

コメント

タイトルとURLをコピーしました