Adding logging to your app
Every production app needs a logger functionality that allows you to output log messages at varying levels of severity (information/warning/debug) to the (web browser's debug) console or a file. This recipe will enable you to do just that quickly and easily.
Getting ready
Use the logging package developed by the Dart team available from pub for this purpose. Add it to your pubspec.yaml
file, and add the code line import 'package:logging/logging.dart'
; to your code. See it in action in bank_terminal_polymer
. We add the import to the code of the Polymer component and model class BankAccount
.
How to do it...
- In
web\bank_account.dart
, we have at the top level the following code:import 'package:logging/logging.dart'; final Logger log = new Logger('Bank Account');
- We change the constructor to the following code:
BankAccount.created() : super.created() { setupLogger(); log.info('Bank Account component is created'); } setupLogger() is the place where you can define the format of your logs, the following code presents a minimal format: setupLogger() { // Set up logger. Logger.root.level = Level.ALL; Logger.root.onRecord.listen((LogRecord rec) { print('${rec.level.name}: ${rec.time}: ${rec.message}'); }); }
- In
checkAmount()
, we add the following warning message:checkAmount(String in_amount) { try { amount = double.parse(in_amount); } on FormatException catch(ex) { log.warning("Amount $in_amount is not a double!"); return false; } return true; }
- In the
model
class inlib\bank_account.dart
file, we add an"info"
message when theBankAccount
object is created:log.info('Bank Account is created')
, and in thetransact
method, we add"severe message"
when the balance becomes negative:transact(double amount) { balance += amount; if (amount < 0 && (-amount) > balance) { log.severe("Balance will go negative!"); } date_modified = new DateTime.now(); }
- If we then run the app, input an amount
50q
, and then an amount-5000
, which will make our balance negative. This means we will get the following console output:INFO: 2014-04-28 11:27:33.525: Bank Account component is created
FINE: 2014-04-28 11:27:33.551: [Instance of '_Binding']: bindProperties: [value] to [bank-account].[Symbol("bac")]
FINE: 2014-04-28 11:27:33.557: [bank-account] cancelUnbindAll
FINE: 2014-04-28 11:27:33.561: [bank-app] cancelUnbindAll
INFO: 2014-04-28 11:27:33.561: Bank Account is created
FINE: 2014-04-28 11:27:39.172: >>> [bank-account]: dispatch enter
INFO: 2014-04-28 11:27:39.176: <<< [bank-account]: dispatch enter
WARNING: 2014-04-28 11:27:44.089: Amount 50qs is not a double!
SEVERE: 2014-04-28 11:29:02.778: Balance will go negative!
INFO: 2014-04-28 11:29:02.778: <<< [bank-account]: dispatch transact
How it works...
The object of the Logging
class must first be configured; otherwise, nothing happens. This is done in setupLogger()
, which does the following things:
- It sets the level of the messages (choose between
SHOUT
,SEVERE
,WARNING
,INFO
,CONFIG
,FINE
,FINER
,FINEST
,ALL
, orOFF
, or predefine your own). - It sets up an event handler to listen for the onRecord stream. This processes objects of type
LogRecord
, which have access to the name, time, message, and stacktrace. Then, you code what you want to do with this event, print it to the console, write it in a file, send it in a mail, and so on.
There's more...
The following remarks tell you what to do in some special cases. To quickly display errors in a web app, you can add the following code in your code:
window.console.error('Something bad occurred');
If you want to log something asynchronously, use this snippet:
Future futr = doAsync(); futr.then((result) { log.fine('This result came back: $result'); processResult(result); }) .catchError((e, stackTrace) => log.severe('Something went wrong - ', e, stackTrace));