Dartでのログ出力方法
Dartでログ出力を行う方法としては、まずprint
関数があります。これはdart:coreパッケージに入っており、import
無しで使用可能で、クライアントとWebの両方で使用することができます。
main() {
print('hoge');
}
次にWeb向けであればdart:htmlのconsole
を使うことができます。これはJavaScriptから使えるものと同じものです。
import 'dart:html';
main() {
console.log('hoge');
console.info('foo');
console.debug('bar');
}
しかし、これらだけでは物足りないことがあります。例えば、
- ログレベルをコントロールしたい
- ログをまとめて保存したり送信したりしたい
これらをしようとすると、独自の仕組みを作ってあげる必要があります。
そんなときには、Dartチーム謹製の公式パッケージ Logging が役に立ちます。
Loggingを使ってログ出力
このパッケージは、始めに「ログをどう出力するか」を設定して上げる必要があります。
import 'package:logging/logging.dart';
final log = new Logger('hoge');
main() {
Logger.root.level = Level.All;
Logger.root.onRecord.listen((LogRecord rec) {
print('${rec.level.name}: ${rec.time}: ${rec.message}');
});
}
Logger.root.level
で、先に出力するログレベルを指定します。上の例では、すべてのログを出力するようになります。
そして、Logger.root.onRecord.listen
によって、どのようにログ出力するか、を書く必要があります。上の例ではprint
によって出力するようになっています。
Loggingの設計
このLoggingの設計は、Closure JSのLogger、java.util.logging.Loggerに似せて作られたようです。
用意されているログ出力用のメソッド、ログレベルの定義がほぼ同じになっています。
ログ出力
Loggerのインスタンスを作る
import 'package:logging/logging.dart';
final log = new Logger('hoge');
main() {
Logger.root.level = Level.All;
Logger.root.onRecord.listen((LogRecord rec) {
print('${rec.level.name}: ${rec.time}: ${rec.message}');
});
}
このサンプルコードではfinal log = new Logger('hoge')
として、ログ出力用のLoggerのインスタンスを作成していました。これを使用してログ出力することができます。
このLogger
コンストラクタの第一引数にString
で名前をあてるのが必須になり、この名前はユニークな名前である必要があります。
ログ出力用メソッド
Logger
には、以下のログ出力用メソッドがあります。
ログ出力メソッド | 説明 |
---|---|
config(message, [Object error, StackTrace stackTrace]) → void | Level.CONFIGのログを出力する |
fine(message, [Object error, StackTrace stackTrace]) → void | Level.FINEのログを出力する |
finer(message, [Object error, StackTrace stackTrace]) → void | Level.FINERのログを出力する |
finest(message, [Object error, StackTrace stackTrace]) → void | Level.FINESTのログを出力する |
info(message, [Object error, StackTrace stackTrace]) → void | Level.INFOのログを出力する |
severe(message, [Object error, StackTrace stackTrace]) → void | Level.SEVEREのログを出力する |
shout(message, [Object error, StackTrace stackTrace]) → void | Level.SHOUTのログを出力する |
warning(message, [Object error, StackTrace stackTrace]) → void | Level.CONFIGのログを出力する |
log(Level logLevel, message, [Object error, StackTrace stackTrace, Zone zone]) → void | ログレベルを指定してログを出力する |
import 'package:logging/logging.dart';
final log = new Logger('hoge');
main() {
Logger.root.level = Level.All;
Logger.root.onRecord.listen((LogRecord rec) {
print('${rec.level.name}: ${rec.time}: ${rec.message}');
});
String result = '何らかの結果';
log.fine('結果が得られました: $result');
result = null;
if (result == null) {
log.severe('何の成果も得られませんでした!!');
}
}
Loggerのインスタンスを複数作る
Logger
のインスタンスを複数作ることで、用途の違うログ出力を分けることができます。
// レンダリング関連のログ
final renderLog = new Logger('render');
// ゲームロジックのログ
final gameLog = new Logger('game');
各Loggerインスタンスごとに出力するログレベルを変える場合は、hierarchicalLoggingEnabled
をtrue
にする必要があります。
import 'package:logging/logging.dart';
// レンダリング関連のログ
final renderLog = new Logger('render');
// ゲームロジックのログ
final gameLog = new Logger('game');
main() {
Logger.root.onRecord.listen((LogRecord rec) {
print('${rec.level.name}: ${rec.time}: ${rec.message}');
});
hierarchicalLoggingEnabled = true;
// レンダリング関連のログを出力しない
renderLog.level = Level.OFF;
}
ログレベル
ログレベルは、LoggingパッケージのLevelクラスによって定義されていて、このログレベルはLogger.root.level
に設定することで、出力するログレベルをコントロールすることができます。
ログレベル | 説明 | Level.value |
---|---|---|
OFF | 全てのログ無し | 2000 |
SHOUT | デバッグ時に目立つ騒がしいログ | 1200 |
SEVERE | 深刻な障害情報 | 1000 |
WARNING | 問題の可能性があるログ | 900 |
INFO | 情報提供 | 800 |
CONFIG | コンフィグ設定のメッセージ | 700 |
FINE | トレース用情報 | 500 |
FINER | そこそこ詳細なトレース用情報 | 400 |
FINEST | かなり詳細なトレース用情報 | 300 |
ALL | すべてのログ | 0 |
上記で設定したログレベルよりもLevel.valueが大きいログが出力されるようになります。
例えば、OFF
に設定した場合は、2000
より大きいログが無い場合、ログは何も出なくなります。
INFO
に設定した場合は、INFO
,SEVERE
,SHOUT
のログが出るようになります。
main() {
Logger.root.level = Level.ALL; // すべてのログを出力する
Logger.root.level = Level.OFF; // すべてのログを出力しない
Logger.root.level = Level.INFO; // INFO以上のログを出力する
}
ログ出力先をカスタマイズする
上記の例では、ログを`print'で出力していました。
import 'package:logging/logging.dart';
final log = new Logger('hoge');
main() {
Logger.root.level = Level.All;
Logger.root.onRecord.listen((LogRecord rec) {
print('${rec.level.name}: ${rec.time}: ${rec.message}');
});
}
これを、例えばList
に入れることによって、あとからログを送信する、などと言ったことも可能になります。
import 'package:logging/logging.dart';
final log = new Logger('hoge');
final logs = <String>[];
main() {
Logger.root.level = Level.All;
Logger.root.onRecord.listen((LogRecord rec) {
var message = '${rec.level.name}: ${rec.time}: ${rec.message}';
print(message);
logs.add(message);
});
}
ログはデバッグで役立つので、Loggingパッケージを活用していきたいです。