SHOEISHA iD

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

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

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

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

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

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

loggerパッケージ

 loggerパッケージの特徴としては、以下のような点が挙げられます。

  • 出力先のデフォルトがコンソールであり指定する必要がない
  • ログ出力時に時間、呼び出し元ソースと行数などの出力がある
  • 表示が分かりやすい
  • 出力フォーマットや出力先など役割毎にカスタマイズできる

 総じて、前述したloggingパッケージよりも高機能です。

 Dartのパッケージリポジトリで今回紹介する2つのロガーパッケージの評価をみると、前述したloggingパッケージよりもこちらのパッケージの方が評価が高く、多くのFlutter開発者がこのパッケージの方を支持していることが覗えます。

簡単な利用方法

 リスト7のようなコードを記述すると、図1のような出力になります。

[リスト7]ログの出力例(lib/SampleOneScreen.dartの抜粋)

import 'package:logger/logger.dart';

var log = Logger();

try {
    log.d("debug message");
    log.i("info message");
    throw new StateError("state error");
}
catch(e){
    log.w("error ",error: e);
}

図1:ログの出力結果例
図1:ログの出力結果例

 このように文字情報だけではなく、色や表示枠などで分かりやすい出力になることが魅力です。また、先のloggingパッケージではlistenを利用して出力方法を実装していましたが、このパッケージではコンソールログ(print結果の出力先)への出力であれば特に何もする必要はありません。

ログレベル

 ログレベルには表3のようなレベルがあり、メソッドには各レベルの頭文字(ただし小文字)を利用します。loggingよりも一般的なレベル分類であり、メソッド名はAndroid APIと同じようになっています。好みは分かれますが、個人的にはこちらのレベル名称の方が分かりやすいと思います。

表3:ログレベルと内部的な重要度の値
ログレベル 重要度の値 メソッド 説明
all 0 - すべてのログを出力対象
trace 1000 t() トレース、またはより詳細なデバッグ
debug 2000 d() デバッグ
info 3000 i() 通常
warning 4000 w() 警告
error 5000 e() エラー
fatal 6000 f() 重要なエラー
off 10000 - すべてのログ

 ログレベルを設定する場合には、リスト8のように設定します。

[リスト8]ログレベルの設定(lib/SampleOneScreen.dartの抜粋)

Logger.level = Level.info; // (1) グローバルのデフォルト設定
var log = Logger(
    level: Level.info      // (2) 個別の設定
);

 (1)のように設定する事でデフォルトレベルを設定出来ます。また、インスタンス毎にレベルを設定する場合には(2)のようにlevelプロパティで設定します。また、出力されるログはログレベルより重要度が高いものが出力されるのは、前述したloggingパッケージと同様です。

ログ出力のカスタマイズ

 ログ出力をカスタマイズするには、Loggerインスタンス作成時にリスト9のようにPrettyPrinterクラスを明記します。PrettyPrinterクラスはデフォルトで利用されるクラスですが、さまざまなプロパティがあり、それらを使って出力がカスタマイズできるようになっています。

[リスト9]ログ出力フォーマットのカスタマイズ(lib/SampleOneScreen.dartの抜粋)

var log = Logger(
    printer: PrettyPrinter(
        printEmojis: false,
        colors: false,
        methodCount: 0,
        noBoxingByDefault : true
    )
);

 実行結果が図2です。

図2:PrettyPrinterのカスタマイズ出力例
図2:PrettyPrinterのカスタマイズ出力例

 各プロパティは表4のようになっています。

表4:主なPrettyPrinterのプロパティ
プロパティ名 説明
methodCount stackTraceの表示スタック数
errorMethodCount エラー時のstackTraceの表示スタック数
lineLength 一行に表示される文字数
colors 色の表示をON/OFF
printEmojis 絵文字の表示をON/OFF
printTime 時間の表示をON/OFF
noBoxingByDefault 枠の表示をON/OFF
excludeBox レベル毎の枠の表示をON/OFF

独自の出力フォーマットを定義する

 また、出力フォーマットはPrettyPrinterを使わず、すべてカスタマイズすることも可能で、リスト10のようにLogPrinterクラスを継承して定義します。

[リスト10]ログ出力フォーマットのカスタマイズ(lib/SampleOneScreen.dartの抜粋)

var log = Logger(
    printer: CustomPrinter(),
);
// (1) LogPrinterを継承しクラスを定義
class CustomPrinter extends LogPrinter{
  @override
  // (2) logメソッドを実装
  List<String> log(LogEvent event) {
    var buf = StringBuffer();
    buf.write("${event.level} - ${event.time.hour}:${event.time.minute}:${event.time.second} - ${event.message}");
    if(event.error != null){
      buf.write("error - ${event.error}");
      if(event.stackTrace == null){
        if(event.error is Error){
          Error err = event.error as Error;
          buf.write("stacktrace - ${err.stackTrace}");
        }
      }
    }
    if(event.stackTrace != null){
      buf.write("stacktrace - ${event.stackTrace}");
    }
    // (3) 出力
    return [buf.toString()];
  }
}

 (1)でLogPrinterを継承してクラスを定義します。

 また、(2)のようにlogメソッドで出力フォーマットを定義します。注意すべき点は、(3)のようにログ出力を複数行として分割することが前提になっていることです。

 そして、実行結果が図3です。

図3:CustomPrinterの出力例
図3:CustomPrinterの出力例

 また、LogEventのプロパティには表5があります。

表5:LogEventでの主なプロパティ
変数名 説明
time DateTime ログの出力時刻
level Level ログレベル
message dynamic ログメッセージ用のオブジェクト。通常は文字列等で指定
error Object エラーオブジェクト(ログ出力時の第二引数で指定した場合のみ)
stackTrace StackTrace スタックトレース情報(ログ出力時の第三引数で指定した場合のみ)

 また、ここでは説明しませんが、Loggerでのoutputプロパティで出力先も変更することが出来、printerと同様の手順でLogOutputを継承したクラスを作成し、指定すれば可能です。

ログ出力のカスタマイズ

 ログの出力先をカスタマイズするには、LogOutputを継承したクラスを作成することで可能です。リスト11はその実装例です。

[リスト11]ログ出力先のカスタマイズ(lib/SampleOneScreen.dartの抜粋)

var log = Logger(
    // (1) 出力設定
    output: CustomLogOutput()
);

// (2)
class CustomLogOutput extends LogOutput{

  @override
  void output(OutputEvent event) {
    var client = http.Client();
    var f = client.post(
        Uri.http('192.168.1.1', 'flutter/log'),
        body: {'time': "${event.origin.time}", 'level' : "${event.level}", 'message' : event.lines.join(",") });
    f.then((res){
      // print("${res.body}");
    });
  }
}

 (1)でoutputにカスタマイズしたクラスを指定します。そして、(2)のようにLogOutputを継承します。

最後に

 ログ出力はアプリ開発時のデバッグでも有用ですが、実際にはテストや本稼動時の調査時に大変役立ちます。ただし、開発当初は最適なログ管理方法がわかりにくく、具体的にどのような個所、もしくはどのような点に注意したらよいかということは、プロジェクトが大きくなったり、テストや実稼動時になって分かってくることも多々あります。

 そのため、当初は必要でないと思っていても、後に様々なカスタマイズが必要になってきます。今回、紹介したロガーパッケージはそれらのニーズに対してどちらも十分に対応出来ると思いますので、開発当初からログの仕組みを導入しておくことをお勧めします。

参考資料

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

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
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」など、さまざまなカンファレンスを企画・運営しています。

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

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

メールバックナンバー