Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何引入阿里云ARMS前端监控? #102

Open
FrankKai opened this issue Sep 30, 2018 · 4 comments
Open

如何引入阿里云ARMS前端监控? #102

FrankKai opened this issue Sep 30, 2018 · 4 comments

Comments

@FrankKai
Copy link
Owner

老大对我目前手上的项目引入了阿里云ARMS前端监控,但是我自己对ARMS SDK的API以及如何注入到Vue中不是很懂,因此这篇博客诞生了。

@FrankKai
Copy link
Owner Author

FrankKai commented Sep 30, 2018

/**
 * 阿里前端监控
 * 配置文档 https://www.npmjs.com/package/alife-logger
 */
import BrowerLogger from 'alife-logger';
const logger = (() => {
  if (process.env.NODE_ENV === 'production') {
    try {
      return BrowerLogger.singleton({
        pid: '241asf2342141@dfaf1', // 这是项目ID,新建一个应用站点后自动生成,在单个应用站点内部的`设置->应用设置`查看
        imgUrl: 'https://arms-retcode.aliyuncs.com/r.png?', // 日志上传地址,源码中默认值就是这个地址
        enableSPA: true, // 是否监听页面的 hashchange 事件并重新上报 PV,适用于单页面应用场景
        sendResource: true, // 是否上报资源数据
      });
    } catch (e) {
      // eslint-disable-next-line no-console
      console.error('init logger fail', e);
    }
  } else {
    return {
      error() {},
    };
  }
})();

export default logger;

This was referenced Oct 3, 2018
@FrankKai
Copy link
Owner Author

FrankKai commented Oct 3, 2018

enableSPA: true和hashchange事件是什么意思呢?

开启单页应用的PV上报。
就拿vue来说,通过vue-router进行页面切换时,每个url都会带一个#,例如从http://foo.com/#/bar跳转到http://bar.com/#/baz
严格意义上说,这不算是一次page change,但是由于我们是单页应用,所以也算是一次page change,因此我们需要一个事件去监听#后面的内容的变化,这个事件就是hashchange,每次#后面的内容变化,都会算做一次PV。
关于hashchange的更多细节,可以到一些低调的浏览器事件查看,或者到hashchange查看。

@FrankKai
Copy link
Owner Author

FrankKai commented Oct 3, 2018

为什么要采用立即回调函数的方法?

这样更加简洁,若不使用,会是以下形式,非常清晰且入门的写法。

/**
 * 阿里前端监控
 * 配置文档 https://www.npmjs.com/package/alife-logger
 */
import BrowerLogger from 'alife-logger';
const logger;
  // eslint-disable-next-line no-constant-condition
if (process.env.NODE_ENV === 'production') {
  try {
    logger = BrowerLogger.singleton({
      pid: 'hq48j@5503bd6abd48093',
      imgUrl: 'https://arms-retcode.aliyuncs.com/r.png?',
      enableSPA: true,
      sendResource: true,
    });
  } catch (e) {
    // eslint-disable-next-line no-console
    console.error('init logger fail', e);
  }
} else {
  logger = error() {},
}
export default logger;

@FrankKai
Copy link
Owner Author

FrankKai commented Oct 3, 2018

如何注入到vue项目中呢?

main.js

import arms from '@/arms';

Vue.config.errorHandler = (err, vm, info) => {
    arms.error(err, { filename: `${vm.$vnode.tag}, ${info}`});
};

Vue.config是什么?

Vue.config是一个对象,包含vue的一些全局配置,可以在启动应用之前修改属性。
它包含slient,optionMergeStrategies,devtools,errorHandler,warnHandler,ignoreElements,keyCodes,performance,productionTip等配置项。

这次主要的任务是学习Vue.config.errorHandler,附带着把Vue.config.productionTip = false也了解下。

Vue.config.errorHandler

在组件渲染函数或者watchers期间,分配一个处理器给uncaught error。

Vue.config.errorHandler = function (err, vm, info) {
    // err 错误信息
    // vm Vue实例
    // info Vue-specific error信息
}

关键词:捕获错误 捕获uncaught error 前端错误追踪 避免前端页面崩溃

  • 2.2.0版本开始,钩子会捕获组件生命周期的错误。
  • 2.4.0+,可以捕获Vue custom event handler中的错误,最典型的自定义事件就是vm.$on('eventName', handler)

Vue.config.errorHandler源码:

function globalHandleError (err, vm, info) {
  if (config.errorHandler) {
    try {
      return config.errorHandler.call(null, err, vm, info) // 有定义就返回自定义的运行后的Vue的config.errorHandler。可以用于将错误上报给第三方前端错误追踪服务,例如阿里云ARMS,Sentry,Bugsnag等等
    } catch (e) {
      logError(e, null, 'config.errorHandler'); // 运行错误的话抛出异常
    }
  }
  logError(err, vm, info); // 当errorHandler为undefined时,被捕获的错误会通过console.error输出避免崩溃,其实也就是默认会捕获uncaught error并且输出,避免崩溃。
}

logError源码:

function logError (err, vm, info) {
  {
    warn(("Error in " + info + ": \"" + (err.toString()) + "\""), vm);
  }
  /* istanbul ignore else */
  if ((inBrowser || inWeex) && typeof console !== 'undefined') {
    console.error(err); 
  } else {
    throw err
  }
}

errorHandler内部函数为什么是arms.error(err, { filename: `${vm.$vnode.tag}, ${info}`});?

https://www.npmjs.com/package/alife-logger 给出了错误信息上报接口的文档。
__bl.error(error, pos)
error为JS的Error对象,filename是pos的一个key,filename后面的模板字符串是为了唯一定位错误信息文件。

vm.$vnode.tag是什么?

http://foo.com/#/friend 的vm.$vnode.tag为vue-component-136-record。
http://foo.com/#/autoreply 的vm.$node.tag为vue-component-138-autoreply。
源码在vnode.js。

Vue.config.errorHandler中的info可能是哪些值?

vue/src/core/util/error.js 源码会暴露一个handlerError函数,通过搜索'handlerEroor'关键词,找到可能输出的值。

handleError(err, vm, `@render`); // src/platforms/weex/runtime/recycle-list/render-component-template.js
handleError(e, vm, `render`); // src/core/instance/render.js
handleError(e, vm, `event handler for "${event}"`); // src/core/instance/events.js 
handleError(e, vnode.context, `directive ${dir.name} ${hook} hook`); // src/core/vdom/modules/directives.js
handleError(e, vm, `getter for watcher "${this.expression}"`); //  src/core/observer/watcher.js
handleError(e, ctx, 'nextTick'); // src/core/util/next-tick.js
handleError(e, vm, `${hook} hook`); // src/core/instance/lifecycle.js 
handleError(e, vm, `data()`); // src/core/instance/state.js
handleError(e, ctx, 'nextTick'); // packages/weex-vue-framework/factory.js,dist目录下的文件基本都有此方法
handleError(e, vm, (hook + " hook"));// packages/vue-server-renderer/build.js,basic.js

filename: `${vm.$vnode.tag}, ${info}`对应ARMS前端监控平台的什么位置?

在访问明细表格的File字段,可以找到filename对应的信息,例如File: vue-component-109-chatFriend, nextTick

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant