UNPKG

shatter_monitor

Version:
170 lines (151 loc) 5.67 kB
import { InitOptions } from '../types/index' import { obj2query } from 'utils' import { catchXhr, catchFetch } from './catchRequest' import { SendType } from './types/sendType' import { ERRORTYPES, ERRORNAMETYPES } from '../common/errorType' import { logMethods } from '../common/logMethods' import { BindStaticEvent } from './eventHandle' import Hooks from './hooks' function hasSendBeacon() { return window.navigator && !!window.navigator.sendBeacon } function getHttpType(url) { const first = url.substr && url.substr(0, 5) if (!first) { return 'unknown' } else if (first === 'https') { return 'https' } else if (first === 'http:') { return 'http' } else { return 'other' } } const sendImgLog = function(url) { new Image().src = url; } const sendBeacon = function(params, type='formData') { if (type !== 'formData') return const formData = new FormData() for (const item in params) { if (item === 'dsn') continue let content = params[item] if (typeof content === 'object') { content = JSON.stringify(content) } formData.append(item, content) } window.navigator.sendBeacon(params.dsn, formData) } class ErrorForShatter { private options: InitOptions private sendType: logMethods = logMethods['img'] private hooks constructor(options: InitOptions){ this.options = options this._init() } _init() { const op = this.options const { blockConsole, blockPromise, blockError, blockSource, blockXhr, blockFetch, blockTry, blockHttpRequest, onlyHttpRequest } = op this.hooks = new Hooks(op) if (hasSendBeacon() && !op.onlyImg) { this.sendType = logMethods['beacon'] } if (!onlyHttpRequest) { BindStaticEvent(this, { blockConsole, blockPromise, blockError, blockSource, blockTry }) } if (!blockHttpRequest) { if (!blockXhr) { catchXhr((event: any, args: IArguments, openArgs: IArguments, openTime: number) => { const target = event.currentTarget const url = target.responseURL || openArgs[1] const fetchTimeline = new Date().getTime() - openTime this.report({ name: ERRORNAMETYPES['ajaxError'], url: url, type: ERRORTYPES['FETCH_ERROR'], fetchTimeline, request: { method: openArgs[0], httpType: getHttpType(url), data: (args && args[0]) || '' }, response: { status: target.status, data: target.statusText } }) }) } if (!blockFetch) { catchFetch((res: Response, args: IArguments, openTime: number) => { res.text().then(text => { const url = res.url || args[0] const fetchTimeline = new Date().getTime() - openTime this.report({ name: ERRORNAMETYPES['fetchError'], url: url, msg: res.statusText, type: ERRORTYPES['FETCH_ERROR'], fetchTimeline, request: { httpType: getHttpType(url), method: args[1].method, data: args[1].body || '' }, response: { status: res.status, data: text || res.statusText } }) }) }, (error: string, args: IArguments, openTime: number) => { const httpType = getHttpType(args[0]) const fetchTimeline = new Date().getTime() - openTime this.report({ name: ERRORNAMETYPES['fetchError'], msg: error, url: args[0], fetchTimeline, type: ERRORTYPES['FETCH_ERROR'], request: { httpType: httpType, data: args[1].body, method: args[1].method } }) }) } } } report(params: SendType) { const dsn = params.dsn || this.options.dsn const { appkey } = this.options Object.assign(params, { _t: new Date().getTime(), appkey }) const pass = this.hooks.beforeSendData(params) if (!pass) return false const query = obj2query(params) if (this.options.debug) { console.log(`${this.sendType} log to : ${dsn}?${query}`) return } if (this.sendType === 'img') { sendImgLog(`${dsn}?${query}`) } else if (this.sendType === 'beacon') { sendBeacon(Object.assign(params, { dsn })) } } } export { ErrorForShatter, sendBeacon, sendImgLog }