手机自动化测试: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;

};

posted @ 2015-11-13 16:06  北京茑萝信息  阅读(223)  评论(0编辑  收藏  举报