首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

使用 HTML5 File API 实现客户端 log(3)

使用 HTML5 File API 实现客户端 log(3)

使用 HTML5 File API 实现输出客户端 log 信息到文件在传统的客户端 log 设计中,只能将客户端 log 输出到浏览器的控制台,但在客户环境中,客户端程序一旦出错,客户将收集不到这些 log 信息,对于开发人员来说,          一旦客户端程序出错,需要模拟客户的真实环境,重现错误信息,这将是一件非常有挑战的工作,因为客户的实际环境千差万别。本文将根据上面传统客户端 log 的设计,使用 HTML5 File API 实现          将客户端 log 输出到文件中,一旦客户端程序出错,可以很容易的收集到这些 log 信息。
1. 实现 Web Workers
本文中需要使用同步版本的 File API,所以需要实现一个 Web Workers 用来将信息输出到文件中。在 html5.Log 类中,通过 postMessage/onmessage API 实现和 Web Workers 的数据交互。
清单 5. 实现 Web Workers
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 解决 File API 浏览器兼容性问题
self.requestFileSystemSync = self.webkitRequestFileSystemSync
    || self.requestFileSystemSync;
self.BlobBuilder = self.BlobBuilder || self.WebKitBlobBuilder
    || self.MozBlobBuilder;

var html5logFolder = null;
self.onmessage = function(e) {
    var data = e.data;
    switch (data.cmd){
        // 初始化 log 文件夹
        case "init":{
            var fs = self.requestFileSystemSync(PERSISTENT, data.grantedBytes);
            html5logFolder = fs.root.getDirectory('html5logs', {create: true});
            break;
        }
        // 写内容到 log 文件
        case "log":{
            var fileEntry = html5logFolder.getFile(data.logFileName, {create: true});
            var fileWriter = fileEntry.createWriter();
            var blob = new BlobBuilder();
            blob.append(data.logEntryStr);
            fileWriter.seek(fileWriter.length);
            fileWriter.write(blob.getBlob('text/plain'));
            break;
        }
    }
};




在 Web Workers JavaScript 文件中,通过 onmessage 方法,接受 html5.Log 类中发过来的命令。在 init 命令中,将申请相应的磁盘空间,并创建一个 html5logs 的文件夹,其中 create:true 表示如果文件夹不存在则创建,存在则返回文件夹示例。在 log 命令中,将把 log 内容输出到具体的 log 文件中。同理 getFile 方法中的 create:true 参数意义和 getDirectory 方法一样。
2. 重构 html5.Log 类,实现与 Web Workers 交互
首先,需要在 html5.Log 类中创建一个 Web Workers。在 METHODMAP 属性后面加上私有的属性 _logData 和 _logWorker。                        其中 _logData 用来表示 Web Workers 中的 init 命令是否已经被调用了,而 _logWorker 用来表示真正的 Web Workers 实例。
清单 6. 添加类属性
1
2
3
METHODMAP:{"1":"error","2":"warn","3":"info","4":"debug"},
_logData:{"status":false},
_logWorker:new Worker('HTML5File.js'),




然后,在 html5.Log 类的构造函数中使用 postMessage 方法,向 Web Workers 发送 init 命令。          
清单 7. 向 Web Workers 发送 init 命令
1
2
3
4
5
6
7
8
9
10
11
12
13
constructor: function(grantedBytes) {
    //1 表示记录错误信息,2 表示记录警告信息,3 表示记录一般信息,4 表示记录调式信息
    this.logLevel = 1;
    this.indent = 0;

    if(!this._logData.status){// 所有实例只初始化一次
        this._logData.status = true;
     this._logWorker.postMessage({"cmd":"init","grantedBytes":grantedBytes});
    }
    this._logWorker.onmessage = function(e) {
        // 用来接收 Web Workers 返回的数据
    }
}




最后,在 html5.Log 类的 _record 方法中,调用 _writeLogEntryToFile 方法并在这个方法里使用 postMessage 方法,向 Web Workers 发送 log 命令,传递 log 文件名称以及要记录的 log 信息作为参数。
清单 8. 向 Web Workers 发送 log 命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
_record: function(level, location, message, extra) {
    var logEntry = {
        level: level,
        time: new Date(),
        loc: location,
        msg: message,
        extra: extra,
        indent: this.indent
    };     
    if (level <= this.logLevel) {
        var logInfo = this._formatLogEntry(logEntry);
        this._writeLogEntryToFile(logEntry,logInfo);
    }
},
_writeLogEntryToFile:function(logEntryObj,logEntryStr){
    // 每一天创建一个 log 文件
    var logFileName = dojo.date.locale.format(logEntryObj.time,
        {datePattern: "yyyy-MM-dd'.log'","selector":"date"});
    this._logWorker.postMessage({"cmd":"log","logFileName":logFileName,"logEntryStr":logEntryStr});
}

返回列表