一般我們想要捕獲的異常大概分類:
所以捕獲錯(cuò)誤總結(jié)下來(lái):
// 1、try catch 中的 catch 錯(cuò)誤捕獲
可以在 webpack 打包時(shí)候,使用 AST 方式解析并在 catch 中插入日志上報(bào)代碼
// 2、error 事件
window.addEventListener( 'error', error => {
let data = {} // 此處與上面的 onerror 會(huì)重復(fù)事件
let { colno, lineno, message, filename, error, stack } = error //不一定所有瀏覽器都支持 colno 參數(shù)
let col = colno || (window.event && window.event.errorCharacter) || 0
data.url = url
data.line = line
data.col = col
if (!!stack){
//如果瀏覽器有堆棧信息
//直接使用
data.msg = stack.toString()
}else if (!!arguments.callee){
//嘗試通過(guò)callee拿堆棧信息
let ext = []
let f = arguments.callee.caller, c = 3 //這里只拿三層堆棧信息
while (f && (--c>0)) {
ext.push(f.toString())
if (f === f.caller) {
break //如果有環(huán)
}
f = f.caller
}
ext = ext.join(",") data.msg = ext
}
console.log('3、addEventListener error 捕獲階段>>>異常:', data)
}, true )
// 3、unhandledrejection
window.addEventListener('unhandledrejection', function(e) {
// e.preventDefault();
// 阻止異常向上拋出
console.log('4、promise 異常 unhandledrejection :', e)
})
// 4、errorHandler
Vue.config.errorHandler = function(err, vm, info) {
// vm 為拋出異常的 Vue 實(shí)例
// info 為 Vue 特定的錯(cuò)誤信息,比如錯(cuò)誤所在的生命周期鉤子
let {
message, // 異常信息
name, // 異常名稱
script, // 異常腳本url
line, // 異常行號(hào)
column, // 異常列號(hào)
stack // 異常堆棧信息
} = err
console.log('2、vue errorHandler :>> ', err, vm, info) }
復(fù)制代碼
既然異常已經(jīng)捕獲到了,那我們?cè)趺刺幚砟兀绾紊蠄?bào),需要上報(bào)哪些內(nèi)容?
1、一般日志分類等級(jí)
log、debug、info、warn、error
復(fù)制代碼
2、分場(chǎng)景使用日志上報(bào)類型
log: 記錄流程信息
debug: 記錄調(diào)試關(guān)鍵信息
info: 記錄業(yè)務(wù)功能點(diǎn),是否觸發(fā)成功或者失敗
warn: 頁(yè)面警告信息
error: 頁(yè)面錯(cuò)誤或者業(yè)務(wù)異常信息
復(fù)制代碼
3、日志上報(bào)信息附帶信息
1、用戶id、session、用戶名
2、當(dāng)前錯(cuò)誤信息
3、可以用來(lái)重現(xiàn)、推斷當(dāng)前錯(cuò)誤發(fā)生的信息
4、上報(bào)時(shí)間
5、日志等級(jí)等等
復(fù)制代碼
4、日志上報(bào)策略
1、達(dá)量上傳,設(shè)置一個(gè)緩存數(shù)量,到達(dá)即上報(bào)。因?yàn)椴荒芤话l(fā)生錯(cuò)誤就要上報(bào),會(huì)影響用戶的網(wǎng)絡(luò)。 2、日志埋點(diǎn)處各自有各自的上報(bào)等級(jí)。 需要有一個(gè)總配置地方,配置當(dāng)前的上報(bào)等級(jí) 這樣各處埋點(diǎn)可以判斷當(dāng)前需要上報(bào)的日志等級(jí),等級(jí)小于設(shè)置值的話,不可上報(bào)。
3、本地緩存若暫存過(guò)多,需要?jiǎng)h除前面的數(shù)據(jù)
4、抽樣上報(bào)
5、設(shè)置緩存有效時(shí)間 等等
復(fù)制代碼
上報(bào)之后,接下來(lái)的步驟就是在服務(wù)端收集分析歸類展示,基于badjs我們搭建一整套日志解析系統(tǒng)
badjs 服務(wù)安裝
1、前期預(yù)備工作
為了快速搭建,我們統(tǒng)一使用 docker 安裝
備注:windows 環(huán)境使用 docker,需要安裝 Docker Desktop
2、項(xiàng)目安裝
github 克隆項(xiàng)目到本地
git clone https://github.com/BetterJS/badjs-installer
復(fù)制代碼
子項(xiàng)目下載以及依賴安裝
// 克隆下載 badjs-acceptor、badjs-mq、badjs-storage、badjs-web 項(xiàng)目
yarn clone
// 安裝各項(xiàng)目的依賴
yarn install
復(fù)制代碼
3、修改配置項(xiàng)
4、啟動(dòng)項(xiàng)目
yarn start
查看 badjs-web 的啟動(dòng)端口,訪問(wèn) http://localhost:port 可以看到日志后臺(tái)管理服務(wù)頁(yè)面
1、badjs-acceptor 接受客戶端上報(bào)的日志
badjs-acceptor 收到日志上報(bào),發(fā)送到 badjs-mq
package.json 中配置 dispatcher 分發(fā)屬性, 表示向 badjs-mq 請(qǐng)求的信息:如請(qǐng)求端口(10001)
復(fù)制代碼
2、badjs-mq 消息隊(duì)列,保證消息有序穩(wěn)定被接受
badjs-mq 接收 badjs-acceptor 的請(qǐng)求
package.json 中配置 acceptor 接收屬性, 表示用來(lái)接收信息所配置的接口信息:如端口(10001)。
badjs-mq 再分發(fā)到 badjs-storage
package.json 中配置 dispatcher 分發(fā)屬性, 表示向 badjs-storage 請(qǐng)求的信息:如端口(10000)
復(fù)制代碼
3、badjs-storage 存儲(chǔ)模塊
badjs-storage: 接收來(lái)自 badjs-mq 的請(qǐng)求,再寫入到 mongodb
package.json 中配置 acceptor 接收屬性, 表示用來(lái)接收信息所配置的接口信息:如端口(10000)
復(fù)制代碼
4、badjs-web 日志后臺(tái)管理系統(tǒng)
badjs-web 查詢?nèi)罩敬鎯?chǔ),分類查看日志信息,解析日志內(nèi)容
package.json 中配置 acceptor 接收屬性, badjs-acceptor 可請(qǐng)求的端口
package.json 中配置 storage 存儲(chǔ)屬性, 查詢 mongodb 數(shù)據(jù)
package.json 中配置 mysql 數(shù)據(jù)庫(kù)屬性, 查詢 mysql 數(shù)據(jù)等等
復(fù)制代碼
badjs-report 重寫了 window.onerror 來(lái)捕獲錯(cuò)誤
1、安裝
yarn add badjs-report
復(fù)制代碼
2、初始化
import badjs from 'badjs-report'
badjs.init({
// 必須配置項(xiàng)
id: 1 // 此 id 為 badjs-web 啟動(dòng)后,申請(qǐng)的項(xiàng)目的 id,上報(bào)的日志根據(jù)該 id 區(qū)分業(yè)務(wù)模塊
url: 'http://badjs-acceptor啟動(dòng)后的地址', // 日志上報(bào)到的地方
// 選擇配置
uin: 123, // 指定用戶的 id (該插件默認(rèn)讀取 qq uin)
delay: 1000, // 延遲多少毫秒,合并緩沖區(qū)中的上報(bào)(默認(rèn) 1000)
ignore: [/Script error/i], // 忽略某個(gè)錯(cuò)誤,遇到該錯(cuò)誤不進(jìn)行上報(bào)
random: 1, // 抽樣上報(bào), 值可以設(shè)置 0-1 之間。1 表示 100% 上報(bào)(默認(rèn)為 1)
repeat: 5, // 重復(fù)上報(bào)次數(shù)(對(duì)于同一個(gè)錯(cuò)誤超過(guò)多少次不上報(bào);避免單個(gè)用戶同一錯(cuò)誤上報(bào)過(guò)多的情況)
onReport: function(id, errObj) {}, // 上報(bào)日志之后的回調(diào)。id 為上報(bào)的 id,errorObj 為上報(bào)的錯(cuò)誤對(duì)象
submit: function(url) {}, // 覆蓋原來(lái)的上報(bào)方式,原來(lái)是使用 new Image() 形式上報(bào),可以修改成自己想要上報(bào)的方式,比如使用 post 內(nèi)部構(gòu)造好的 url
ext: {}, // 擴(kuò)展屬性,后端做擴(kuò)展處理屬性。設(shè)置了 ext 的值,就會(huì)作為 'ext=設(shè)置的值' 合并到構(gòu)造好的上報(bào) url 中
offlineLog: false, // 是否開(kāi)啟離線日志(默認(rèn)不開(kāi)啟為 false)
offlineLogExp: 5 // 離線有效時(shí)間(默認(rèn)最近5天)
})
復(fù)制代碼
3、手動(dòng)上報(bào)
a、badjs.report('error msg')
b、badjs.report({
msg: 'error msg', // 需要上報(bào)的錯(cuò)誤信息
target: 'error.js', // 發(fā)生錯(cuò)誤的 js 文件
rowNum: 1, // 發(fā)生錯(cuò)誤的行數(shù)
colNum: 2 // 發(fā)生錯(cuò)誤的列數(shù)
})
復(fù)制代碼
4、延遲上報(bào)
暫存
badjs.push('error msg')
badjs.push({
msg: 'error msg', // 需要上報(bào)的錯(cuò)誤信息
target: 'error.js', // 發(fā)生錯(cuò)誤的 js 文件
rowNum: 1, // 發(fā)生錯(cuò)誤的行數(shù)
colNum: 2 // 發(fā)生錯(cuò)誤的列數(shù)
})
復(fù)制代碼
立即上報(bào)
badjs.report({
msg: 'error msg', // 需要上報(bào)的錯(cuò)誤信息
target: 'error.js', // 發(fā)生錯(cuò)誤的 js 文件
rowNum: 1, // 發(fā)生錯(cuò)誤的行數(shù)
colNum: 2 // 發(fā)生錯(cuò)誤的列數(shù)
})
復(fù)制代碼
5、上報(bào)離線日志
badjs.reportOfflineLog()
復(fù)制代碼
眾所周知,水經(jīng)注可以提供全國(guó)7137GB海量谷歌地球離線影像數(shù)據(jù),該數(shù)據(jù)存儲(chǔ)在一塊8TB硬盤中。為了方便大家構(gòu)建離線三維地球,于是將全國(guó)高程數(shù)據(jù)和全國(guó)地名數(shù)據(jù)整合存儲(chǔ)在一起,但由于8T硬盤可用空間已不足以存儲(chǔ)所有數(shù)據(jù),因此將8TB移動(dòng)硬盤升級(jí)到了10TB移動(dòng)硬盤。為了便于區(qū)分,我們將這塊10TB數(shù)據(jù)硬盤命名為"水經(jīng)注全國(guó)離線地圖3.0",下面我們將對(duì)硬盤中的離線地圖數(shù)據(jù)作一個(gè)簡(jiǎn)要說(shuō)明。
希捷10TB硬盤
最開(kāi)始,在一塊8TB移動(dòng)硬盤中,水經(jīng)注全國(guó)離線地圖數(shù)據(jù)只存儲(chǔ)了全國(guó)7137GB谷歌衛(wèi)星影像,我們姑且把它稱為"水經(jīng)注全國(guó)離線地圖1.0"。當(dāng)時(shí),由于還有剩余空間,還順便存儲(chǔ)了要交付給客戶的韓國(guó)數(shù)據(jù),如下圖所示。
水經(jīng)注全國(guó)離線地圖1.0
為了滿足用戶對(duì)構(gòu)建離線三維系統(tǒng)的需求,后來(lái)在8TB硬盤中新增了全國(guó)離線DEM數(shù)據(jù),這里可以算作是"水經(jīng)注全國(guó)離線地圖2.0",如下圖所示。
水經(jīng)注全國(guó)離線地圖2.0
鑒于有的用戶不只是需要衛(wèi)星影像和高程數(shù)據(jù),特將全國(guó)地名標(biāo)簽數(shù)據(jù)也整合到了一起,由于8TB硬盤不足以存儲(chǔ),于是將硬盤升級(jí)到10TB,即為"水經(jīng)注全國(guó)離線地圖3.0",如下圖所示。
水經(jīng)注全國(guó)離線地圖3.0
水經(jīng)注全國(guó)離線地圖數(shù)據(jù)的每一次更新內(nèi)容,將會(huì)記錄在附帶的"更新日志"文件中,如下圖所示。
水經(jīng)注全國(guó)離線地圖更新日志
全國(guó)離線谷歌衛(wèi)星地圖數(shù)據(jù)大小為7.01TB,包含1-19級(jí),其中第19級(jí)分辨率為0.6米。該數(shù)據(jù)一共包含5834個(gè)文件,即共2917個(gè)金字塔文件塊,如下圖所示。
全國(guó)離線谷歌衛(wèi)星地圖文件
全國(guó)離線谷歌衛(wèi)星地圖數(shù)據(jù)包括中國(guó)范圍所有海域和島嶼,接圖表如下圖所示。
全國(guó)谷歌衛(wèi)星離線地圖接圖表
全國(guó)離線地名標(biāo)簽數(shù)據(jù)一共259GB,包含1-19級(jí),其中第19級(jí)地名路網(wǎng)相當(dāng)于1:2000比例尺。該數(shù)據(jù)一共包含4626個(gè)文件,即共2313個(gè)金字塔文件塊,如下圖所示。
全國(guó)離線地名標(biāo)簽文件
按理說(shuō),地名標(biāo)簽的個(gè)數(shù)應(yīng)該與衛(wèi)星地圖數(shù)據(jù)的個(gè)數(shù)是完全相同的,但由于在海洋區(qū)域無(wú)任何地名標(biāo)注,因此海洋區(qū)域只下載了有島嶼的區(qū)域,這就是文件總數(shù)比衛(wèi)星地圖文件少的原因,這一點(diǎn)從接圖表就可以看出來(lái),如下圖所示。
全國(guó)離線地名標(biāo)簽接圖表
全國(guó)高程DEM一共33.7GB,包含6到15級(jí),由于數(shù)據(jù)源來(lái)自谷歌地球,因此精度與谷歌地球的高程數(shù)據(jù)完全一致。該數(shù)據(jù)一花包含70個(gè)文件,即35個(gè)金字塔分塊文件,如下圖所示。
全國(guó)離線高程DEM文件
由于高程數(shù)據(jù)是從第6級(jí)開(kāi)始下載,金字塔文件塊數(shù)相對(duì)較少,因此提供的高程DEM數(shù)據(jù)范圍為矩形范圍,完全包含了整個(gè)中國(guó)疆域范圍,如下圖所示。
全國(guó)離線高程DEM接圖表
以上就是關(guān)于水經(jīng)注全國(guó)離線地圖的全部說(shuō)明,主要包括了全國(guó)離線衛(wèi)星地圖、全國(guó)離線地名標(biāo)簽和全國(guó)離線高程DEM等相關(guān)說(shuō)明。