錯誤碼的設計使用

2020-08-14 01:04:38

一、前言

承接上一篇的日誌系統,有了日誌系統爲什麼還要設計錯誤碼系統呢,單純的日誌系統,再單應用的時候看日誌解決問題還是可以勝任的,而出錯也一般都是自身設定,資源超限諸如此類的,而企業級商用的系統,往往都是若幹係統協調呼叫,其中任何一個系統出了問題,都有可能導致某個服務或者功能不可用,再通過呼叫順序依次排查日誌,不僅費時費力,而且由於相互依賴呼叫很難定位,那麼日誌系統在這時候就顯得有點促襟見肘,錯誤碼這個設計思想就孕育而生。

錯誤碼使用場景

  1. 通過錯誤碼設定監控大盤。
  2. 通過日誌進行問題排查,快速定位問題。
  3. 後端服務之間錯誤碼傳遞。
  4. 前端展示的錯誤提示/OpenAPI。

各個系統間面向日誌錯誤碼標準和一個面向外部傳遞的錯誤碼應該建立一個統一的標準。

PS:本文部分引自阿裡巴巴《Java 開發手冊》,下稱《手冊》。

二 什麼是錯誤碼

好的錯誤碼必須快速知曉錯誤來源而且易於記憶和對比。

好的錯誤碼必須能夠脫離文件和系統平臺達到線下輕量溝通的目的(這個要求比較高)。

錯誤碼的制定原則:快速溯源、簡單易記、溝通標準化。

說明:錯誤碼想得過於完美和複雜,就像康熙字典中的生僻字一樣,用詞似乎精準,但是字典不容易隨身攜帶並且簡單易懂。

正例:錯誤碼回答的問題是誰的錯?錯在哪?

1)錯誤碼必須能夠快速知曉錯誤來源,可快速判斷是誰的問題。

2)錯誤碼易於記憶和比對(程式碼中容易 equals)。

3)錯誤碼能夠脫離文件和系統平臺達到線下輕量化地自由溝通的目的。

三 錯誤碼規範

錯誤碼定義要有字母也要有數位

  1. 純數位錯誤碼

錯誤碼即人性,感性認知+口口相傳,使用純數位來進行錯誤碼編排不利於感性記憶和分類。

說明:數位是一個整體,每位數位的地位和含義是相同的。

反例:一個五位數位 12345,第1位是錯誤等級,第 2 位是錯誤來源,345 是編號,人的大腦不會主動地分辨每位數位的不同含義。

《手冊》說明了純數位錯誤碼存在的問題。

  1. 純字母錯誤碼

那麼純字母錯誤碼不香嗎?有兩個問題:

對於使用漢語的我們用英語去準確描述一個錯誤有時是比較困難的。

純英文字母的錯誤碼不利於排序。

錯誤碼儘量有利於不同文化背景的開發者進行交流與程式碼共同作業。

說明:英文單詞形式的錯誤碼不利於非英語母語國家(如阿拉伯語、希伯來語、俄羅斯語等)之間的開發者互相共同作業。

3. 基於以上兩點
其實實際使用場景中比較推薦的是純數位+文件的方式,用頭幾位作爲系統標識,中間幾位爲系統的模組標識,最後幾位爲實際錯誤碼,這樣便於維護擴充套件,區分系統的時候查詢文件就可以可以快速確認。
例如:10 001 0001
10訂單系統 001數據庫連線模組 0001數據庫連線超時

快速溯源 | 簡單易記 | 溝通標準化

什麼是快速溯源?就是一眼看上去就知道哪裏出了什麼問題。

李雷負責 A 服務,韓梅梅負責 B 服務。韓梅梅發現服務 B 出現了一個錯誤碼,韓梅梅能夠快速定位這是服務 A 的內部業務異常造成的問題,這個時候韓梅梅就可以拿着錯誤碼找到李雷說,「hi,Li Lei,How old are you。(李雷,怎麼老是你)」。李雷拿過來錯誤碼一看,內心萬馬奔騰,一下就能知道這是上遊 Polly 負責的應用阿爾法出了錯。

四 面向日誌的錯誤碼

輸出到日誌的錯誤碼有兩個用途:

用來快速溯源找到問題。

用來形成監控大盤。

錯誤碼不能直接輸出給使用者作爲提示資訊使用。

說明:堆疊(stack_trace)、錯誤資訊(error_message)、錯誤碼(error_code)、提示資訊(user_tip)是一個有效關聯並互相跳脫的和諧整體,但是請勿互相越俎代庖。

在獲取第三方服務錯誤碼時,向上拋出允許本系 本係統跳脫,由 C 轉爲 B,並且在錯誤資訊上帶上原有的第三方錯誤碼。

結合錯誤碼設計原則、錯誤碼用途、規約建議,面向伺服器端日誌的錯誤碼應該是如下形式。

《手冊》中建議
錯誤碼分爲一級宏觀錯誤碼、二級宏觀錯誤碼、三級宏觀錯誤碼。

錯誤碼即人性,感性認知+口口相傳,使用純數位來進行錯誤碼編排不利於感性記憶和分類。

說明:數位是一個整體,每位數位的地位和含義是相同的。

反例:一個五位數位 12345,第 1 位是錯誤等級,第 2 位是錯誤來源,345 是編號,人的大腦不會主動地分辨每位數位的不同含義。

按照《手冊》的建議設計出的面向日誌的錯誤碼定義共十三位(十位有意義,三位連線符),並且應該具有如下分類:

應用標識,表示錯誤屬於哪個應用,三位數位。

功能域標識,表示錯誤屬於應用中的哪個功能模組,三位數位。

錯誤型別,表示錯誤屬於那種型別,一位字母。

錯誤編碼,錯誤型別下的具體錯誤,三位數位。

《手冊》還有一條是規定錯誤碼應該如何定義:

錯誤碼爲字串型別,共 5 位,分成兩個部分:錯誤產生來源+四位數位編號。

說明:錯誤產生來源分爲 A/B/C,A 表示錯誤來源於使用者,比如參數錯誤,使用者安裝版本過低,使用者支付超時等問題;B 表示錯誤來源於當前系統,往往是業務邏輯出錯,或程式健壯性差等問題;C 表示錯誤來源於第三方服務,比如 CDN 服務出錯,訊息投遞超時等問題;四位數位編號從 0001 到 9999,大類之間的步長間距預留 100。

五位錯誤碼的好處是易記,但是對於面向日誌的錯誤碼場景利用錯誤碼製作需要分類的業務監控大盤將變得比較困難,比如統計應用 A 的功能 B 的錯誤出現次數。

同樣在系統間傳遞這個型別的錯誤碼非常有可能發生錯誤碼衝突。

《手冊》對於錯誤碼定義我認爲非常適合面向外部傳遞的錯誤碼。簡單、易記、是大家熟悉的錯誤碼樣式,並且透出的錯誤碼數量是非常有限的。

不用列舉定義錯誤碼

國際化支援是一個不使用列舉定義錯誤碼很重要的理由。

我們通過 i18n 的支援可以做到錯誤碼、錯誤狀態、錯誤描述的管理。

五 面向外部傳遞的錯誤碼

面向外部傳遞的錯誤碼是爲了把域內的錯誤資訊傳遞出去。

可以讓域外系統通過錯誤碼進行錯誤碼進行後續的動作或是中斷操作或是記錄日誌繼續執行。

可以讓前端通過錯誤碼給出使用者準確的錯誤提示或者忽略錯誤進行重試。

全部正常,但不得不填充錯誤碼,約定俗成的返回五個零:00000。