写一个VUE错误日志收集插件

144 阅读1分钟

error-logger.js

import store from '@/store'
import { errorLogger } from '@/server/errorLoggerApi'

export default function (app, options = {}) {
  // 设置一个默认的 options
  const defaultOptions = {
    logToConsole: true, // 是否把错误日志打印到控制台
    remotoLogging: false // 是否把错误日志发送到服务器
  }
  const config = { ...defaultOptions, ...options }

  // (1)全局Vue错误
  app.config.errorHandler = (err, vm, info) => {
    logError(err, info)
  }

  // (2)捕获未处理的 Promise 错误
  window.addEventListener('unhandledrejection', (event) => {
    logError(event.reason, 'promise rejection error!!!')
  })

  // 错误处理函数
  async function logError(error, info) {
    // 同时记录在vuex中
    store.commit('addErrorLog', { error, info })
    if (config.logToConsole) {
      console.error(`[错误收集:${info}]`, error)
    }

    // 是否发送到远程服务器
    if (config.remotoLogging && config.remoteUrl) {
      // 调用上送错误日志接口
      const errorInfo = {
        error: error.message, // 错误消息
        stack: error.stack, // 错误堆栈
        info, // 具体错误说明信息
        time: new Date().toISOString() // 记录时间
      }
      await errorLogger(errorInfo)
    }
  }
}

main.js

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { useErrorLogStore } from '@/stores/useErrorLogStore.js'
import App from './App.vue'
// 引入自定义插件
import ErrorLogger from '@/plugins/ErrorLogger/error-logger'

const app = createApp(App)
const pinia = createPinia()
// 获取数据仓库
const errorLogStore = useErrorLogStore()
app.use(pinia)
// 使用插件
app.use(ErrorLogger, {
  logToConsole: true,
  remotoLogging: true,
})

app.mount('#app')
errorLogStore.setErrorLog(JSON.parse(localStorage.getItem('errorLog')))

stores/useErrorLogStore.js

import { defineStore } from 'pinia'

export const useErrorLogStore = defineStore('errorLog', {
  // 定义数据状态
  state: () => {
    return {
      errorLog: []
    }
  },
  // 定义了修改数据状态的两个方法
  actions: {
    addErrorLog(log) {
      this.errorLog.push(log)
	  localStorage.setItem('errorLog', JSON.stringify(this.errorLog))
    },
    setErrorLog(errorLog) {
      this.errorLog = errorLog
    }
  }
})

errorLog.vue

<template>
  <div>
    <h1>错误日志</h1>
    <ul>
      <li v-for="error in errorLogStore.errorLog" :key="error.time">{{ error.time }} - {{ error.message }}</li>
    </ul>
  </div>
</template>

<script setup>
import { useErrorLogStore } from '@/stores/useErrorLogStore.js'
// 获取数据仓库
const errorLogStore = useErrorLogStore()

</script>