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

LogManager::getSingleton().logImage(someImage)

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

LOG(someImage)

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

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

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

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

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

COMMENT(subject)

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

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

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

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

Tech Report:
---------------------------------------------------------
* SubjectA:
Comment1 - FileName - LineNo
Code Segment of Comment1
Comment2 - FileName - LineNo
Code Segment of Comment2
...
* SubjectB:
...
---------------------------------------------------------
同一個(gè)Subject可以對(duì)應(yīng)多個(gè)代碼段,單擊Report里的 Comment 可以跳轉(zhuǎn)到先前 Comment生成的超鏈接日的地。
Code Segment由LogManager根據(jù)__FILE__和__LINE__從文件里讀取

3.變量記錄宏

一些有用的宏對(duì)記錄變量很有好處
#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需要有一個(gè)方法給出所用的文件對(duì)象,如 ofstream或 FILE*,這樣,對(duì)于大數(shù)據(jù)量的日志,比如幾千個(gè)int值,可以用這個(gè)文件對(duì)象直接輸入,而省去每一行記錄日期時(shí)間的麻煩

5.替換stdout或cout

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

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

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