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输出。