SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Flutterで始めるモバイルアプリ開発

【Flutter解説】ロガーパッケージを活用してもっとアプリ開発や管理をしやすく!

Flutterで始めるモバイルアプリ開発 第28回

loggingパッケージ

 loggingパッケージは、非常にシンプルな、分かりやすいパッケージです。また、Flutter以外のDartプロジェクトでも使いやすいことが特徴です。

[リスト1]利用コード例(lib/logging.dartより抜粋)

import 'package:logging/logging.dart';

// (1) ログ出力レベルの設定
Logger.root.level = Level.ALL;
// (2) ログの出力実装
Logger.root.onRecord.listen((LogRecord event) {
    print("${event.time} - ${event.loggerName}(${event.level.name}) - ${event.message}");
});

// (3) ログの記述処理
var log = Logger("sample-one");
log.info("widget initState()");

 (1)でログ出力レベルを指定します。(2)が実際のログをどのように出力するかの実装です。すべてのログ出力はこのlistenメソッドで登録した関数として処理ができます。この登録がないと、何も出力はされません。また、listenメソッドを複数回実行して、出力定義も複数定義することも可能です。

 また、(3)がログ処理側のコードになります。実際には(3)のコード相当を各々のコード内で記述しますが、どこに記述しても(2)の部分で出力処理されます。

 これを実行した場合の出力がリスト2のようになります。

[リスト2]実行結果例

flutter: 2024-04-16 15:17:37.011550 - sample-one(INFO) - widget initState()

 このように、出力フォーマットもとてもシンプルに指定できます。

ログレベル

 ログレベルは、ログを出力する際の重要度を示す値で、表1のようなレベルがあります。表1はログレベルの低いものから順にまとめています。

表1:ログレベルと内部的な重要度の値
ログレベル 重要度の値 説明
ALL 0 すべてのログを出力対象
FINEST 300 最も詳細なトレース
FINER 400 詳細なトレース
FINE 500 通常のトレース
CONFIG 700 構成情報
INFO 800 通常のログレベル
WARNING 900 潜在的な、あるいは重要な警告
SEVERE 1000 重大な障害
SHOUT 1200 重要なデバッグ情報
OFF 2000 すべてのログを出力対象としない

 レベル毎のメッセージ出力はリスト2のように各レベル名と同じメソッド(小文字)で、リスト3のように使います。

[リスト3]ログレベルの指定と利用例(lib/logging.dartより抜粋)

var log = Logger("level-sample");
Logger.root.level = Level.CONFIG; // (1) ログレベルを指定 (700)

log.fine("fine message"); // (2) 出力されない
// (3) 以下のメッセージは出力される
log.config("config message");
log.info("info message");
log.warning("warn message");

// (4) 出力する対象か確認
if(log.isLoggable(Level.FINE)){
    // ここで何らかの負荷がかかるコードの実行をする
    log.fine("fine message");
}

 ログレベルを(1)のようにCONFIGレベルに指定した場合、それより重要度が高いログレベルが出力対象となり、(2)のfineメソッドは出力が行われません。そして、(3)以降の指定と同じレベル以上のログレベルが出力対象となります。また、ログ記述のコード部分が出力対象でない場合に処理自体したくないというケースがあります。例えば、複雑な計算や外部からデータ取得した結果をログ出力する場合、そのような負荷がかかる処理は必要な時以外実行したくはありません。そのような場合には、(4)のようにあらかじめログが出力対象か調べてから、ログ出力を行います。

ログ情報の詳細

 ログ出力時のLogRecordオブジェクトには表2のようなプロパティがあり、これらを使ってログメッセージを生成します。

表2:LogRecordでの主なプロパティ
変数名 説明
sequenceNumber int ログ出力毎のシーケンス番号。0から始まる。
time DateTime ログの出力時刻。
loggerName String Loggerオブジェクトを作成したときの名前。
level Level ログレベル
message Object ログメッセージ用のオブジェクト。通常は文字列等で指定する。
error Object エラーオブジェクト。ログ出力時の第二引数で指定した場合のみ。
stackTrace StackTrace スタックトレース情報。ログ出力時の第三引数で指定した場合のみ。

 リスト4のようなコードを記述した場合には、リスト5のような出力がされます。

[リスト4]ログ出力のカスタマイズ例(lib/logging.dartより抜粋)

Logger.root.onRecord.listen((LogRecord event){
    print("${event.sequenceNumber} - time : ${event.time}");
    print("${event.sequenceNumber} - loggerName : ${event.loggerName}");
    print("${event.sequenceNumber} - level : ${event.level}");
    print("${event.sequenceNumber} - message : ${event.message}");

    if(event.error != null){
      print("${event.sequenceNumber} - error - (${event.error.runtimeType}) - [${event.error.toString()}]");
    }

    if(event.stackTrace != null){
      print(event.stackTrace);
    }
});

[リスト5]ログの出力例

0 - time : 2024-05-06 15:11:04.400697
0 - loggerName : main
0 - level : WARNING
0 - message : error
0 - error - (StateError) - [Bad state: status error]
#0      main (package:sample28/logging.dart:8:5)
#1      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:19)
#2      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)

ログ出力先の設定

 ログフォーマットだけではなく、出力先の変更もこのlistenメソッドで登録する関数内で定義可能です。リスト6はログの出力をHTTPにて外部サーバに送信する場合の実装例です。

[リスト6]ログ出力をhttpを通じて別のサーバに送信する例(lib/logging.dartより抜粋)

var client = http.Client();
Logger.root.onRecord.listen((LogRecord event){
    var f = client.post(
        Uri.http('192.168.1.1', 'flutter/log'),
        body: {'time': "${event.time}", 'name': "${event.loggerName}", 'level' : "${event.level}", 'message' : "${event.message}" });

    f.then((res){
      // print("${res.body}");
    });
});

 大量のログの出力が発生する場合には、まとめて送信するなどの対応が必要になりますが、そのような対応もこのメソッド内で実装していきます。

次のページ
loggerパッケージ

この記事は参考になりましたか?

Flutterで始めるモバイルアプリ開発連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

WINGSプロジェクト について> 有限会社 WINGSプロジェクト が運営する、テクニカル執筆コミュニティ(代表 ...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/19645 2024/06/20 11:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー