這是我參與8月更文挑戰的第4天,活動詳情查看:8月更文挑戰前端
上一篇講了搭建前端監控系統的資源監控,由於本系列文章主要是講關於前端收集數據的SDK的實現,這一篇來說接口監控,對接口的監控主要是對接口的性能接口。ios
接口的性能監控在系統上咱們能夠在後端進行統計,可是在瀏覽器上發送請求時,可能會出現跨域問題,chrom也有本身的請求隊列,並行請求機制。客戶端可能會受到多種因素的影響,有時候可能會產生同一接口在不一樣客戶端的表現不同,因此在前端統計更能準確的得出接口在當前客戶端的性能或出現的問題。ajax
let xhr = new XMLHttpRequest();
xhr.open('GET', '/url', true);
xhr.send();
複製代碼
獲取xhr的請求狀態, 有以下鉤子函數json
xhr.onload
xhr.onloadend
xhr.onerror
xhr.ontimeout
xhr其餘方法axios
設置超時事件 xhr.timeout = number
設置爲0則表示前端永不超時後端
設置指望的返回數據,chrom會對不一樣的reopenseType進行不一樣的處理跨域
xhr.responseType = 'json';
promise
設置請求頭 xhr.setRequestHeader('Content-type', 'application/json');
瀏覽器
摘自MDN:markdown
Fetch API 提供了一個 JavaScript 接口,用於訪問和操縱 HTTP 管道的一些具體部分,例如請求和響應。它還提供了一個全局
fetch()
方法,該方法提供了一種簡單,合理的方式來跨網絡異步獲取資源。
fetch返回的是promise, fetch相較於XMLHttpRequest有不少不一樣區別,在MDN上有詳細的介紹。fetch
咱們對資源須要進行上報的數據以下:
// xhr hook
let xhr = window.XMLHttpRequest
if (xhr._myxhr_flag === true) {
return void 0
}
xhr._myxhr_flag = true
let _originOpen = xhr.prototype.open
xhr.prototype.open = function (method, url, async, user, password) {
// TODO myxhr url check
this._myxhr_xhr_info = {
url: url,
method: method,
status: null
}
return _originOpen.apply(this, arguments)
}
let _originSend = xhr.prototype.send
xhr.prototype.send = function (value) {
let _self = this
this._myxhr_start_time = Date.now()
let ajaxEnd = event => () => {
if (_self.response) {
let responseSize = null
switch (_self.responseType) {
case 'json':
responseSize = JSON && JSON.stringify(_this.response).length
break
case 'blob':
case 'moz-blob':
responseSize = _self.response.size
break
case 'arraybuffer':
responseSize = _self.response.byteLength
case 'document':
responseSize =
_self.response.documentElement &&
_self.response.documentElement.innerHTML &&
_self.response.documentElement.innerHTML.length + 28
break
default:
responseSize = _self.response.length
}
_self._myxhr_xhr_info.event = event
_self._myxhr_xhr_info.status = _self.status
_self._myxhr_xhr_info.success =
(_self.status >= 200 && _self.status <= 206) || _self.status === 304
_self._myxhr_xhr_info.duration = Date.now() - _self._myxhr_start_time
_self._myxhr_xhr_info.responseSize = responseSize
_self._myxhr_xhr_info.requestSize = value ? value.length : 0
_self._myxhr_xhr_info.type = 'xhr'
cb(this._myxhr_xhr_info)
}
}
// TODO myxhr url check
this.addEventListener('load', ajaxEnd('load'), false)
this.addEventListener('error', ajaxEnd('error'), false)
this.addEventListener('abort', ajaxEnd('abort'), false)
return _originSend.apply(this, arguments)
}
複製代碼
重寫fetch,添加了攔截函數
// fetch hook
if (window.fetch) {
let _origin_fetch = window.fetch
window.fetch = function () {
let startTime = Date.now()
let args = [].slice.call(arguments)
let fetchInput = args[0]
let method = 'GET'
let url
if (typeof fetchInput === 'string') {
url = fetchInput
} else if ('Request' in window && fetchInput instanceof window.Request) {
url = fetchInput.url
if (fetchInput.method) {
method = fetchInput.method
}
} else {
url = '' + fetchInput
}
if (args[1] && args[1].method) {
method = args[1].method
}
// TODO eagle check
let fetchData = {
method: method,
url: url,
status: null
}
return _origin_fetch.apply(this, args).then(function (response) {
fetchData.status = response.status
fetchData.type = 'fetch'
fetchData.duration = Date.now() - startTime
cb(fetchData)
return response
})
}
}
複製代碼