1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| import { Options, DefaultOptions, LoggerAndErrorConfig, PostLoggerAndErrorData } from "../types"
const MouseEventList: string[] = ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseenter', 'mouseout', 'mouseenter']; export default class LoggerAndError { public opt: Options private version: string; public constructor(options: Options) { this.opt = Object.assign(this.init(), options) this.installEvent() }
private init(): DefaultOptions { this.version = LoggerAndErrorConfig.version
window.history['pushState'] = this.createHistoryEvent('pushState') window.history['replaceState'] = this.createHistoryEvent('replaceState')
return <DefaultOptions>{ sdkVersion: this.version, historyRouter: false, hashRouter: false, jsError: false, domLogger: false, } }
private createHistoryEvent = <T extends keyof History>(type: T): () => any => { const original = history[type]
return function(this: any) { var e = new Event(type) window.dispatchEvent(e) const res = original.apply(this, arguments) return res } }
private installEvent() { if (this.opt.historyRouter) { this.captureEvents(['pushState', 'replaceState', 'popstate'], 'history-pv') } if (this.opt.hashRouter) { this.captureEvents(['hashchange'], 'hash-pv') } if (this.opt.domLogger) { this.domEvents() } if (this.opt.jsError) { this.jsError() } }
private captureEvents<T>(MouseEventList: string[], targetKey: string, data?: T) { MouseEventList.forEach(event => { window.addEventListener(event, () => { this.sendLoggerAndError({event, targetKey, data}) }) }) }
private domEvents() { MouseEventList.forEach(event => { window.addEventListener(event, (e) => { const target = e.target as HTMLElement const targetKey = target.getAttribute('target-key') if (targetKey) { this.sendLoggerAndError({ targetKey, event, }) } }) }) }
public setUuid<T extends DefaultOptions['uuid']>(uuid: T) { this.opt.uuid = uuid }
public seExtra<T extends DefaultOptions['extra']>(extra: T) { this.opt.extra = extra }
private jsError() { this.errorEvent() this.promiseReject() }
private errorEvent() { window.addEventListener('error', (event) => { this.sendLoggerAndError({ targetKey: 'message', event: 'error', message: event.message, detail: event }) }) }
private promiseReject() { window.addEventListener('unhandledrejection', (event) => { event.promise.catch(error => { this.sendLoggerAndError({ targetKey: 'reject', event: 'promise', message: error }) }) }) }
public sendLoggerAndError<T extends PostLoggerAndErrorData>(data: T) { this.postData(data) }
private postData<T>(data: T) { const params = Object.assign(this.opt, data, {time: new Date().getTime}) let headers = { type: 'application/x-www-form-urlencoded' } let blob = new Blob([JSON.stringify(params)], headers)
navigator.sendBeacon(this.opt.postUrl, blob) } }
|