1.HTML日志
對日志系統(tǒng)的文本輸出部分稍做修改,每一行前加<P>,后加</P>,輸出結(jié)果就成了一個可瀏覽的HTML,然后,凡HTML能包括的東西,都能讓日志系統(tǒng)去LOG,做成一個圖文并茂的日志,這對于科研應(yīng)用來說有很重要的意義,因?yàn)榻?jīng)常生成臨時的圖像,或者需要對某個數(shù)據(jù)結(jié)果可視化,這時候如果只要一個簡單的語句如

LogManager::getSingleton().logImage(someImage)

或者用宏進(jìn)一步簡化

LOG(someImage)

就完成了臨時圖像的自動命名,并保存,然后添加到日志里,那將是很有吸引力的,生成的日志有點(diǎn)像一個Report,可以直接發(fā)給Boss看,當(dāng)工作匯報 :)

為了對LOG進(jìn)去的媒體內(nèi)容有一定的處理,如顯示的時候縮放到合適的大小等,需要在日志文件的頭部加入一些Javascript的代碼,這需要日志系統(tǒng)的支持,能在開始記日志的時候判斷當(dāng)前日志文件是否已經(jīng)存在,只在不存在的時候才加入相應(yīng)的頁首代碼。

當(dāng)然,更進(jìn)一步可以做成結(jié)構(gòu)化的日志,這個還有待嘗試

2.Comment - Report 機(jī)制
如果寫的程序經(jīng)常發(fā)生變化,那么時間長了以后,日志下來的數(shù)據(jù)是由什么樣的代碼產(chǎn)生的,就會不記得了,導(dǎo)致大量的數(shù)據(jù)沒有辦法分析,這里我用這樣的辦法

在產(chǎn)生數(shù)據(jù)的代碼附近用這樣一個語句

COMMENT(subject)

subject是一個字符串值,表示這一部分?jǐn)?shù)據(jù)的主題,這個宏展開以后是這樣的

LogManager::getSingleton().addComment(subject, __FILE__, __LINE__);

這個函數(shù)在HTML的日志文件里新增一行,并生成一個超鏈接目的地,同時LogManager記下這個(string, string, int)組合

在LogManager被關(guān)閉的時候,會對所有的 Comment根據(jù) Subject歸類,生成一個Techinical Report,像下面這樣

Tech Report:
---------------------------------------------------------
* SubjectA:
Comment1 - FileName - LineNo
Code Segment of Comment1
Comment2 - FileName - LineNo
Code Segment of Comment2
...
* SubjectB:
...
---------------------------------------------------------
同一個Subject可以對應(yīng)多個代碼段,單擊Report里的 Comment 可以跳轉(zhuǎn)到先前 Comment生成的超鏈接日的地。
Code Segment由LogManager根據(jù)__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.直接數(shù)據(jù)記錄

LogManager需要有一個方法給出所用的文件對象,如 ofstream或 FILE*,這樣,對于大數(shù)據(jù)量的日志,比如幾千個int值,可以用這個文件對象直接輸入,而省去每一行記錄日期時間的麻煩

5.替換stdout或cout

經(jīng)常有些第三方的庫用printf或者cout來輸出信息,需要想辦法把這些內(nèi)容也catch到自己的日志系統(tǒng)里,對于printf模式的,可以用

FILE* fid = fopen();
*stdout = *fid;

來實(shí)現(xiàn),而對于cout型的,不好辦,可以自己寫一個新的ostream子類,然后用宏把cout重新define一下,設(shè)成自己的ostream,并重寫一下sync函數(shù)來capture輸出。