Commit 80ac80c142bfee46994a5cf3e94af825172b518d

Authored by wangfan
1 parent 4570476b

qnlog

  1 +var xbossdebug = require('utils/xbossdebug.js') // 引用xbossdebug
  2 +xbossdebug.config.key = 'maizuo' // key为自定义唯一值,用于后端记录时区分应用
  3 +xbossdebug.config.url = 'https://nb-insight.qiniuapi.com/v5/repos/ding1lite/data'; // 上报服务端地址
  4 +xbossdebug.config.setSystemInfo = true; // 获取系统信息
  5 +xbossdebug.config.setLocation = true; // 获取用户位置信息
  6 +
1 var mta=require('mta-wechat-analysis') 7 var mta=require('mta-wechat-analysis')
2 var uri_dc = require('utils/uri.js') 8 var uri_dc = require('utils/uri.js')
3 global.regeneratorRuntime = require('lib/regenerator/runtime-module') 9 global.regeneratorRuntime = require('lib/regenerator/runtime-module')
1 { 1 {
2 "description": "项目配置文件。", 2 "description": "项目配置文件。",
3 "setting": { 3 "setting": {
4 - "urlCheck": true, 4 + "urlCheck": false,
5 "es6": true, 5 "es6": true,
6 "postcss": true, 6 "postcss": true,
7 "minified": true, 7 "minified": true,
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 "nodeModules": true 9 "nodeModules": true
10 }, 10 },
11 "compileType": "miniprogram", 11 "compileType": "miniprogram",
12 - "libVersion": "2.4.2", 12 + "libVersion": "2.6.1",
13 "appid": "wxd3dc4206c76f14fc", 13 "appid": "wxd3dc4206c76f14fc",
14 "projectname": "xcx-book", 14 "projectname": "xcx-book",
15 "isGameTourist": false, 15 "isGameTourist": false,
  1 +(function (global, factory) {
  2 + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  3 + typeof define === 'function' && define.amd ? define(factory) :
  4 + (global.XbossDebug = factory());
  5 +}(this, (function () {
  6 + var utils = {
  7 + typeDecide: function typeDecide(o, type) {
  8 + return Object.prototype.toString.call(o) === '[object ' + type + ']';
  9 + },
  10 + isFunction: function isFunction(f) {
  11 + return utils.typeDecide(f, 'Function');
  12 + },
  13 + isString: function isString(f) {
  14 + return utils.typeDecide(f, 'String');
  15 + },
  16 + serializeObj: function serializeObj(obj) {
  17 + var parames = '';
  18 + Object.keys(obj).forEach(function (name) {
  19 + if (utils.typeDecide(obj[name], 'Object')) {
  20 + parames += name + '=' + JSON.stringify(obj[name]);
  21 + } else {
  22 + parames += name + '=' + obj[name] + '^';
  23 + }
  24 + });
  25 + return encodeURIComponent(parames.substr(0, parames.length - 1));
  26 + },
  27 + noop: function noop() {},
  28 + now: function now() {
  29 + return new Date().getTime();
  30 + }
  31 + };
  32 +
  33 + var classCallCheck = function (instance, Constructor) {
  34 + if (!(instance instanceof Constructor)) {
  35 + throw new TypeError("Cannot call a class as a function");
  36 + }
  37 + };
  38 +
  39 + var createClass = function () {
  40 + function defineProperties(target, props) {
  41 + for (var i = 0; i < props.length; i++) {
  42 + var descriptor = props[i];
  43 + descriptor.enumerable = descriptor.enumerable || false;
  44 + descriptor.configurable = true;
  45 + if ("value" in descriptor) descriptor.writable = true;
  46 + Object.defineProperty(target, descriptor.key, descriptor);
  47 + }
  48 + }
  49 +
  50 + return function (Constructor, protoProps, staticProps) {
  51 + if (protoProps) defineProperties(Constructor.prototype, protoProps);
  52 + if (staticProps) defineProperties(Constructor, staticProps);
  53 + return Constructor;
  54 + };
  55 + }();
  56 +
  57 + var inherits = function (subClass, superClass) {
  58 + if (typeof superClass !== "function" && superClass !== null) {
  59 + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
  60 + }
  61 +
  62 + subClass.prototype = Object.create(superClass && superClass.prototype, {
  63 + constructor: {
  64 + value: subClass,
  65 + enumerable: false,
  66 + writable: true,
  67 + configurable: true
  68 + }
  69 + });
  70 + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
  71 + };
  72 +
  73 + var possibleConstructorReturn = function (self, call) {
  74 + if (!self) {
  75 + throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  76 + }
  77 +
  78 + return call && (typeof call === "object" || typeof call === "function") ? call : self;
  79 + };
  80 +
  81 + var Config = function () {
  82 + function Config(options) {
  83 + classCallCheck(this, Config);
  84 +
  85 + this.config = {
  86 + version: '1.0.0',
  87 + setSystemInfo: false,
  88 + setLocation: false,
  89 + key: '',
  90 + mergeReport: true, // mergeReport 是否合并上报, false 关闭, true 启动(默认)
  91 + delay: 1000, // 当 mergeReport 为 true 可用,延迟多少毫秒,合并缓冲区中的上报(默认)
  92 + url: '', // 指定错误上报地址
  93 + except: [/^Script error\.?/, /^Javascript error: Script error\.? on line 0/], // 忽略某个错误
  94 + random: 1, // 抽样上报,1~0 之间数值,1为100%上报(默认 1)
  95 + repeat: 5 // 重复上报次数(对于同一个错误超过多少次不上报)
  96 + };
  97 + this.config = Object.assign(this.config, options);
  98 + }
  99 +
  100 + createClass(Config, [{
  101 + key: 'get',
  102 + value: function get$$1(name) {
  103 + return this.config[name];
  104 + }
  105 + }, {
  106 + key: 'set',
  107 + value: function set$$1(name, value) {
  108 + this.config[name] = value;
  109 + return this.config[name];
  110 + }
  111 + }]);
  112 + return Config;
  113 + }();
  114 +
  115 + /**
  116 + * 事件管理器
  117 + */
  118 + var Events = function () {
  119 + function Events() {
  120 + classCallCheck(this, Events);
  121 +
  122 + this.handlers = {};
  123 + }
  124 +
  125 + /**
  126 + * 事件注册
  127 + * @param {*} event 事件名字
  128 + * @param {*} handlers 执行函数
  129 + */
  130 +
  131 +
  132 + createClass(Events, [{
  133 + key: "on",
  134 + value: function on(event, handlers) {
  135 + this.handlers[event] = this.handlers[event] || [];
  136 + this.handlers[event].push(handlers);
  137 + return this.handlers[event];
  138 + }
  139 +
  140 + /**
  141 + * 事件注销
  142 + * @param {*} event 事件名字
  143 + */
  144 +
  145 + }, {
  146 + key: "off",
  147 + value: function off(event) {
  148 + if (this.handlers[event]) {
  149 + delete this.handlers[event];
  150 + }
  151 + }
  152 +
  153 + /**
  154 + * 触发事件
  155 + * @param {*} event 事件名字
  156 + * @param {*} args 执行参数
  157 + */
  158 +
  159 + }, {
  160 + key: "trigger",
  161 + value: function trigger(event, args) {
  162 + var _this = this;
  163 +
  164 + var arg = args || [];
  165 + var funcs = this.handlers[event];
  166 + if (funcs) {
  167 + return funcs.every(function (f) {
  168 + var ret = f.apply(_this, arg);
  169 + return ret !== false;
  170 + });
  171 + }
  172 + return true;
  173 + }
  174 + }]);
  175 + return Events;
  176 + }();
  177 +
  178 + var Report = function (_Events) {
  179 + inherits(Report, _Events);
  180 +
  181 + function Report(options) {
  182 + classCallCheck(this, Report);
  183 +
  184 + var _this = possibleConstructorReturn(this, (Report.__proto__ || Object.getPrototypeOf(Report)).call(this, options));
  185 +
  186 + _this.errorQueue = []; // 记录错误队列
  187 + _this.repeatList = {}; // 记录重复异常数据
  188 + _this.config = new Config().config;
  189 + ['log', 'debug', 'info', 'warn', 'error'].forEach(function (type, index) {
  190 + _this[type] = function (msg) {
  191 + return _this.handleMsg(msg, type, index);
  192 + };
  193 + });
  194 + return _this;
  195 + }
  196 +
  197 + // options 动态设置
  198 +
  199 +
  200 + createClass(Report, [{
  201 + key: 'setOptions',
  202 + value: function setOptions(options) {
  203 + Object.assign(this.config, options);
  204 + }
  205 +
  206 + // 重复出现的错误,只上报config.repeat次
  207 +
  208 + }, {
  209 + key: 'repeat',
  210 + value: function repeat(error) {
  211 + var rowNum = error.rowNum || '';
  212 + var colNum = error.colNum || '';
  213 + var repeatName = error.msg + rowNum + colNum;
  214 + this.repeatList[repeatName] = this.repeatList[repeatName] ? this.repeatList[repeatName] + 1 : 1;
  215 + return this.repeatList[repeatName] > this.config.repeat;
  216 + }
  217 +
  218 + // 忽略错误
  219 +
  220 + }, {
  221 + key: 'except',
  222 + value: function except(error) {
  223 + var oExcept = this.config.except;
  224 + var result = false;
  225 + var v = null;
  226 + if (utils.typeDecide(oExcept, 'Array')) {
  227 + for (var i = 0, len = oExcept.length; i < len; i++) {
  228 + v = oExcept[i];
  229 + if (utils.typeDecide(v, 'RegExp') && v.test(error.msg)) {
  230 + result = true;
  231 + break;
  232 + }
  233 + }
  234 + }
  235 + return result;
  236 + }
  237 +
  238 + // 请求服务端
  239 +
  240 + }, {
  241 + key: 'request',
  242 + value: function request(url, params, cb) {
  243 + if (!this.config.key) {
  244 + throw new Error('please set key in xbossdebug.config.key');
  245 + }
  246 + params.key = this.config.key;
  247 + Object.keys(params).forEach(k=>{
  248 + if(typeof params[k]=='object'){
  249 + params[k]=JSON.stringify(params[k])
  250 + }
  251 + })
  252 + wx.request({
  253 + url: url,
  254 + header:{
  255 + 'Content-Type':'application/x-www-form-urlencoded',
  256 + 'Authorization':'Pandora uva-aaonM8dukeR6phc9yuPBrOXk9brrNW_PxLD7:7tPHErlJKJvfergSuE2nLkfvbqQ='
  257 + },
  258 + method: 'POST',
  259 + data: params,
  260 + success: cb
  261 + });
  262 + }
  263 + }, {
  264 + key: 'report',
  265 + value: function report(cb) {
  266 + var _this2 = this;
  267 +
  268 + var mergeReport = this.config.mergeReport;
  269 +
  270 + if (this.errorQueue.length === 0) return this.config.url;
  271 + var curQueue = mergeReport ? this.errorQueue : [this.errorQueue.shift()];
  272 + if (mergeReport) this.errorQueue = [];
  273 + var url = this.config.url;
  274 +
  275 + var params = {
  276 + error: curQueue,
  277 + systemInfo: this.systemInfo,
  278 + breadcrumbs: this.breadcrumbs,
  279 + locationInfo: this.locationInfo,
  280 + networkType: this.networkType,
  281 + notifierVersion: this.config.version
  282 + };
  283 + this.request(url, params, function () {
  284 + if (cb) {
  285 + cb.call(_this2);
  286 + }
  287 + _this2.trigger('afterReport');
  288 + });
  289 + return url;
  290 + }
  291 +
  292 + // 发送
  293 +
  294 + }, {
  295 + key: 'send',
  296 + value: function send(cb) {
  297 + var _this3 = this;
  298 +
  299 + if (!this.trigger('beforeReport')) return;
  300 + var callback = cb || utils.noop;
  301 + var delay = this.config.mergeReport ? this.config.delay : 0;
  302 + setTimeout(function () {
  303 + _this3.report(callback);
  304 + }, delay);
  305 + }
  306 +
  307 + // push错误到pool
  308 +
  309 + }, {
  310 + key: 'catchError',
  311 + value: function catchError(error) {
  312 + var rnd = Math.random();
  313 + if (rnd >= this.config.random) {
  314 + return false;
  315 + }
  316 + if (this.repeat(error)) {
  317 + return false;
  318 + }
  319 + if (this.except(error)) {
  320 + return false;
  321 + }
  322 + this.errorQueue.push(error);
  323 + return this.errorQueue;
  324 + }
  325 +
  326 + // 手动上报
  327 +
  328 + }, {
  329 + key: 'handleMsg',
  330 + value: function handleMsg(msg, type, level) {
  331 + if (!msg) {
  332 + return false;
  333 + }
  334 + var errorMsg = utils.typeDecide(msg, 'Object') ? msg : { msg: msg };
  335 + errorMsg.level = level;
  336 + errorMsg.type = type;
  337 + errorMsg.time = Date.now();
  338 + if (this.catchError(errorMsg)) {
  339 + this.send();
  340 + }
  341 + return errorMsg;
  342 + }
  343 + }]);
  344 + return Report;
  345 + }(Events);
  346 +
  347 + var XbossDebug = function (_Report) {
  348 + inherits(XbossDebug, _Report);
  349 +
  350 + function XbossDebug(options) {
  351 + classCallCheck(this, XbossDebug);
  352 +
  353 + var _this = possibleConstructorReturn(this, (XbossDebug.__proto__ || Object.getPrototypeOf(XbossDebug)).call(this, options));
  354 +
  355 + _this.breadcrumbs = []; // 函数执行面包屑
  356 + _this.activePage = {};
  357 + _this.rewriteApp();
  358 + _this.rewritePage();
  359 + return _this;
  360 + }
  361 +
  362 + // 劫持原小程序App方法
  363 +
  364 +
  365 + createClass(XbossDebug, [{
  366 + key: 'rewriteApp',
  367 + value: function rewriteApp() {
  368 + var originApp = App;
  369 +
  370 + var self = this;
  371 + App = function App(app) {
  372 + // 合并方法,插入记录脚本
  373 + ['onLaunch', 'onShow', 'onHide', 'onError'].forEach(function (methodName) {
  374 + var userDefinedMethod = app[methodName]; // 暂存用户定义的方法
  375 + if (methodName === 'onLaunch') {
  376 + self.getNetworkType();
  377 + self.config.setLocation && self.getLocation();
  378 + self.config.setSystemInfo && self.getSystemInfo();
  379 + }
  380 + app[methodName] = function (options) {
  381 + var breadcrumb = {
  382 + type: 'function',
  383 + time: utils.now(),
  384 + belong: 'App', // 来源
  385 + method: methodName,
  386 + path: options && options.path, // 页面路径
  387 + query: options && options.query, // 页面参数
  388 + scene: options && options.scene // 场景编号
  389 + };
  390 + self.pushToBreadcrumb(breadcrumb); // 把执行对象加入到面包屑中
  391 + methodName === 'onError' && self.error({ msg: options }); // 错误上报
  392 + return userDefinedMethod && userDefinedMethod.call(this, options);
  393 + };
  394 + });
  395 + return originApp(app);
  396 + };
  397 + }
  398 +
  399 + // 劫持原小程序Page方法
  400 +
  401 + }, {
  402 + key: 'rewritePage',
  403 + value: function rewritePage() {
  404 + var _this2 = this;
  405 +
  406 + var originPage = Page;
  407 + Page = function Page(page) {
  408 + Object.keys(page).forEach(function (methodName) {
  409 + typeof page[methodName] === 'function' && _this2.recordPageFn(page, methodName);
  410 + });
  411 + // 强制记录两生命周期函数
  412 + page.onReady || _this2.recordPageFn(page, 'onReady');
  413 + page.onLoad || _this2.recordPageFn(page, 'onLoad');
  414 + // 执行原Page对象
  415 + return originPage(page);
  416 + };
  417 + }
  418 +
  419 + // 获取当前显示的页面
  420 +
  421 + }, {
  422 + key: 'getActivePage',
  423 + value: function getActivePage() {
  424 + var curPages = getCurrentPages();
  425 + if (curPages.length) {
  426 + return curPages[curPages.length - 1];
  427 + }
  428 + return {};
  429 + }
  430 +
  431 + // 记录函数执行情况,最多记录20个
  432 +
  433 + }, {
  434 + key: 'pushToBreadcrumb',
  435 + value: function pushToBreadcrumb(obj) {
  436 + this.breadcrumbs.push(obj);
  437 + this.breadcrumbs.length > 20 && this.breadcrumbs.shift();
  438 + }
  439 +
  440 + // 记录Page执行信息
  441 +
  442 + }, {
  443 + key: 'recordPageFn',
  444 + value: function recordPageFn(page, methodName) {
  445 + var userDefinedMethod = page[methodName];
  446 +
  447 + var self = this;
  448 + page[methodName] = function () {
  449 + if (methodName === 'onLoad' || methodName === 'onShow') {
  450 + self.activePage = self.getActivePage();
  451 + }
  452 + var breadcrumb = {
  453 + type: 'function',
  454 + time: utils.now(),
  455 + belong: 'Page',
  456 + method: methodName,
  457 + route: self.activePage && self.activePage.route,
  458 + options: self.activePage && self.activePage.options
  459 + };
  460 + methodName === 'onLoad' && (breadcrumb.args = arguments);
  461 + self.methodFilter(methodName) && self.pushToBreadcrumb(breadcrumb);
  462 + return userDefinedMethod && userDefinedMethod.apply(this, arguments);
  463 + };
  464 + }
  465 +
  466 + // 过滤方法,可以在这里做黑白名单
  467 +
  468 + }, {
  469 + key: 'methodFilter',
  470 + value: function methodFilter(methodName) {
  471 + return methodName !== 'onPageScroll'; // 把onPageScroll方法过滤掉
  472 + }
  473 + }, {
  474 + key: 'getNetworkType',
  475 + value: function getNetworkType() {
  476 + var _this3 = this;
  477 +
  478 + wx.getNetworkType({
  479 + success: function success(res) {
  480 + _this3.networkType = res.networkType;
  481 + }
  482 + });
  483 + }
  484 + }, {
  485 + key: 'getSystemInfo',
  486 + value: function getSystemInfo() {
  487 + var _this4 = this;
  488 +
  489 + wx.getSystemInfo({
  490 + success: function success(res) {
  491 + _this4.systemInfo = res;
  492 + }
  493 + });
  494 + }
  495 + }, {
  496 + key: 'getLocation',
  497 + value: function getLocation() {
  498 + var _this5 = this;
  499 +
  500 + wx.getLocation({
  501 + type: 'wgs84',
  502 + success: function success(res) {
  503 + _this5.locationInfo = res;
  504 + }
  505 + });
  506 + }
  507 + }]);
  508 + return XbossDebug;
  509 + }(Report);
  510 +
  511 + var xbossdebug = new XbossDebug();
  512 +
  513 + return xbossdebug;
  514 +
  515 +})));