案例展示
- 错误上报
- 监控前端性能
- 行为监控(暂未实现,可参考微信的埋点上报)
实现
错误上报
main.js
// 错误上报
function saveError(message) {
if (isDev()) return
if (message) {
// 手动触发的错误上报
captureError({
message,
des: 'user_handler',
})
}
Vue.config.errorHandler = (err) => {
// vue错误上报
captureError({
message: err.message,
des: 'errorHandler',
})
}
window.addEventListener('error', function (event) {
// js执行错误
captureError({
message: event.message,
des: 'error',
})
})
window.addEventListener('unhandledrejection', function (event) {
let type = getType(event.reason)
let message = event.reason
if(['array','object'].includes(type)){
message = JSON.stringify(event.reason)
}
// promise错误
captureError({
message,
des: 'promise错误 - unhandledrejection',
})
})
function captureError({ message, des }) {
let message_type = getType(message)
switch (message_type) {
case 'array':
message = JSON.stringify(message)
break
case 'object':
message = JSON.stringify(message)
break
case 'error':
message = message.toString()
break
case 'promiserejectionevent':
message = message.reason.toString()
break
default:
break
}
const type = 3
const name = `博客项目错误上报(${isPc()? 'PC端' : '移动端'})})`
if (!message) return
let errStore = getSessionStorage('errStore') || []
let index = errStore.findIndex((item) => item.message === message)
// 防止重复上报
if (index > -1) return
setSessionStorage('errStore', [...errStore, { message }])
// 上报错误信息 img上报
let img = new Image()
let url = (window.location.hash || '未知链接').replace('#', '')
let params = {
type,
name,
content: message,
url,
des,
}
img.src = `${baseURL}page_point?${paramsJoin(params)}`
}
}
saveError()
// 全局绑定一个报错的方法
Vue.prototype.saveError = saveError
监控前端性能
- 每次同步用户信息时,一起上报
post_user_sync() {
if (!this.getNeedApi('post_user_sync', this.routeName)) return
let { email, password } = this.userdata
if (!email || !password) return
let params = {
email,
password,
sync: 'sync',
}
if (
!this.isDev() &&
window.performance &&
this.isObject(window.performance.timing)
) {
let { timing } = window.performance
let arr = [
{
label: '脚本加载时间',
value: timing.domComplete - timing.domInteractive,
},
{
label: '白屏时间',
value: timing.domLoading - timing.fetchStart,
},
{
label: '页面完全加载时间',
value: timing.loadEventStart - timing.navigationStart,
},
]
// 网络情况
let netInfo = {}
if (this.isObject(navigator.connection)) {
let { downlink, effectiveType, rtt } = navigator.connection
netInfo = {
downlink,
effectiveType,
rtt,
}
}
let data = {
load_time: arr,
netInfo,
}
params = {
...params,
...data,
}
}
httpApi.post_user_sync(params).then((res) => {
this.postNeedApi('post_user_sync')
this.setUserData({
user: res.data.data,
})
}).catch((e) => {
console.log('同步用户信息失败', e)
})
},