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

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.

主站蜘蛛池模板: 锡林浩特市| 云梦县| 嵩明县| 新巴尔虎右旗| 承德市| 沅江市| 延川县| 时尚| 临洮县| 兴和县| 象州县| 天等县| 南澳县| 松潘县| 陵川县| 辛集市| 论坛| 云林县| 黄陵县| 嘉禾县| 利津县| 锡林浩特市| 四平市| 广东省| 榆树市| 甘谷县| 博罗县| 哈尔滨市| 高尔夫| 团风县| 女性| 民县| 安新县| 分宜县| 图木舒克市| 巴楚县| 孝感市| 新竹县| 峨山| 厦门市| 建水县|