# track **Repository Path**: dafu204/track ## Basic Information - **Project Name**: track - **Description**: 数据监控 - **Primary Language**: Unknown - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 6 - **Forks**: 4 - **Created**: 2023-02-24 - **Last Updated**: 2025-07-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # track #### 介绍 数据监控插件 - 兼容传统多页面项目,Vue,React #### 软件架构 监控插件: rollup+js node服务器: node+express 监控系统展示页面: Vite+Vue3+TS #### 安装教程 监控插件: track node服务器: track\test\server 监控系统展示页面: track\test\webTable 文件刚拉取下来的,直接双击npmIThree.bat初始化三个项目 如果你想直接调试这个插件的源码 ```js npm link  // 创建软连接,创建好之后在d:\Program Files\nodejs\node_modules\tracking文件里可以看到 npm link 包名  // 在项目里使用上一步创建的软连接 // 插件 PS C:\Users\64018\Desktop\track> npm link // 被监控项目 PS C:\Users\64018\Desktop\pay_center> npm link track // import track from 'track' ``` 如果你就想直接使用插件,用node服务器和监控系统展示页面看下效果就够了 ```js npm i track_dove // import track from 'track_dove' ``` #### 使用说明 node服务器和监控系统展示页面,使用npm run dev启动项目 被监控项目里所需要的配置 ```js // main.js import track from 'track' 或者 import track from 'track_dove' let optionsObj = { needLog: true, // 控制台要不要看到插件初始化完成的日志 trackError: false, // 监控错误 openErrorRecord: false, // 开启错误录屏,更有利于捕捉错误 trackPerformance: true, // 监控项目性能,开启了之后也会白屏检测会自动调用下边的whiteBoxElements属性 whiteBoxElements:['html','body','#app'], // 纯白屏容的时候才会出现的容器盒子.前两个标签是绝对有的,第三个就看自己项目的盒子属性了,一般Vue项目body下边都是
chain: [ // 这部分是单个埋点 // 监听点击事件 { type: 'clickEvent', rule: { // urls: [], // 触发的页面地址,非必填,空数组就是所有页面,选填 selectorId: 'track' // 必填.标签上的id属性,例如
}, // 埋点触发的回调,trackData:返回的埋点数据,send:去对接上报接口方法,可以提前按自己需求过滤数据 handler: function (trackData, send) { send(trackData) } }, // 监听页面停留 { type: 'pageStayTime', rule: { urls: [] // 选填 }, handler: function (trackData, send) { send(trackData) } }, // 监听请求 { type: 'requestTime', rule: { urls: ['http://localhost:8080/test1'] // 接口请求url,必填 }, handler: function (trackData, send) { send(trackData) } }, // 下边部分是同时埋点多个,链式埋点:clickEvent,requestTime,这两者串联执行 // chain数组里有很多条链路 // 链路埋点除了最后一个点上报,在这之前就只做逻辑处理,要想上报就去单次埋点里上报..不要逻辑搞乱了 { status: { beginTime: 0, // 链路开始时间 }, pointList: [ { type: 'clickEvent', rule: { urls: ['http://localhost:9001/#/loginSub'], selectorId: 'track' }, handler: function (trackData, send) { console.log('链路埋点1') this.status.beginTime = trackData.currentTime } }, { type: 'requestTime', rule: { urls: ['http://localhost:8080/test2'] }, handler: function (trackData, send) { console.log('链路埋点2') console.log(this.status.beginTime, 'this.status.beginTime--------------') // 你有开始时间才会上报你,没有开始时间你就不是从上边的点过来的 if (this.status.beginTime) { trackData.describe = new Date().getTime() - this.status.beginTime // 总时长 trackData.type = 'clickToRequest_time' send(trackData, '点击按钮到保存接口完成') } } } ] } ], // 上报 send: (sendData, remark) => { console.log(`最终上报类别:${sendData.type}`, sendData) // let data = new URLSearchParams(sendData).toString() // new Image().src = `http://localhost:8080/sendData?${data}` sendData.entryName = 'pay_center' // 添加项目名称字段 sendData.remark = remark const fd = new FormData() for (let key in sendData) { fd.append(key, sendData[key]) } fetch("http://localhost:8080/sendData", { method: 'post', body: fd }).then(function (response) { if (response.status >= 400) { throw new Error("Bad response from server") } return response.text(); }).then(function (data) { console.log(data) }).catch(function (err) { console.log(err) }); } } // 不同类型的项目初始化的写法不一样: // Vue import Vue from 'vue' Vue.use(track, optionsObj) // React track.init(optionsObj) // 传统多页面项目 Track.init(optionsObj) ``` ```js // package.json "postbuild": "node handelSourceMap.js", // handelSourceMap.js. 如果用的Vite,后缀就是.cjs const fs = require('fs'); const path = require('path') const axios = require('axios') let jsPath = path.join(__dirname, 'dist','static','js') // 具体路径就看你的.map文件具体位置了 const pathArr = [] fs.readdir(jsPath,function(err,files){ if(!err){ const fd = {} for (const item of files) { if(item.endsWith('.map')){ pathArr.push({name:item,path:path.join(jsPath, item)}) } } axios.post('http://localhost:8080/setSourceMap',{data:{name:'pay_center',pathArr}}).then((res)=>{ if(res.data.result === 1){ console.log(res.data.result,'res.data.result') for (const item of pathArr) { fs.unlinkSync(item.path); //直接删除文件 } } }).catch((err)=>{ console.log(err) }) }else{ console.log(err) } }) ``` #### 关于这个插件的文章: https://juejin.cn/post/7229698783646679100#heading-9