官术网_书友最值得收藏!

Logging

I reached many points of difficulty in my early software projects where the only thing left to do was to resort to logging, to figure out what was going on. Soon I grew to enjoy logging and made it a key point when starting a new project. It is an extra pair of eyes to help you test—especially when you are not looking, such as when running a data collector continuously.

The Dart package logging provides facilities for logging, however it does not do anything useful with the output, or to put it another way, the handling of the storage of the logging is entirely in the hands of the application.

A simple example of logging

Open up this chapter's Logging folder, which is a standalone example containing a range of logging:

  Logger log = new Logger('DataMonitor');

  Logger.root.level = Level.ALL;
  Logger.root.onRecord.listen((LogRecord rec) {
    String logMessage = '${rec.level.name}\t${rec.time}\t\t${rec.message}';
    String exceptionMessage = '';
    if (rec.error != null) {
      print("$logMessage \t${rec.error.message}");
      print(exceptionMessage);
      print(rec.stackTrace);
    } else {
      print("$logMessage");
    }
  });

The Logger object is initialized and the level property set to Level.ALL. Setting this property gives control over the detail of logging occurring. The custom handler for an incoming log message simply prints it to standard output. Other possibilities are writing to disk, database, or a network socket:

  log.info("This is my first logging program in Dart");
  log.fine("Level 1 detail.");
  log.finer("Level 2 detail.");
  log.finest("Level 3 detail.");
  log.shout("Something bad.");

The Logger class has numerous methods for logging out at different levels, and this also helps produce readable code. By having levels of logging, this can assist with analysis of the logs file. For example, if an application's logs are being looked at to get a general overview of what is going on, the info level of logging would be examined. If a low-level bug is occurring, the approach would be to check the logging down to the finest level. Each method also allows the passing of an Exception and a stack trace:

try {
  throw new Exception("We have a problem!");
} catch (exception, stackTrace) {
  log.severe("Something really bad.", exception, stackTrace);
}

The name passed to the Logger constructor, in this case DataMonitor, identifies a unique object. Any other scope can declare a Logger object with the same name, and the same instance will be returned.

Data monitor logging

For the QuakeMonitorFS, the application launch and the calls to the web service will be recorded. Network connections are not perfect, so we will want to know if the program has not been able to access the web service. Lets have a look at the following code snippet:

Logger log;

setupLogging() {
  log = new Logger('DataMonitor');
  Logger.root.level = Level.ALL;
  Logger.root.onRecord.listen((LogRecord rec) {
    var entry = '${rec.level.name}\t${rec.time}\t\t${rec.message}\n';
    File logStore = new File("datamonlog.txt");
    logStore.writeAsStringSync(entry, mode: FileMode.APPEND);
  });
  log.info('Earthquake Monitor - Data fetcher. Starting...');
}

The logging is set up in bin/main.dart and the output appended to a text file. Note that this is not saved to the data sub-folder, as it may get lost with all the data files.

In the fetchData method of the DataMonitor class, the Logger object is set up in the constructor, and key events will be noted. The different levels of logging are used (info, fine, severe, and so on), which would allow an operator of the program to adjust the level of logging to the desired level.

主站蜘蛛池模板: 怀安县| 昭平县| 汶上县| 柘城县| 土默特左旗| 洛阳市| 建平县| 驻马店市| 北宁市| 东宁县| 京山县| 越西县| 合山市| 通许县| 台安县| 溧阳市| 岗巴县| 翼城县| 永福县| 灵台县| 大竹县| 肥西县| 寿光市| 广宗县| 光泽县| 泸水县| 天镇县| 漳浦县| 左贡县| 永善县| 天镇县| 正蓝旗| 城固县| 潜江市| 依兰县| 肥城市| 长子县| 长治县| 宜昌市| 衡阳县| 寿宁县|