1.HTML日志
對日志系統的文本輸出部分稍做修改,每一行前加<P>,后加</P>,輸出結果就成了一個可瀏覽的HTML,然后,凡HTML能包括的東西,都能讓日志系統去LOG,做成一個圖文并茂的日志,這對于科研應用來說有很重要的意義,因為經常生成臨時的圖像,或者需要對某個數據結果可視化,這時候如果只要一個簡單的語句如
LogManager::getSingleton().logImage(someImage)
或者用宏進一步簡化
LOG(someImage)
就完成了臨時圖像的自動命名,并保存,然后添加到日志里,那將是很有吸引力的,生成的日志有點像一個Report,可以直接發給Boss看,當工作匯報 :)
為了對LOG進去的媒體內容有一定的處理,如顯示的時候縮放到合適的大小等,需要在日志文件的頭部加入一些Javascript的代碼,這需要日志系統的支持,能在開始記日志的時候判斷當前日志文件是否已經存在,只在不存在的時候才加入相應的頁首代碼。
當然,更進一步可以做成結構化的日志,這個還有待嘗試
2.Comment - Report 機制
如果寫的程序經常發生變化,那么時間長了以后,日志下來的數據是由什么樣的代碼產生的,就會不記得了,導致大量的數據沒有辦法分析,這里我用這樣的辦法
在產生數據的代碼附近用這樣一個語句
COMMENT(subject)
subject是一個字符串值,表示這一部分數據的主題,這個宏展開以后是這樣的
LogManager::getSingleton().addComment(subject, __FILE__, __LINE__);
這個函數在HTML的日志文件里新增一行,并生成一個超鏈接目的地,同時LogManager記下這個(string, string, int)組合
在LogManager被關閉的時候,會對所有的 Comment根據 Subject歸類,生成一個Techinical Report,像下面這樣
Tech Report:
---------------------------------------------------------
* SubjectA:
Comment1 - FileName - LineNo
Code Segment of Comment1
Comment2 - FileName - LineNo
Code Segment of Comment2
...
* SubjectB:
...
---------------------------------------------------------
同一個Subject可以對應多個代碼段,單擊Report里的 Comment 可以跳轉到先前 Comment生成的超鏈接日的地。
Code Segment由LogManager根據__FILE__和__LINE__從文件里讀取
3.變量記錄宏
一些有用的宏對記錄變量很有好處
#define LOGVAR(x) ToolLib::LOG(#x + std::string(" = ") + TOSTR(x))
#define LOGARR(x, i) ToolLib::LOG(#x + std::string("[") + TOSTR(i) + "] = " + TOSTR(x[i]))
用了這些宏就可以隨處記錄變量的值
4.直接數據記錄
LogManager需要有一個方法給出所用的文件對象,如 ofstream或 FILE*,這樣,對于大數據量的日志,比如幾千個int值,可以用這個文件對象直接輸入,而省去每一行記錄日期時間的麻煩
5.替換stdout或cout
經常有些第三方的庫用printf或者cout來輸出信息,需要想辦法把這些內容也catch到自己的日志系統里,對于printf模式的,可以用
FILE* fid = fopen();
*stdout = *fid;
來實現,而對于cout型的,不好辦,可以自己寫一個新的ostream子類,然后用宏把cout重新define一下,設成自己的ostream,并重寫一下sync函數來capture輸出。