嵌套/格式化日志记录

时间:2012-02-01 13:32:38

标签: c++ logging

也许这是一个微不足道的问题,很多/大多数/所有优秀的框架都能做到,但我正在寻找一个记录器类/框架(尽可能简单)使其变得简单有一个嵌套的日志输出,如

[time] A::doSomething start
[time]   doing this
[time]   doing that
[time]   calling B
[time]   B::somethingElse start
[time]     do
[time]     re
[time]     mi
[time]     c::foo start
[time]       ...
[time]     c::foo end
[time]   B::somethingElse end
[time] A::doSomething end

我在搜索互联网时最接近的是nested diagnostic contexts in log4j。但是a)这是针对java和b)我不确定这是否提供了我正在寻找的东西......

在文档中有这个“当离开上下文时,调用NDC.pop”。如果可能的话,我想拥有更多基于堆栈的魔法。

那里有没有可以做我正在寻找的项目?

TIA

1 个答案:

答案 0 :(得分:0)

我不知道有任何日志记录框架,但我玩过足够漂亮的打印机,我知道这并不困难。

假设存在支持pushpop操作的Logger类:

class LogNester: private boost::noncopyable {
public:
  LogNester(Logger& l): logger(l) { logger.push(); }
  ~LogNester() { logger.pop(); }

private:
  Logger& logger;
};

用法:

void foo() {
  LogNester _(GlobalLogger);

  // do something
}

一个重点:您需要命名变量,LogNester(GlobalLogger)将仅为此语句推送和弹出(oups),而命名变量将活到范围的最后。

如果你厌倦了每次都想出新​​名字(我能理解),你可以随时使用一个宏:

#define NESTLOG() LogNester BOOST_PP_CAT(log, __LINE__)(GlobalLogger);

但是,它并不完全是......自动化的,因为您需要在每个方法输入时定义LogNester对象。从理论上讲,只要你不介意有点慢下来,你应该能够神奇地获得深度:使用堆栈调用信息。 gcc使用backtrace实用程序

完成此操作
#include <execinfo.h> // GNU/Linux specific header

inline unsigned depth() {
  void* Stack[64];
  return backtrace(Stack, sizeof(Stack));
}

然后,增强您的日志记录宏:

#define LOG(Message_) \
  do { \
    GlobalLogger.log(__FILE__, __LINE__, __FUNCTION__, depth(), Message_); \
  } while(0)

当然,这在很大程度上取决于是否内联电话。

我个人认为__FILE____LINE____FUNCTION__足以满足我的需求。