【问题标题】:Nested/Formatted logging嵌套/格式化日志记录
【发布时间】:2012-02-01 13:32:37
【问题描述】:

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

[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

【问题讨论】:

  • 我找到了一个简单的单例类,它带有宏,可以根据调试定义进行调用,如果您需要创建一个,则最容易创建,否则只需执行项目已经在做的事情。
  • “项目”目前使用一个非常简单的记录器类。我继承了一堆流控制不明确的代码和许多具有多个退出点的函数/方法,纯未经过滤的意大利面条代码。而现在,我已经迫不及待地想用新的日志记录代码来抹黑代码,至少可以知道发生了什么:(
  • @AdrianAlbrecht:一个方法中有多个退出点并没有错……但是长方法通常不好:)

标签: c++ logging


【解决方案1】:

我不知道任何日志记录框架,但我已经使用了足够多漂亮的打印机,我知道这并不难。

假设存在支持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__ 足以满足我的需求。

【讨论】:

    猜你喜欢
    • 2015-08-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 2013-12-15
    • 1970-01-01
    • 2011-03-27
    • 2011-08-12
    • 1970-01-01
    相关资源
    最近更新 更多