打log的原則
- 異常分支或錯(cuò)誤處理一定要打log
- 重大操作時(shí)一定要打log,下面打log場(chǎng)景會(huì)講述
log格式的原則
1、時(shí)間戳必須有,最好能夠精確到微秒精確到秒的時(shí)間戳,相信很多人都熟悉,這能夠確認(rèn)問(wèn)題的時(shí)間和系統(tǒng)uptime的對(duì)比,能夠進(jìn)一步還原問(wèn)題的場(chǎng)景。至于到微秒,在多線程程序下,如果進(jìn)程停止響應(yīng),可以從日志時(shí)間看是否死鎖。一般格式:
[2017-01-09 12:16:30.541]
2、打log位置的文件名和代碼行數(shù)這個(gè)不用說(shuō),用于定位問(wèn)題根源。其實(shí)最重要是防止扯皮。因?yàn)?a target="_blank">程序員大多喜歡copy-paste,如果你不加文件名和行數(shù),某程序員copy了你的代碼,修改了點(diǎn),出錯(cuò)了,到時(shí)候把你拉下水。一般格式:
[2017-01-09 12:16:30.541][network.c:541]
3、有進(jìn)程id有些log機(jī)制在進(jìn)程重啟時(shí),不會(huì)重新生成一個(gè)日志文件,而是直接在同一個(gè)日志文件后面添加日志。或者,有時(shí)候同一程序的多個(gè)進(jìn)程同時(shí)運(yùn)行,可能也會(huì)寫(xiě)入到同一個(gè)日志文件。
一般格式:
[2017-01-09 12:16:30.541][network.c:541][pid=15529]
4、有線程id在多線程程序,如果不加線程id,很難追溯程序的行為。
一般格式:
[2017-01-09 12:16:30.541][network.c:541][pid=15529][thread=0x12345]
5、有日志的級(jí)別日志是反映問(wèn)題的,有不同緊急程序的問(wèn)題,自然有不同的日志級(jí)別。一般采用Error,Warning,Info,Debug。定義不同級(jí)別,也可以方便在日志查找問(wèn)題來(lái)源。
一般格式:
[2017-01-09 12:16:30.541][network.c:541][pid=15529][thread=0x12345][Error]
打log的場(chǎng)景1、申請(qǐng)內(nèi)存時(shí),失敗的話,要把申請(qǐng)大小打印出來(lái)
以前我申請(qǐng)內(nèi)存失敗也是簡(jiǎn)單地打印:
[2017-01-09 12:16:30.541][network.c:541][pid=15529][thread=0x12345][Error]Failedtoallocatememory
后來(lái)在重構(gòu)時(shí)遇到一個(gè)問(wèn)題:進(jìn)程跑的時(shí)間一久,大概一天多,別的程序向它發(fā)消息都會(huì)收到失敗響應(yīng),在日志里就是一大堆內(nèi)存失敗的消息"Failed to allocate memory"。
用"free"命令來(lái)看,物理內(nèi)存還有好幾G空閑,而用“top”命令來(lái)看,該進(jìn)程也只是占700M內(nèi)存。當(dāng)時(shí)我就懷疑是不是內(nèi)存碎片導(dǎo)致。于是我把申請(qǐng)內(nèi)存的大小也打印出來(lái),就收到一堆這樣的:
[2017-01-09 12:16:30.541][network.c:541][pid=15529][thread=0x12345][Error]Failed to allocate memory of size 65536
[2017-01-09 12:16:30.588][network.c:541][pid=15529][thread=0x12345][Error]Failedtoallocatememoryofsize1048576
當(dāng)時(shí)就看那些代碼引用的數(shù)據(jù)結(jié)構(gòu),最小也有64K,大的16M都有,基本一個(gè)結(jié)構(gòu)包括很多個(gè)大數(shù)組。當(dāng)時(shí)就把那些數(shù)組全改為指針,再進(jìn)一步申請(qǐng),代碼繁瑣了,但這種問(wèn)題再也不會(huì)出現(xiàn)。再看bug系統(tǒng),原來(lái)這個(gè)問(wèn)題存在很多,在其它程序也存在,當(dāng)時(shí)都找不到根因,只是用過(guò)一段時(shí)間重啟進(jìn)程來(lái)解決2、 函數(shù)參數(shù)非空判斷時(shí),要打印日志原因不說(shuō),看對(duì)比:
之前:
if ( ( pInfo == NULL ) || ( pHandler == NULL ) )
{
log( ERROR, "invalid arguments" );
}
之后:
if ( ( pInfo == NULL ) || ( pHandler == NULL ) )
{
log( ERROR, "invalid arguments:(pInfo, pHandler )=(%p,%p)",
pInfo, pHandler );
}
3、加載和卸載模塊,無(wú)論是正常還是異常情況都要打印
畢竟這些操作大多都是一次性操作。對(duì)性能影響不大。
[2017-01-09 12:16:30.588][modules.c:54][pid=15529][thread=0x12345][Error]Failedtoloadmodulelibftp.so,error=modulealreadyloaded
4、操作文件目錄時(shí),失敗要把文件名和錯(cuò)誤碼打印出來(lái)
如:
[2017-01-09 12:16:30.588][config.c:120][pid=15529][thread=0x12345][Error]Failedtoopenfileconf/ftp.xml,errno=(13:Permissiondenied)
假設(shè)這個(gè)錯(cuò)誤導(dǎo)致進(jìn)程初始化失敗,且環(huán)境在客戶那邊,維護(hù)人員就可以確認(rèn)并自己解決這個(gè)問(wèn)題。5、操作socket時(shí),把IP,端口號(hào)或路徑名(Unix socket )和錯(cuò)誤碼打印出來(lái)
如:
[2017-01-09 12:16:30.588][network.c:541][pid=15529][thread=0x12345][Error]Failedtoconnecttohost(10.17.128.10:9981),errno=(111:Connectionrefused)
假設(shè)在客戶環(huán)境出錯(cuò),維護(hù)人員可以根據(jù)日志來(lái)確認(rèn)10.17.128.10這臺(tái)機(jī)器是否在線,是否開(kāi)啟了相應(yīng)的服務(wù),或者服務(wù)是開(kāi)啟了,可能只是端口配置錯(cuò)了(這種情況是扯皮最多的)6、操作數(shù)據(jù)庫(kù)時(shí),把相應(yīng)操作的IP,端口,庫(kù),用戶名,sql語(yǔ)句和錯(cuò)誤打印出來(lái)
如:
[2017-01-09 12:16:30.588][dbmgr.c:781][pid=15529][thread=0x12345][Error]user tiger failed to operate in host (10.17.128.10:3365) with db test, sql="select * from users", error="no table users exists"
在客戶環(huán)境下,維護(hù)人員可以通過(guò)命令行來(lái)驗(yàn)證這些問(wèn)題,來(lái)確定問(wèn)題。可能有人會(huì)考慮安全性,畢竟在日志中把IP,端口,庫(kù),用戶名都暴露出來(lái)了,這樣好像不妥。但如果是從事過(guò)通信行業(yè)的網(wǎng)上問(wèn)題維護(hù),就知道,可維護(hù)性比這種細(xì)節(jié)的安全性還要重要。7、創(chuàng)建新進(jìn)程時(shí),需要把程序名,參數(shù)和錯(cuò)誤碼打印出來(lái)如:
[2017-01-09 12:16:30.588][process.c:154][pid=15529][thread=0x12345][Error]failed to execute program "iptables -L", errno=(2:No such file or directory)
往往在客戶環(huán)境,由于運(yùn)維人員水平參差不齊,可能誤操作或漏操作,導(dǎo)致文件缺失或權(quán)限出錯(cuò),這種錯(cuò)誤在公司的模擬環(huán)境根本不會(huì)出現(xiàn)。如果日志夠詳細(xì),能夠減少很多工作量。8、解析文件時(shí),需要把文件名,字段,行號(hào)打印出來(lái)如:
[2017-01-09 12:16:30.588][config.c:120][pid=15529][thread=0x12345][Error]Failed to parse file conf/ftp.xml, line:20, tag <host> is not closed
結(jié)語(yǔ)上面的原則,基本是每一條是血的教訓(xùn)。以前在H時(shí)見(jiàn)得太多因?yàn)槿罩静蝗珜?dǎo)致的麻煩,前方的客戶經(jīng)理不斷向客戶懇求寬限時(shí)間,維護(hù)人員不斷地在客戶環(huán)境找出蛛絲馬跡,后方領(lǐng)導(dǎo)也不斷地調(diào)配資源來(lái)跟蹤問(wèn)題,后方測(cè)試人員不斷地測(cè)試,嘗試問(wèn)題復(fù)現(xiàn),后方開(kāi)發(fā)人員就不斷地看代碼。在Z也見(jiàn)過(guò)因?yàn)槿罩静蝗瑢?dǎo)致被客戶罰錢(qián)次數(shù)過(guò)多,整個(gè)產(chǎn)品都虧損了。像?@帝都鐵匠 說(shuō)的“感覺(jué)學(xué)會(huì)log,程序就算入門(mén)了”。
-
程序
+關(guān)注
關(guān)注
117文章
3798瀏覽量
81459 -
Log
+關(guān)注
關(guān)注
0文章
14瀏覽量
11355 -
線程
+關(guān)注
關(guān)注
0文章
507瀏覽量
19763
原文標(biāo)題:感覺(jué)學(xué)會(huì)log,程序就算入門(mén)了
文章出處:【微信號(hào):c-stm32,微信公眾號(hào):STM32嵌入式開(kāi)發(fā)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
FPGA入門(mén)容易,關(guān)鍵是怎么進(jìn)階!
教大家如何看懂電路圖
討論labview如何算入門(mén)?
總結(jié)大佬經(jīng)驗(yàn),如何學(xué)習(xí)STM32?(入門(mén)、進(jìn)階)
單片機(jī)開(kāi)發(fā)怎么才算入門(mén)了
輕松入門(mén)開(kāi)發(fā)ARM程序
![輕松<b class='flag-5'>入門(mén)</b>開(kāi)發(fā)ARM<b class='flag-5'>程序</b>](https://file.elecfans.com/web2/M00/48/7E/pYYBAGKhtAmARGrNAAAWir3s3FI058.jpg)
輕松入門(mén)開(kāi)發(fā)ARM程序
云計(jì)算入門(mén)指南
LOG112,LOG2112,pdf(Precision Logarithmic and Log Ratio Ampli
LOG101/LOG104偏流調(diào)零電路
![<b class='flag-5'>LOG</b>101/<b class='flag-5'>LOG</b>104偏流調(diào)零電路](https://file1.elecfans.com//web2/M00/A4/E6/wKgZomUMNiOAfouvAAB-g2urIBs861.jpg)
通信原理易入門(mén) 上手 輕松學(xué)會(huì)現(xiàn)代通信原理
![通信原理易<b class='flag-5'>入門(mén)</b> 上手 輕松<b class='flag-5'>學(xué)會(huì)</b>現(xiàn)代通信原理](https://file.elecfans.com/web2/M00/49/AA/pYYBAGKhvEqACTiqAAAbxLE0-FM249.png)
如何讓?xiě)?yīng)用程序感覺(jué)更快
基于Rust的Log日志庫(kù)介紹
Log4cpp優(yōu)勢(shì)及優(yōu)點(diǎn)
![<b class='flag-5'>Log</b>4cpp優(yōu)勢(shì)及優(yōu)點(diǎn)](https://file1.elecfans.com/web2/M00/AF/06/wKgZomVMe4OAfI4oAAJ9PjTiDQ0235.jpg)
評(píng)論