此页面需要javascript支持,请在浏览器中启用javascript

sentry前端监控for vue(1)

性能
Performance
H5
vue
sentry
共925个字,阅读时间 5 分钟
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://icebreaker.top/articles/2021/1/22-sentry-vue-1

从 sentry 入手监控

简单的在 sentry.io注册了一个账户

开始由向导进入并且添加监控
发现它针对大量的平台,搞了很多的 sdk 啥的
我按照监控我线上的博客站 icebreaker.top 的思路

选择了 4 项贴合的

  • javascript
  • vue
  • node.js
  • express

如图所示:

从 Vue Clinet 开始

yarn add @sentry/vue @sentry/tracing
import Vue from "vue";
import * as Sentry from "@sentry/browser";
import { Integrations } from "@sentry/tracing";

Sentry.init({
  Vue,
  dsn: "https://xxx.ingest.sentry.io",
  autoSessionTracking: true,
  integrations: [
    new Integrations.BrowserTracing(),
  ],

  // We recommend adjusting this value in production, or using tracesSampler
  // for finer control
  tracesSampleRate: 1.0,
});

类似这样,他就做到了前端的简单的监控
当然我们肯定要深入其中,查看@sentry/vue源码中,到底在哪些地方埋了点的

@sentry/vue

从 npm 上查看依赖,看到在运行时是依赖的 @sentry/browser

我们先按照 Readme 的方式

import Vue from 'vue'
import App from './App'
import router from './router'
import * as Sentry from '@sentry/vue'

Sentry.init({
  Vue: Vue,
  dsn: '__PUBLIC_DSN__',
})

clone getsentry/sentry-javascript

看了一下,所有 js 的都在里面,也用了 lerna ,有点意思

@sentry/vue 看了一下 rollup,ts 打了 2 个 iife (立即执行函数) 包,都是 ES5 Browser Tracing Bundle
只是一个用 terser 压缩了一个没有

tsconfig.esm.json 里面是 ts 打包到 esm/ 下的

显然一个是给 es6 编程用的,一个 cdn 或者下载下来直接使用的

我们主要看 esm

从 代码看,从@sentry/browser导出了大量的 func,index.ts里也没有默认导出

所以要 import * as Sentry from '@sentry/vue' 来用

我们主要看针对 Vue 的自定义部分

sdk.ts/vuerouter.ts

sdk

这部分就包含了,最重要的 init 方法,看看做了哪些事情

  • 拿 Vue 的根实例从 window 或者传入
  • 一堆初始化和 meta 信息

下面主要就是 2 个了

  • browserInit
  • VueHelper

browserInit@sentry/browser 的配置,我们主要就看 VueHelper

VueHelper

  • setup

默认开启错误追踪_attachErrorHandler, 按选项开启_startTracing

错误追踪很简单,拿到 Vue 根实例,劫持一下Vue.config.errorHandler

还用了setTimeout 0这种,让它本身的发送请求,进入下一个宏事件循环,Get!
原话是

// Capture exception in the next event loop, to make sure that all breadcrumbs are recorded in time.

主要看发送到 sentry 服务器的有哪些东西 metadata:

  • componentName
  • propsData (optional)
  • lifecycleHook info info 是 Vue 特定的错误信息,比如错误所在的生命周期钩子

然后就去走 getCurrentHub withScope captureException 这些应该就是发送方法

居然还有事务 getTransaction

_startTracing

_applyTracingHooks

// Don't attach twice, just in case
    if (vm.$options.$_sentryPerfHook) {
      return;
    }
    vm.$options.$_sentryPerfHook = true;

rootHandler 处理根节点的
childHandler 处理子节点的

主要都用的 vm.$once(hook:${hook})

span transaction 这种目前看不懂,要后续看其他包的时候才可以知道

now 拿的是'@sentry/utils', 难道是 Date.now () or performance 里的?

hooks

// Each component has it's own scope, so all activities are only related to one of them

appliedTracingHooks 一个 500ms 的宏事件,打出一个 warn?

接下来用一个全局的 mixin, 附加自个的 beforeCreate hook
在里面清除 appliedTracingHooks 事件和 applyTracingHooks(this)

applyTracingHooks 里面也是根据 internalHooks 去劫持原先的钩子

// Mappings from operation to corresponding lifecycle hook.
const HOOKS: { [key in Operation]: Hook[] } = {
  activate: ['activated', 'deactivated'],
  create: ['beforeCreate', 'created'],
  destroy: ['beforeDestroy', 'destroyed'],
  mount: ['beforeMount', 'mounted'],
  update: ['beforeUpdate', 'updated'],
};

然而想要理解这套,还是必须从 '@sentry/types'去找到 Span, Transaction 究竟是个啥

vue-router

vueRouterInstrumentation

检测 vue-routeronError hooks 和 添加一个全局的导航守卫

有意思的是,他通过闭包,在闭包外声明了一个 firstLoad 的 flag:boolean

用来判断,页面是直接进入的,还是通过导航进入的。学习到了

总结

Vue 检测

  • Vue.config.xxxxHandler
  • lifecycle hooks
  • mixin

Vue-Router

  • Navigation Guards
  • router.onError