userAgent
我们在行为监控中,请求头字段userAgent 其实有很多信息,需要获取上报,但是直接手动处理较为繁琐,因此通通过这个 'ua-parser-js';
// 获取用户设备相关信息
getUserAgent = (useragent) => {
const parserData = parser(useragent);
const browserName = parserData.browser.name; // 浏览器名
const browserVersion = parserData.browser.version; // 浏览器版本号
const osName = parserData.os.name; // 操作系统名
const osVersion = parserData.os.version // 操作系统版本号
const deviceType = parserData.device.type; // 设备类型
const deviceVendor = parserData.device.vendor || ''; // 设备所属公司
const deviceModel = parserData.device.model || ''; // 设备型号
const engineName = parserData.engine.name; // engine名
const engineVersion = parserData.engine.version; // engine版本号
return {
browserName,
browserVersion,
osName,
osVersion,
deviceType,
deviceVendor,
deviceModel,
engineName,
engineVersion,
};
}
用户行为记录栈
一些用户行为分析,以及错误排查的时候,是需要将关键行为,按照顺序存储上报,
BreadStack = ()=>{
class Stack {
// 这里用constructor 貌似不是很好
//为什么要用静态的
private maxBread: number;
private stack: any[];
push = (item) => {
if (this.stack.length >= this.maxBread) {
this.stack.shift()
}
this.stack.push(item)
}
pop = () => {
return this.stack.pop()
}
getStack = () => {
return this.stack.length
}
// 这种清除方法真的好吗
clear = () => {
this.stack = []
}
}
}
}
路由信息监听
- 一般主要针对于spad 单页面应用来进行 监听。
// 重写pushState 和 replaceState 因为监听不到
wrHistory = (type) => {
let origin = window.history[type]
if (type === 'pushState') {
let event = new Event('pushState')
window.dispatchEvent(event)
}
if (type === 'replaceState') {
let event = new Event('replaceState')
window.dispatchEvent(event)
}
return origin.apply(this, type)
}
rewriteHistory = () => {
window.history.pushState = this.wrHistory('pushState')
window.history.replaceState = this.wrHistory('replaceState')
}
// 监听路由变化
watchHashRouteChange = (handle: Function) => {
window.addEventListener('hashchange', () => {
handle()
})
}
watchHistoryRouteChange = (handle: Function) => {
window.addEventListener('popstate', () => {
handle()
})
}
initRouter = () => {
const handle = () => {
const metrics = {
type: 'router',
url: window.location.href,
time: new Date().getTime(),
}
this.metrics.set(metricsName.RCR, metrics)
// 记录到行为记录追踪
const behavior = {
category: metricsName.RCR,
data: metrics,
...this.getExtends(),
} as behaviorStack;
this.breadcrumbs.push(behavior);
}
this.watchHashRouteChange(handle)
this.watchHashRouteChange(handle)
}
pv,uv
PV是页面访问量UV是24小时内(00:00-24:00)访问的独立用户数。
pv 再用户访问当前路由页面进行记录,uv 后端配合ip 及登录信息判断是否为首次登陆
initPv = () => {
const handler = () => {
const metrices = {
origin: window.location.origin,
pathname: window.location.pathname,
time: new Date().getTime(),
originInfo: this.getOriginInfo()
}
this.userSendHandler(metrices)
}
// 页面加载完毕后进行上报
afterLoad(() => {
handler()
})
}
如何上报呢
一般来将,常见方式,一个是用XHR 以及fetch 请求上报,img标签,以及H5里得sendBeacon 来,但是我当时业务上实际采用得 sendBeacon 加降级ajax 上报处理。
xhr 方式,兼容性更好,但是可能阻塞页面加载,以及特殊场景无法覆盖,关闭 sendbeaco 非阻塞式,但是兼容性差 img,虽然支持跨越,但是由于是get请求,资源存入url ,不同浏览器对于url 地址请求可能会被截断,长度会有要求。