前端监控就是通过页面埋点上报,来获取用户信息、异常信息、交互信息等,并对这些信息分析与计算,来提升网站的用户体验。
监控信息
-
用户信息
-
环境信息
-
事件信息
用户信息可以通过登录来获取。
环境信息包含了终端系统、浏览器信息、网络、语言等。
const devInfo = {
osType: osType(),
browserType,
browserVersion,
language: window.navigator.language,
netType: window.navigator.connection?.type,
evn: browserRouter ? 'prod' : 'dev',
appName: name,
appVersion: version,
};
事件信息主要是用户交互、路由跳转、页面异常、请求异常等。
页面埋点
用户交互
用户交互可以自定义埋点组件来监控。
例如,对点击事件进行监控。
const ReportButton = props => {
const {value, label, text, description, onClick, ...rest} = props;
const handleClick = e => {
repot({
text: text || props.children,
value,
label,
description,
type: 'click',
});
onClick?.(e);
};
return <Button {...rest} onClick={handleClick} />;
};
当我们需要埋点时,直接使用 ReportButton
即可。
路由跳转
我们可以使用路由钩子来监控路由跳转,可以得到用户在当前页面停留时间等信息。
const routeReport = () => {
const uuid = uuidv4();
report({actionType: 'routeChange', uuid, prevUuid});
prevUuid = uuid;
};
通过 beforeunload
监听页面关闭或刷新:
window.addEventListener('beforeunload', e => {
const isLogin = e.target.location.pathname.indexOf('/user/') === 0 || e.target.location.hash.indexOf('#/user/') === 0;
if (!isLogin) {
report({actionType: 'close', prevUuid});
}
}, false);
页面异常
通过 ErrorBoundary
来上报页面异常:
const pageError = ({error}) => {
const errStack = error?.message?.slice(0, 120).split('. ').slice(0, 2).join('. ');
report({actionType: 'pageError', text: errStack});
};
const ErrorBoundary = props => <HandleError {...props} report={pageError} />;
export default ErrorBoundary;
请求异常
在我们的 fetch
请求函数抛出异常时上报信息:
const fetch = ({method, url, ...opt}) => fetchApi(method)(`${TARGET}${url}`, {...opt, headers: getToken(), credentials: 'omit'})
.catch(err => {
report({actionType: 'fetchError', text: err.message, value: url});
throw err.message;
});
信息处理
当我们获取了一些基础信息时,我们就可以通过数据分析、归纳,来完善系统稳定性,找出用户关注点等。
简单实现
创建数据表
const schemas = {
// user info
uid: {type: String, required: true},
userName: {type: String},
userRole: {type: Number},
projectId: {type: String},
projectName: {type: String},
ip: {type: String, required: true},
// system info
osType: {type: String, required: true},
browserType: {type: String, required: true},
browserVersion: {type: String},
language: {type: String},
netType: {type: String},
evn: {type: String},
appName: {type: String},
appVersion: {type: String},
// route info
route: {type: String},
routeName: {type: String},
// action info
actionType: {type: String, required: true},
category: {type: String},
text: {type: String},
label: {type: String},
value: {type: String},
description: {type: String},
startTime: {type: Number},
endTime: {type: Number},
};
创建接口
router:
const beforeRender = (input, next) => {
const {path, prevPath} = input;
const validPath = path.split('?')[0];
if (validPath === initPath) {
return next({path: '/'});
}
if (!isAuthed() && !whiteRoutes.includes(validPath)) {
return next({path: '/user/signin'});
}
if (path !== prevPath && demoBackReg.test(prevPath)) {
// designReg
return confirmDesignPage(next);
}
next();
routeReport();
};
// ErrorBoundary
const pageError = ({error}) => {
const errStack = error?.message?.slice(0, 120).split('. ').slice(0, 2).join('. ');
report({actionType: 'pageError', text: errStack});
};
const errorBoundary = props => <HandleError {...props} report={pageError} />;
export default {
browserRouter,
beforeRender,
basepath,
errorBoundary,
};
导航栏:
const handleNavClick = (props, item) => {
report({
actionType: 'click',
category: 'navbar',
text: item.name || item.title || item.type,
value: item.type,
});
const {handle, path, link} = item;
if (typeof handle === 'function') {
return handle(item);
}
if (link) {
return window.open(link);
}
if (path) {
return props.router.push(path);
}
};
展示页面
拿到数据可以通过不同纬度去作分析与展示,比如时间、操作系统、项目名、浏览器等。
原文始发于微信公众号(前端道萌):前端监控系统
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/101923.html