本文適用范圍:Linux系統使用語言:C/C++
打log的原則
- 異常分支或錯誤處理一定要打log
- 重大操作時一定要打log,下面打log場景會講述
log格式的原則
1、時間戳必須有,最好能夠精確到微秒精確到秒的時間戳,相信很多人都熟悉,這能夠確認問題的時間和系統uptime的對比,能夠進一步還原問題的場景。至于到微秒,在多線程程序下,如果進程停止響應,可以從日志時間看是否死鎖。一般格式:
[2017-01-09 12:16:30.541]
2、打log位置的文件名和代碼行數這個不用說,用于定位問題根源。其實最重要是防止扯皮。因為程序員大多喜歡copy-paste,如果你不加文件名和行數,某程序員copy了你的代碼,修改了點,出錯了,到時候把你拉下水。一般格式:
[2017-01-09 12:16:30.541][network.c:541]
3、有進程id有些log機制在進程重啟時,不會重新生成一個日志文件,而是直接在同一個日志文件后面添加日志。或者,有時候同一程序的多個進程同時運行,可能也會寫入到同一個日志文件。
一般格式:
[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、有日志的級別日志是反映問題的,有不同緊急程序的問題,自然有不同的日志級別。一般采用Error,Warning,Info,Debug。定義不同級別,也可以方便在日志查找問題來源。
一般格式:
[2017-01-09 12:16:30.541][network.c:541][pid=15529][thread=0x12345][Error]
打log的場景1、申請內存時,失敗的話,要把申請大小打印出來
以前我申請內存失敗也是簡單地打印:
[2017-01-09 12:16:30.541][network.c:541][pid=15529][thread=0x12345][Error]Failedtoallocatememory
后來在重構時遇到一個問題:進程跑的時間一久,大概一天多,別的程序向它發消息都會收到失敗響應,在日志里就是一大堆內存失敗的消息"Failed to allocate memory"。
用"free"命令來看,物理內存還有好幾G空閑,而用“top”命令來看,該進程也只是占700M內存。當時我就懷疑是不是內存碎片導致。于是我把申請內存的大小也打印出來,就收到一堆這樣的:
[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
當時就看那些代碼引用的數據結構,最小也有64K,大的16M都有,基本一個結構包括很多個大數組。當時就把那些數組全改為指針,再進一步申請,代碼繁瑣了,但這種問題再也不會出現。再看bug系統,原來這個問題存在很多,在其它程序也存在,當時都找不到根因,只是用過一段時間重啟進程來解決2、 函數參數非空判斷時,要打印日志原因不說,看對比:
之前:
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、加載和卸載模塊,無論是正常還是異常情況都要打印
畢竟這些操作大多都是一次性操作。對性能影響不大。
[2017-01-09 12:16:30.588][modules.c:54][pid=15529][thread=0x12345][Error]Failedtoloadmodulelibftp.so,error=modulealreadyloaded
4、操作文件目錄時,失敗要把文件名和錯誤碼打印出來
如:
[2017-01-09 12:16:30.588][config.c:120][pid=15529][thread=0x12345][Error]Failedtoopenfileconf/ftp.xml,errno=(13:Permissiondenied)
假設這個錯誤導致進程初始化失敗,且環境在客戶那邊,維護人員就可以確認并自己解決這個問題。5、操作socket時,把IP,端口號或路徑名(Unix socket )和錯誤碼打印出來
如:
[2017-01-09 12:16:30.588][network.c:541][pid=15529][thread=0x12345][Error]Failedtoconnecttohost(10.17.128.10:9981),errno=(111:Connectionrefused)
假設在客戶環境出錯,維護人員可以根據日志來確認10.17.128.10這臺機器是否在線,是否開啟了相應的服務,或者服務是開啟了,可能只是端口配置錯了(這種情況是扯皮最多的)6、操作數據庫時,把相應操作的IP,端口,庫,用戶名,sql語句和錯誤打印出來
如:
[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"
在客戶環境下,維護人員可以通過命令行來驗證這些問題,來確定問題。可能有人會考慮安全性,畢竟在日志中把IP,端口,庫,用戶名都暴露出來了,這樣好像不妥。但如果是從事過通信行業的網上問題維護,就知道,可維護性比這種細節的安全性還要重要。7、創建新進程時,需要把程序名,參數和錯誤碼打印出來如:
[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)
往往在客戶環境,由于運維人員水平參差不齊,可能誤操作或漏操作,導致文件缺失或權限出錯,這種錯誤在公司的模擬環境根本不會出現。如果日志夠詳細,能夠減少很多工作量。8、解析文件時,需要把文件名,字段,行號打印出來如:
[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
結語上面的原則,基本是每一條是血的教訓。以前在H時見得太多因為日志不全導致的麻煩,前方的客戶經理不斷向客戶懇求寬限時間,維護人員不斷地在客戶環境找出蛛絲馬跡,后方領導也不斷地調配資源來跟蹤問題,后方測試人員不斷地測試,嘗試問題復現,后方開發人員就不斷地看代碼。在Z也見過因為日志不全,導致被客戶罰錢次數過多,整個產品都虧損了。像?@帝都鐵匠 說的“感覺學會log,程序就算入門了”。
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
程序
+關注
關注
116文章
3778瀏覽量
80860 -
Log
+關注
關注
0文章
14瀏覽量
11313 -
線程
+關注
關注
0文章
504瀏覽量
19653
原文標題:感覺學會log,程序就算入門了
文章出處:【微信號:c-stm32,微信公眾號:STM32嵌入式開發】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
FPGA入門容易,關鍵是怎么進階!
本帖最后由 hughqfb 于 2013-1-19 17:34 編輯
FPGA總算入門了,但接下來的學習疲軟心理讓我十分的懊惱。為什么我發現自己學習到一定程度后就不愿意學習了呢?當時學習
發表于 01-19 17:23
教大家如何看懂電路圖
本帖最后由 wpf1633 于 2013-12-3 00:09 編輯
本附件適合初學者,包含各個電子元件的符號,以及一些最基本的電路圖,弄懂這些電路,你就算入門了
發表于 12-03 00:06
討論labview如何算入門?
labview 和其他編程語言一樣,(最起碼都是編程語言)那么怎么才算入門?入門之后怎么去有效率的研究學習呢?當然學無止境,但是 學要有方法,歡迎過來人指點迷津。
發表于 12-07 08:50
總結大佬經驗,如何學習STM32?(入門、進階)
之內的不會的可以查資料,但是一定要要有自己的思想,完成了我覺得就算入門了。------Llinuxu六、關于初學者是否要弄懂底層函數 初學者沒必要弄懂底層函數。項目需要用到什么再去研究什么。比如你的項目
發表于 06-10 09:15
單片機開發怎么才算入門了
記得開始學單片機的時候,也很想知道自己到底學的怎樣了,到了什么水平,到處問人單片機開發怎么才算入門了,最后老師跟我說:能做一個萬年歷出來就算入門了
發表于 01-19 06:27
輕松入門開發ARM程序
很多朋友都想自己動手開發ARM 應用程序,卻不知從哪兒下手。我們編寫本手冊的目的就是想幫助這些初學者輕松的入門。應該說,入門學會開發ST ARM 應用
發表于 01-19 22:20
?31次下載
云計算入門指南
云計算入門指南:Sun 公司云計算技術可順利地擴展您的基礎設施,以抓住新的商業機會。
云計算在許多方面只是互聯網的一個比喻詞,亦即計算和數據資源日益遷移到 Web
發表于 02-10 09:50
?0次下載
LOG112,LOG2112,pdf(Precision Logarithmic and Log Ratio Ampli
The LOG112 and LOG2112 are versatile integrated circuits that compute the logarithm or log ratio
發表于 09-26 01:10
?38次下載
如何讓應用程序感覺更快
好的設計實際上可以讓時間加快!
......好吧......不,不是真的,但是Luke W確實分享了一些非常聰明的設計技巧,讓你的應用程序感覺更快 - 令人著迷
基于Rust的Log日志庫介紹
Rust是一門系統級編程語言,因其安全性、高性能和并發性而備受歡迎。在Rust應用程序中,日志記錄是一項非常重要的任務,因為它可以幫助開發人員了解應用程序的運行情況并解決問題。Rust的Log庫提供
評論