上一期介紹的逼近法是一種臨時起意的觀察,因為在過程中,是隨著每一回合的觀察結果,決定接下來要鋪設的觀察點。雖然這樣子的做法,實務上也有其需要,但事實上,現代的軟體開發,多半都已經透過日誌程式庫(Logging Library),內建除錯的基礎設施。

在談「除錯的基礎設施」之前,先來看看關於日誌程式庫的二三事。基本上,日誌程式庫是提供應用程式撰寫日誌檔(Log File)相關機制的程式庫。應用程式或系統,可以將系統曾經運行過的狀態或發生過的事件記錄在日誌檔中。之後透過觀察日誌檔裡的記錄,了解曾經發生過的事件,或者系統是否曾經進入預期之外的狀態。

一個好的日誌程式庫,應該要提供幾個功能:(1)選擇記錄的媒介、(2)記錄訊時,可設定的日誌等級、(3)提供訊息記錄的格式、(4)提供盡可能詳盡的記錄地點。

日誌檔一般來說,使用的記錄媒介就是檔案。但好的日誌程式庫,應該提供全方位的選擇,例如直接從Console印出訊息,或是將記錄寫入資料庫,甚至是透過Socket的方式,將訊息送往遠端的伺服器並且記錄於遠端。

一般來說,最常使用的就是檔案,日誌程式庫一般都會提供多種便利的檔案記錄方式,例如固定的日誌檔大小,倘若記錄的訊息超過所設定的大小時,自動刪去最舊的訊息。

另一類常用的日誌檔形式,是自動記錄每天一份的日誌檔,採用這種記錄方式,要追查某一天所發生的事件,就格外地容易了。

所謂的日誌等級(Logging Level),指的是所記錄訊息的重要性。常見的日誌程式庫,大致上都會將記錄的訊息(依重要性遞增)區分為:Trace、Debug、Info、Warn、Error、Fatal等。

而利用日誌程式庫記錄訊息時,可以指定訊息記錄的等級,例如指定一條記錄的訊息是Info等級,而系統在運行時,會被設定一個日誌等級,例如是Debug。這時候,所有欲記錄的訊息等級倘若大於等於Debug(例如Info或Warn),便會被記錄下來,反之,若記錄的訊息等級小於Debug時,便不會被記錄下來。

透過日誌等級的設定,我們就可以彈性控制系統所記錄的訊息,在測試甚至是追蹤臭蟲的期間,可以將等級調低,例如調低至Trace,如此一來,便會盡可能地詳盡記錄所有的訊息。但在正式上線的環境,可以將記錄等級調高,例如調至Error,避免太多無謂的記錄,一來影響系統的效能,二來浪費大量的儲存空間。

好的日誌程式庫應提供盡可能詳盡的資訊記錄,並且允許彈性的設定訊息記錄的格式,以便允許系統所記錄的訊息,以不同的格式呈現。例如記錄訊息的程式模組、程式檔案行數、執行時的執行緒編號、訊息記錄的時間、以及訊息內容等。

透過日誌程式庫,我們就可寫下像是這樣子的Java程式碼:


在這段程式碼中,我們利用log.info()記錄Info(意指information,用來描述一些運行相關資訊的)等級的訊息,像是記錄這段程式開始執行、結束執行,以及總共執行的工作個數(nJobEntry)。程式並且利用log.error()記錄過程中發生的異常。

除此之外,它也利用log.debug()記錄執行每個工作需要花費的時間,由於這個資訊僅基於在測試階段需要了解程式執行的效能,所以將它的日誌等級設為debug,待系統上線後,便不會印出此一訊息。

在日誌檔的設定部分,倘若我們以Java社群中廣為開發者所採用的log4j做為日誌程式庫的話,可以寫下如下述的設定內容(細詳的設定,可參見log4j的說明文件):


在上述的設定中,我們將整個系統的日誌等級設為Debug級,並且設定日誌訊息將記錄於A1輸出器及標準輸入(stdout)。而A1輸出器使用的是log4j所提供的固定大小的檔案記錄方式,在設定中指定了這個記錄檔最大不會超過10MB,同時也指定了訊息記錄的格式(ConversionPattern)。從這邊就可以觀察出,log4j提供了十分彈性而且功能強大的設定方式。

在開發的同時建立這樣子的「除錯基礎設施」,能夠對除錯派上什麼用場呢?當我們撰寫每一段程式碼,都包含著「自我記錄」的程式碼時,等於是將中斷點或記錄點記錄在系統的每一片段中。一旦有任何的臭蟲被回報,或是發現了系統有任何異常的情況,只消檢視日誌檔的記錄訊息,便可以快速的縮小診斷的範圍,甚至直接找出問題的根本導因。

這種做法之所以稱得上是一種基礎設施,是因為它並不是等到問題發生才開始進行觀察及檢測,而是在問題發生前,也就是在開發的同時,提供記錄系統狀態及事件的程式碼。等到問題發生時,便立即能夠提供詳盡的訊息協助研判問題的所在,加速問題解決的速度。

相較於等問題發生後,才設定中斷點或記錄訊息,「除錯基礎設施」支持的方式,顯然健全許多,也是一個更系統性的除錯方式。

這種程式碼「自我記錄」的觀念頗值得採用。因為開發團隊可以建立開發階段的文化及慣例,甚至是規定,要求程式員在撰寫程式片段(例如函式)時,都必須依照一定的方式記錄日誌訊息,例如進入函式、離開函式、所發生的錯誤(像是開檔失敗,或是建檔已存在)、函式中所運用的重要變數之值、或是函式進入了預期以外的執行路徑等。不同重要程度的訊息必須設定適當的日誌等級。

倘若同一開發團隊的成員,都能依循相同的日誌慣例(Logging Convention),系統在測試、除錯、甚至是上線運作時,便能夠留下足夠詳盡的日誌記錄,在問題發生時,可以於第一線提供初步的診斷線索,這是建立「除錯基礎設施」的重要目的。

《作者簡介》王建興
清華大學資訊工程系的博士研究生,研究興趣包括電腦網路、點對點網路、分散式網路管理、以及行動式代理人,專長則是Internet應用系統的開發。曾參與過的開發專案性質十分廣泛而且不同,從ERP、PC GAME到P2P網路電話都在他的涉獵範圍之內。

熱門新聞

Advertisement