1. 程式人生 > 其它 >Vue2.x專案整合ExceptionLess監控

Vue2.x專案整合ExceptionLess監控

前言

一直以來我們都是用Sentry做專案監控,不過前段時間我們的Sentry壞掉了(我搞壞的)

但監控又是很有必要的,在sentry修好之前,我想先尋找一個臨時的替代方案,同時發現網上關於ExceptionLess的資料少得可憐,ExceptionLess官方的文件也不是很完善,翻了好久文件和原始碼,於是有了本文……

關於ExceptionLess

寫.NetCore的同學應該不會陌生,這個是.Net平臺的一款監控工具,跟Sentry差不多,不過我們覺得介面比sentry清爽,資訊也比較清晰一目瞭然,所以我們的.NetCore服務監控全都用ExceptionLess來做。

然後ExceptionLess也是支援前端的,因此,我打算先暫時用ExceptionLess來做我們的前端專案監控。

準備工作

在ExceptionLess中建立一個專案,這個懂的都懂,不重複了~

ExceptionLess提供了好幾種模式,有Node.js、也有瀏覽器應用,這裡我選的是瀏覽器應用。

官方還有關於Vue的例子,不過是vue3.x版本的,因為我們目前還在用vue2.x,所以只能自己基於瀏覽器應用的SDK封裝一個來用~

安裝ExceptionLess客戶端

使用yarn安裝客戶端

yarn add exceptionless

我使用的版本是^1.6.4

整合ExceptionLess

src/utils下建立一個新的js檔案:exceptionless.js

import {ExceptionlessClient} from 'exceptionless/dist/exceptionless';

const exLessClient = ExceptionlessClient.default;
exLessClient.config.apiKey = '';
exLessClient.config.serverUrl = ''

const install = Vue => {
  if (install.installed)
    return

  install.installed = true

  Object.defineProperties(Vue.prototype, {
    $exLess: {
      get() {
        return exLessClient
      }
    }
  })
}

export default install

這樣實現了把ExceptionLess封裝為一個Vue模組

然後編輯main.js,準備註冊模組

import Exceptionless from './utils/exceptionless'
// Exceptionless模組
Vue.use(Exceptionless)

這樣,在需要提交日誌的地方就可以直接使用:

this.$exLess.submitLog('測試資訊')
this.$exLess.submitException(error)

整合到全域性異常處理

如果所有異常要自己手動捕獲提交的話就太麻煩了,而且會有漏網之魚

我參考了網上的資料,搞了個vue全域性異常處理,把沒有手動捕獲的異常收集起來,然後一併提交到ExceptionLess平臺。

直接上程式碼,src/utils/errorHandler.js

import {ExceptionlessClient} from 'exceptionless/dist/exceptionless';

const exLessClient = ExceptionlessClient.default;

function isPromise(ret) {
  return (ret && typeof ret.then === 'function' && typeof ret.catch === "function")
}

const errorHandler = (error, vm, info) => {
  console.error('丟擲全域性異常', 'vm=', vm, 'info=', info)
  console.error(error)
  exLessClient.submitException(error)
}

function registerActionHandle(actions) {
  Object.keys(actions).forEach(key => {
    let fn = actions[key]
    actions[key] = function (...args) {
      let ret = fn.apply(this, args)
      if (isPromise(ret)) {
        return ret.catch(errorHandler)
      } else { // 預設錯誤處理
        return ret
      }
    }
  })
}

const registerVuex = (instance) => {
  if (instance.$options['store']) {
    let actions = instance.$options['store']['_actions'] || {}
    if (actions) {
      let tempActions = {}
      Object.keys(actions).forEach(key => {
        tempActions[key] = actions[key][0]
      })
      registerActionHandle(tempActions)
    }
  }
}
const registerVue = (instance) => {
  if (instance.$options.methods) {
    let actions = instance.$options.methods || {}
    if (actions) {
      registerActionHandle(actions)
    }
  }
}

let GlobalError = {
  install: (Vue, options) => {
    /**
     * 全域性異常處理
     * @param {*} error
     * @param {*} vm
     */
    Vue.config.errorHandler = errorHandler
    Vue.mixin({
      beforeCreate() {
        registerVue(this)
        registerVuex(this)
      }
    })
    Vue.prototype.$throw = errorHandler
  }
}

export default GlobalError

main.js中註冊

import ErrorHandler from "./utils/errorHandler"

// 全域性非同步處理模組
Vue.use(ErrorHandler)

搞定~

參考資料