李驪
(西安市軌道交通集團(tuán)有限公司建設(shè)分公司,陜西西安 710018)
北京地鐵6號(hào)線于2012年12月30日正式開(kāi)通運(yùn)營(yíng),是國(guó)內(nèi)首條采用TIAS(行車綜合自動(dòng)化系統(tǒng))的線路。而正在建設(shè)中的北京3號(hào)線、12號(hào)線、17號(hào)線及19號(hào)線,其上層監(jiān)控系統(tǒng)也都采用了T1AS[1]。TIAS 將自動(dòng)列車監(jiān)控系統(tǒng)(ATS)和綜合監(jiān)控系統(tǒng)(ISCS)深度集成,即集成了信號(hào)、機(jī)電、電力、通信等不同業(yè)務(wù)的應(yīng)用功能,提供統(tǒng)一的人機(jī)界面,具有豐富的跨系統(tǒng)聯(lián)動(dòng)功能,極大地提高了調(diào)度的工作效率[1]。
日志記錄作為TIAS 中不可或缺的功能,是目前最常見(jiàn)的故障信息載體[2],在故障問(wèn)題分析和查找中發(fā)揮著重要作用。一般日志模塊,僅提供日志文件名稱、文件存儲(chǔ)位置、文件大小、日志描述字符串、日志記錄時(shí)間等接口。日志模塊的使用人員通過(guò)設(shè)置日志文件名稱、位置、大小對(duì)日志模塊進(jìn)行初始化操作后,通過(guò)寫日志接口傳遞字符串描述參數(shù),完成一條日志的記錄。
由于上述方法僅以一個(gè)字符串參數(shù)描述日志的記錄,未對(duì)日志記錄的格式做出規(guī)范,因此受制于開(kāi)發(fā)人員的編程習(xí)慣等因素,日志記錄格式各異,當(dāng)軟件出現(xiàn)問(wèn)題時(shí),無(wú)法準(zhǔn)確快速的定位問(wèn)題。
開(kāi)發(fā)人員用于軟件自測(cè)跟蹤、調(diào)試的日志,多數(shù)情況下,在軟件正式上線后,應(yīng)該屏蔽。但由于開(kāi)發(fā)人員疏漏,這些日志在軟件正式上線后,沒(méi)有被刪除或者屏蔽,導(dǎo)致這些日志被記錄到了上線軟件的日志中,與其他需要真正記錄系統(tǒng)錯(cuò)誤、警告等的日志混淆在一起,影響日志記錄的有效性。
按等級(jí),將日志信息分為四類,分別為Debug級(jí)、Info級(jí)、Warn級(jí)、ERROR級(jí)、FATAL 級(jí)。Debug級(jí),打印狀態(tài)信息、提示信息等,以便開(kāi)發(fā)過(guò)程中跟蹤、調(diào)試,開(kāi)發(fā)完成、正式上線后,日志系統(tǒng)將自動(dòng)屏蔽這些信息的記錄日志;Info級(jí),記錄應(yīng)用中正常但有意義和有價(jià)值的事情,如用戶登陸、數(shù)據(jù)庫(kù)查詢語(yǔ)句等;Warn級(jí),屬于比較輕微的“告警”,程序出現(xiàn)這些異常,影響不大,可以正常使用,程序正式上線后,日志系統(tǒng)將這些信息寫入記錄日志中;Error級(jí),屬于普通“錯(cuò)誤”,不需要立即被處理,不會(huì)造成一連串的影響或巨大影響,但需要被記錄且監(jiān)控,程序正式上線后,日志系統(tǒng)將這些信息寫入記錄日志中;FATAL 級(jí),屬于嚴(yán)重的“錯(cuò)誤”,如導(dǎo)致程序功能損壞,宕機(jī)等,程序正式上線后,日志系統(tǒng)將這些信息寫入記錄日志中。
日志文件格式如下:
程序名稱—模塊名稱—自定義—等級(jí)名稱.log
通常我們做記錄時(shí),一般包括時(shí)間、地點(diǎn)、人物、事件、類型、等級(jí)等要素,因此,一條規(guī)范的日志記錄,應(yīng)包括序號(hào)、日期,程序名稱、程序模塊、等級(jí)名稱、記錄描述等,其中序號(hào)、日期,程序名稱、程序模塊、等級(jí)名稱是一個(gè)日志記錄不可或缺的。日志系統(tǒng)在設(shè)計(jì)時(shí),一般也都會(huì)設(shè)計(jì)這部分。但記錄描述,為了考慮其可擴(kuò)展性和靈活性,一般僅以字符串作為輸入?yún)?shù),這就造成記錄描述根據(jù)個(gè)人習(xí)慣去任意書寫,記錄描述五花八門,沒(méi)有固定的格式,更沒(méi)有標(biāo)識(shí)易于日志查閱和分析。如圖1 所示。
圖1 傳統(tǒng)日志記錄Fig.1 Traditional logging
清晰的規(guī)范的記錄描述,應(yīng)有明確標(biāo)識(shí),規(guī)范化的語(yǔ)言,如圖2所示。
圖2 清晰的規(guī)范的日志記錄Fig.2 Clear and canonical logging
為了滿足不同日志記錄格式的需求,規(guī)范日志記錄格式的靈活性,增加記錄模板。以規(guī)范日志的記錄格式,便于閱讀和查找。
記錄模板由記錄項(xiàng)列表組成,其中記錄項(xiàng)包括記錄描述、記錄類型、記錄數(shù)據(jù)三部分。日志系統(tǒng)對(duì)外寫日志的接口參數(shù)由原來(lái)的字符串改為記錄項(xiàng)列表。
如圖2所示。記錄模板的記錄項(xiàng)列表如表1。
表1 記錄項(xiàng)列表Tab.1 List of record items
為保證記錄模板的可擴(kuò)展性,“記錄類型”除了字符串,整型外,也可以是布爾類型、浮點(diǎn)類型等常用數(shù)據(jù)類型。
當(dāng)日志系統(tǒng)啟動(dòng)時(shí),首先加載記錄模板。當(dāng)日志系統(tǒng)接收到新的記錄項(xiàng)列表后,首先在記錄模板中按“記錄描述”字段進(jìn)行查找,如果新記錄項(xiàng)列表的描述在日志模板的描述中均被找到,則按照以下格式打印在日志中,否則不打印。
調(diào)試開(kāi)關(guān)主要用于程序自測(cè)和調(diào)試。當(dāng)程序開(kāi)發(fā)階段,調(diào)試階段或者允許現(xiàn)場(chǎng)調(diào)試時(shí),可以打開(kāi)調(diào)試開(kāi)關(guān),顯示Debug級(jí)、Info級(jí)、Warn級(jí)、ERROR級(jí)、FATAL級(jí)日志。調(diào)試開(kāi)關(guān)默認(rèn)為關(guān)閉狀態(tài)。當(dāng)程序正式運(yùn)營(yíng)后,關(guān)閉調(diào)試開(kāi)關(guān)。
考慮到程序員的編寫習(xí)慣和日志系統(tǒng)的靈活性,Debug級(jí)日志可以無(wú)需做規(guī)范性日志書寫原則,因此不需在記錄模板中進(jìn)行記錄字段的合法性檢查,即可調(diào)試開(kāi)關(guān)開(kāi)放時(shí),打印在日志中。
本方案技術(shù)關(guān)鍵點(diǎn)在于:(1)日志信息按等級(jí)劃分,結(jié)合調(diào)試開(kāi)關(guān),可以使程序在正式上線后,自動(dòng)屏蔽掉不必要的日志記錄信息??砂吹燃?jí)查找問(wèn)題,提高問(wèn)題查找速度。(2)采用記錄模板的方式,不但能靈活的添加各種記錄字段描述,還可以規(guī)范日志打印格式。(3)寫日志接口采用記錄項(xiàng)作為參數(shù),日志模塊對(duì)輸入?yún)?shù)以模板中記錄的描述為參考進(jìn)行篩選,防止開(kāi)發(fā)人員隨意輸入日志描述。
日志系統(tǒng)包括日志記錄模塊、日志檢查模塊、日志模板管理模塊、日志輸出模塊四大部分。
日志記錄模塊主要負(fù)責(zé)日志的創(chuàng)建和日志記錄管理(LogManager),由LogManager對(duì)象根據(jù)不同程序名稱,模塊名稱,等級(jí)名稱接收各種日志信息的日志對(duì)象。并同步將日志分派給日志檢查模塊。
日志檢查模塊主要負(fù)責(zé)除Debug級(jí)日志以外的其他等級(jí)日志合法性的檢查。根據(jù)日志記錄模塊分派的日志,依據(jù)模板日志中記錄項(xiàng)列表中的“記錄描述”,檢查日志記錄的合法性,并將合法日志傳輸?shù)饺罩据斎肽K。
日志管理模塊主要負(fù)責(zé)日志記錄項(xiàng)列表的增加、刪除和修改以及存儲(chǔ)。
日志輸出模塊則負(fù)責(zé)日志輸出器(Appender)的創(chuàng)建和管理,以及日志的輸出。系統(tǒng)中允許有多個(gè)不同的日志輸出器,日志輸出器負(fù)責(zé)將日志記錄到存儲(chǔ)介質(zhì)當(dāng)中。
系統(tǒng)結(jié)構(gòu)如圖3 所示。
圖3 系統(tǒng)結(jié)構(gòu)圖Fig.3 System structure diagram
LogManager是整個(gè)日志系統(tǒng)結(jié)構(gòu)的用戶使用接口,程序員可以通過(guò)該接口記錄日志。為了實(shí)現(xiàn)對(duì)日志進(jìn)行分類,系統(tǒng)設(shè)計(jì)允許存在多個(gè)LogManager對(duì)象,每一個(gè)LogManager 負(fù)責(zé)一類日志的記錄,如程序名稱、程序模塊、等級(jí)名稱、自定義類型等屬性。LogManager類同時(shí)實(shí)現(xiàn)了對(duì)其對(duì)象本身的管理,在客戶端創(chuàng)建和發(fā)送日志時(shí),這些屬性會(huì)被使用到。LogManager對(duì)象在接收到客戶端創(chuàng)建和發(fā)送的日志消息時(shí),同時(shí)將該日志消息包裝成日志系統(tǒng)內(nèi)部所使用的日志對(duì)象LogItem,Debug級(jí)的日志對(duì)象除了發(fā)送端所發(fā)送的消息以外,還會(huì)包裝諸如發(fā)送端類名、發(fā)送事件、發(fā)送方法名、發(fā)送行號(hào)等。這些額外的消息對(duì)于系統(tǒng)的跟蹤和調(diào)試都非常有價(jià)值。包裝好的LogItem最終被發(fā)送給日志輸出器(Appender),由這些日志輸出器負(fù)責(zé)將日志信息寫入最終媒介,輸出器的類型和個(gè)數(shù)均不固定,所有的輸出器通過(guò)日志輸出器管理對(duì)象進(jìn)行管理,通常通過(guò)配置文件即可方便擴(kuò)展出多個(gè)輸出器。
本方案具有以下優(yōu)點(diǎn):
(1)避免軟件自測(cè)跟蹤、調(diào)試的日志被打印到了正式上線的軟件日志中。
(2)通過(guò)日志記錄格式,規(guī)范日志打印格式,提高問(wèn)題查找和分析的速度。
以下為日志打印記錄
42 25.07.2020.10.22.020 [初始化]開(kāi)始加載設(shè)備狀態(tài)配置文件
46 25.07.2020.10.22.030 [檢查]配置文件
47 25.07.2020.10.22.100 [成功]結(jié)束加載設(shè)備狀態(tài)配置文件
49 25.07.2020.10.23.000 [失敗]網(wǎng)絡(luò)連接[IP]191.128..50.101
本文通過(guò)調(diào)整日志模塊的結(jié)構(gòu),將日志模塊按等級(jí)和用途分類,重新定義日志記錄的描述方式,規(guī)范日志記錄,提高日志記錄的信息有效性。不但提高了軟件的開(kāi)發(fā)質(zhì)量,而且提高了問(wèn)題分析和查找的效率,使得通過(guò)日志查找、定位、分析、解決問(wèn)題的能力不再受制于開(kāi)發(fā)人員。軟件維護(hù)人員,甚至到運(yùn)營(yíng)維護(hù)人員也可以通過(guò)規(guī)范、清晰易懂的語(yǔ)言描述,快速查找定位問(wèn)題。