在Vue中搭建前端监控日志_vue日志记录_I'm Mr.C的博客-程序员宅基地

技术标签: Vue.js  前端  vue.js  javascript  

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

前端也可以通过设置“监控”观察用户,在遇到一些无法复现、奇奇怪怪的问题,或者单个用户所在的环境与大部分用户的环境不一样时产生的问题,例如 该用户对浏览器设置了不允许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: {
    
  }
})

在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
    });
  })

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')

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

在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
})

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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_44849271/article/details/126684282

智能推荐

1019: 公园门票 ZZULIOJ-程序员宅基地

1019: 公园门票题目描述某公园门票的票价是每人50元,一次购票满30张,每张可以少收2元。试编写自动计费系统程序。输入输入一个正整数,表示购票的数量。输出输出一个整数,表示用户实际需要支付的金额。样例输入 Copy30样例输出 Copy1440#include<stdio.h>int main(){ int n,a; scanf("%d",&n); if(n>=30) a=48*n; else _1019: 公园门票

CEF3开发者系列之CEF3入门-程序员宅基地

CEF全称Chromium Embedded Framework,是一个基于Google Chromium 的开源项目。Google Chromium项目主要是为Google Chrome应用开发的,而CEF的目标则是为第三方应用提供可嵌入浏览器支持。CEF3不仅开源,而且跨平台,框架的开发者也不断的在更新,英文资料较丰富,对HTML5,CSS3等支持也很好。目前CEF3被全球很多公司使用,国内使...

更改注册表字体_李晓瑞_廊坊师范提高班十五期_新浪博客-程序员宅基地

今天敲百例的第73个-“下拉式菜单”,内容是更改字体,但运行的时候,只有第一个华文彩云能够显示,另外几个字体,即便选择了,字体也不会更改,我就去word里找了一下有没有这几个字体,结果没找到,李老师过来了,我说了一下来龙去脉后,李老师说“你把word里有的字体写到代码里试试呀!”真的诶,我怎么没想到呢,就是呀,可以试试,一试还真是可以变换字体了,老师说,那几种字体没在注册表里..._如何在注册表中修改字体

Content-disposition 实现文件下载-程序员宅基地

自己实例代码如下import java.io.BufferedOutputStream;import java.io.OutputStream;import java.net.URLEncoder;import javax.servlet.http.HttpServletResponse;import org.springframework.stereotype.Controller;import...

cmd不能识别python问题_cmdpython 显示没下载-程序员宅基地

cmd不能识别python问题原因分析:没有设置环境变量如何设置环境变量?点击此处设置环境变量后在cmd中输入python依然没有显示正确的结果,怎么办?答案:重启试试看,我在重启后就正常了。..._cmdpython 显示没下载

随便推点

十天的心理挑战_30天积极心理挑战-程序员宅基地

十天的心理挑战如果本书所教你的都没做,但至少这一样练习得好好做,我称其为“十天的心理挑战”它曾确实帮助过我,何以见得?因为他使我得以控制自己的内心,不在继续朝负面去想。你作好准备了吗?以下就是游戏的规则:一.在随后一连十天里,心里不可有任何一刻的消极或负面念头、情绪、问话、字眼或引喻。二.当你一有消极或负面的反映时----一定会有的-----就要立即提问自己好多_30天积极心理挑战

强大助手:Notepad++全面功能总结,认识Notepad++,这一篇就够了_notepad++怎么选择块-程序员宅基地

1 、文本得到焦点,按住Alt,拖动选择区域,可进行块选中。并且按住Alt,拖动选择区域,可再同时按Shift+End进行相关行的后续选中(文本区和搜索区都可),快捷键为Alt+Shift+方向键。或者点击一个位置,再按住Alt+Shift,点击另一个位置,也可以块选中。2 、文本得到焦点,按住Shift,在下一个焦点处点击,进行连续区域选中。3 、文本得到焦点,按住Shift,在左侧栏行号或..._notepad++怎么选择块

zynq设计学习笔记6——自定义含AXI4接口IP核-ps与pl的交互_墨漓_lyl的博客-程序员宅基地

在本实验中,我们将采用封装带有AXI4接口的IP的方式,实现PS和PL的数据交换,另外自定义IP核可以定制化系统设计,以达到设计重用的目的,可以很大程度上简化系统设计和缩短产品上市的时间。本次实验任务:通过自定义一个含有AXI总线的加减法器 IP核,接收ps端数据,在pl端进行计算后,将结果发送到ps端并通过uart打印出来。并用pl端控制的LED灯显示此时计算的是加法还是减法。下面开始实验步骤。步骤一:打开Vivado后,点击下图位置的Manage IP,并在选项中选择New IP Location。

angular 2.0 关于新版angular-cli的应用_angular 老项目和新项目的angular cli-程序员宅基地

1.以前写过一个webstorm借助angular-cli搭建angular2.0项目的博客。 后来许久没有接触过angular,现在拾起来的时候发现已经更新,用法变了。所以来记录下,以免其他友看到照成误区。2.这也是说明一个道理,别人写下的东西你不一定适用,因为技术的东西说变就变,谁知道的。基于Node环境,安装angular-cli。 新版的已经变成安装@angular/cli。所以_angular 老项目和新项目的angular cli

Linux网络编程(1)——网络基础-程序员宅基地

网络:跨主机的 “进程间” 通信。协议:一种彼此双方都认可的协议。为什么分层?网络协议非常复杂,不分层就太复杂了。好处:拆分成多个层,就是类似分成多个模块,同时降低了系统的耦合程度。根据需要,可以随意替换其中的某一层协议网络的协议分层:OSI七层模型<只存在教科书中>:应用层 表示层 会话层 传输层 网络层 数据链路层 物理层...

Python最新暴力破解WiFi,攻破所有密码限制,最强破解!_wifidic-程序员宅基地

暴力破解wifi密码这个代码也是非常简单,这里需要用Python中的pywifi这个库,所以需要在DOS命令下安装这个库,同样使用pip install pywifi,很简单就安装成功了,我用的是Python3,所以各位看的时候需要注意这一点。接下来我们一步一步分析主要代码,后面同样附上完整的代码。对了,需要注意一点,就是电脑必须是要用无线网卡的。..._wifidic