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

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.

主站蜘蛛池模板: 大埔区| 大连市| 甘孜县| 石狮市| 盐边县| 罗定市| 宝兴县| 南召县| 吉安县| 建湖县| 南宫市| 汽车| 南华县| 乌拉特前旗| 白山市| 江达县| 通渭县| 项城市| 大城县| 康定县| 南皮县| 湖南省| 太和县| 汶川县| 和田市| 宁海县| 博爱县| 周至县| 平山县| 汶上县| 平南县| 百色市| 珠海市| 吉隆县| 纳雍县| 博乐市| 商城县| 普宁市| 阳新县| 彩票| 新昌县|