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

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.

主站蜘蛛池模板: 黑山县| 仙游县| 罗平县| 来宾市| 静宁县| 巧家县| 屏东县| 靖州| 蓝田县| 长岛县| 仲巴县| 田阳县| 慈溪市| 南宫市| 大竹县| 临沭县| 临漳县| 益阳市| 河北区| 海南省| 辽阳市| 溆浦县| 明光市| 莎车县| 永吉县| 梁河县| 顺义区| 双柏县| 陇南市| 左权县| 大庆市| 梁平县| 凤山市| 苗栗市| 五常市| 阳江市| 香河县| 肇州县| 上犹县| 垣曲县| 中江县|