• 在Vue中搭建前端监控日志


    监控可以观察到人的动作、周围的环境,如果有情况也可以通过监控还原现场。

    前端也可以通过设置“监控”观察用户,在遇到一些无法复现、奇奇怪怪的问题,或者单个用户所在的环境与大部分用户的环境不一样时产生的问题,例如 该用户对浏览器设置了不允许cookie 等;这些问题通过前端监控记录下来,让开发者模拟出问题环境、操作步骤,能更好的解决问题。

    进入正题

    首页,要考虑的是监控要记录什么?
    1、用户的环境
    2、用户点击哪个页面中的元素
    3、请求了哪些接口,接口又返回了什么
    4、页面报了什么错

    监控要怎么实现
    1、可以采用数组的形式记录,给每个元素一个唯一标识作为步骤记录器
    2、其他思路能实现记录也可以

    监控什么时候上传到服务器端
    一般是页面刷新或者关闭前发送


    Vue2:

    需要使用到Vuex,因为要将记录的数据存放到Vuex中
    store.js:

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        monitoring:[],
      },
      mutations: {
        setMonitoring(state,data){
          state.monitoring.push({
            ...data,
            nowPage:window.location.href,
            steps:state.monitoring.length+1,
            time:`${new Date().getFullYear()}-${new Date().getMonth()+1}-${new Date().getDate()}-${new Date().getHours()}:${new Date().getMinutes()}:${new Date().getSeconds()}`
          })
        }
      },
      actions: {
      },
      modules: {
      }
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在src目录下新建monitoring文件夹(名字可以自定义),monitoring文件夹下创建一个index.js文件

    在这里插入图片描述
    monitoring中的index.js

    import store from "@/store";//引入Vuex的store
    //获取当前浏览器的Storage大小
    function get_cache_size(t){
        t = t == undefined ? "l" : t;
        var obj = "";
        if(t==='l'){
            if(!window.localStorage) {
                return "当前不支持localStorage存储"
            }else{
                obj = window.localStorage;
            }
        }else{
            if(!window.sessionStorage) {
                return "当前不支持sessionStorage存储"
            }else{
                obj = window.sessionStorage;
            }
        }
        var size = 0;
        if(obj!==""){
            for(let item in obj) {
                if(obj.hasOwnProperty(item)) {
                    size += obj.getItem(item).length;
                }
            }
        }
        return size
    }
    //存储当前Storage大小
    store.commit("setMonitoring",{
        title:`当前Location大小:${get_cache_size('l')};当前Session大小:${get_cache_size('s')}`
    })
    store.commit("setMonitoring",{
        title:`浏览器cookie设置:${navigator.cookieEnabled==true?'开启':'禁用'};当前Cookie:${document.cookie || "暂无"}`
    })
    //监听页面隐藏或者打开
    window.addEventListener("visibilitychange",()=>{
        if(document.hidden){
            store.commit("setMonitoring",{
                title:"离开/隐藏页面"
            })
        }else{
            store.commit("setMonitoring",{
                title:"进入页面"
            })
        }
    })
    //监听鼠标点击事件
    window.addEventListener('mouseup',(event)=>{
        store.commit("setMonitoring",{
            title:"用户点击",
            Element:event.path[0].outerHTML
        })
    })
    //监听报错信息
    window.addEventListener("error",(err)=>{
        store.commit("setMonitoring",{
            title:"报错",
            errorMsg:err.message
        })
    })
    //在页面刷新、关闭前发送记录的数据,fetch能保证浏览器结束进程前发送请求
    window.addEventListener('beforeunload',()=>{
        let arr=JSON.stringify(store.state.monitoring);
        fetch('http://192.168.10.170:8081/sendData', {
          method: 'POST',
          headers:{
            'Accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded'
          },
          params:arr,
          keepalive: true
        });
      })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    main.js:

    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    import "@/monitoring";//引入文件
    
    Vue.config.productionTip = false
    
    new Vue({
      router,
      store,
      render: h => h(App)
    }).$mount('#app')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    router/index.js

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import store from "@/store";
    
    Vue.use(VueRouter)
    
    const routes = [
      {
        path:"/",
        redirect:"/test"
      }
    ]
    
    const router = new VueRouter({
      routes
    })
    
    router.afterEach((to,from)=>{
      store.commit('setMonitoring',{
        title:"切换页面",
        formPage:from.path,
        toPage:to.path,
      })
    })
    
    export default router
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    axios拦截器中记录

    import axios from "axios"
    import store from "@/store"
    
    axios.interceptors.request.use((config)=>{
        store.commit("setMonitoring",{
            title:"发请求",
            data:JSON.stringify(config)
        })
        return config
    })
    
    axios.interceptors.response.use((config)=>{
        store.commit("setMonitoring",{
            title:"接收请求",
            data:JSON.stringify(config)
        })
        return config
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    最后看看效果:
    点击TEST文本会发送请求
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    基于python的PDF文件解析器汇总
    “揭秘淘宝店铺所有商品接口:一键获取海量热销宝贝信息!“
    2022卡塔尔世界杯来临,体育界最新创意二维码案例大盘点!
    C++函数传递数组方法及原理刨析
    基于JAVA青岛滨海药店管理系统的设计与实现计算机毕业设计源码+数据库+lw文档+系统+部署
    happens-before 和 as-if-serial 对比
    Unity Addressables实现web文件夹更新资源
    Pnpm:包管理的新星,如何颠覆 Npm 和 Yarn
    面试设计模式-责任链模式
    超简单理解冒泡排序
  • 原文地址:https://blog.csdn.net/qq_44849271/article/details/126684282