今天我們回顧這樣的一個線上bug,這個線上bug引起了整個拿去花產(chǎn)品的所有用戶的還款失敗菇篡,用戶在點擊還款按鈕的時候漩符,會提示:“出錯啦,請稍后再試”驱还。
這個bug同樣也導致我們的前端同事淚眼含珠嗜暴,測試同學梨花帶雨。
bug原因是在點擊還款按鈕的時候议蟆,調(diào)用了下面的代碼:
let summary = {}
try {
summary = JSON.parse(payorderSummary);
} catch (e) {
summary = {}
Sentry.errorWithScope({
level: 'fatal',
tag: { msg: '跳轉(zhuǎn)C端支付錯誤' },
err: e
})
}
上面的 Sentry.errorWithScope
函數(shù)的作用闷沥,是將異常上報到sentry服務(wù)器中,不過因為大意咐容,Sentry.errorWithScope
這個函數(shù)的內(nèi)部代碼也會報錯往外拋異常狐赡,最終導致在上報異常的時候發(fā)生異常,影響外層的業(yè)務(wù)邏輯疟丙。
那Sentry. errorWithScope
中是哪一行報了錯呢:
if (tag) Object.keys.map(key => /* 此處省略n行 */)
可以看出 Object.keys
是個方法,而不是數(shù)組鸟雏,所以沒有 map
方法享郊,因此會報錯。
這個bug其實反映了不少的問題:
第一孝鹊,Sentry.errorWithScope
的代碼實現(xiàn)炊琉,是我們開發(fā)拷貝另外一個項目組的同事的,因為其主要的功能是上報日志又活,跟業(yè)務(wù)無關(guān)苔咪,因此這種代碼應(yīng)該獨立出業(yè)務(wù)項目,做成一個npm包來使用柳骄。
第二团赏,上報異常的時候,我們發(fā)現(xiàn)耐薯,需要手動的在catch
中填寫相對應(yīng)的上報代碼舔清,并不是非常的友好丝里,能不能使用自動化的方式,自動的幫助我們添加上報代碼呢体谒?答案是肯定的杯聚,我們可以利用babel
插件來轉(zhuǎn)化我們的代碼,也就是說抒痒,當babel在轉(zhuǎn)化我們的代碼的時候幌绍,如果遇到catch
,就自動的在catch
下面添加Sentry
上報異常的代碼:
try {
const num = JSON.parse("123") // 這行會拋異常
} catch (e) {
Sentry. errorWithScope(e) // 這行是通過babel插件轉(zhuǎn)化代碼時故响,自動添加的
// 你的處理代碼
}
上面的插件已經(jīng)寫出來了傀广,只不過略微變通的一下,可以點擊查看并使用:babel-plugin-catch-log
這個插件會自動的識別出你代碼的catch
語句被去,并且自動的加上一個收集異常的代碼:__elog.push(e)
(紅框部分):
因此主儡,我們在使用Sentry進行日志上報的時候,就不需要在每個try...catch...
中手動的添加捕獲代碼惨缆,只需要統(tǒng)一在某個地方定時監(jiān)控一下__elog
數(shù)組糜值,如果里面有異常,就取出來上報:
setInterval(() => {
const err = __elog.shift()
Sentry. errorWithScope({err})
}, 1000)
總結(jié):通過babel-plugin-catch-log插件坯墨,可以自動收集和處理異常寂汇,減少人工參與,也避免了不必要的bug捣染。