前言
我们前面已经对前端错误、前端接口实现了监控采集,今天我们来实现前端流量监控。

流量指标
这里参考我们之前的文章前端应用监控前端部分方案设计,在这里面我们详细介绍了我们的流量是怎么计算的,我们这里主要介绍我们是如何实现PV的,也就是一个系统的页面的访问量采集和统计。
具体实现
-
监听pushState、replaceState、hashchange
-
自定义事件
typescript
/**
* @description 用来监听页面变化
* @author
*/
export class PageObserver {
private bt1 = null;
private bt2 = null;
private bt3 = null;
constructor() {
history.pushState = this.replaceAndPush('pushState');
history.replaceState = this.replaceAndPush('replaceState');
}
private replaceAndPush(type: string) {
let orig = history[type];
return function () {
let rv = orig.apply(this, arguments);
let e;
if (!!_global.ActiveXObject || 'ActiveXObject' in window) {
e = document.createEvent(type.toLocaleLowerCase());
} else {
e = new Event(type.toLocaleLowerCase());
}
e['arguments'] = arguments;
_global.dispatchEvent(e);
return rv;
}
}
public pageChangeObserve(options) {
on(_global, EVENTTYPES.POPSTATE, event => {
this.bt1 && clearTimeout(this.bt1);
this.bt1 = setTimeout(() => {
PageObserver.popStateHandle(event, options)
}, 300);
}, true);
on(_global, EVENTTYPES.PUSHSTATE, event => {
this.bt2 && clearTimeout(this.bt2);
this.bt2 = setTimeout(() => {
PageObserver.pushStateHandle(event, options)
}, 300);
}, true);
on(_global, EVENTTYPES.LOAD, event => {
this.bt3 && clearTimeout(this.bt3);
let time: string | number;
if (performance.timing && performance.timing.domLoading && performance.timing.domComplete) {
time = performance.timing.domComplete - performance.timing.domLoading;
} else {
time = 1000;
}
this.bt3 = setTimeout(() => {
PageObserver.loadHandle(event, options);
}, time);
}, true);
on(document, EVENTTYPES.VISIBILITYCHAGE, () => {
PageObserver.visibilityHandle(options);
}, true);
}
private static pushStateHandle(event: Event, opts: IParams) {
creatPageLog(event, opts);
}
private static popStateHandle(event: Event, opts: IParams) {
creatPageLog(event, opts);
}
private static loadHandle(event: Event, opts: IParams) {
creatPageLog(event, opts);
}
private static visibilityHandle(opts: IParams) {
if (document.visibilityState !== 'visible') {
let apiArr = getLocalStorage(ARRAYNAME.APIARR) || '[]';
let logArr = getLocalStorage(ARRAYNAME.LOGARR) || '[]';
let pageArr = getLocalStorage(ARRAYNAME.PAGEARR) || '[]';
if (JSON.parse(apiArr).length > 0) {
let obj = [...JSON.parse(apiArr)];
apiInfoReport(opts.apiContextReportUrl, {
apiContexts: obj,
sendTime: getTimeStamp()
},opts)
setLocalStorage(ARRAYNAME.APIARR, '[]');
}
if (JSON.parse(logArr).length > 0) {
let obj = [...JSON.parse(logArr)];
apiInfoReport(opts.logContextReportUrl, {
logContexts: obj,
sendTime: getTimeStamp()
}, opts)
setLocalStorage(ARRAYNAME.LOGARR, '[]');
}
if (JSON.parse(pageArr).length > 0) {
let obj = [...JSON.parse(pageArr)];
apiInfoReport(opts.pageContextReportUrl, {
pageContexts: obj,
sendTime: getTimeStamp()
}, opts)
setLocalStorage(ARRAYNAME.PAGEARR, '[]');
}
}
}
}
总结
经过测试不管是hash模式还是history模式以及reload我们都能够正确采集页面地址信息,结合我们之前的sessionId和唯一的userId,实现我们对我们网站的PV的采集,便于统计我们系统的流量。