溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何進(jìn)行數(shù)據(jù)采集和數(shù)據(jù)上報(bào)

發(fā)布時(shí)間:2021-10-20 10:01:26 來(lái)源:億速云 閱讀:178 作者:iii 欄目:web開(kāi)發(fā)

本篇內(nèi)容介紹了“如何進(jìn)行數(shù)據(jù)采集和數(shù)據(jù)上報(bào)”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

數(shù)據(jù)采集

性能數(shù)據(jù)采集

性能數(shù)據(jù)采集需要使用 window.performance  API

https://developer.mozilla.org/zh-CN/docs/Web/API/Performance 

Performance 接口可以獲取到當(dāng)前頁(yè)面中與性能相關(guān)的信息,它是 High Resolution Time API 的一部分,同時(shí)也融合了 Performance Timeline API、Navigation Timing API、 User Timing API 和 Resource Timing API。

從 MDN 的文檔可以看出,window.performance.timing 包含了頁(yè)面加載各個(gè)階段的起始及結(jié)束時(shí)間。

如何進(jìn)行數(shù)據(jù)采集和數(shù)據(jù)上報(bào)

這些屬性需要結(jié)合下圖一起看,更好理解:

如何進(jìn)行數(shù)據(jù)采集和數(shù)據(jù)上報(bào)

在這里插入圖片描述

為了方便大家理解 timing 各個(gè)屬性的意義,我在知乎找到一位網(wǎng)友對(duì)于 timing 寫(xiě)的簡(jiǎn)介,在此轉(zhuǎn)載一下。

timing: {          // 同一個(gè)瀏覽器上一個(gè)頁(yè)面卸載(unload)結(jié)束時(shí)的時(shí)間戳。如果沒(méi)有上一個(gè)頁(yè)面,這個(gè)值會(huì)和fetchStart相同。   navigationStart: 1543806782096,   // 上一個(gè)頁(yè)面unload事件拋出時(shí)的時(shí)間戳。如果沒(méi)有上一個(gè)頁(yè)面,這個(gè)值會(huì)返回0。  unloadEventStart: 1543806782523,   // 和 unloadEventStart 相對(duì)應(yīng),unload事件處理完成時(shí)的時(shí)間戳。如果沒(méi)有上一個(gè)頁(yè)面,這個(gè)值會(huì)返回0。   unloadEventEnd: 1543806782523,   // 第一個(gè)HTTP重定向開(kāi)始時(shí)的時(shí)間戳。如果沒(méi)有重定向,或者重定向中的一個(gè)不同源,這個(gè)值會(huì)返回0。   redirectStart: 0,   // 最后一個(gè)HTTP重定向完成時(shí)(也就是說(shuō)是HTTP響應(yīng)的最后一個(gè)比特直接被收到的時(shí)間)的時(shí)間戳。   // 如果沒(méi)有重定向,或者重定向中的一個(gè)不同源,這個(gè)值會(huì)返回0.    redirectEnd: 0,   // 瀏覽器準(zhǔn)備好使用HTTP請(qǐng)求來(lái)獲取(fetch)文檔的時(shí)間戳。這個(gè)時(shí)間點(diǎn)會(huì)在檢查任何應(yīng)用緩存之前。  fetchStart: 1543806782096,   // DNS 域名查詢開(kāi)始的UNIX時(shí)間戳。          //如果使用了持續(xù)連接(persistent connection),或者這個(gè)信息存儲(chǔ)到了緩存或者本地資源上,這個(gè)值將和fetchStart一致。   domainLookupStart: 1543806782096,   // DNS 域名查詢完成的時(shí)間.   //如果使用了本地緩存(即無(wú) DNS 查詢)或持久連接,則與 fetchStart 值相等   domainLookupEnd: 1543806782096,   // HTTP(TCP) 域名查詢結(jié)束的時(shí)間戳。          //如果使用了持續(xù)連接(persistent connection),或者這個(gè)信息存儲(chǔ)到了緩存或者本地資源上,這個(gè)值將和 fetchStart一致。   connectStart: 1543806782099,   // HTTP(TCP) 返回瀏覽器與服務(wù)器之間的連接建立時(shí)的時(shí)間戳。          // 如果建立的是持久連接,則返回值等同于fetchStart屬性的值。連接建立指的是所有握手和認(rèn)證過(guò)程全部結(jié)束。   connectEnd: 1543806782227,   // HTTPS 返回瀏覽器與服務(wù)器開(kāi)始安全鏈接的握手時(shí)的時(shí)間戳。如果當(dāng)前網(wǎng)頁(yè)不要求安全連接,則返回0。   secureConnectionStart: 1543806782162,   // 返回瀏覽器向服務(wù)器發(fā)出HTTP請(qǐng)求時(shí)(或開(kāi)始讀取本地緩存時(shí))的時(shí)間戳。   requestStart: 1543806782241,   // 返回瀏覽器從服務(wù)器收到(或從本地緩存讀?。┑谝粋€(gè)字節(jié)時(shí)的時(shí)間戳。          //如果傳輸層在開(kāi)始請(qǐng)求之后失敗并且連接被重開(kāi),該屬性將會(huì)被數(shù)制成新的請(qǐng)求的相對(duì)應(yīng)的發(fā)起時(shí)間。   responseStart: 1543806782516,   // 返回瀏覽器從服務(wù)器收到(或從本地緩存讀取,或從本地資源讀?。┳詈笠粋€(gè)字節(jié)時(shí)          //(如果在此之前HTTP連接已經(jīng)關(guān)閉,則返回關(guān)閉時(shí))的時(shí)間戳。   responseEnd: 1543806782537,   // 當(dāng)前網(wǎng)頁(yè)DOM結(jié)構(gòu)開(kāi)始解析時(shí)(即Document.readyState屬性變?yōu)椤發(fā)oading”、相應(yīng)的 readystatechange事件觸發(fā)時(shí))的時(shí)間戳。   domLoading: 1543806782573,   // 當(dāng)前網(wǎng)頁(yè)DOM結(jié)構(gòu)結(jié)束解析、開(kāi)始加載內(nèi)嵌資源時(shí)(即Document.readyState屬性變?yōu)椤癷nteractive”、相應(yīng)的readystatechange事件觸發(fā)時(shí))的時(shí)間戳。   domInteractive: 1543806783203,   // 當(dāng)解析器發(fā)送DOMContentLoaded 事件,即所有需要被執(zhí)行的腳本已經(jīng)被解析時(shí)的時(shí)間戳。   domContentLoadedEventStart: 1543806783203,   // 當(dāng)所有需要立即執(zhí)行的腳本已經(jīng)被執(zhí)行(不論執(zhí)行順序)時(shí)的時(shí)間戳。   domContentLoadedEventEnd: 1543806783216,   // 當(dāng)前文檔解析完成,即Document.readyState 變?yōu)?nbsp;'complete'且相對(duì)應(yīng)的readystatechange 被觸發(fā)時(shí)的時(shí)間戳   domComplete: 1543806783796,   // load事件被發(fā)送時(shí)的時(shí)間戳。如果這個(gè)事件還未被發(fā)送,它的值將會(huì)是0。   loadEventStart: 1543806783796,   // 當(dāng)load事件結(jié)束,即加載事件完成時(shí)的時(shí)間戳。如果這個(gè)事件還未被發(fā)送,或者尚未完成,它的值將會(huì)是0.   loadEventEnd: 1543806783802  }

通過(guò)以上數(shù)據(jù),我們可以得到幾個(gè)有用的時(shí)間

// 重定向耗時(shí)  redirect: timing.redirectEnd - timing.redirectStart,  // DOM 渲染耗時(shí) dom: timing.domComplete - timing.domLoading,  // 頁(yè)面加載耗時(shí)  load: timing.loadEventEnd - timing.navigationStart,  // 頁(yè)面卸載耗時(shí)  unload: timing.unloadEventEnd - timing.unloadEventStart,  // 請(qǐng)求耗時(shí)  request: timing.responseEnd - timing.requestStart,  // 獲取性能信息時(shí)當(dāng)前時(shí)間  time: new Date().getTime(),

還有一個(gè)比較重要的時(shí)間就是白屏?xí)r間,它指從輸入網(wǎng)址,到頁(yè)面開(kāi)始顯示內(nèi)容的時(shí)間。

將以下腳本放在 </head> 前面就能獲取白屏?xí)r間。

<script>      whiteScreen = new Date() - performance.timing.navigationStart      // 通過(guò) domLoading 和 navigationStart 也可以      whiteScreen = performance.timing.domLoading - performance.timing.navigationStart  </script>

通過(guò)這幾個(gè)時(shí)間,就可以得知頁(yè)面首屏加載性能如何了。

另外,通過(guò) window.performance.getEntriesByType('resource') 這個(gè)方法,我們還可以獲取相關(guān)資源(js、css、img...)的加載時(shí)間,它會(huì)返回頁(yè)面當(dāng)前所加載的所有資源。

如何進(jìn)行數(shù)據(jù)采集和數(shù)據(jù)上報(bào)

在這里插入圖片描述

它一般包括以下幾個(gè)類(lèi)型:

  •  sciprt

  •  link

  •  img

  •  css

  •  fetch

  •  other

  •  xmlhttprequest

我們只需用到以下幾個(gè)信息:

// 資源的名稱(chēng)  name: item.name,  // 資源加載耗時(shí)  duration: item.duration.toFixed(2),  // 資源大小  size: item.transferSize,  // 資源所用協(xié)議  protocol: item.nextHopProtocol,

現(xiàn)在,寫(xiě)幾行代碼來(lái)收集這些數(shù)據(jù)。

// 收集性能信息  const getPerformance = () => {      if (!window.performance) return      const timing = window.performance.timing      const performance = {          // 重定向耗時(shí)          redirect: timing.redirectEnd - timing.redirectStart,          // 白屏?xí)r間          whiteScreen: whiteScreen,          // DOM 渲染耗時(shí)          dom: timing.domComplete - timing.domLoading,          // 頁(yè)面加載耗時(shí)          load: timing.loadEventEnd - timing.navigationStart,          // 頁(yè)面卸載耗時(shí)          unload: timing.unloadEventEnd - timing.unloadEventStart,          // 請(qǐng)求耗時(shí)          request: timing.responseEnd - timing.requestStart,          // 獲取性能信息時(shí)當(dāng)前時(shí)間          time: new Date().getTime(),      }      return performance  }  // 獲取資源信息  const getResources = () => {      if (!window.performance) return      const data = window.performance.getEntriesByType('resource')      const resource = {          xmlhttprequest: [],          css: [],          other: [],          script: [],          img: [],          link: [],          fetch: [],          // 獲取資源信息時(shí)當(dāng)前時(shí)間          time: new Date().getTime(),      }     data.forEach(item => {          const arry = resource[item.initiatorType]          arry && arry.push({              // 資源的名稱(chēng)              name: item.name,              // 資源加載耗時(shí)              duration: item.duration.toFixed(2),              // 資源大小              size: item.transferSize,              // 資源所用協(xié)議              protocol: item.nextHopProtocol,          })      })      return resource  }

小結(jié)

通過(guò)對(duì)性能及資源信息的解讀,我們可以判斷出頁(yè)面加載慢有以下幾個(gè)原因:

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2.  資源過(guò)多、過(guò)大

  3.  網(wǎng)速過(guò)慢

  4.  DOM 元素過(guò)多

除了用戶網(wǎng)速過(guò)慢,我們沒(méi)辦法之外,其他兩個(gè)原因都是有辦法解決的,性能優(yōu)化的文章和書(shū)籍網(wǎng)上已經(jīng)有很多了,有興趣可自行查找資料了解。

PS:其實(shí)頁(yè)面加載慢還有其他原因,例如沒(méi)有使用按需加載、沒(méi)有使用 CDN 等等。不過(guò)這里我們強(qiáng)調(diào)的僅通過(guò)對(duì)性能和資源信息的解讀來(lái)獲取原因。

錯(cuò)誤數(shù)據(jù)采集

目前所能捕捉的錯(cuò)誤有三種:

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2.  資源加載錯(cuò)誤,通過(guò) addEventListener('error', callback, true) 在捕獲階段捕捉資源加載失敗錯(cuò)誤。

  3.  js 執(zhí)行錯(cuò)誤,通過(guò) window.onerror 捕捉 js 錯(cuò)誤。

  4.  promise 錯(cuò)誤,通過(guò) addEventListener('unhandledrejection', callback)捕捉 promise 錯(cuò)誤,但是沒(méi)有發(fā)生錯(cuò)誤的行數(shù),列數(shù)等信息,只能手動(dòng)拋出相關(guān)錯(cuò)誤信息。

我們可以建一個(gè)錯(cuò)誤數(shù)組變量 errors 在錯(cuò)誤發(fā)生時(shí),將錯(cuò)誤的相關(guān)信息添加到數(shù)組,然后在某個(gè)階段統(tǒng)一上報(bào),具體如何操作請(qǐng)看下面的代碼:

// 捕獲資源加載失敗錯(cuò)誤 js css img...  addEventListener('error', e => {      const target = e.target     if (target != window) {          monitor.errors.push({              type: target.localName,              url: target.src || target.href,              msg: (target.src || target.href) + ' is load error',              // 錯(cuò)誤發(fā)生的時(shí)間              time: new Date().getTime(),          })      }  }, true)  // 監(jiān)聽(tīng) js 錯(cuò)誤  window.onerror = function(msg, url, row, col, error) {      monitor.errors.push({          type: 'javascript',          row: row,          col: col,          msg: error && error.stack? error.stack : msg,          url: url,          // 錯(cuò)誤發(fā)生的時(shí)間          time: new Date().getTime(),     })  }  // 監(jiān)聽(tīng) promise 錯(cuò)誤 缺點(diǎn)是獲取不到行數(shù)數(shù)據(jù)  addEventListener('unhandledrejection', e => {      monitor.errors.push({          type: 'promise',          msg: (e.reason && e.reason.msg) || e.reason || '',          // 錯(cuò)誤發(fā)生的時(shí)間          time: new Date().getTime(),      })  })

小結(jié)

通過(guò)錯(cuò)誤收集,可以了解到網(wǎng)站發(fā)生錯(cuò)誤的類(lèi)型及數(shù)量,從而做出相應(yīng)的調(diào)整,以減少錯(cuò)誤發(fā)生。完整代碼和 DEMO 會(huì)在文章末尾放出,大家可以復(fù)制代碼(HTML文件)在本地測(cè)試一下。

數(shù)據(jù)上報(bào)

性能數(shù)據(jù)上報(bào)

性能數(shù)據(jù)可以在頁(yè)面加載完之后上報(bào),盡量不要對(duì)頁(yè)面性能造成影響。

window.onload = () => {      // 在瀏覽器空閑時(shí)間獲取性能及資源信息      // https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestIdleCallback      if (window.requestIdleCallback) {          window.requestIdleCallback(() => {              monitor.performance = getPerformance()              monitor.resources = getResources()          })      } else {          setTimeout(() => {              monitor.performance = getPerformance()              monitor.resources = getResources()          }, 0)      }  }

當(dāng)然,你也可以設(shè)一個(gè)定時(shí)器,循環(huán)上報(bào)。不過(guò)每次上報(bào)最好做一下對(duì)比去重再上報(bào),避免同樣的數(shù)據(jù)重復(fù)上報(bào)。

錯(cuò)誤數(shù)據(jù)上報(bào)

我在 DEMO 里提供的代碼,是用一個(gè) errors 數(shù)組收集所有的錯(cuò)誤,再在某一階段統(tǒng)一上報(bào)(延時(shí)上報(bào))。

其實(shí),也可以改成在錯(cuò)誤發(fā)生時(shí)上報(bào)(即時(shí)上報(bào))。這樣可以避免“收集完錯(cuò)誤,但延時(shí)上報(bào)還沒(méi)觸發(fā),用戶卻已經(jīng)關(guān)掉網(wǎng)頁(yè)導(dǎo)致錯(cuò)誤數(shù)據(jù)丟失”的問(wèn)題。

// 監(jiān)聽(tīng) js 錯(cuò)誤  window.onerror = function(msg, url, row, col, error) {      const data = {          type: 'javascript',          row: row,          col: col,          msg: error && error.stack? error.stack : msg,          url: url,          // 錯(cuò)誤發(fā)生的時(shí)間          time: new Date().getTime(),      }         // 即時(shí)上報(bào)      axios.post({ url: 'xxx', data, })  }

經(jīng)網(wǎng)友提醒,可以使用 navigator.sendBeacon() 來(lái)進(jìn)行上報(bào)。

window.addEventListener('unload', logData, false);  function logData() {      navigator.sendBeacon("/log", analyticsData);  }

它的技術(shù)特點(diǎn)是:

使用 sendBeacon() 方法會(huì)使用戶代理(瀏覽器)在有機(jī)會(huì)時(shí)異步地向服務(wù)器發(fā)送數(shù)據(jù),同時(shí)不會(huì)延遲頁(yè)面的卸載或影響下一導(dǎo)航的載入性能。這就解決了提交分析數(shù)據(jù)時(shí)的所有的問(wèn)題:數(shù)據(jù)可靠,傳輸異步并且不會(huì)影響下一頁(yè)面的加載。

擴(kuò)展

SPA

window.performance API 是有缺點(diǎn)的,在 SPA 切換路由時(shí),window.performance.timing 的數(shù)據(jù)不會(huì)更新。所以我們需要另想辦法來(lái)統(tǒng)計(jì)切換路由到加載完成的時(shí)間。拿 Vue 舉例,一個(gè)可行的辦法就是切換路由時(shí),在路由的全局前置守衛(wèi) beforeEach 里獲取開(kāi)始時(shí)間,在組件的 mounted 鉤子里執(zhí)行 vm.$nextTick 函數(shù)來(lái)獲取組件的渲染完畢時(shí)間。

router.beforeEach((to, from, next) => {   store.commit('setPageLoadedStartTime', new Date())  })
mounted() {   this.$nextTick(() => {    this.$store.commit('setPageLoadedTime', new Date() - this.$store.state.pageLoadedStartTime)   })  }

除了性能和錯(cuò)誤監(jiān)控,其實(shí)我們還可以收集更多的信息。

用戶信息收集

navigator

使用 window.navigator 可以收集到用戶的設(shè)備信息,操作系統(tǒng),瀏覽器信息...

UV(Unique visitor)

是指通過(guò)互聯(lián)網(wǎng)瀏覽這個(gè)網(wǎng)頁(yè)的訪客,00:00-24:00 內(nèi)相同的設(shè)備訪問(wèn)只被計(jì)算一次。一天內(nèi)同個(gè)訪客多次訪問(wèn)僅計(jì)算一個(gè) UV。

在用戶訪問(wèn)網(wǎng)站時(shí),可以生成一個(gè)隨機(jī)字符串+時(shí)間日期,保存在本地。在網(wǎng)頁(yè)發(fā)生請(qǐng)求時(shí)(如果超過(guò)當(dāng)天24小時(shí),則重新生成),把這些參數(shù)傳到后端,后端利用這些信息生成 UV 統(tǒng)計(jì)報(bào)告。

PV(Page View)

即頁(yè)面瀏覽量或點(diǎn)擊量,用戶每 1 次對(duì)網(wǎng)站中的每個(gè)網(wǎng)頁(yè)訪問(wèn)均被記錄 1 個(gè)PV。用戶對(duì)同一頁(yè)面的多次訪問(wèn),訪問(wèn)量累計(jì),用以衡量網(wǎng)站用戶訪問(wèn)的網(wǎng)頁(yè)數(shù)量。

頁(yè)面停留時(shí)間

傳統(tǒng)網(wǎng)站

用戶在進(jìn)入 A 頁(yè)面時(shí),通過(guò)后臺(tái)請(qǐng)求把用戶進(jìn)入頁(yè)面的時(shí)間捎上。過(guò)了 10 分鐘,用戶進(jìn)入 B 頁(yè)面,這時(shí)后臺(tái)可以通過(guò)接口捎帶的參數(shù)可以判斷出用戶在 A 頁(yè)面停留了 10 分鐘。

SPA

可以利用 router 來(lái)獲取用戶停留時(shí)間,拿 Vue 舉例,通過(guò) router.beforeEach、destroyed 這兩個(gè)鉤子函數(shù)來(lái)獲取用戶停留該路由組件的時(shí)間。

瀏覽深度

通過(guò) document.documentElement.scrollTop 屬性以及屏幕高度,可以判斷用戶是否瀏覽完網(wǎng)站內(nèi)容。

頁(yè)面跳轉(zhuǎn)來(lái)源

通過(guò) document.referrer 屬性,可以知道用戶是從哪個(gè)網(wǎng)站跳轉(zhuǎn)而來(lái)。

小結(jié)

通過(guò)分析用戶數(shù)據(jù),我們可以了解到用戶的瀏覽習(xí)慣、愛(ài)好等等信息,想想真是恐怖,毫無(wú)隱私可言。

DEMO

<!DOCTYPE html>  <html>  <head>      <meta charset="UTF-8">      <meta name="viewport" content="width=device-width, initial-scale=1.0">      <meta http-equiv="X-UA-Compatible" content="ie=edge">      <script>          function monitorInit() {              const monitor = {                  // 數(shù)據(jù)上傳地址                  url: '',                  // 性能信息                  performance: {},                  // 資源信息                  resources: {},                  // 錯(cuò)誤信息                  errors: [],                  // 用戶信息                  user: {                      // 屏幕寬度                      screen: screen.width,                      // 屏幕高度                      height: screen.height,                      // 瀏覽器平臺(tái)                      platform: navigator.platform,                      // 瀏覽器的用戶代理信息                      userAgent: navigator.userAgent,                      // 瀏覽器用戶界面的語(yǔ)言                      language: navigator.language,                  },                  // 手動(dòng)添加錯(cuò)誤                  addError(error) {                      const obj = {}                      const { type, msg, url, row, col } = error                      if (type) obj.type = type                      if (msg) obj.msg = msg                      if (url) obj.url = url                      if (row) obj.row = row                     if (col) obj.col = col                      obj.time = new Date().getTime()                      monitor.errors.push(obj)                  },                  // 重置 monitor 對(duì)象                  reset() {                     window.performance && window.performance.clearResourceTimings()                      monitor.performance = getPerformance()                      monitor.resources = getResources()                      monitor.errors = []                  },                  // 清空 error 信息                  clearError() {                      monitor.errors = []                  },                  // 上傳監(jiān)控?cái)?shù)據(jù)                  upload() {                      // 自定義上傳                      // axios.post({                      //     url: monitor.url,                     //     data: {                      //         performance,                      //         resources,                      //         errors,                      //         user,                     //     }                      // })                  },                  // 設(shè)置數(shù)據(jù)上傳地址                  setURL(url) {                      monitor.url = url                  },              }              // 獲取性能信息              const getPerformance = () => {                  if (!window.performance) return                  const timing = window.performance.timing                  const performance = {                      // 重定向耗時(shí)                      redirect: timing.redirectEnd - timing.redirectStart,                      // 白屏?xí)r間                      whiteScreen: whiteScreen,                      // DOM 渲染耗時(shí)                      dom: timing.domComplete - timing.domLoading,                      // 頁(yè)面加載耗時(shí)                      load: timing.loadEventEnd - timing.navigationStart,                      // 頁(yè)面卸載耗時(shí)                      unload: timing.unloadEventEnd - timing.unloadEventStart,                      // 請(qǐng)求耗時(shí)                      request: timing.responseEnd - timing.requestStart,                      // 獲取性能信息時(shí)當(dāng)前時(shí)間                      time: new Date().getTime(),                  }                  return performance              }              // 獲取資源信息              const getResources = () => {                  if (!window.performance) return                  const data = window.performance.getEntriesByType('resource')                  const resource = {                      xmlhttprequest: [],                     css: [],                      other: [],                      script: [],                      img: [],                      link: [],                      fetch: [],                      // 獲取資源信息時(shí)當(dāng)前時(shí)間                      time: new Date().getTime(),                  }                  data.forEach(item => {                      const arry = resource[item.initiatorType]                      arry && arry.push({                          // 資源的名稱(chēng)                          name: item.name,                          // 資源加載耗時(shí)                         duration: item.duration.toFixed(2),                          // 資源大小                          size: item.transferSize,                          // 資源所用協(xié)議                          protocol: item.nextHopProtocol,                      })                  })                  return resource              }              window.onload = () => {                  // 在瀏覽器空閑時(shí)間獲取性能及資源信息 https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestIdleCallback                  if (window.requestIdleCallback) {                      window.requestIdleCallback(() => {                          monitor.performance = getPerformance()                          monitor.resources = getResources()                          console.log('頁(yè)面性能信息')                          console.log(monitor.performance)                          console.log('頁(yè)面資源信息')                          console.log(monitor.resources)                      })                  } else {                      setTimeout(() => {                          monitor.performance = getPerformance()                          monitor.resources = getResources()                          console.log('頁(yè)面性能信息')                         console.log(monitor.performance)                          console.log('頁(yè)面資源信息')                          console.log(monitor.resources)                      }, 0)                  }              }              // 捕獲資源加載失敗錯(cuò)誤 js css img...              addEventListener('error', e => {                 const target = e.target                  if (target != window) {                      monitor.errors.push({                          type: target.localName,                          url: target.src || target.href,                          msg: (target.src || target.href) + ' is load error',                          // 錯(cuò)誤發(fā)生的時(shí)間                          time: new Date().getTime(),                      })                      console.log('所有的錯(cuò)誤信息')                      console.log(monitor.errors)                  }              }, true)              // 監(jiān)聽(tīng) js 錯(cuò)誤              window.onerror = function(msg, url, row, col, error) {                  monitor.errors.push({                      type: 'javascript', // 錯(cuò)誤類(lèi)型                      row: row, // 發(fā)生錯(cuò)誤時(shí)的代碼行數(shù)                      col: col, // 發(fā)生錯(cuò)誤時(shí)的代碼列數(shù)                      msg: error && error.stack? error.stack : msg, // 錯(cuò)誤信息                      url: url, // 錯(cuò)誤文件                      time: new Date().getTime(), // 錯(cuò)誤發(fā)生的時(shí)間                  })                  console.log('所有的錯(cuò)誤信息')                  console.log(monitor.errors)              }              // 監(jiān)聽(tīng) promise 錯(cuò)誤 缺點(diǎn)是獲取不到行數(shù)數(shù)據(jù)              addEventListener('unhandledrejection', e => {                  monitor.errors.push({                      type: 'promise',                      msg: (e.reason && e.reason.msg) || e.reason || '',                      // 錯(cuò)誤發(fā)生的時(shí)間                      time: new Date().getTime(),                  })                  console.log('所有的錯(cuò)誤信息')                  console.log(monitor.errors)              })              return monitor          }         const monitor = monitorInit()      </script>      <link rel="stylesheet" href="test.css">      <title>Document</title>  </head>  <body>      <button class="btn1">錯(cuò)誤測(cè)試按鈕1</button>      <button class="btn2">錯(cuò)誤測(cè)試按鈕2</button>      <button class="btn3">錯(cuò)誤測(cè)試按鈕3</button>      <img src="https://avatars3.githubusercontent.com/u/22117876?s=460&v=4" alt="">      <img src="test.png" alt="">  <script src="192.168.10.15/test.js"></script>  <script>  document.querySelector('.btn1').onclick = () => {      setTimeout(() => {          console.log(button)      }, 0)  }  document.querySelector('.btn2').onclick = () => {      new Promise((resolve, reject) => {          reject({              msg: 'test.js promise is error'          })      })  }  document.querySelector('.btn3').onclick = () => {      throw ('這是一個(gè)手動(dòng)扔出的錯(cuò)誤')  }  </script>  </body>  </html>

“如何進(jìn)行數(shù)據(jù)采集和數(shù)據(jù)上報(bào)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI