手机自动化测试:Appium源码分析之跟踪代码分析九
手机自动化测试:Appium源码分析之跟踪代码分析九
poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标。如果对课程感兴趣,请大家咨询qq:908821478。
// set up distributed logging before everything else
var npmlog = global._global_npmlog = require('npmlog');
// npmlog is used only for emitting, we use winston for output
//不利用npmlog输出信息,而是利用winston来输出,所以将npmlog的等级设置为silent
npmlog.level = "silent";
//日志管理系统
var winston = require('winston')
//文件操作模块
, fs = require('fs')
//获取系统信息的模块
, os = require('os')
//处理和转换文件路径
, path = require('path')
//工具模块
, util = require('util');
//日期处理模块
require('date-utils');
//log等级定义
var levels = {
debug: 1
, info: 2
, warn: 3
, error: 4
};
//各等级对应的字体颜色
var colors = {
info: 'cyan'
, debug: 'grey'
, warn: 'yellow'
, error: 'red'
};
//定义log等级对应关系的字典
var npmToWinstonLevels = {
silly: 'debug'
, verbose: 'debug'
, info: 'info'
, http: 'info'
, warn: 'warn'
, error: 'error'
};
var logger = null;
//时区
var timeZone = null;
//堆栈
var stackTrace = null;
// capture any logs emitted by other packages using our global distributed
// logger and pass them through winston
npmlog.on('log', function (logObj) {
//根据传入的参数,得到对应的log等级,如果参数未被定义过,也就是说在字典中未找到,那么就设置为info
var winstonLevel = npmToWinstonLevels[logObj.level] || 'info';
//获得消息体
var msg = logObj.message && logObj.prefix ?
(logObj.prefix + ": " + logObj.message) :
(logObj.prefix || logObj.message);
logger[winstonLevel](msg);
console.log("==========npmlog.on=================");
});
//将当前日期转化为YYYY-MM-DD HH24:MI:SS:LL形式
var timestamp = function () {
var date = new Date();
if (!timeZone) {
//date.getTimezoneOffset()时差,精确到分钟,乘以60000,精确到毫秒数
date = new Date(date.valueOf() + date.getTimezoneOffset() * 60000);
}
return date.toFormat("YYYY-MM-DD HH24:MI:SS:LL");
};
// Strip the color marking within messages.
// We need to patch the transports, because the stripColor functionality in
// Winston is wrongly implemented at the logger level, and we want to avoid
// having to create 2 loggers.
//解决winston在日志实现上bug,有时候会产生2个logger器
function applyStripColorPatch(transport) {
var _log = transport.log.bind(transport);
transport.log = function (level, msg, meta, callback) {
var code = /\u001b\[(\d+(;\d+)*)?m/g;
msg = ('' + msg).replace(code, '');
_log(level, msg, meta, callback);
};
}
//将log信息传输到控制台上
var _createConsoleTransport = function (args, logLvl) {
var transport = new (winston.transports.Console)({
name: "console"
, timestamp: args.logTimestamp ? timestamp : undefined
, colorize: !args.logNoColors
, handleExceptions: true
, exitOnError: false
, json: false
, level: logLvl
});
if (args.logNoColors) applyStripColorPatch(transport);
return transport;
};
//将log信息传输到文件中
var _createFileTransport = function (args, logLvl) {
var transport = new (winston.transports.File)({
name: "file"
, timestamp: timestamp
, filename: args.log
, maxFiles: 1
, handleExceptions: true
, exitOnError: false
, json: false
, level: logLvl
}
);
applyStripColorPatch(transport);
return transport;
};
//将log信息传输到webhook中,webhook就是将log信息传输到某一个指定url上,将log信息传输到web服务器上
var _createWebhookTransport = function (args, logLvl) {
var host = null,
port = null;
if (args.webhook.match(':')) {
var hostAndPort = args.webhook.split(':');
host = hostAndPort[0];
port = parseInt(hostAndPort[1], 10);
}
var transport = new (winston.transports.Webhook)({
name: "webhook"
, host: host || '127.0.0.1'
, port: port || 9003
, path: '/'
, handleExceptions: true
, exitOnError: false
, json: false
, level: logLvl
});
applyStripColorPatch(transport);
return transport;
};
//管理分配上面三种log表现形式:控制台,文件,web。其中控制台是必须的,文件和web是根据配置来产生的
var _createTransports = function (args) {
var transports = [];
var consoleLogLevel = null,
fileLogLevel = null;
if (args.loglevel && args.loglevel.match(":")) {
// --log-level arg can optionally provide diff logging levels for console and file separated by a colon
var lvlPair = args.loglevel.split(':');
consoleLogLevel = lvlPair[0] || consoleLogLevel;
fileLogLevel = lvlPair[1] || fileLogLevel;
} else {
consoleLogLevel = fileLogLevel = args.loglevel;
}
transports.push(_createConsoleTransport(args, consoleLogLevel));
if (args.log) {
try {
// if we don't delete the log file, winston will always append and it will grow infinitely large;
// winston allows for limiting log file size, but as of 9.2.14 there's a serious bug when using
// maxFiles and maxSize together. https://github.com/flatiron/winston/issues/397
if (fs.existsSync(args.log)) {
fs.unlinkSync(args.log);
}
transports.push(_createFileTransport(args, fileLogLevel));
} catch (e) {
console.log("Tried to attach logging to file " + args.log +
" but an error occurred: " + e.msg);
}
}
if (args.webhook) {
try {
transports.push(_createWebhookTransport(args, fileLogLevel));
} catch (e) {
console.log("Tried to attach logging to webhook at " + args.webhook +
" but an error occurred. " + e.msg);
}
}
return transports;
};
var _appDir = path.dirname(require.main.filename);
//将堆栈信息转化为字符串
var _stackToString = function (stack) {
var str = os.EOL + " [------TRACE------]" + os.EOL;
var len = stack.length < 15 ? stack.length : 15;
for (var i = 0; i < len; i++) {
var fileName = stack[i].getFileName();
// ignore calls from this file
if (fileName === __filename) continue;
var substr = " at ";
try {
var typeName = stack[i].getTypeName();
substr += util.format("%s.%s (%s:%d:%d)" + os.EOL, typeName, stack[i].getFunctionName(),
path.relative(_appDir, stack[i].getFileName()), stack[i].getLineNumber(),
stack[i].getColumnNumber());
str += substr;
} catch (e) { }
}
return str;
};
var _addStackTrace = function (fn, stackTrace) {
var _fn = fn;
return function (msg) {
//os.EOL为行结束符
_fn(msg + os.EOL + _stackToString(stackTrace.get()) + os.EOL);
console.log("==========_addStackTrace=================");
};
};
//log系统初始化
module.exports.init = function (args) {
// set de facto param passed to timestamp function
timeZone = args.localTimezone;
// by not adding colors here and not setting 'colorize' in transports
// when logNoColors === true, console output is fully stripped of color.
if (!args.logNoColors) {
winston.addColors(colors);
}
//初始化log器,准备控制台输出(文件和webhook都准备好)
logger = new (winston.Logger)({
transports: _createTransports(args)
});
//设置log等级
logger.setLevels(levels);
// 8/19/14 this is a hack to force Winston to print debug messages to stdout rather than stderr.
// TODO: remove this if winston provides an API for directing streams.
//将debug的信息转化为info等级的lgo
if (levels[logger.transports.console.level] === levels.debug) {
logger.debug = function (msg) { logger.info('[TesterHome] ' + msg); };
}
//如果允许同步堆栈信息,就要在相应的log输出信息中追加这些信息
if (args.asyncTrace) {
stackTrace = require('stack-trace');
//将堆栈信息追加到等级为info的log信息中,后面两个类似
logger.info = _addStackTrace(logger.info, stackTrace);
logger.warn = _addStackTrace(logger.warn, stackTrace);
logger.error = _addStackTrace(logger.error, stackTrace);
}
};
//以get函数对外提供
module.exports.get = function () {
if (logger === null) {
exports.init({});
}
return logger;
};
手机自动化测试:Appium源码分析之跟踪代码分析九的更多相关文章
- 手机自动化测试:Appium源码分析之跟踪代码分析八
手机自动化测试:Appium源码分析之跟踪代码分析八 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家 ...
- 手机自动化测试:Appium源码分析之跟踪代码分析七
手机自动化测试:Appium源码分析之跟踪代码分析七 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.poptest推出手机自 ...
- 手机自动化测试:Appium源码分析之跟踪代码分析六
手机自动化测试:Appium源码分析之跟踪代码分析六 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.poptest推出手机自 ...
- 手机自动化测试:Appium源码分析之跟踪代码分析五
手机自动化测试:Appium源码分析之跟踪代码分析五 手机自动化测试是未来很重要的测试技术,作为一名测试人员应该熟练掌握,POPTEST举行手机自动化测试的课程,希望可以训练出优秀的手机测试开发工 ...
- 手机自动化测试:appium源码分析之bootstrap三
手机自动化测试:appium源码分析之bootstrap三 研究bootstrap源码,我们可以通过代码的结构,可以看出来appium的扩展思路和实现方式,从中可以添加我们自己要的功能,针对app ...
- 手机自动化测试:appium源码分析之bootstrap二
手机自动化测试:appium源码分析之bootstrap二 在bootstrap项目中的io.appium.android.bootstrap.handler包中的类都是对应的指令类, priva ...
- 手机自动化测试:appium源码分析之bootstrap一
手机自动化测试:appium源码分析之bootstrap一 前言: poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.popte ...
- 手机自动化测试:appium源码分析之bootstrap十七
手机自动化测试:appium源码分析之bootstrap十七 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣 ...
- 手机自动化测试:appium源码分析之bootstrap十六
手机自动化测试:appium源码分析之bootstrap十六 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣 ...
随机推荐
- 剑指offer编程题Java实现——面试题6重建二叉树
题目: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2, ...
- Angular.js之自定义指令学习笔记
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- javascript中加var和不加var的区别
Javascript是遵循ECMAScript标准下的一个产物,自然ECMAScript的标准其要遵循. 先来看下var关键字的定义和用法 var 语句用于声明变量. JavaScript 变量的创建 ...
- js实现二级联动下拉列表菜单
二级联动下拉列表菜单的难点在于对后台返回的数据进行解析,不多逼逼,直接上代码 上图是后台返回的数据 实现代码如下: var deviceNotExist = true;//防止数据重复 if(data ...
- ViewPager基础入门
效果图: 实现了三个view间的相互滑动 第一个VIEW向第二个VIEW滑动 第二个VIEW向第三个VIEW滑动 ...
- vue + socket.io实现一个简易聊天室
vue + vuex + elementUi + socket.io实现一个简易的在线聊天室,提高自己在对vue系列在项目中应用的深度.因为学会一个库或者框架容易,但要结合项目使用一个库或框架就不是那 ...
- Java代码块详解
Java中代码块指的是用 {} 包围的代码集合,分为4种:普通代码块,静态代码块,同步代码块,构造代码块 普通代码块: 定义:在方法.循环.判断等语句中出现的代码块 修饰:只能用标签修饰 位置:普通代 ...
- RabbitMQ(从安装到使用)
RabbitMQ 一,RabbitMQ简单介绍: RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Messa ...
- H5微信播放全屏问题
在ios和安卓手机里的微信下播放视频时,会遇到不少问题,例如需要手动点击,视频才会播放,并且视频会跳出微信框,出现控制条,如果视频不是腾讯视频,播放完毕会出现腾讯视频的广告推送等问题 解决办法:给vi ...
- MySQL C#教程
这是关于MySQL数据库的C#教程,包含了对MySQL数据库基本操作: 数据库访问组件MySql Connect/NET MySql Connect/NET是MySQL官方提供给C#的接口,封装的非常 ...