DartVM服务器开发闲话Flutter和DartDart

DartVM服务器开发(第五天)

2018-08-25  本文已影响27人  rhyme_lph

因为家里来了同学玩,所以昨天没有更新,今天我们来学习一下使用logging这个强大的日志工具库

1. 添加logging依赖

在项目根目录下的pubspec.yaml文件中添加logging的依赖

#....
dependencies:
  http_server: ^0.9.8
  logging: ^0.11.3+2

然后运行pub get命令

运行成功.png

2.初始化

导入logging这个包到你需要使用的dart文件中

import 'package:logging/logging.dart';

初始化logging工具

//监听器能监听的范围
  Logger.root.level=Level.ALL;
//日志监听器
  Logger.root.onRecord.listen((rec){
//rec的类为LogRecord
    print('${rec.level}::${rec.time}::${rec.message}');
  });

上面代码的level就是下面onRecord监听能覆盖的范围,我们传入ALL,就是全部的日志输出都监听,LogRecord是一个日志记录类,里面包换的日志的相关信息,我们来了解下这个类吧

类型 参数 介绍
Level level 日志的覆盖范围(重要性相反):ALL>FINEST>FINER>FINE>CONFIG>INFO>WARNING>SEVERE>SHOUT>OFF
String message 日志消息
Object object 非字符串日志消息
String loggerName 日志名字
DateTime time 日志时间
int sequenceNumber 唯一序列号
Object error 非字符串错误信息
StackTrace stackTrace 记录时的堆栈
Zone zone 日志所属区域

接下来,我们在服务器初始化后,输出一条日志

//....
 var requestServer = await HttpServer.bind(InternetAddress.loopbackIPv6, 8080);
  Logger.root.info('服务器启动:http://localhost:${requestServer.port}');
//....

然后运行我们的项目


image.png

可以看到我们成功的输出了一条日志,日志等级为Info
接下来,我们改一下初始化日志工具的等级

//...监听器只接受错误范围的信息
  Logger.root.level=Level.WARNING;
//...

然后再次运行一下项目


可以看到没有记录消息.png

可以看到,日志监听没有接收到INFO的输出的日志,所以,只能接收WARNING以下的等级

3.记录日志输出到文件中

logging这个日志工具库,本质上是不帮你输出到文件的,所以,我们之前不是已经定义过一个记录到文件的方法嘛,下面是结合日志工具方法

   Logger.root.level=Level.ALL;
  Logger.root.onRecord.listen((rec){
    //基本的消息
    String log='${rec.sequenceNumber}::${rec.level}::${rec.time}::${rec.message}';
    //添加错误信息
    if(rec.error!=null){
      log+='\n::${rec.error}';
    }
    //添加错误的堆栈
    if(rec.stackTrace!=null){
      log+='\n::${rec.stackTrace.toString()}';
    }
    //输出日志到控制台
    print(log);
    //只记录等级大于等于info的信息
    if(rec.level.value>=Level.INFO.value){
      writeLog(log);
    }
  });

//.....
void writeLog(String log) async {
  var date = DateTime.now();
  var year = date.year;
  var month = date.month;
  var day = date.day;

  //如果recursive为true,会创建命名目录及父级目录
  Directory directory =
  await new Directory('log/$year').create(recursive: true);

  File file = new File('${directory.path}/$year-$month-$day.log');
  file.exists().then((isExists) {
    file.writeAsString(isExists ? '\n\n$log' : log, mode: FileMode.append);
  });
}

4.记录异常

当发生异常时,我们可以把它记录下来,并输出到文件中,这个是很有必要的,在维护中,可以根据这个异常信息,去排查bug,下面介绍添加异常,及堆栈信息

staticFiles.errorPageHandler=(request){
    if(request.uri.pathSegments.last.endsWith('.html')){
      staticFiles.serveFile(new File(webPath+'/404.html'), request);
    }else{
      try{
          handleMessage(request);
          throw ArgumentError('Warning happen');
      }catch(e){
        try{
          //有可能没有回复客户端,所以这里回复一次
          request.response
            ..statusCode=HttpStatus.internalServerError
            ..close();
        }catch(_){}
         Logger.root.warning('请求消息发生异常',e,e.runtimeType==ArgumentError?e.stackTrace:null);
      }
    }
  };

我这里手动触发一条异常,然后我们运行服务器,给服务器发送一条请求消息


异常.png

可以看到,我们的服务器产生了异常,异常详细的记录我们在哪里出现错误,我们再来看看日志文件


生成了日志文件了.png

生成了日志文件了,来看看里面的内容


异常文件.png

可以看到跟日志文件一样,接下来,来看一下我封装的日志工具类

import 'dart:io';
import 'package:logging/logging.dart';

class LogUt {
  static LogUt log=new LogUt();
  final Level level=Level.ALL;
  LogUt(){
    Logger.root..level=level
        ..onRecord.listen((rec){
          //基本的消息
          String log='${rec.sequenceNumber}::${rec.level}::${rec.time}::${rec.message}';
          //添加错误信息
          if(rec.error!=null){
            log+='\n::${rec.error}';
          }
         //添加错误的堆栈
          if(rec.stackTrace!=null){
            log+='\n::${rec.stackTrace.toString()}';
          }
          print(log);

          //只记录等级大于info的信息
          if(rec.level.value>=Level.INFO.value){
            writeLog(log);
          }
        });
  }

  void finest(message, [Object error, StackTrace stackTrace]) =>
      Logger.root.log(Level.FINEST, message, error, stackTrace);

  void finer(message, [Object error, StackTrace stackTrace]) =>
      Logger.root.log(Level.FINER, message, error, stackTrace);

  void fine(message, [Object error, StackTrace stackTrace]) =>
      Logger.root.log(Level.FINE, message, error, stackTrace);

  void config(message, [Object error, StackTrace stackTrace]) =>
      Logger.root.log(Level.CONFIG, message, error, stackTrace);

  void info(message, [Object error, StackTrace stackTrace]) =>
      Logger.root.log(Level.INFO, message, error, stackTrace);

  void warning(message, [Object error, StackTrace stackTrace]) =>
      Logger.root.log(Level.WARNING, message, error, stackTrace);

  void severe(message, [Object error, StackTrace stackTrace]) =>
      Logger.root.log(Level.SEVERE, message, error, stackTrace);

  void shout(message, [Object error, StackTrace stackTrace]) =>
      Logger.root.log(Level.SHOUT, message, error, stackTrace);

}

void writeLog(String log) async {
  var date = DateTime.now();
  var year = date.year;
  var month = date.month;
  var day = date.day;

  //如果recursive为true,会创建命名目录及父级目录
  Directory directory =
  await new Directory('log/$year').create(recursive: true);

  File file = new File('${directory.path}/$year-$month-$day.log');
  file.exists().then((isExists) {
    file.writeAsString(isExists ? '\n\n$log' : log, mode: FileMode.append);
  });
}

然后就可以通过导入该工具使用了,并且不用初始化,下面是使用

  LogUt.log.finest('服务器启动:http://localhost:${requestServer.port}');

好了,今天的学习就到这里了,明天见!

如果想继续学习DartVM服务器开发,请关注我,学习更多骚操作!

上一篇下一篇

猜你喜欢

热点阅读